From 74a10cdd0a16357e38e276a664380ab55c1291f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Wed, 8 Feb 2023 19:52:02 +0100 Subject: [PATCH 001/142] Update Cypress support commands, add missing peer dep (#4382) --- .../volto-testing/cypress/support/commands.js | 515 +++++++++++++++--- .../cypress/support/constants.js | 1 + packages/volto-testing/package.json | 1 + packages/volto-testing/yarn.lock | 8 + 4 files changed, 444 insertions(+), 81 deletions(-) create mode 100644 packages/volto-testing/cypress/support/constants.js diff --git a/packages/volto-testing/cypress/support/commands.js b/packages/volto-testing/cypress/support/commands.js index fe15844360..e97938364a 100644 --- a/packages/volto-testing/cypress/support/commands.js +++ b/packages/volto-testing/cypress/support/commands.js @@ -1,10 +1,20 @@ import '@testing-library/cypress/add-commands'; import { getIfExists } from '../helpers'; +import { ploneAuth } from './constants'; const HOSTNAME = Cypress.env('BACKEND_HOST') || 'localhost'; const GUILLOTINA_API_URL = `http://${HOSTNAME}:8081/db/web`; const PLONE_SITE_ID = Cypress.env('SITE_ID') || 'plone'; -const PLONE_API_URL = Cypress.env('API_PATH') || `http://${HOSTNAME}:55001/${PLONE_SITE_ID}`; +const PLONE_API_URL = + Cypress.env('API_PATH') || `http://${HOSTNAME}:55001/${PLONE_SITE_ID}`; + +const SLATE_SELECTOR = '.content-area .slate-editor [contenteditable=true]'; +const SLATE_TITLE_SELECTOR = '.block.inner.title [contenteditable="true"]'; + +const ploneAuthObj = { + user: ploneAuth[0], + pass: ploneAuth[1], +}; // --- AUTOLOGIN ------------------------------------------------------------- Cypress.Commands.add('autologin', (usr, pass) => { @@ -15,8 +25,8 @@ Cypress.Commands.add('autologin', (usr, pass) => { password = pass || 'admin'; } else { api_url = PLONE_API_URL; - user = usr || 'admin'; - password = pass || 'secret'; + user = usr || ploneAuth[0]; + password = pass || ploneAuth[1]; } return cy @@ -36,9 +46,12 @@ Cypress.Commands.add( contentType, contentId, contentTitle, + contentDescription, path = '', allow_discussion = false, transition = '', + bodyModifier = (body) => body, + image = false, }) => { let api_url, auth; if (Cypress.env('API') === 'guillotina') { @@ -49,45 +62,46 @@ Cypress.Commands.add( }; } else { api_url = PLONE_API_URL; - auth = { - user: 'admin', - pass: 'secret', - }; + auth = ploneAuthObj; } + + const defaultParams = { + method: 'POST', + url: `${api_url}/${path}`, + headers: { + Accept: 'application/json', + }, + auth: auth, + body: { + '@type': contentType, + id: contentId, + title: contentTitle, + description: contentDescription, + allow_discussion: allow_discussion, + }, + }; + if (contentType === 'File') { - return cy.request({ - method: 'POST', - url: `${api_url}/${path}`, - headers: { - Accept: 'application/json', - }, - auth: auth, - body: { - '@type': contentType, - id: contentId, - title: contentTitle, + const params = { + ...defaultParams, + body: bodyModifier({ + ...defaultParams.body, file: { data: 'dGVzdGZpbGUK', encoding: 'base64', filename: 'lorem.txt', 'content-type': 'text/plain', }, - allow_discussion: allow_discussion, - }, - }); + }), + }; + + return cy.request(params); } if (contentType === 'Image') { - return cy.request({ - method: 'POST', - url: `${api_url}/${path}`, - headers: { - Accept: 'application/json', - }, - auth: auth, - body: { - '@type': contentType, - id: contentId, - title: contentTitle, + const params = { + ...defaultParams, + body: bodyModifier({ + ...defaultParams.body, image: { data: 'iVBORw0KGgoAAAANSUhEUgAAANcAAAA4CAMAAABZsZ3QAAAAM1BMVEX29fK42OU+oMvn7u9drtIPisHI4OhstdWZyt4fkcXX5+sAg74umMhNp86p0eJ7vNiKw9v/UV4wAAAAAXRSTlMAQObYZgAABBxJREFUeF7tmuty4yAMhZG4X2zn/Z92J5tsBJwWXG/i3XR6frW2Y/SBLIRAfaQUDNt8E5tLUt9BycfcKfq3R6Mlfyimtx4rzp+K3dtibXkor99zsEqLYZltblTecciogoh+TXfY1Ve4dn07rCDGG9dHSEEOg/GmXl0U1XDxTKxNK5De7BxsyyBr6gGm2/vPxKJ8F6f7BXKfRMp1xIWK9A+5ks25alSb353dWnDJN1k35EL5f8dVGifTf/4tjUuuFq7u4srmXC60yAmldLXIWbg65RKU87lcGxJCFqUPv0IacW0PmSivOZFLE908inPToMmii/roG+MRV/O8FU88i8tFsxV3a06MFUw0Qu7RmAtdV5/HVVaOVMTWNOWSwMljLhzhcB6XIS7OK5V6AvRDNN7t5VJWQs1J40UmalbK56usBG/CuCHSYuc+rkUGeMCViNRARPrzW52N3oQLe6WifNliSuuGaH3czbVNudI9s7ZLUCLHVwWlyES522o1t14uvmbblmVTKqFjaZYJFSTPP4dLL1kU1z7p0lzdbRulmEWLxoQX+z9ce7A8GqEEucllLxePuZwdJl1Lezu0hoswvTPt61DrFcRuujV/2cmlxaGBC7Aw6cpovGANwRiSdOAWJ5AGy4gLL64dl0QhUEAuEUNws+XxV+OKGPdw/hESGYF9XEGaFC7sNLMSXWJjHsnanYi87VK428N2uxpOjOFANcagLM5l+7mSycM8KknZpKLcGi6jmzWGr/vLurZ/0g4u9AZuAoeb5r1ceQhyiTPY1E4wUR6u/F3H2ojSpXMMriBPT9cezTto8Cx+MsglHL4fv1Rxrb1LVw9yvyQpJ3AhFnLZfuRLH2QsOG3FGGD20X/th/u5bFAt16Bt308KjF+MNOXgl/SquIEySX3GhaZvc67KZbDxcCDORz2N8yCWPaY5lyQZO7lQ29fnZbt3Xu6qoge4+DjXl/MocySPOp9rlvdyznahRyHEYd77v3LhugOXDv4J65QXfl803BDAdaWBEDhfVx7nKofjoVCgxnUAqw/UAUDPn788BDvQuG4TDtdtUPvzjSlXAB8DvaDOhhrmhwbywylXAm8CvaouikJTL93gs3y7Yy4VYbIxOHrcMizPqWOjqO9l3Uz52kibQy4xxOgqhJvD+w5rvokOcAlGvNCfeqCv1ste1stzLm0f71Iq3ZfTrPfuE5nhPtF+LvQE2lffQC7pYtQy3tdzdrKvd5TLVVzDetScS3nEKmmwDyt1Cev1kX3YfbvzNK4fzrlw+cB6vm+uiUgf2zdXI62241LawCb7Pi5FXFPF8KpzDoF/Sw2lg+GrHNbno1mhPu+VCF/vfMnw06PnUl6j48dVHD3jHNHPua+fc3o/5yp/zsGi0vYtzi3Pz5mHd4T6BWMIlewacd63AAAAAElFTkSuQmCC', @@ -95,38 +109,75 @@ Cypress.Commands.add( filename: 'image.png', 'content-type': 'image/png', }, - }, - }); + }), + }; + + return cy.request(params); } if ( ['Document', 'News Item', 'Folder', 'CMSFolder'].includes(contentType) ) { - return cy - .request({ - method: 'POST', - url: `${api_url}/${path}`, - headers: { - Accept: 'application/json', + const params = { + ...defaultParams, + body: { + ...defaultParams.body, + blocks: { + 'd3f1c443-583f-4e8e-a682-3bf25752a300': { '@type': 'title' }, + '7624cf59-05d0-4055-8f55-5fd6597d84b0': { '@type': 'slate' }, }, - auth: auth, - body: { - '@type': contentType, - id: contentId, - title: contentTitle, - blocks: { - 'd3f1c443-583f-4e8e-a682-3bf25752a300': { '@type': 'title' }, - '7624cf59-05d0-4055-8f55-5fd6597d84b0': { '@type': 'text' }, - }, - blocks_layout: { - items: [ - 'd3f1c443-583f-4e8e-a682-3bf25752a300', - '7624cf59-05d0-4055-8f55-5fd6597d84b0', - ], - }, - allow_discussion: allow_discussion, + blocks_layout: { + items: [ + 'd3f1c443-583f-4e8e-a682-3bf25752a300', + '7624cf59-05d0-4055-8f55-5fd6597d84b0', + ], }, - }) - .then(() => { + }, + }; + + if (image) { + let sourceFilename = 'cypress/fixtures/halfdome2022.jpg'; + let imageObject = { + encoding: 'base64', + filename: 'image.jpg', + 'content-type': 'image/jpg', + }; + if (typeof image === 'object') { + sourceFilename = image.sourceFilename; + imageObject = { + ...imageObject, + ...image, + }; + } + cy.readFile(sourceFilename, 'base64').then((encodedImage) => { + const withImageParams = { + ...params, + body: bodyModifier({ + ...params.body, + preview_image: { + ...imageObject, + data: encodedImage, + }, + }), + }; + + return cy.request(withImageParams).then(() => { + if (transition) { + cy.setWorkflow({ + path: path || contentId, + review_state: transition, + }); + } + console.log(`${contentType} created`); + }); + }); + } else { + const documentParams = { + ...params, + body: bodyModifier({ + ...params.body, + }), + }; + return cy.request(documentParams).then(() => { if (transition) { cy.setWorkflow({ path: path || contentId, @@ -135,6 +186,7 @@ Cypress.Commands.add( } console.log(`${contentType} created`); }); + } } else { return cy .request({ @@ -144,12 +196,12 @@ Cypress.Commands.add( Accept: 'application/json', }, auth: auth, - body: { + body: bodyModifier({ '@type': contentType, id: contentId, title: contentTitle, allow_discussion: allow_discussion, - }, + }), }) .then(() => { if (transition) { @@ -163,6 +215,7 @@ Cypress.Commands.add( } }, ); + // Remove content Cypress.Commands.add('removeContent', ({ path = '' }) => { let api_url, auth; @@ -174,13 +227,35 @@ Cypress.Commands.add('removeContent', ({ path = '' }) => { }; } else { api_url = PLONE_API_URL; + auth = ploneAuthObj; + } + + return cy.request({ + method: 'DELETE', + url: `${api_url}/${path}`, + headers: { + Accept: 'application/json', + }, + auth: auth, + }); +}); + +// Get content +Cypress.Commands.add('getContent', ({ path = '' }) => { + let api_url, auth; + if (Cypress.env('API') === 'guillotina') { + api_url = GUILLOTINA_API_URL; auth = { - user: 'admin', - pass: 'secret', + user: 'root', + pass: 'root', }; + } else { + api_url = PLONE_API_URL; + auth = ploneAuthObj; } + return cy.request({ - method: 'DELETE', + method: 'get', url: `${api_url}/${path}`, headers: { Accept: 'application/json', @@ -189,6 +264,92 @@ Cypress.Commands.add('removeContent', ({ path = '' }) => { }); }); +// --- Add DX Content-Type ---------------------------------------------------------- +Cypress.Commands.add('addContentType', (name) => { + let api_url, auth; + api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone'; + auth = ploneAuthObj; + + return cy + .request({ + method: 'POST', + url: `${api_url}/@controlpanels/dexterity-types/${name}`, + headers: { + Accept: 'application/json', + }, + auth: auth, + body: { + title: name, + }, + }) + .then(() => console.log(`${name} content-type added.`)); +}); + +// --- Remove DX behavior ---------------------------------------------------------- +Cypress.Commands.add('removeContentType', (name) => { + let api_url, auth; + api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone'; + auth = ploneAuthObj; + + return cy + .request({ + method: 'DELETE', + url: `${api_url}/@controlpanels/dexterity-types/${name}`, + headers: { + Accept: 'application/json', + }, + auth: auth, + body: {}, + }) + .then(() => console.log(`${name} content-type removed.`)); +}); + +// --- Add DX field ---------------------------------------------------------- +Cypress.Commands.add('addSlateJSONField', (type, name) => { + let api_url, auth; + api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone'; + auth = ploneAuthObj; + + return cy + .request({ + method: 'POST', + url: `${api_url}/@types/${type}`, + headers: { + Accept: 'application/json', + }, + auth: auth, + body: { + id: name, + title: name, + description: 'Slate JSON Field', + factory: 'SlateJSONField', + required: false, + }, + }) + .then(() => console.log(`${name} SlateJSONField field added to ${type}`)); +}); + +// --- Remove DX field ---------------------------------------------------------- +Cypress.Commands.add('removeSlateJSONField', (type, name) => { + let api_url, auth; + api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone'; + auth = ploneAuthObj; + + return cy + .request({ + method: 'DELETE', + url: `${api_url}/@types/${type}/${name}`, + headers: { + Accept: 'application/json', + }, + auth: auth, + body: {}, + }) + .then(() => + console.log(`${name} SlateJSONField field removed from ${type}`), + ); +}); + // --- CREATE USER -------------------------------------------------------- Cypress.Commands.add( 'createUser', @@ -196,8 +357,18 @@ Cypress.Commands.add( username = 'editor', fullname = 'editor', email = 'editor@local.dev', - password = 'secret', + password = 'password', roles = ['Member', 'Reader', 'Editor'], + groups = { + '@id': 'http://localhost:3000/@users', + items: [ + { + id: 'AuthenticatedUsers', + title: 'AuthenticatedUsers', + }, + ], + items_total: 1, + }, }) => { let api_url, auth, path; if (Cypress.env('API') === 'guillotina') { @@ -209,10 +380,7 @@ Cypress.Commands.add( path = 'users'; } else { api_url = PLONE_API_URL; - auth = { - user: 'admin', - pass: 'secret', - }; + auth = ploneAuthObj; path = '@users'; } @@ -231,6 +399,7 @@ Cypress.Commands.add( email: email, password: password, roles: roles, + groups: groups, }, }) .then(() => console.log(`User ${username} created`)); @@ -249,10 +418,7 @@ Cypress.Commands.add('removeUser', (username = 'editor') => { path = 'users'; } else { api_url = PLONE_API_URL; - auth = { - user: 'admin', - pass: 'secret', - }; + auth = ploneAuthObj; path = '@users'; } @@ -268,6 +434,56 @@ Cypress.Commands.add('removeUser', (username = 'editor') => { .then(() => console.log(`User ${username} removed`)); }); +// --- GROUP ----------------------------------------------------------------- + +Cypress.Commands.add( + 'createGroup', + ({ + groupname = 'teachers', + email = 'teachers@local.dev', + password = ploneAuth[1], + roles = ['Member', 'Reader'], + users = { + '@id': 'http://localhost:3000/@groups', + items: [], + items_total: 0, + }, + }) => { + let api_url, auth, path; + if (Cypress.env('API') === 'guillotina') { + api_url = GUILLOTINA_API_URL; + auth = { + user: 'root', + pass: 'root', + }; + path = 'groups'; + } else { + api_url = PLONE_API_URL; + auth = ploneAuthObj; + path = '@groups'; + } + + return cy + .request({ + method: 'POST', + url: `${api_url}/${path}`, + headers: { + Accept: 'application/json', + }, + auth: auth, + body: { + '@type': 'Group', + groupname: groupname, + email: email, + password: password, + roles: roles, + users: users, + }, + }) + .then(() => console.log(`Group ${groupname} created`)); + }, +); + // --- SET WORKFLOW ---------------------------------------------------------- Cypress.Commands.add( 'setWorkflow', @@ -284,10 +500,7 @@ Cypress.Commands.add( }) => { let api_url, auth; api_url = PLONE_API_URL; - auth = { - user: 'admin', - pass: 'secret', - }; + auth = ploneAuthObj; return cy.request({ method: 'POST', url: `${api_url}/${path}/@workflow/${review_state}`, @@ -350,10 +563,7 @@ Cypress.Commands.add('waitForResourceToLoad', (fileName, type) => { Cypress.Commands.add('setRegistry', (record, value) => { let api_url, auth; api_url = PLONE_API_URL; - auth = { - user: 'admin', - pass: 'secret', - }; + auth = ploneAuthObj; return cy.request({ method: 'PATCH', @@ -370,7 +580,12 @@ Cypress.Commands.add('setRegistry', (record, value) => { // Low level command reused by `setSelection` and low level command `setCursor` Cypress.Commands.add('selection', { prevSubject: true }, (subject, fn) => { - cy.wrap(subject).trigger('mousedown').then(fn).trigger('mouseup'); + cy.wrap(subject) + .trigger('mousedown') + .wait(1000) //multiple waits between selecting the text to ensure toolbar is visible. + .then(fn) + .wait(1000) + .trigger('mouseup'); cy.document().trigger('selectionchange'); return cy.wrap(subject); @@ -437,6 +652,126 @@ Cypress.Commands.add( }, ); +Cypress.Commands.add( + 'pasteClipboard', + { prevSubject: true }, + (query, htmlContent) => { + return cy + .wrap(query) + .type(' {backspace}') + .trigger('paste', createHtmlPasteEvent(htmlContent)); + }, +); + +Cypress.Commands.add('toolbarSave', () => { + // Save + cy.get('#toolbar-save', { timeout: 10000 }).click(); + cy.waitForResourceToLoad('@navigation'); + cy.waitForResourceToLoad('@breadcrumbs'); + cy.waitForResourceToLoad('@actions'); + cy.waitForResourceToLoad('@types'); +}); + +Cypress.Commands.add('clearSlate', (selector) => { + return cy + .get(selector) + .focus() + .click() + .wait(1000) + .type('{selectAll}') + .wait(1000) + .type('{backspace}'); +}); + +Cypress.Commands.add('getSlate', (createNewSlate = false) => { + let slate; + if (createNewSlate) { + cy.get('.block.inner').last().type('{moveToEnd}{enter}'); + } + cy.getIfExists( + SLATE_SELECTOR, + () => { + slate = cy.get(SLATE_SELECTOR).last(); + }, + () => { + slate = cy.get(SLATE_SELECTOR, { timeout: 10000 }).last(); + }, + ); + return slate; +}); + +Cypress.Commands.add('getSlateTitle', () => { + return cy.get(SLATE_TITLE_SELECTOR, { + timeout: 10000, + }); +}); + +Cypress.Commands.add('clearSlateTitle', () => { + return cy.clearSlate(SLATE_TITLE_SELECTOR); +}); + +// Slate commands +Cypress.Commands.add('typeInSlate', { prevSubject: true }, (subject, text) => { + return ( + cy + .wrap(subject) + .then((subject) => { + subject[0].dispatchEvent( + new InputEvent('beforeinput', { + inputType: 'insertText', + data: text, + }), + ); + return subject; + }) + // TODO: do this only for Electron-based browser which does not understand instantaneously + // that the user inserted some text in the block + .wait(1000) + ); +}); + +Cypress.Commands.add('lineBreakInSlate', { prevSubject: true }, (subject) => { + return ( + cy + .wrap(subject) + .then((subject) => { + subject[0].dispatchEvent( + new InputEvent('beforeinput', { inputType: 'insertLineBreak' }), + ); + return subject; + }) + // TODO: do this only for Electron-based browser which does not understand instantaneously + // that the block was split + .wait(1000) + ); +}); + +Cypress.Commands.add('setSlateSelection', (subject, query, endQuery) => { + cy.get('.slate-editor.selected [contenteditable=true]') + .focus() + // .click() + .setSelection(subject, query, endQuery) + .wait(1000); // this wait is needed for the selection change to be detected after +}); + +Cypress.Commands.add('getSlateEditorAndType', (type) => { + cy.getSlate().focus().click().type(type); +}); + +Cypress.Commands.add('setSlateCursor', (subject, query, endQuery) => { + cy.get('.slate-editor.selected [contenteditable=true]') + .focus() + .click() + .setCursor(subject, query, endQuery) + .wait(1000); // this wait is needed for the selection change to be detected after +}); + +Cypress.Commands.add('clickSlateButton', (button) => { + cy.get(`.slate-inline-toolbar .button-wrapper a[title="${button}"]`, { + timeout: 1000, + }).click({ force: true }); // force click is needed to ensure the button in visible in view. +}); + // Helper functions function getTextNode(el, match) { const walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false); @@ -459,6 +794,24 @@ function setBaseAndExtent(...args) { document.getSelection().setBaseAndExtent(...args); } +function createHtmlPasteEvent(htmlContent) { + return Object.assign( + new Event('paste', { bubbles: true, cancelable: true }), + { + clipboardData: { + getData: () => htmlContent, + types: ['text/html'], + }, + }, + ); +} + +Cypress.Commands.add('addNewBlock', (blockName, createNewSlate = false) => { + let block; + block = cy.getSlate(createNewSlate).type(`/${blockName}{enter}`); + return block; +}); + Cypress.Commands.add('navigate', (route = '') => { return cy.window().its('appHistory').invoke('push', route); }); diff --git a/packages/volto-testing/cypress/support/constants.js b/packages/volto-testing/cypress/support/constants.js new file mode 100644 index 0000000000..4cdc2876dc --- /dev/null +++ b/packages/volto-testing/cypress/support/constants.js @@ -0,0 +1 @@ +export const ploneAuth = ['admin', 'secret']; diff --git a/packages/volto-testing/package.json b/packages/volto-testing/package.json index cb7799ba4f..1effd4f616 100644 --- a/packages/volto-testing/package.json +++ b/packages/volto-testing/package.json @@ -59,6 +59,7 @@ "@testing-library/cypress": "8.0.7", "@testing-library/jest-dom": "5.16.4", "@testing-library/react": "12.1.5", + "axe-core": "4.6.3", "cypress": "11.1.0", "cypress-axe": "1.0.0", "cypress-file-upload": "5.0.8" diff --git a/packages/volto-testing/yarn.lock b/packages/volto-testing/yarn.lock index 35b73bb426..ec67ffda95 100644 --- a/packages/volto-testing/yarn.lock +++ b/packages/volto-testing/yarn.lock @@ -263,6 +263,7 @@ __metadata: "@testing-library/cypress": 8.0.7 "@testing-library/jest-dom": 5.16.4 "@testing-library/react": 12.1.5 + axe-core: 4.6.3 cypress: 11.1.0 cypress-axe: 1.0.0 cypress-file-upload: 5.0.8 @@ -673,6 +674,13 @@ __metadata: languageName: node linkType: hard +"axe-core@npm:4.6.3": + version: 4.6.3 + resolution: "axe-core@npm:4.6.3" + checksum: d0c46be92b9707c48b88a53cd5f471b155a2bfc8bf6beffb514ecd14e30b4863e340b5fc4f496d82a3c562048088c1f3ff5b93b9b3b026cb9c3bfacfd535da10 + languageName: node + linkType: hard + "balanced-match@npm:^1.0.0": version: 1.0.2 resolution: "balanced-match@npm:1.0.2" From 2052645a52662ce0a9cac2f71c7ff3af8978f1d2 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Wed, 8 Feb 2023 19:53:46 +0100 Subject: [PATCH 002/142] Changelog --- packages/volto-testing/news/4382.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/volto-testing/news/4382.feature diff --git a/packages/volto-testing/news/4382.feature b/packages/volto-testing/news/4382.feature new file mode 100644 index 0000000000..9e7fb5bdba --- /dev/null +++ b/packages/volto-testing/news/4382.feature @@ -0,0 +1 @@ +Update Cypress support commands, add missing peer dependency `axe-core` @sneridagh From 1154b49f5baa8dd61f5d469da506f86fc1a7b05f Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Wed, 8 Feb 2023 19:54:29 +0100 Subject: [PATCH 003/142] Release @plone/volto-testing 3.1.0 --- packages/volto-testing/CHANGELOG.md | 7 +++++++ packages/volto-testing/news/4382.feature | 1 - packages/volto-testing/package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 packages/volto-testing/news/4382.feature diff --git a/packages/volto-testing/CHANGELOG.md b/packages/volto-testing/CHANGELOG.md index ce81401d93..ff65a00722 100644 --- a/packages/volto-testing/CHANGELOG.md +++ b/packages/volto-testing/CHANGELOG.md @@ -8,6 +8,13 @@ +## 3.1.0 (2023-02-08) + +### Feature + +- Update Cypress support commands, add missing peer dependency `axe-core` @sneridagh [#4382](https://github.com/plone/volto/issues/4382) + + ## 3.0.0 (2022-12-15) ### Breaking diff --git a/packages/volto-testing/news/4382.feature b/packages/volto-testing/news/4382.feature deleted file mode 100644 index 9e7fb5bdba..0000000000 --- a/packages/volto-testing/news/4382.feature +++ /dev/null @@ -1 +0,0 @@ -Update Cypress support commands, add missing peer dependency `axe-core` @sneridagh diff --git a/packages/volto-testing/package.json b/packages/volto-testing/package.json index 1effd4f616..abba91f379 100644 --- a/packages/volto-testing/package.json +++ b/packages/volto-testing/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "3.0.0", + "version": "3.1.0", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" From c3f7b37ab3bdd5a635f5c8128ff6e71843e53412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Thu, 9 Feb 2023 11:42:31 +0100 Subject: [PATCH 004/142] Add SCSS support in core (#4383) --- news/4383.feature | 1 + package.json | 8 ++ razzle.config.js | 1 + yarn.lock | 337 +++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 311 insertions(+), 36 deletions(-) create mode 100644 news/4383.feature diff --git a/news/4383.feature b/news/4383.feature new file mode 100644 index 0000000000..b0985dbd96 --- /dev/null +++ b/news/4383.feature @@ -0,0 +1 @@ +Add scss support in core @sneridagh diff --git a/package.json b/package.json index a5584aa372..f1c9190f5f 100644 --- a/package.json +++ b/package.json @@ -137,6 +137,12 @@ "stylelint-prettier" ], "overrides": [ + { + "files": [ + "**/*.scss" + ], + "customSyntax": "postcss-scss" + }, { "files": [ "**/*.less" @@ -316,6 +322,7 @@ "postcss-load-config": "3.1.4", "postcss-loader": "4.3.0", "postcss-overrides": "3.1.4", + "postcss-scss": "4.0.6", "prepend-http": "2", "prettier": "2.0.5", "pretty-bytes": "5.3.0", @@ -326,6 +333,7 @@ "razzle": "4.2.17", "razzle-dev-utils": "4.2.17", "razzle-plugin-bundle-analyzer": "4.2.17", + "razzle-plugin-scss": "4.2.18", "rc-time-picker": "3.7.3", "react": "17.0.2", "react-anchor-link-smooth-scroll": "1.0.12", diff --git a/razzle.config.js b/razzle.config.js index a17a2541fe..992f8c17dc 100644 --- a/razzle.config.js +++ b/razzle.config.js @@ -330,6 +330,7 @@ const defaultPlugins = [ { object: require('./webpack-plugins/webpack-svg-plugin') }, { object: require('./webpack-plugins/webpack-bundle-analyze-plugin') }, { object: require('./jest-extender-plugin') }, + 'scss', ]; const plugins = addonExtenders.reduce( diff --git a/yarn.lock b/yarn.lock index 0138d12329..0ba2e37af2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2863,6 +2863,7 @@ __metadata: postcss-load-config: 3.1.4 postcss-loader: 4.3.0 postcss-overrides: 3.1.4 + postcss-scss: 4.0.6 prepend-http: 2 prettier: 2.0.5 pretty-bytes: 5.3.0 @@ -2873,6 +2874,7 @@ __metadata: razzle: 4.2.17 razzle-dev-utils: 4.2.17 razzle-plugin-bundle-analyzer: 4.2.17 + razzle-plugin-scss: 4.2.18 rc-time-picker: 3.7.3 react: 17.0.2 react-anchor-link-smooth-scroll: 1.0.12 @@ -5660,6 +5662,16 @@ __metadata: languageName: node linkType: hard +"adjust-sourcemap-loader@npm:3.0.0": + version: 3.0.0 + resolution: "adjust-sourcemap-loader@npm:3.0.0" + dependencies: + loader-utils: ^2.0.0 + regex-parser: ^2.2.11 + checksum: 5ceabea85219fcafed06f7d1aafb37dc761c6435e4ded2a8c6b01c69844250aa94ef65a4d07210dc7566c2d8b4c9ba8897518db596a550461eed26fbeb76b96f + languageName: node + linkType: hard + "agent-base@npm:6, agent-base@npm:^6.0.0, agent-base@npm:^6.0.2": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -6033,6 +6045,13 @@ __metadata: languageName: node linkType: hard +"arity-n@npm:^1.0.4": + version: 1.0.4 + resolution: "arity-n@npm:1.0.4" + checksum: 3d76e16907f7b8a9452690c1efc301d0fbecea457365797eccfbade9b8d1653175b2c38343201bf26fdcbf0bcbb31eab6d912e7c008c6d19042301dc0be80a73 + languageName: node + linkType: hard + "arr-diff@npm:^4.0.0": version: 4.0.0 resolution: "arr-diff@npm:4.0.0" @@ -7623,6 +7642,13 @@ __metadata: languageName: node linkType: hard +"camelcase@npm:5.3.1, camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": + version: 5.3.1 + resolution: "camelcase@npm:5.3.1" + checksum: e6effce26b9404e3c0f301498184f243811c30dfe6d0b9051863bd8e4034d09c8c2923794f280d6827e5aa055f6c434115ff97864a16a963366fb35fd673024b + languageName: node + linkType: hard + "camelcase@npm:^2.0.0": version: 2.1.1 resolution: "camelcase@npm:2.1.1" @@ -7630,13 +7656,6 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": - version: 5.3.1 - resolution: "camelcase@npm:5.3.1" - checksum: e6effce26b9404e3c0f301498184f243811c30dfe6d0b9051863bd8e4034d09c8c2923794f280d6827e5aa055f6c434115ff97864a16a963366fb35fd673024b - languageName: node - linkType: hard - "camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" @@ -7801,6 +7820,25 @@ __metadata: languageName: node linkType: hard +"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.4.1, chokidar@npm:^3.4.2": + version: 3.5.3 + resolution: "chokidar@npm:3.5.3" + dependencies: + anymatch: ~3.1.2 + braces: ~3.0.2 + fsevents: ~2.3.2 + glob-parent: ~5.1.2 + is-binary-path: ~2.1.0 + is-glob: ~4.0.1 + normalize-path: ~3.0.0 + readdirp: ~3.6.0 + dependenciesMeta: + fsevents: + optional: true + checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c + languageName: node + linkType: hard + "chokidar@npm:^2.1.8": version: 2.1.8 resolution: "chokidar@npm:2.1.8" @@ -7824,25 +7862,6 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:^3.4.1, chokidar@npm:^3.4.2": - version: 3.5.3 - resolution: "chokidar@npm:3.5.3" - dependencies: - anymatch: ~3.1.2 - braces: ~3.0.2 - fsevents: ~2.3.2 - glob-parent: ~5.1.2 - is-binary-path: ~2.1.0 - is-glob: ~4.0.1 - normalize-path: ~3.0.0 - readdirp: ~3.6.0 - dependenciesMeta: - fsevents: - optional: true - checksum: b49fcde40176ba007ff361b198a2d35df60d9bb2a5aab228279eb810feae9294a6b4649ab15981304447afe1e6ffbf4788ad5db77235dc770ab777c6e771980c - languageName: node - linkType: hard - "chownr@npm:^1.1.1, chownr@npm:^1.1.2": version: 1.1.4 resolution: "chownr@npm:1.1.4" @@ -8322,6 +8341,15 @@ __metadata: languageName: node linkType: hard +"compose-function@npm:3.0.3": + version: 3.0.3 + resolution: "compose-function@npm:3.0.3" + dependencies: + arity-n: ^1.0.4 + checksum: 9f17d431e3ee4797c844f2870e13494079882ac3dbc54c143b7d99967b371908e0ce7ceb71c6aed61e2ecddbcd7bb437d91428a3d0e6569aee17a87fcbc7918f + languageName: node + linkType: hard + "compressible@npm:~2.0.16": version: 2.0.18 resolution: "compressible@npm:2.0.18" @@ -8484,6 +8512,22 @@ __metadata: languageName: node linkType: hard +"convert-source-map@npm:1.7.0": + version: 1.7.0 + resolution: "convert-source-map@npm:1.7.0" + dependencies: + safe-buffer: ~5.1.1 + checksum: bcd2e3ea7d37f96b85a6e362c8a89402ccc73757256e3ee53aa2c22fe915adb854c66b1f81111be815a3a6a6ce3c58e8001858e883c9d5b4fe08a853fa865967 + languageName: node + linkType: hard + +"convert-source-map@npm:^0.3.3": + version: 0.3.5 + resolution: "convert-source-map@npm:0.3.5" + checksum: 33b209aa8f33bcaa9a22f2dbf6bfb71f4a429d8e948068d61b6087304e3194c30016d1e02e842184e653b74442c7e2dd2e7db97532b67f556aded3d8b4377a2c + languageName: node + linkType: hard + "convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.5.0, convert-source-map@npm:^1.6.0, convert-source-map@npm:^1.7.0": version: 1.9.0 resolution: "convert-source-map@npm:1.9.0" @@ -8982,6 +9026,18 @@ __metadata: languageName: node linkType: hard +"css@npm:^2.0.0": + version: 2.2.4 + resolution: "css@npm:2.2.4" + dependencies: + inherits: ^2.0.3 + source-map: ^0.6.1 + source-map-resolve: ^0.5.2 + urix: ^0.1.0 + checksum: a35d483c5ccc04bcde3b1e7393d58ad3eee1dd6956df0f152de38e46a17c0ee193c30eec6b1e59831ad0e74599385732000e95987fcc9cb2b16c6d951bae49e1 + languageName: node + linkType: hard + "css@npm:^3.0.0": version: 3.0.0 resolution: "css@npm:3.0.0" @@ -9215,6 +9271,16 @@ __metadata: languageName: node linkType: hard +"d@npm:1, d@npm:^1.0.1": + version: 1.0.1 + resolution: "d@npm:1.0.1" + dependencies: + es5-ext: ^0.10.50 + type: ^1.0.1 + checksum: 49ca0639c7b822db670de93d4fbce44b4aa072cd848c76292c9978a8cd0fff1028763020ff4b0f147bd77bfe29b4c7f82e0f71ade76b2a06100543cdfd948d19 + languageName: node + linkType: hard + "damerau-levenshtein@npm:^1.0.4": version: 1.0.8 resolution: "damerau-levenshtein@npm:1.0.8" @@ -10505,6 +10571,17 @@ __metadata: languageName: node linkType: hard +"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50": + version: 0.10.62 + resolution: "es5-ext@npm:0.10.62" + dependencies: + es6-iterator: ^2.0.3 + es6-symbol: ^3.1.3 + next-tick: ^1.1.0 + checksum: 25f42f6068cfc6e393cf670bc5bba249132c5f5ec2dd0ed6e200e6274aca2fed8e9aec8a31c76031744c78ca283c57f0b41c7e737804c6328c7b8d3fbcba7983 + languageName: node + linkType: hard + "es5-shim@npm:^4.5.13": version: 4.6.7 resolution: "es5-shim@npm:4.6.7" @@ -10512,6 +10589,17 @@ __metadata: languageName: node linkType: hard +"es6-iterator@npm:2.0.3, es6-iterator@npm:^2.0.3": + version: 2.0.3 + resolution: "es6-iterator@npm:2.0.3" + dependencies: + d: 1 + es5-ext: ^0.10.35 + es6-symbol: ^3.1.1 + checksum: 6e48b1c2d962c21dee604b3d9f0bc3889f11ed5a8b33689155a2065d20e3107e2a69cc63a71bd125aeee3a589182f8bbcb5c8a05b6a8f38fa4205671b6d09697 + languageName: node + linkType: hard + "es6-shim@npm:^0.35.5": version: 0.35.7 resolution: "es6-shim@npm:0.35.7" @@ -10519,6 +10607,16 @@ __metadata: languageName: node linkType: hard +"es6-symbol@npm:^3.1.1, es6-symbol@npm:^3.1.3": + version: 3.1.3 + resolution: "es6-symbol@npm:3.1.3" + dependencies: + d: ^1.0.1 + ext: ^1.1.2 + checksum: cd49722c2a70f011eb02143ef1c8c70658d2660dead6641e160b94619f408b9cf66425515787ffe338affdf0285ad54f4eae30ea5bd510e33f8659ec53bcaa70 + languageName: node + linkType: hard + "escalade@npm:^3.0.2, escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -11257,6 +11355,15 @@ __metadata: languageName: node linkType: hard +"ext@npm:^1.1.2": + version: 1.7.0 + resolution: "ext@npm:1.7.0" + dependencies: + type: ^2.7.2 + checksum: ef481f9ef45434d8c867cfd09d0393b60945b7c8a1798bedc4514cb35aac342ccb8d8ecb66a513e6a2b4ec1e294a338e3124c49b29736f8e7c735721af352c31 + languageName: node + linkType: hard + "extend-shallow@npm:^2.0.1": version: 2.0.1 resolution: "extend-shallow@npm:2.0.1" @@ -13533,6 +13640,13 @@ __metadata: languageName: node linkType: hard +"immutable@npm:^4.0.0": + version: 4.2.4 + resolution: "immutable@npm:4.2.4" + checksum: 3be84eded37b05e65cad57bfba630bc1bf170c498b7472144bc02d2650cc9baef79daf03574a9c2e41d195ebb55a1c12c9b312f41ee324b653927b24ad8bcaa7 + languageName: node + linkType: hard + "immutable@npm:~3.7.4": version: 3.7.6 resolution: "immutable@npm:3.7.6" @@ -17173,6 +17287,13 @@ __metadata: languageName: node linkType: hard +"next-tick@npm:^1.1.0": + version: 1.1.0 + resolution: "next-tick@npm:1.1.0" + checksum: 83b5cf36027a53ee6d8b7f9c0782f2ba87f4858d977342bfc3c20c21629290a2111f8374d13a81221179603ffc4364f38374b5655d17b6a8f8a8c77bdea4fe8b + languageName: node + linkType: hard + "nice-try@npm:^1.0.4": version: 1.0.5 resolution: "nice-try@npm:1.0.5" @@ -19038,6 +19159,24 @@ __metadata: languageName: node linkType: hard +"postcss-scss@npm:4.0.6": + version: 4.0.6 + resolution: "postcss-scss@npm:4.0.6" + peerDependencies: + postcss: ^8.4.19 + checksum: 133a1cba31e2e167f4e841e66ec6a798eaf44c7911f9182ade0b5b1e71a8198814aa390b8c9d5db6b01358115232e5b15b1a4f8c5198acfccfb1f3fdbd328cdf + languageName: node + linkType: hard + +"postcss-scss@npm:^3.0.4": + version: 3.0.5 + resolution: "postcss-scss@npm:3.0.5" + dependencies: + postcss: ^8.2.7 + checksum: e927317fa095a6a2375ba923d70c9f0f31dc6fd61148885fc7c3d85cc55450601288be3d0a890cf34473807d27a15693135a8c076581e8ae29fffa175a1b37a3 + languageName: node + linkType: hard + "postcss-selector-parser@npm:^3.0.0": version: 3.1.2 resolution: "postcss-selector-parser@npm:3.1.2" @@ -19105,6 +19244,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:7.0.36": + version: 7.0.36 + resolution: "postcss@npm:7.0.36" + dependencies: + chalk: ^2.4.2 + source-map: ^0.6.1 + supports-color: ^6.1.0 + checksum: 4cfc0989b9ad5d0e8971af80d87f9c5beac5c84cb89ff22ad69852edf73c0a2fa348e7e0a135b5897bf893edad0fe86c428769050431ad9b532f072ff530828d + languageName: node + linkType: hard + "postcss@npm:8.4.13": version: 8.4.13 resolution: "postcss@npm:8.4.13" @@ -19126,7 +19276,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.2.15, postcss@npm:^8.2.4, postcss@npm:^8.3.11": +"postcss@npm:^8.2.15, postcss@npm:^8.2.4, postcss@npm:^8.2.7, postcss@npm:^8.3.11": version: 8.4.21 resolution: "postcss@npm:8.4.21" dependencies: @@ -19804,6 +19954,27 @@ __metadata: languageName: node linkType: hard +"razzle-plugin-scss@npm:4.2.18": + version: 4.2.18 + resolution: "razzle-plugin-scss@npm:4.2.18" + dependencies: + autoprefixer: ^10.2.3 + css-loader: ^5.0.0 + deepmerge: ^4.2.2 + postcss-load-config: ^3.0.0 + postcss-loader: ^4.2.0 + postcss-scss: ^3.0.4 + resolve-url-loader: ^3.1.2 + sass: ^1.29.0 + sass-loader: ^10.0.3 + peerDependencies: + mini-css-extract-plugin: ">=0.9.0 <1.0.0" + razzle: 4.2.18 + razzle-dev-utils: 4.2.18 + checksum: 87a70a6327183eb077d5beb8ea5a04b679e104fc554c351ee497090ce1fb99f9c2b800562abb1bfb9b31661599d189c293539f5bac3cd45cd4a9aea2ba8e3b91 + languageName: node + linkType: hard + "razzle-start-server-webpack-plugin@npm:4.2.17": version: 4.2.17 resolution: "razzle-start-server-webpack-plugin@npm:4.2.17" @@ -21125,6 +21296,13 @@ __metadata: languageName: node linkType: hard +"regex-parser@npm:^2.2.11": + version: 2.2.11 + resolution: "regex-parser@npm:2.2.11" + checksum: 78200331ec0cc372302d287a4946c38681eb5fe435453fca572cb53cac0ba579e5eb3b9e25eac24c0c80a555fb3ea7a637814a35da1e9bc88e8819110ae5de24 + languageName: node + linkType: hard + "regexp.prototype.flags@npm:^1.2.0, regexp.prototype.flags@npm:^1.4.3": version: 1.4.3 resolution: "regexp.prototype.flags@npm:1.4.3" @@ -21484,6 +21662,24 @@ __metadata: languageName: node linkType: hard +"resolve-url-loader@npm:^3.1.2": + version: 3.1.5 + resolution: "resolve-url-loader@npm:3.1.5" + dependencies: + adjust-sourcemap-loader: 3.0.0 + camelcase: 5.3.1 + compose-function: 3.0.3 + convert-source-map: 1.7.0 + es6-iterator: 2.0.3 + loader-utils: ^1.2.3 + postcss: 7.0.36 + rework: 1.0.1 + rework-visit: 1.0.0 + source-map: 0.6.1 + checksum: eb52911eff20723f07409cc12138d254fa0dd4a4f3b1ba11ee1b29912afb03f1272aaddb523658be1e3a946e0d1bf6f603d0e107753ab83d48ad2116cf04b7f6 + languageName: node + linkType: hard + "resolve-url@npm:^0.2.1": version: 0.2.1 resolution: "resolve-url@npm:0.2.1" @@ -21574,6 +21770,23 @@ __metadata: languageName: node linkType: hard +"rework-visit@npm:1.0.0": + version: 1.0.0 + resolution: "rework-visit@npm:1.0.0" + checksum: 969ca1f4e5bf4a1755c464a9b498da51eb3f28a798cf73da2cf0a3a3ab7b21a2f05c9d3bfa5fb81c8aaf5487dd31679efa67b8d0f418277ef5deb2a230b17c81 + languageName: node + linkType: hard + +"rework@npm:1.0.1": + version: 1.0.1 + resolution: "rework@npm:1.0.1" + dependencies: + convert-source-map: ^0.3.3 + css: ^2.0.0 + checksum: 13e5054d81ac84eee488fd4bacd20d08f35683bd8e296b4358e7f0a41b2d30a959313b7794f388f336705ad18d36af6ee7080e1b6c1313ecf33bc51d1bd95971 + languageName: node + linkType: hard + "rfdc@npm:^1.3.0": version: 1.3.0 resolution: "rfdc@npm:1.3.0" @@ -21773,6 +21986,44 @@ __metadata: languageName: node linkType: hard +"sass-loader@npm:^10.0.3": + version: 10.4.1 + resolution: "sass-loader@npm:10.4.1" + dependencies: + klona: ^2.0.4 + loader-utils: ^2.0.0 + neo-async: ^2.6.2 + schema-utils: ^3.0.0 + semver: ^7.3.2 + peerDependencies: + fibers: ">= 3.1.0" + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + sass: ^1.3.0 + webpack: ^4.36.0 || ^5.0.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + checksum: df9a65a62247e95305299ccbdf212cffdcdb69490928aecdf4f3dcf539b5302ed7cbffa663f83c5fc3ce0864decf84257a9ce484f6df4cb4426feeb88445dcd0 + languageName: node + linkType: hard + +"sass@npm:^1.29.0": + version: 1.58.0 + resolution: "sass@npm:1.58.0" + dependencies: + chokidar: ">=3.0.0 <4.0.0" + immutable: ^4.0.0 + source-map-js: ">=0.6.2 <2.0.0" + bin: + sass: sass.js + checksum: a7219634881d2de6441fb619787fb1a02e3fa0333fb715be26aa335ba49d6bdb4f1105d9df70a80a67200893022b08346745783dc49046095d94fc6e044492d6 + languageName: node + linkType: hard + "sax@npm:1.2.x, sax@npm:~1.2.4": version: 1.2.4 resolution: "sax@npm:1.2.4" @@ -22501,14 +22752,14 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.0.2": +"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.2": version: 1.0.2 resolution: "source-map-js@npm:1.0.2" checksum: c049a7fc4deb9a7e9b481ae3d424cc793cb4845daa690bc5a05d428bf41bf231ced49b4cf0c9e77f9d42fdb3d20d6187619fc586605f5eabe995a316da8d377c languageName: node linkType: hard -"source-map-resolve@npm:^0.5.0": +"source-map-resolve@npm:^0.5.0, source-map-resolve@npm:^0.5.2": version: 0.5.3 resolution: "source-map-resolve@npm:0.5.3" dependencies: @@ -22548,6 +22799,13 @@ __metadata: languageName: node linkType: hard +"source-map@npm:0.6.1, source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.0, source-map@npm:~0.6.1": + version: 0.6.1 + resolution: "source-map@npm:0.6.1" + checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 + languageName: node + linkType: hard + "source-map@npm:^0.5.0, source-map@npm:^0.5.6, source-map@npm:^0.5.7": version: 0.5.7 resolution: "source-map@npm:0.5.7" @@ -22555,13 +22813,6 @@ __metadata: languageName: node linkType: hard -"source-map@npm:^0.6.0, source-map@npm:^0.6.1, source-map@npm:~0.6.0, source-map@npm:~0.6.1": - version: 0.6.1 - resolution: "source-map@npm:0.6.1" - checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2 - languageName: node - linkType: hard - "source-map@npm:^0.7.3": version: 0.7.4 resolution: "source-map@npm:0.7.4" @@ -24141,6 +24392,20 @@ __metadata: languageName: node linkType: hard +"type@npm:^1.0.1": + version: 1.2.0 + resolution: "type@npm:1.2.0" + checksum: dae8c64f82c648b985caf321e9dd6e8b7f4f2e2d4f846fc6fd2c8e9dc7769382d8a52369ddbaccd59aeeceb0df7f52fb339c465be5f2e543e81e810e413451ee + languageName: node + linkType: hard + +"type@npm:^2.7.2": + version: 2.7.2 + resolution: "type@npm:2.7.2" + checksum: 0f42379a8adb67fe529add238a3e3d16699d95b42d01adfe7b9a7c5da297f5c1ba93de39265ba30ffeb37dfd0afb3fb66ae09f58d6515da442219c086219f6f4 + languageName: node + linkType: hard + "typed-array-length@npm:^1.0.4": version: 1.0.4 resolution: "typed-array-length@npm:1.0.4" From 5132e7a77fafc4de6dd1b9e84e2fbfd6ea3bf4c8 Mon Sep 17 00:00:00 2001 From: Rob Gietema Date: Thu, 9 Feb 2023 14:52:46 +0100 Subject: [PATCH 005/142] Use open in new tab setting for link types (#4384) --- news/4384.feature | 1 + src/components/theme/Navigation/NavItem.jsx | 1 + .../Navigation/__snapshots__/Navigation.test.jsx.snap | 1 + src/components/theme/View/LinkView.jsx | 9 ++++++++- 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 news/4384.feature diff --git a/news/4384.feature b/news/4384.feature new file mode 100644 index 0000000000..8680e794ef --- /dev/null +++ b/news/4384.feature @@ -0,0 +1 @@ +Use open in new tab setting for link types. @robgietema \ No newline at end of file diff --git a/src/components/theme/Navigation/NavItem.jsx b/src/components/theme/Navigation/NavItem.jsx index 0468acf786..992759eb1f 100644 --- a/src/components/theme/Navigation/NavItem.jsx +++ b/src/components/theme/Navigation/NavItem.jsx @@ -28,6 +28,7 @@ const NavItem = ({ item, lang }) => { key={item.url} className="item" rel="noopener noreferrer" + target={settings.openExternalLinkInNewTab ? '_blank' : '_self'} > {item.title} diff --git a/src/components/theme/Navigation/__snapshots__/Navigation.test.jsx.snap b/src/components/theme/Navigation/__snapshots__/Navigation.test.jsx.snap index 950e63b053..17a73e9bae 100644 --- a/src/components/theme/Navigation/__snapshots__/Navigation.test.jsx.snap +++ b/src/components/theme/Navigation/__snapshots__/Navigation.test.jsx.snap @@ -49,6 +49,7 @@ exports[`Navigation renders a navigation component including external links 1`] className="item" href="https://store.plone.org" rel="noopener noreferrer" + target="_self" > Store diff --git a/src/components/theme/View/LinkView.jsx b/src/components/theme/View/LinkView.jsx index 420c992d39..e31334bae3 100644 --- a/src/components/theme/View/LinkView.jsx +++ b/src/components/theme/View/LinkView.jsx @@ -9,6 +9,7 @@ import { isInternalURL, flattenToAppURL } from '@plone/volto/helpers'; import { Container } from 'semantic-ui-react'; import { UniversalLink } from '@plone/volto/components'; import { FormattedMessage } from 'react-intl'; +import config from '@plone/volto/registry'; /** * View container class. @@ -58,6 +59,7 @@ class LinkView extends Component { */ render() { const { remoteUrl } = this.props.content; + const { openExternalLinkInNewTab } = config.settings; return (

{this.props.content.title}

@@ -72,7 +74,12 @@ class LinkView extends Component { id="The link address is:" defaultMessage="The link address is:" />{' '} - + {flattenToAppURL(remoteUrl)}

From fca412a61a50b34980e7600129bbbce2e86a0c95 Mon Sep 17 00:00:00 2001 From: Alin Voinea Date: Mon, 13 Feb 2023 11:35:13 +0200 Subject: [PATCH 006/142] Fix Cannot read properties of undefined (reading 'translations') (#4377) --- news/4377.bugfix | 1 + src/components/manage/Toolbar/Toolbar.jsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 news/4377.bugfix diff --git a/news/4377.bugfix b/news/4377.bugfix new file mode 100644 index 0000000000..5a3d81d2eb --- /dev/null +++ b/news/4377.bugfix @@ -0,0 +1 @@ +Fix Cannot read properties of undefined (reading 'translations') @avoinea diff --git a/src/components/manage/Toolbar/Toolbar.jsx b/src/components/manage/Toolbar/Toolbar.jsx index b8793a5f1a..d9f46c89e3 100644 --- a/src/components/manage/Toolbar/Toolbar.jsx +++ b/src/components/manage/Toolbar/Toolbar.jsx @@ -510,7 +510,7 @@ class Toolbar extends Component { ((this.props.content.is_folderish && this.props.types.length > 0) || (config.settings.isMultilingual && - this.props.content['@components'].translations)) && ( + this.props.content['@components']?.translations)) && ( @@ -46,7 +46,7 @@ const ImageSizeWidget = (props) => { aria-label={intl.formatMessage(messages.medium)} onClick={() => onChange(id, 'm')} active={value === 'm'} - disabled={disabled} + disabled={disabled || isDisabled} >
M
@@ -58,7 +58,7 @@ const ImageSizeWidget = (props) => { aria-label={intl.formatMessage(messages.large)} onClick={() => onChange(id, 'l')} active={value === 'l' || value === undefined} - disabled={disabled} + disabled={disabled || isDisabled} >
L
diff --git a/src/components/manage/Widgets/PasswordWidget.jsx b/src/components/manage/Widgets/PasswordWidget.jsx index 99e554d109..233d33e883 100644 --- a/src/components/manage/Widgets/PasswordWidget.jsx +++ b/src/components/manage/Widgets/PasswordWidget.jsx @@ -31,6 +31,7 @@ const PasswordWidget = (props) => { minLength, maxLength, placeholder, + isDisabled, } = props; return ( @@ -39,7 +40,7 @@ const PasswordWidget = (props) => { id={`field-${id}`} name={id} type="password" - disabled={props.isDisabled} + disabled={isDisabled} value={value || ''} placeholder={placeholder} onChange={({ target }) => diff --git a/src/components/manage/Widgets/TextWidget.jsx b/src/components/manage/Widgets/TextWidget.jsx index 528c9085a4..e39f7a0051 100644 --- a/src/components/manage/Widgets/TextWidget.jsx +++ b/src/components/manage/Widgets/TextWidget.jsx @@ -97,6 +97,7 @@ class TextWidget extends Component { minLength, maxLength, placeholder, + isDisabled, } = this.props; return ( @@ -105,7 +106,7 @@ class TextWidget extends Component { id={`field-${id}`} name={id} value={value || ''} - disabled={this.props.isDisabled} + disabled={isDisabled} icon={icon || null} placeholder={placeholder} onChange={({ target }) => diff --git a/src/components/manage/Widgets/TextareaWidget.jsx b/src/components/manage/Widgets/TextareaWidget.jsx index b9596696dd..4116c28fcf 100644 --- a/src/components/manage/Widgets/TextareaWidget.jsx +++ b/src/components/manage/Widgets/TextareaWidget.jsx @@ -23,7 +23,7 @@ import { FormFieldWrapper } from '@plone/volto/components'; * ``` */ const TextareaWidget = (props) => { - const { id, maxLength, value, onChange, placeholder } = props; + const { id, maxLength, value, onChange, placeholder, isDisabled } = props; const [lengthError, setlengthError] = useState(''); const onhandleChange = (id, value) => { @@ -44,7 +44,7 @@ const TextareaWidget = (props) => { id={`field-${id}`} name={id} value={value || ''} - disabled={props.isDisabled} + disabled={isDisabled} placeholder={placeholder} onChange={({ target }) => onhandleChange(id, target.value === '' ? undefined : target.value) diff --git a/src/components/theme/Comments/__snapshots__/Comments.test.jsx.snap b/src/components/theme/Comments/__snapshots__/Comments.test.jsx.snap index 66bf3e344a..dc55e5f694 100644 --- a/src/components/theme/Comments/__snapshots__/Comments.test.jsx.snap +++ b/src/components/theme/Comments/__snapshots__/Comments.test.jsx.snap @@ -17,7 +17,6 @@ exports[`Comments renders a comments component 1`] = ` >
Date: Thu, 23 Feb 2023 11:55:37 +0200 Subject: [PATCH 017/142] On error pages, don't switch to default site language (#4425) --- news/4425.bugfix | 1 + src/server.jsx | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 news/4425.bugfix diff --git a/news/4425.bugfix b/news/4425.bugfix new file mode 100644 index 0000000000..59ce9dd624 --- /dev/null +++ b/news/4425.bugfix @@ -0,0 +1 @@ +On SSR-generated error pages, don't change the user's language to the default site language @tiberiuichim diff --git a/src/server.jsx b/src/server.jsx index 8895375b0e..df5290aa5d 100644 --- a/src/server.jsx +++ b/src/server.jsx @@ -224,18 +224,23 @@ server.get('/*', (req, res) => { loadOnServer({ store, location, routes, api }) .then(() => { - // The content info is in the store at this point thanks to the asynconnect - // features, then we can force the current language info into the store when - // coming from an SSR request - const contentLang = - store.getState().content.data?.language?.token || - config.settings.defaultLanguage; - const cookie_lang = req.universalCookies.get('I18N_LANGUAGE') || config.settings.defaultLanguage || req.headers['accept-language']; + // The content info is in the store at this point thanks to the asynconnect + // features, then we can force the current language info into the store when + // coming from an SSR request + + // TODO: there is a bug here with content that, for any reason, doesn't + // present the language token field, for some reason. In this case, we + // should follow the cookie rather then switching the language + const contentLang = store.getState().content.get?.error + ? cookie_lang + : store.getState().content.data?.language?.token || + config.settings.defaultLanguage; + if (cookie_lang !== contentLang) { const newLocale = toLangUnderscoreRegion( new locale.Locales(contentLang).best(supported).toString(), From 262d33291edc99984481fdf4292a2f411d4af6df Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 24 Feb 2023 07:29:39 -0800 Subject: [PATCH 018/142] Tidy up backend/index.md (#4431) --- docs/source/backend/index.md | 60 +++++++++++++++++------------------- news/4431.documentation | 1 + 2 files changed, 29 insertions(+), 32 deletions(-) create mode 100644 news/4431.documentation diff --git a/docs/source/backend/index.md b/docs/source/backend/index.md index 3f3eb9c9be..4b5c35a609 100644 --- a/docs/source/backend/index.md +++ b/docs/source/backend/index.md @@ -9,38 +9,33 @@ myst: # Integration with the backend -## Plone backend integration - -Integration with the Plone CMS is provided by the Plone API framework, namely -[`plone.restapi`](https://github.com/plone/plone.restapi) and its lower-level -[`plone.rest]`(https://github.com/plone/plone.rest). For details please check -the [`plone.restapi` documentation website](https://plonerestapi.readthedocs.io/en/latest/). - -Some of the more interesting integration features that you can look up in the -`plone.restapi` documentation include the following. - -- **Endpoints**: the equivalent of Plone "views", these are REST API endpoints - that you can call from the frontend. The response should be in JSON format. - You'll use these for any type of interaction with the backend. -- **Content expansions**: additional information that can be added to the main - response. For example, when fetching "content" information, you may want to - also include information about the author. You could write an expansion that - automatically inserts that information if the HTTP GET parameter `?expand=author` is present in - the request. It is also possible to create expansion elements that will - automatically insert their content in the response, without the need for the - request parameter. -- **Block transformers**: these are named subscribers that can be used to - automatically change the information that is sent to the frontend for some of - the blocks. They can also do the opposite, to process the information - coming from the frontend on create or update operations, and change the way - the block value is stored in the database. There are multiple use cases for - this type of feature. For example to automatically convert incoming links in - block values to resolveuid-based links, and to convert them back to absolute - URLs when retrieving the block value from the frontend. -- **Search and indexing integration**: by providing the right adapters, you can - extract searchable text from blocks. - -### Proxied backend routes +Integration with the Plone CMS is provided by the Plone API framework, namely [`plone.restapi`](https://github.com/plone/plone.restapi) and its lower-level [`plone.rest`](https://github.com/plone/plone.rest). +For details, check the {doc}`plone.restapi/docs/source/index` documentation. + +Some of the more interesting integration features that you can look up in the `plone.restapi` documentation include the following. + +Endpoints +: The equivalent of Plone "views", these are REST API endpoints that you can call from the frontend. + The response should be in JSON format. + You'll use these for any type of interaction with the backend. + +Content expansions +: Additional information that can be added to the main response. + For example, when fetching "content" information, you may want to also include information about the author. + You could write an expansion that automatically inserts that information if the HTTP GET parameter `?expand=author` is present in the request. + It is also possible to create expansion elements that will automatically insert their content in the response, without the need for the request parameter. + +Block transformers +: These are named subscribers that can be used to automatically change the information that is sent to the frontend for some of the blocks. + They can also do the opposite, to process the information coming from the frontend on create or update operations, and change the way the block value is stored in the database. + There are multiple use cases for this type of feature. + For example to automatically convert incoming links in block values to resolveuid-based links, and to convert them back to absolute URLs when retrieving the block value from the frontend. + +Search and indexing integration +: By providing the right adapters, you can extract searchable text from blocks. + + +## Proxied backend routes Access to images and files are a special use case in Volto. Usually in plain HTML, `src` and `href` attributes resource calls cannot be wrapped in a JavaScript backend call. @@ -54,4 +49,5 @@ Thus the Node Express server takes care of proxying and enhancing them at the sa ```{todo} This section contains pointers for backend integration with Plone. Contributions for the Guillotina backend are needed. +See https://github.com/plone/volto/issues/4430 ``` diff --git a/news/4431.documentation b/news/4431.documentation new file mode 100644 index 0000000000..b89db2a531 --- /dev/null +++ b/news/4431.documentation @@ -0,0 +1 @@ +Fix links, convert features to definition list, add link to issue for TODO. @stevepiercy From cd8b640a0c8588fda2fee4a291996c28dab4c126 Mon Sep 17 00:00:00 2001 From: Ion Lizarazu Date: Mon, 27 Feb 2023 10:49:53 +0100 Subject: [PATCH 019/142] Add options to override listing blocks "no results". Add a default noResultsComponents, and another for the imageGallery variation (#3602) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mikel Larreategi Co-authored-by: Tiberiu Ichim Co-authored-by: Steve Piercy Co-authored-by: Víctor Fernández de Alba Co-authored-by: Katja Süss --- docs/source/blocks/index.md | 1 + docs/source/blocks/listing-block.md | 65 +++++++++++++++++++ locales/ca/LC_MESSAGES/volto.po | 7 +- locales/de/LC_MESSAGES/volto.po | 7 +- locales/en/LC_MESSAGES/volto.po | 7 +- locales/es/LC_MESSAGES/volto.po | 7 +- locales/eu/LC_MESSAGES/volto.po | 7 +- locales/fr/LC_MESSAGES/volto.po | 7 +- locales/it/LC_MESSAGES/volto.po | 7 +- locales/ja/LC_MESSAGES/volto.po | 7 +- locales/nl/LC_MESSAGES/volto.po | 7 +- locales/pt/LC_MESSAGES/volto.po | 7 +- locales/pt_BR/LC_MESSAGES/volto.po | 7 +- locales/ro/LC_MESSAGES/volto.po | 7 +- locales/volto.pot | 7 +- locales/zh_CN/LC_MESSAGES/volto.po | 7 +- news/3602.feat | 1 + .../Listing/DefaultNoResultsComponent.jsx | 13 ++++ .../Listing/GalleryNoResultsComponent.jsx | 10 +++ .../manage/Blocks/Listing/ListingBody.jsx | 18 +++-- .../__snapshots__/ListingBody.test.jsx.snap | 1 - src/config/Blocks.jsx | 4 ++ 22 files changed, 186 insertions(+), 25 deletions(-) create mode 100644 docs/source/blocks/listing-block.md create mode 100644 news/3602.feat create mode 100644 src/components/manage/Blocks/Listing/DefaultNoResultsComponent.jsx create mode 100644 src/components/manage/Blocks/Listing/GalleryNoResultsComponent.jsx diff --git a/docs/source/blocks/index.md b/docs/source/blocks/index.md index be691f9b1c..2f4d427f1f 100644 --- a/docs/source/blocks/index.md +++ b/docs/source/blocks/index.md @@ -18,5 +18,6 @@ settings editcomponent block-style-wrapper extensions +listing-block ssr ``` diff --git a/docs/source/blocks/listing-block.md b/docs/source/blocks/listing-block.md new file mode 100644 index 0000000000..c0f6dbcc44 --- /dev/null +++ b/docs/source/blocks/listing-block.md @@ -0,0 +1,65 @@ +--- +myst: + html_meta: + "description": "The listing block provides an additional extension letting the developer modify the default 'No results found' message using the configuration of the block" + "property=og:description": "The listing block provides an additional extension letting the developer modify the default 'No results found' message using the configuration of the block" + "property=og:title": "Listing block extensions mechanism" + "keywords": "Volto, Plone, frontend, React, Upgrade, Guide, Block extensions, variations, schema enhancers, listing block" +--- + +(extensions-block-extensions-mechanism)= + +# Listing block extensions + +The listing block is a special block that can be configured to run a catalog query in the backend and show the results of that search. + +Apart from the {ref}`standard variation ` and {ref}`schema enchancing extensions `, the listing block provides a configurable way to handle the "No results" message. + +When the listing block configured search returns no results, Volto presents a default "No results found" message. +But sometimes you want to change such a message to offer more meaningful messages, or do some other fancy stuff in that case. +For instance, you may want to show a "There are no future events" or "There are no images in the gallery" message for a given listing block. + +To achieve that, you can configure a new `noResultsComponent` when configuring the listing block, and provide a custom component to render such a message. +To do that, you need to reconfigure that option in the configuration of your project: + +```jsx +import { FormattedMessage } from 'react-intl'; + +const MyNoResultsComponent = (props) => { + return ( + + ); +}; + +const applyConfig = (config) => { + config.blocks.listing['noResultsComponent'] = MyNoResultsComponent; + return config; +}; +``` + +In addition to that, each variation configured for the listing block can have a custom no results template. +This way you can provide specific no results messages per-variation. +This can be done, like in the earlier step, stating that in the configuration: + +```jsx +import { FormattedMessage } from 'react-intl'; + +const MyNoResultsComponent = (props) => { + return ( + + ); +}; + +const applyConfig = (config) => { + config.blocks.listing.variations.default[ + 'noResultsComponent' + ] = MyNoResultsComponent; + return config; +}; +``` diff --git a/locales/ca/LC_MESSAGES/volto.po b/locales/ca/LC_MESSAGES/volto.po index 8b158c0993..95ef023613 100644 --- a/locales/ca/LC_MESSAGES/volto.po +++ b/locales/ca/LC_MESSAGES/volto.po @@ -2184,6 +2184,11 @@ msgstr "No s'ha establert cap imatge al camp de contingut de la imatge principal msgid "No image set in image content field" msgstr "No s'ha establert cap imatge al camp de contingut de la imatge" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2218,7 +2223,7 @@ msgstr "Sense opcions" msgid "No results found" msgstr "Sense resultats" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/de/LC_MESSAGES/volto.po b/locales/de/LC_MESSAGES/volto.po index ef32238d8d..752593787b 100644 --- a/locales/de/LC_MESSAGES/volto.po +++ b/locales/de/LC_MESSAGES/volto.po @@ -2181,6 +2181,11 @@ msgstr "Im Feld 'Lead-Bild' wurde kein Bild gesetzt." msgid "No image set in image content field" msgstr "Im Feld 'Bild' wurde kein Bild gesetzt" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "Keine Bilder gefunden" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2215,7 +2220,7 @@ msgstr "Keine Option" msgid "No results found" msgstr "Keine Ergebnisse gefunden" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/en/LC_MESSAGES/volto.po b/locales/en/LC_MESSAGES/volto.po index 40163bf5b8..c016dd8240 100644 --- a/locales/en/LC_MESSAGES/volto.po +++ b/locales/en/LC_MESSAGES/volto.po @@ -2175,6 +2175,11 @@ msgstr "" msgid "No image set in image content field" msgstr "" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2209,7 +2214,7 @@ msgstr "" msgid "No results found" msgstr "" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/es/LC_MESSAGES/volto.po b/locales/es/LC_MESSAGES/volto.po index 9938caaf64..8e2c45b45b 100644 --- a/locales/es/LC_MESSAGES/volto.po +++ b/locales/es/LC_MESSAGES/volto.po @@ -2186,6 +2186,11 @@ msgstr "No hay imagen en el campo de imagen principal" msgid "No image set in image content field" msgstr "No hay imagen en el campo de imagen" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "No hay imágenes." + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2220,7 +2225,7 @@ msgstr "No hay opciones" msgid "No results found" msgstr "No hay resultados" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/eu/LC_MESSAGES/volto.po b/locales/eu/LC_MESSAGES/volto.po index ee5b33e669..181828dac3 100644 --- a/locales/eu/LC_MESSAGES/volto.po +++ b/locales/eu/LC_MESSAGES/volto.po @@ -2182,6 +2182,11 @@ msgstr "Ez dago irudirik dagokion eremuan" msgid "No image set in image content field" msgstr "Ez dago irudirik dagokion eremuan" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "Ez da irudirik aurkitu." + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2216,7 +2221,7 @@ msgstr "Ez du aukerarik" msgid "No results found" msgstr "Ez da emaitzarik aurkitu." -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/fr/LC_MESSAGES/volto.po b/locales/fr/LC_MESSAGES/volto.po index 1b21a0fc93..051c376b02 100644 --- a/locales/fr/LC_MESSAGES/volto.po +++ b/locales/fr/LC_MESSAGES/volto.po @@ -2192,6 +2192,11 @@ msgstr "Aucune image pour le champ de l'image de garde" msgid "No image set in image content field" msgstr "Aucune image pour le champ image" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2226,7 +2231,7 @@ msgstr "Aucune option" msgid "No results found" msgstr "Aucun résultat trouvé" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/it/LC_MESSAGES/volto.po b/locales/it/LC_MESSAGES/volto.po index 165811906d..af8d24a1c4 100644 --- a/locales/it/LC_MESSAGES/volto.po +++ b/locales/it/LC_MESSAGES/volto.po @@ -2175,6 +2175,11 @@ msgstr "Nessuna immagine impostata come Immagine di testata" msgid "No image set in image content field" msgstr "Nessuna immagine impostata" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2209,7 +2214,7 @@ msgstr "Nessuna opzione" msgid "No results found" msgstr "Nessun risultato" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/ja/LC_MESSAGES/volto.po b/locales/ja/LC_MESSAGES/volto.po index c4c82cd6d5..a8e118ed95 100644 --- a/locales/ja/LC_MESSAGES/volto.po +++ b/locales/ja/LC_MESSAGES/volto.po @@ -2183,6 +2183,11 @@ msgstr "コンテンツフィールドのリード画像がありません" msgid "No image set in image content field" msgstr "コンテンツフィールドの画像がありません" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2217,7 +2222,7 @@ msgstr "選択肢無し" msgid "No results found" msgstr "該当する結果が見つかりません。" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/nl/LC_MESSAGES/volto.po b/locales/nl/LC_MESSAGES/volto.po index eecd466100..d46cf17aa7 100644 --- a/locales/nl/LC_MESSAGES/volto.po +++ b/locales/nl/LC_MESSAGES/volto.po @@ -2182,6 +2182,11 @@ msgstr "Geen afbeelding ingesteld in het Voorbeeldafbeelding veld" msgid "No image set in image content field" msgstr "Geen afbeelding ingesteld in het afbeeldingsveld" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2216,7 +2221,7 @@ msgstr "Geen opties" msgid "No results found" msgstr "Geen resulaten gevonden" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/pt/LC_MESSAGES/volto.po b/locales/pt/LC_MESSAGES/volto.po index 58be14f9e1..8791945a97 100644 --- a/locales/pt/LC_MESSAGES/volto.po +++ b/locales/pt/LC_MESSAGES/volto.po @@ -2183,6 +2183,11 @@ msgstr "" msgid "No image set in image content field" msgstr "" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2217,7 +2222,7 @@ msgstr "" msgid "No results found" msgstr "" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/pt_BR/LC_MESSAGES/volto.po b/locales/pt_BR/LC_MESSAGES/volto.po index a90c869608..d011ec7915 100644 --- a/locales/pt_BR/LC_MESSAGES/volto.po +++ b/locales/pt_BR/LC_MESSAGES/volto.po @@ -2185,6 +2185,11 @@ msgstr "Nenhuma imagem definida no campo de imagem principal" msgid "No image set in image content field" msgstr "Nenhuma imagem definida no campo de imagem" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2219,7 +2224,7 @@ msgstr "Sem opções" msgid "No results found" msgstr "Nenhum resultado encontrado" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/ro/LC_MESSAGES/volto.po b/locales/ro/LC_MESSAGES/volto.po index 45cae9e853..948b7f93ce 100644 --- a/locales/ro/LC_MESSAGES/volto.po +++ b/locales/ro/LC_MESSAGES/volto.po @@ -2175,6 +2175,11 @@ msgstr "Nicio imagine setată în câmpul de conținut imagine de start" msgid "No image set in image content field" msgstr "Nicio imagine setată în câmpul imagine de continut" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2209,7 +2214,7 @@ msgstr "Nicio opțiune" msgid "No results found" msgstr "Nu s-au găsit rezultate" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/volto.pot b/locales/volto.pot index ad52c901f7..913df8e339 100644 --- a/locales/volto.pot +++ b/locales/volto.pot @@ -2177,6 +2177,11 @@ msgstr "" msgid "No image set in image content field" msgstr "" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2211,7 +2216,7 @@ msgstr "" msgid "No results found" msgstr "" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/locales/zh_CN/LC_MESSAGES/volto.po b/locales/zh_CN/LC_MESSAGES/volto.po index 2bb941cd70..87c2928252 100644 --- a/locales/zh_CN/LC_MESSAGES/volto.po +++ b/locales/zh_CN/LC_MESSAGES/volto.po @@ -2181,6 +2181,11 @@ msgstr "" msgid "No image set in image content field" msgstr "在图像内容字段中没有设置图像" +#: components/manage/Blocks/Listing/GalleryNoResultsComponent +# defaultMessage: No images found. +msgid "No images found." +msgstr "" + #: components/manage/Blocks/Listing/ListingBody # defaultMessage: No items found in this container. msgid "No items found in this container." @@ -2215,7 +2220,7 @@ msgstr "没有选项" msgid "No results found" msgstr "未找到结果" -#: components/manage/Blocks/Listing/ListingBody +#: components/manage/Blocks/Listing/DefaultNoResultsComponent #: components/manage/Widgets/ReferenceWidget # defaultMessage: No results found. msgid "No results found." diff --git a/news/3602.feat b/news/3602.feat new file mode 100644 index 0000000000..acf4fae069 --- /dev/null +++ b/news/3602.feat @@ -0,0 +1 @@ +Added a default Component to show when the Listing block has no results, and another only for the ImageGallery variation. Both of them registered in the block registration config. @ionlizarazu diff --git a/src/components/manage/Blocks/Listing/DefaultNoResultsComponent.jsx b/src/components/manage/Blocks/Listing/DefaultNoResultsComponent.jsx new file mode 100644 index 0000000000..60541205e8 --- /dev/null +++ b/src/components/manage/Blocks/Listing/DefaultNoResultsComponent.jsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; + +const DefaultNoResultsComponent = (props) => { + return ( + + ); +}; + +export default DefaultNoResultsComponent; diff --git a/src/components/manage/Blocks/Listing/GalleryNoResultsComponent.jsx b/src/components/manage/Blocks/Listing/GalleryNoResultsComponent.jsx new file mode 100644 index 0000000000..17df20bdcf --- /dev/null +++ b/src/components/manage/Blocks/Listing/GalleryNoResultsComponent.jsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; + +const GalleryNoResultsComponent = (props) => { + return ( + + ); +}; + +export default GalleryNoResultsComponent; diff --git a/src/components/manage/Blocks/Listing/ListingBody.jsx b/src/components/manage/Blocks/Listing/ListingBody.jsx index d289b09b88..8941a233dd 100644 --- a/src/components/manage/Blocks/Listing/ListingBody.jsx +++ b/src/components/manage/Blocks/Listing/ListingBody.jsx @@ -40,6 +40,10 @@ const ListingBody = withQuerystringResults((props) => { const listingRef = createRef(); + const NoResults = variation?.noResultsComponent + ? variation.noResultsComponent + : config.blocks?.blocksConfig['listing'].noResultsComponent; + return listingItems?.length > 0 ? (
{ defaultMessage="No items found in this container." /> )} - {hasLoaded && ( - + {hasLoaded && NoResults && ( + )} @@ -98,11 +99,8 @@ const ListingBody = withQuerystringResults((props) => {
) : (
- {hasLoaded && ( - + {hasLoaded && NoResults && ( + )} diff --git a/src/components/manage/Blocks/Listing/__snapshots__/ListingBody.test.jsx.snap b/src/components/manage/Blocks/Listing/__snapshots__/ListingBody.test.jsx.snap index 352770202f..d91cbc9314 100644 --- a/src/components/manage/Blocks/Listing/__snapshots__/ListingBody.test.jsx.snap +++ b/src/components/manage/Blocks/Listing/__snapshots__/ListingBody.test.jsx.snap @@ -2,7 +2,6 @@ exports[`renders a ListingBody component 1`] = `
- No results found.
Date: Wed, 1 Mar 2023 12:27:28 +0100 Subject: [PATCH 020/142] Remove link to yarnclasic --- docs/source/addons/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/addons/index.md b/docs/source/addons/index.md index d018b62d4a..28b4e2bccd 100644 --- a/docs/source/addons/index.md +++ b/docs/source/addons/index.md @@ -332,7 +332,7 @@ export default applyConfig; If you're developing the add-on and you wish to add an external dependency, you'll have to switch your project to be a [Yarn Workspaces -root](https://classic.yarnpkg.com/en/docs/workspaces/). +root](https://yarnpkg.com/en/docs/workspaces/). So you'll need to add, in your Volto project's `package.json`: From a0170c2a48ad2c99a444fbdfc793fdb3ce1010ad Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 1 Mar 2023 22:33:00 -0800 Subject: [PATCH 021/142] Update link to Yarn 3 Workspaces to avoid redirect to Yarn Classic 1.x. (#4444) --- docs/source/addons/index.md | 4 +--- news/4441.documentation | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) create mode 100644 news/4441.documentation diff --git a/docs/source/addons/index.md b/docs/source/addons/index.md index 28b4e2bccd..cf456c215b 100644 --- a/docs/source/addons/index.md +++ b/docs/source/addons/index.md @@ -330,9 +330,7 @@ export default applyConfig; ## Add third-party dependencies to your add-on -If you're developing the add-on and you wish to add an external dependency, -you'll have to switch your project to be a [Yarn Workspaces -root](https://yarnpkg.com/en/docs/workspaces/). +If you're developing the add-on and you wish to add an external dependency, you'll have to switch your project to be a [Yarn Workspaces root](https://yarnpkg.com/features/workspaces). So you'll need to add, in your Volto project's `package.json`: diff --git a/news/4441.documentation b/news/4441.documentation new file mode 100644 index 0000000000..545ac951b0 --- /dev/null +++ b/news/4441.documentation @@ -0,0 +1 @@ +Update link to Yarn 3 Workspaces to avoid redirect to Yarn Classic 1.x. @stevepiercy From 95a64c9476339fc1a81ff501c220150922d86b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Thu, 2 Mar 2023 10:20:43 +0100 Subject: [PATCH 022/142] Release 16.12.0 (#4445) --- CHANGELOG.md | 19 +++++++++++++++++++ news/4150.bugfix | 1 - news/4180.bugfix | 1 - news/4396.feature | 1 - news/4399.bugfix | 1 - news/4400.bugfix | 1 - news/4404.documentation | 1 - news/4414.bugfix | 1 - package.json | 2 +- packages/volto-slate/package.json | 2 +- 10 files changed, 21 insertions(+), 9 deletions(-) delete mode 100644 news/4150.bugfix delete mode 100644 news/4180.bugfix delete mode 100644 news/4396.feature delete mode 100644 news/4399.bugfix delete mode 100644 news/4400.bugfix delete mode 100644 news/4404.documentation delete mode 100644 news/4414.bugfix diff --git a/CHANGELOG.md b/CHANGELOG.md index c79ed98258..902a8a6162 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,25 @@ +## 16.12.0 (2023-02-21) + +### Feature + +- Provide disabled props to all widgets, and pass disabled props in to babel views. @iFlameing [#4396](https://github.com/plone/volto/issues/4396) + +### Bugfix + +- fix : Restrictive propTypes for widgets . @suman9893 [#4150](https://github.com/plone/volto/issues/4150) +- Add the intl string 'Uploading image' to the image block @bipoza [#4180](https://github.com/plone/volto/issues/4180) +- Fix link integrity overlay is too narrowed @iFlameing [#4399](https://github.com/plone/volto/issues/4399) +- Fix External link Icon shows up in Grid-text block @iRohitSingh [#4400](https://github.com/plone/volto/issues/4400) +- Fix broken links: babeljs.io/… @ksuess [#4414](https://github.com/plone/volto/issues/4414) + +### Documentation + +- Remove inclusion of CHANGELOG.md for volto repo only. Fixes https://github.com/plone/documentation/issues/1431. @stevepiercy [#4404](https://github.com/plone/volto/issues/4404) + + ## 16.11.0 (2023-02-13) ### Feature diff --git a/news/4150.bugfix b/news/4150.bugfix deleted file mode 100644 index d3d7fd6239..0000000000 --- a/news/4150.bugfix +++ /dev/null @@ -1 +0,0 @@ -fix : Restrictive propTypes for widgets . @suman9893 \ No newline at end of file diff --git a/news/4180.bugfix b/news/4180.bugfix deleted file mode 100644 index ddbb25f199..0000000000 --- a/news/4180.bugfix +++ /dev/null @@ -1 +0,0 @@ -Add the intl string 'Uploading image' to the image block @bipoza \ No newline at end of file diff --git a/news/4396.feature b/news/4396.feature deleted file mode 100644 index ee13d6a4cf..0000000000 --- a/news/4396.feature +++ /dev/null @@ -1 +0,0 @@ -Provide disabled props to all widgets, and pass disabled props in to babel views. @iFlameing \ No newline at end of file diff --git a/news/4399.bugfix b/news/4399.bugfix deleted file mode 100644 index 8b3b16b09e..0000000000 --- a/news/4399.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix link integrity overlay is too narrowed @iFlameing \ No newline at end of file diff --git a/news/4400.bugfix b/news/4400.bugfix deleted file mode 100644 index d13fa71b2d..0000000000 --- a/news/4400.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix External link Icon shows up in Grid-text block @iRohitSingh \ No newline at end of file diff --git a/news/4404.documentation b/news/4404.documentation deleted file mode 100644 index 27e02e57c8..0000000000 --- a/news/4404.documentation +++ /dev/null @@ -1 +0,0 @@ -Remove inclusion of CHANGELOG.md for volto repo only. Fixes https://github.com/plone/documentation/issues/1431. @stevepiercy diff --git a/news/4414.bugfix b/news/4414.bugfix deleted file mode 100644 index 6b977f4d36..0000000000 --- a/news/4414.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix broken links: babeljs.io/… @ksuess \ No newline at end of file diff --git a/package.json b/package.json index 352959b864..793969442b 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "16.11.0", + "version": "16.12.0", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" diff --git a/packages/volto-slate/package.json b/packages/volto-slate/package.json index 5c38db35f5..300ba3bc9b 100644 --- a/packages/volto-slate/package.json +++ b/packages/volto-slate/package.json @@ -1,6 +1,6 @@ { "name": "@plone/volto-slate", - "version": "16.11.0", + "version": "16.12.0", "description": "Slate.js integration with Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", From 5bf472dfe56a716924fa5513f61f67414aa578fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Thu, 2 Mar 2023 12:02:43 +0100 Subject: [PATCH 023/142] Add towncrier checker (#4450) --- .github/workflows/towncrier.yml | 32 ++++++++++++++++++++++++++++++++ news/4450.feature | 1 + 2 files changed, 33 insertions(+) create mode 100644 .github/workflows/towncrier.yml create mode 100644 news/4450.feature diff --git a/.github/workflows/towncrier.yml b/.github/workflows/towncrier.yml new file mode 100644 index 0000000000..4be1939820 --- /dev/null +++ b/.github/workflows/towncrier.yml @@ -0,0 +1,32 @@ +name: Towncrier check +on: + pull_request: + types: [assigned, opened, synchronize, reopened, labeled, unlabeled] + branches: + - master + +env: + node-version: 16.x + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + # Fetch all history + fetch-depth: '0' + + - name: Install towncrier + run: pip install towncrier + + - name: Check for presence of a Change Log fragment (only pull requests) + run: | + # Fetch the pull request' base branch so towncrier will be able to + # compare the current branch with the base branch. + # Source: https://github.com/actions/checkout/#fetch-all-branches. + git fetch --no-tags origin master + towncrier check --compare-with origin/master + env: + BASE_BRANCH: ${{ github.base_ref }} + if: github.event_name == 'pull_request' diff --git a/news/4450.feature b/news/4450.feature new file mode 100644 index 0000000000..ae834b5e0e --- /dev/null +++ b/news/4450.feature @@ -0,0 +1 @@ +Add GHA Towncrier syntax checker @sneridagh From 41ce35bfff67d23fda46c3af4754f0b5db0a1be6 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Thu, 2 Mar 2023 12:06:56 +0100 Subject: [PATCH 024/142] Amend Towncrier news item --- news/3602.feat | 1 - 1 file changed, 1 deletion(-) delete mode 100644 news/3602.feat diff --git a/news/3602.feat b/news/3602.feat deleted file mode 100644 index acf4fae069..0000000000 --- a/news/3602.feat +++ /dev/null @@ -1 +0,0 @@ -Added a default Component to show when the Listing block has no results, and another only for the ImageGallery variation. Both of them registered in the block registration config. @ionlizarazu From 9c821190f1e91d2e47e4603d24ef07b60608469e Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Thu, 2 Mar 2023 12:07:16 +0100 Subject: [PATCH 025/142] Amend Towncrier news item (2) --- news/3602.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/3602.feature diff --git a/news/3602.feature b/news/3602.feature new file mode 100644 index 0000000000..acf4fae069 --- /dev/null +++ b/news/3602.feature @@ -0,0 +1 @@ +Added a default Component to show when the Listing block has no results, and another only for the ImageGallery variation. Both of them registered in the block registration config. @ionlizarazu From 4d960a66fd42cd57d1e94d903df2e119757c12cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Thu, 2 Mar 2023 16:14:17 +0100 Subject: [PATCH 026/142] Fix generator adding the jest config for @plone/volto-slate (#4453) --- news/4453.bugfix | 1 + .../generator-volto/generators/app/templates/package.json.tpl | 1 + 2 files changed, 2 insertions(+) create mode 100644 news/4453.bugfix diff --git a/news/4453.bugfix b/news/4453.bugfix new file mode 100644 index 0000000000..7e1422afcb --- /dev/null +++ b/news/4453.bugfix @@ -0,0 +1 @@ +Fix generator adding the jest config for @plone/volto-slate @sneridagh diff --git a/packages/generator-volto/generators/app/templates/package.json.tpl b/packages/generator-volto/generators/app/templates/package.json.tpl index b54b916490..304d309f6e 100644 --- a/packages/generator-volto/generators/app/templates/package.json.tpl +++ b/packages/generator-volto/generators/app/templates/package.json.tpl @@ -46,6 +46,7 @@ "@plone/volto/webpack-plugins/webpack-less-plugin": "/node_modules/@plone/volto/webpack-plugins/webpack-less-plugin", "@plone/volto/babel": "/node_modules/@plone/volto/babel", "@plone/volto/(.*)$": "/node_modules/@plone/volto/src/$1", + "@plone/volto-slate/(.*)$": "/node_modules/@plone/volto/packages/volto-slate/src/$1", "load-volto-addons": "/node_modules/@plone/volto/jest-addons-loader.js", "@package/(.*)$": "/src/$1", "@root/(.*)$": "/src/$1", From 0a7e00fe73055836904d50f4b26cd6adc3255945 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Thu, 2 Mar 2023 17:05:26 +0100 Subject: [PATCH 027/142] Release generate-volto 6.2.4 --- packages/generator-volto/CHANGELOG.md | 11 +++++++++++ {news => packages/generator-volto/news}/4453.bugfix | 0 packages/generator-volto/package.json | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) rename {news => packages/generator-volto/news}/4453.bugfix (100%) diff --git a/packages/generator-volto/CHANGELOG.md b/packages/generator-volto/CHANGELOG.md index a7ea6c8e7c..87e31a4f77 100644 --- a/packages/generator-volto/CHANGELOG.md +++ b/packages/generator-volto/CHANGELOG.md @@ -8,6 +8,17 @@ +## 6.2.4 (2023-03-02) + +### Bugfix + +- Fix generator adding the jest config for @plone/volto-slate @sneridagh [#4453](https://github.com/plone/volto/issues/4453) + +### Internal + +- made razzle.config.js in project template easier to extend @akshatgarg12 [#3424](https://github.com/plone/volto/issues/3424) + + ## 6.2.3 (2023-01-16) ### Bugfix diff --git a/news/4453.bugfix b/packages/generator-volto/news/4453.bugfix similarity index 100% rename from news/4453.bugfix rename to packages/generator-volto/news/4453.bugfix diff --git a/packages/generator-volto/package.json b/packages/generator-volto/package.json index 0ad2c4edc7..fee473cffa 100644 --- a/packages/generator-volto/package.json +++ b/packages/generator-volto/package.json @@ -10,7 +10,7 @@ } ], "license": "MIT", - "version": "6.2.3", + "version": "6.2.4", "repository": { "type": "git", "url": "git+https://github.com/plone/generator-volto.git" From afd92f05a6ede2d22258ececed8eabf70dd31d00 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Thu, 2 Mar 2023 20:40:15 +0200 Subject: [PATCH 028/142] Export App and its connectorAppComponent as standalone (#4413) --- news/4413.internal | 1 + .../generators/app/templates/src/routes.js | 2 +- packages/generator-volto/news/4413.internal | 1 + src/components/theme/App/App.jsx | 138 +++++++++--------- src/config/Components.jsx | 3 +- 5 files changed, 76 insertions(+), 69 deletions(-) create mode 100644 news/4413.internal create mode 100644 packages/generator-volto/news/4413.internal diff --git a/news/4413.internal b/news/4413.internal new file mode 100644 index 0000000000..75b0b573b9 --- /dev/null +++ b/news/4413.internal @@ -0,0 +1 @@ +Expose a named export for the App component, separate its default wrappers as a separate `connectAppComponent` function. @tiberiuichim diff --git a/packages/generator-volto/generators/app/templates/src/routes.js b/packages/generator-volto/generators/app/templates/src/routes.js index ff5d54f5a0..c12c02ae9e 100644 --- a/packages/generator-volto/generators/app/templates/src/routes.js +++ b/packages/generator-volto/generators/app/templates/src/routes.js @@ -15,7 +15,7 @@ import config from '@plone/volto/registry'; const routes = [ { path: '/', - component: App, // Change this if you want a different component + component: config.getComponent('App').component, // Change this if you want a different component routes: [ // Add your routes here ...(config.addonRoutes || []), diff --git a/packages/generator-volto/news/4413.internal b/packages/generator-volto/news/4413.internal new file mode 100644 index 0000000000..22806a52c3 --- /dev/null +++ b/packages/generator-volto/news/4413.internal @@ -0,0 +1 @@ +Get the App component from the registry. This makes it possible to add wrappers over the App@tiberiuichim diff --git a/src/components/theme/App/App.jsx b/src/components/theme/App/App.jsx index d637addcb2..cec83066a1 100644 --- a/src/components/theme/App/App.jsx +++ b/src/components/theme/App/App.jsx @@ -57,7 +57,7 @@ import LockingToastsFactory from '@plone/volto/components/manage/LockingToastsFa * @class App * @extends {Component} */ -class App extends Component { +export class App extends Component { /** * Property types. * @property {Object} propTypes Property types. @@ -259,72 +259,76 @@ export const fetchContent = async ({ store, location }) => { return content; }; -export default compose( - asyncConnect([ - { - key: 'breadcrumbs', - promise: ({ location, store: { dispatch } }) => { - // Do not trigger the breadcrumbs action if the expander is present - if ( - __SERVER__ && - !hasApiExpander('breadcrumbs', getBaseUrl(location.pathname)) - ) { - return dispatch(getBreadcrumbs(getBaseUrl(location.pathname))); - } +export function connectAppComponent(AppComponent) { + return compose( + asyncConnect([ + { + key: 'breadcrumbs', + promise: ({ location, store: { dispatch } }) => { + // Do not trigger the breadcrumbs action if the expander is present + if ( + __SERVER__ && + !hasApiExpander('breadcrumbs', getBaseUrl(location.pathname)) + ) { + return dispatch(getBreadcrumbs(getBaseUrl(location.pathname))); + } + }, }, - }, - { - key: 'content', - promise: ({ location, store }) => - __SERVER__ && fetchContent({ store, location }), - }, - { - key: 'navigation', - promise: ({ location, store: { dispatch } }) => { - // Do not trigger the navigation action if the expander is present - if ( - __SERVER__ && - !hasApiExpander('navigation', getBaseUrl(location.pathname)) - ) { - return dispatch( - getNavigation( - getBaseUrl(location.pathname), - config.settings.navDepth, - ), - ); - } + { + key: 'content', + promise: ({ location, store }) => + __SERVER__ && fetchContent({ store, location }), }, - }, - { - key: 'types', - promise: ({ location, store: { dispatch } }) => { - // Do not trigger the types action if the expander is present - if ( - __SERVER__ && - !hasApiExpander('types', getBaseUrl(location.pathname)) - ) { - return dispatch(getTypes(getBaseUrl(location.pathname))); - } + { + key: 'navigation', + promise: ({ location, store: { dispatch } }) => { + // Do not trigger the navigation action if the expander is present + if ( + __SERVER__ && + !hasApiExpander('navigation', getBaseUrl(location.pathname)) + ) { + return dispatch( + getNavigation( + getBaseUrl(location.pathname), + config.settings.navDepth, + ), + ); + } + }, }, - }, - { - key: 'workflow', - promise: ({ location, store: { dispatch } }) => - __SERVER__ && dispatch(getWorkflow(getBaseUrl(location.pathname))), - }, - ]), - injectIntl, - connect( - (state, props) => ({ - pathname: props.location.pathname, - token: state.userSession.token, - userId: state.userSession.token - ? jwtDecode(state.userSession.token).sub - : '', - content: state.content.data, - apiError: state.apierror.error, - connectionRefused: state.apierror.connectionRefused, - }), - null, - ), -)(App); + { + key: 'types', + promise: ({ location, store: { dispatch } }) => { + // Do not trigger the types action if the expander is present + if ( + __SERVER__ && + !hasApiExpander('types', getBaseUrl(location.pathname)) + ) { + return dispatch(getTypes(getBaseUrl(location.pathname))); + } + }, + }, + { + key: 'workflow', + promise: ({ location, store: { dispatch } }) => + __SERVER__ && dispatch(getWorkflow(getBaseUrl(location.pathname))), + }, + ]), + injectIntl, + connect( + (state, props) => ({ + pathname: props.location.pathname, + token: state.userSession.token, + userId: state.userSession.token + ? jwtDecode(state.userSession.token).sub + : '', + content: state.content.data, + apiError: state.apierror.error, + connectionRefused: state.apierror.connectionRefused, + }), + null, + ), + )(AppComponent); +} + +export default connectAppComponent(App); diff --git a/src/config/Components.jsx b/src/config/Components.jsx index 02e1a54847..afe907f4e0 100644 --- a/src/config/Components.jsx +++ b/src/config/Components.jsx @@ -1,5 +1,6 @@ -import { PreviewImage } from '@plone/volto/components'; +import { App, PreviewImage } from '@plone/volto/components'; export const components = { PreviewImage: { component: PreviewImage }, + App: { component: App }, }; From f22cf6534cbd2c4fd1f69c20eb4db45b910b5cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Thu, 2 Mar 2023 19:44:21 +0100 Subject: [PATCH 029/142] Use latest plone/server breed images (#4454) --- Makefile | 21 ++++++++++--------- api/Makefile | 2 +- api/buildout.cfg | 2 +- api/versions.cfg | 4 ++-- news/4454.internal | 1 + .../generators/app/templates/Makefile | 7 ++++--- 6 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 news/4454.internal diff --git a/Makefile b/Makefile index d7884cfdac..226f1da0d2 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ # https://tech.davis-hansson.com/p/make/ SHELL:=bash .ONESHELL: -.SHELLFLAGS:=-xeu -o pipefail -O inherit_errexit -c +.SHELLFLAGS:=-eu -o pipefail -c .SILENT: .DELETE_ON_ERROR: MAKEFLAGS+=--warn-undefined-variables @@ -13,15 +13,16 @@ MAKEFLAGS+=--no-builtin-rules # Project settings INSTANCE_PORT=8080 -DOCKER_IMAGE=plone/plone-backend:6.0.1 -KGS=plone.volto==4.0.5 -TESTING_ADDONS=plone.app.robotframework==2.0.0 plone.app.testing==7.0.0 +DOCKER_IMAGE=plone/server-dev:6.0.2 +DOCKER_IMAGE_ACCEPTANCE=plone/server-acceptance:6.0.2 +KGS= NODEBIN = ./node_modules/.bin SCRIPTSPACKAGE = ./packages/scripts # Plone 5 legacy DOCKER_IMAGE5=plone/plone-backend:5.2.9 -KGS5=plone.restapi==8.33.3 plone.volto==4.0.5 plone.rest==3.0.0 +KGS5=plone.restapi==8.35.1 plone.volto==4.0.7 plone.rest==3.0.0 +TESTING_ADDONS=plone.app.robotframework==2.0.0 plone.app.testing==7.0.0 # Sphinx variables # You can set these variables from the command line. @@ -202,7 +203,7 @@ start-test-all: ## Start Test .PHONY: start-test-frontend start-test-frontend: ## Start Test Volto Frontend @echo "$(GREEN)==> Start Test Volto Frontend$(RESET)" - RAZZLE_API_PATH=http://localhost:55001/plone yarn build && NODE_ENV=production node build/server.js + RAZZLE_API_PATH=http://localhost:55001/plone yarn build && NODE_ENV=production yarn start:prod .PHONY: start-test-backend start-test-backend: ## Start Test Plone Backend (api folder) @@ -227,7 +228,7 @@ start-test-acceptance-frontend-dev: ## Start the Core Acceptance Frontend Fixtur .PHONY: start-test-acceptance-server test-acceptance-server start-test-acceptance-server test-acceptance-server: ## Start Test Acceptance Server Main Fixture (docker container) - docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e ADDONS='$(KGS) $(TESTING_ADDONS)' -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:default-homepage -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors $(DOCKER_IMAGE) ./bin/robot-server plone.app.robotframework.testing.VOLTO_ROBOT_TESTING + docker run -i --rm -p 55001:55001 $(DOCKER_IMAGE_ACCEPTANCE) .PHONY: start-test-acceptance-frontend start-test-acceptance-frontend: ## Start the Core Acceptance Frontend Fixture @@ -273,7 +274,7 @@ start-test-acceptance-frontend-project: ## Start the Project Acceptance Frontend .PHONY: start-test-acceptance-server-coresandbox test-acceptance-server-coresandbox start-test-acceptance-server-coresandbox test-acceptance-server-coresandbox: ## Start CoreSandbox Test Acceptance Server Fixture (docker container) - docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e ADDONS='$(KGS) $(TESTING_ADDONS)' -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:default-homepage,plone.volto:coresandbox -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors,plone.volto.coresandbox $(DOCKER_IMAGE) ./bin/robot-server plone.app.robotframework.testing.VOLTO_ROBOT_TESTING + docker run -i --rm -p 55001:55001 -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:default-homepage,plone.volto:coresandbox -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors,plone.volto.coresandbox $(DOCKER_IMAGE_ACCEPTANCE) # ZSERVER_PORT=55001 CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors,plone.volto.coresandbox APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:default-homepage,plone.volto:coresandbox ./api/bin/robot-server plone.app.robotframework.testing.VOLTO_ROBOT_TESTING .PHONY: start-test-acceptance-frontend-coresandbox @@ -300,7 +301,7 @@ full-test-acceptance-coresandbox: ## Runs CoreSandbox Full Acceptance Testing in .PHONY: start-test-acceptance-server-multilingual test-acceptance-server-multilingual start-test-acceptance-server-multilingual test-acceptance-server-multilingual: ## Start Multilingual Acceptance Server Multilingual Fixture (docker container) - docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e ADDONS='$(KGS) $(TESTING_ADDONS)' -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:multilingual -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors $(DOCKER_IMAGE) ./bin/robot-server plone.app.robotframework.testing.VOLTO_ROBOT_TESTING + docker run -i --rm -p 55001:55001 -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:multilingual $(DOCKER_IMAGE_ACCEPTANCE) .PHONY: start-test-acceptance-frontend-multilingual start-test-acceptance-frontend-multilingual: ## Start the Multilingual Acceptance Frontend Fixture @@ -322,7 +323,7 @@ full-test-acceptance-multilingual: ## Runs Multilingual Full Acceptance Testing .PHONY: start-test-acceptance-server-workingcopy test-acceptance-server-workingcopy start-test-acceptance-server-workingcopy test-acceptance-server-workingcopy : ## Start the WorkingCopy Acceptance Server Fixture (docker container) - docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e ADDONS='$(KGS) $(TESTING_ADDONS)' -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.app.iterate:default,plone.volto:default-homepage -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors $(DOCKER_IMAGE) ./bin/robot-server plone.app.robotframework.testing.VOLTO_ROBOT_TESTING + docker run -i --rm -p 55001:55001 -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.app.iterate:default,plone.volto:default-homepage $(DOCKER_IMAGE_ACCEPTANCE) # ZSERVER_PORT=55001 CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.app.iterate,plone.volto,plone.volto.cors APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.app.iterate:default,plone.volto:default-homepage ./api/bin/robot-server plone.app.robotframework.testing.VOLTO_ROBOT_TESTING .PHONY: start-test-acceptance-frontend-workingcopy diff --git a/api/Makefile b/api/Makefile index fbe15f133d..3820acf081 100644 --- a/api/Makefile +++ b/api/Makefile @@ -4,7 +4,7 @@ # https://tech.davis-hansson.com/p/make/ SHELL:=bash .ONESHELL: -.SHELLFLAGS:=-xeu -o pipefail -O inherit_errexit -c +.SHELLFLAGS:=-eu -o pipefail -c .SILENT: .DELETE_ON_ERROR: MAKEFLAGS+=--warn-undefined-variables diff --git a/api/buildout.cfg b/api/buildout.cfg index 4ffbe1b383..feb689d278 100644 --- a/api/buildout.cfg +++ b/api/buildout.cfg @@ -1,7 +1,7 @@ [buildout] index = https://pypi.org/simple/ extends = - http://dist.plone.org/release/6.0.1/versions.cfg + http://dist.plone.org/release/6.0.2/versions.cfg version-constraints.cfg versions.cfg parts = instance plonesite site-packages test robot-server diff --git a/api/versions.cfg b/api/versions.cfg index ab0781140f..d404ee2ec3 100644 --- a/api/versions.cfg +++ b/api/versions.cfg @@ -5,8 +5,8 @@ async-generator = 1.10 collective.folderishtypes = 3.0.0 collective.recipe.plonesite = 1.12.0 h11 = 0.12.0 -plone.restapi = 8.33.3 -plone.volto = 4.0.5 +plone.restapi = 8.35.1 +plone.volto = 4.0.7 prompt-toolkit = 2.0.10 pyOpenSSL = 21.0.0 robotframework-debuglibrary = 2.2.2 diff --git a/news/4454.internal b/news/4454.internal new file mode 100644 index 0000000000..252f249c29 --- /dev/null +++ b/news/4454.internal @@ -0,0 +1 @@ +Use latest plone/server breed images @sneridagh diff --git a/packages/generator-volto/generators/app/templates/Makefile b/packages/generator-volto/generators/app/templates/Makefile index 97d8d4dab8..ac5ad96689 100644 --- a/packages/generator-volto/generators/app/templates/Makefile +++ b/packages/generator-volto/generators/app/templates/Makefile @@ -2,14 +2,15 @@ # https://tech.davis-hansson.com/p/make/ SHELL:=bash .ONESHELL: -.SHELLFLAGS:=-xeu -o pipefail -O inherit_errexit -c +.SHELLFLAGS:=-eu -o pipefail -c .SILENT: .DELETE_ON_ERROR: MAKEFLAGS+=--warn-undefined-variables MAKEFLAGS+=--no-builtin-rules # Update the versions depending on your project requirements | Last Updated 2022-12-09 -DOCKER_IMAGE=plone/plone-backend:6.0 +DOCKER_IMAGE=plone/server-dev:6.0.2 +DOCKER_IMAGE_ACCEPTANCE=plone/server-acceptance:6.0.2 KGS= TESTING_ADDONS=plone.app.robotframework==2.0.0 plone.app.testing==7.0.0 NODEBIN = ./node_modules/.bin @@ -71,7 +72,7 @@ patches: .PHONY: start-test-acceptance-server start-test-backend start-test-acceptance-server start-test-backend : ## Start Test Plone Backend @echo "$(GREEN)==> Start Test Plone Backend$(RESET)" - docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e ADDONS='$(KGS) $(TESTING_ADDONS)' -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:default-homepage -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors $(DOCKER_IMAGE) ./bin/robot-server plone.app.robotframework.testing.VOLTO_ROBOT_TESTING + docker run -i --rm -p 55001:55001 $(DOCKER_IMAGE_ACCEPTANCE) ## KGS in case you need a Plone 5.2 series (comment/remove above line): # docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e ADDONS='$(KGS5) $(TESTING_ADDONS)' -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,plone.volto:default-homepage -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,plone.volto,plone.volto.cors $(DOCKER_IMAGE5) ./bin/robot-server plone.app.robotframework.testing.VOLTO_ROBOT_TESTING From 4188d74a58b9464ede28e6b4617aa2fb91d767ee Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Thu, 2 Mar 2023 22:05:12 +0100 Subject: [PATCH 030/142] Amend inconsistencies in generator package after release :/ --- packages/generator-volto/generators/app/templates/Makefile | 2 +- packages/generator-volto/news/3424.internal | 1 - packages/generator-volto/news/4453.bugfix | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 packages/generator-volto/news/3424.internal delete mode 100644 packages/generator-volto/news/4453.bugfix diff --git a/packages/generator-volto/generators/app/templates/Makefile b/packages/generator-volto/generators/app/templates/Makefile index ac5ad96689..f757f08206 100644 --- a/packages/generator-volto/generators/app/templates/Makefile +++ b/packages/generator-volto/generators/app/templates/Makefile @@ -8,7 +8,7 @@ SHELL:=bash MAKEFLAGS+=--warn-undefined-variables MAKEFLAGS+=--no-builtin-rules -# Update the versions depending on your project requirements | Last Updated 2022-12-09 +# Update the versions depending on your project requirements | Last Updated 2023-03-02 DOCKER_IMAGE=plone/server-dev:6.0.2 DOCKER_IMAGE_ACCEPTANCE=plone/server-acceptance:6.0.2 KGS= diff --git a/packages/generator-volto/news/3424.internal b/packages/generator-volto/news/3424.internal deleted file mode 100644 index e45a7b349a..0000000000 --- a/packages/generator-volto/news/3424.internal +++ /dev/null @@ -1 +0,0 @@ -made razzle.config.js in project template easier to extend @akshatgarg12 \ No newline at end of file diff --git a/packages/generator-volto/news/4453.bugfix b/packages/generator-volto/news/4453.bugfix deleted file mode 100644 index 7e1422afcb..0000000000 --- a/packages/generator-volto/news/4453.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix generator adding the jest config for @plone/volto-slate @sneridagh From 7850228a79eb243f2adcf76885981b37e0a4ecc7 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Thu, 2 Mar 2023 22:06:02 +0100 Subject: [PATCH 031/142] Release generate-volto 6.2.5 --- packages/generator-volto/CHANGELOG.md | 7 +++++++ packages/generator-volto/news/4413.internal | 1 - packages/generator-volto/package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 packages/generator-volto/news/4413.internal diff --git a/packages/generator-volto/CHANGELOG.md b/packages/generator-volto/CHANGELOG.md index 87e31a4f77..e48de32eb6 100644 --- a/packages/generator-volto/CHANGELOG.md +++ b/packages/generator-volto/CHANGELOG.md @@ -8,6 +8,13 @@ +## 6.2.5 (2023-03-02) + +### Internal + +- Get the App component from the registry. This makes it possible to add wrappers over the App@tiberiuichim [#4413](https://github.com/plone/volto/issues/4413) + + ## 6.2.4 (2023-03-02) ### Bugfix diff --git a/packages/generator-volto/news/4413.internal b/packages/generator-volto/news/4413.internal deleted file mode 100644 index 22806a52c3..0000000000 --- a/packages/generator-volto/news/4413.internal +++ /dev/null @@ -1 +0,0 @@ -Get the App component from the registry. This makes it possible to add wrappers over the App@tiberiuichim diff --git a/packages/generator-volto/package.json b/packages/generator-volto/package.json index fee473cffa..54c8f88b29 100644 --- a/packages/generator-volto/package.json +++ b/packages/generator-volto/package.json @@ -10,7 +10,7 @@ } ], "license": "MIT", - "version": "6.2.4", + "version": "6.2.5", "repository": { "type": "git", "url": "git+https://github.com/plone/generator-volto.git" From f1a2b8da68b4f6170ddc53fe6b4cf62653d7b322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Thu, 2 Mar 2023 22:22:15 +0100 Subject: [PATCH 032/142] Release 16.13.0 (#4457) --- CHANGELOG.md | 22 ++++++++++++++++++++++ news/3602.feature | 1 - news/4413.internal | 1 - news/4425.bugfix | 1 - news/4431.documentation | 1 - news/4441.documentation | 1 - news/4450.feature | 1 - news/4454.internal | 1 - package.json | 2 +- packages/volto-slate/package.json | 2 +- 10 files changed, 24 insertions(+), 9 deletions(-) delete mode 100644 news/3602.feature delete mode 100644 news/4413.internal delete mode 100644 news/4425.bugfix delete mode 100644 news/4431.documentation delete mode 100644 news/4441.documentation delete mode 100644 news/4450.feature delete mode 100644 news/4454.internal diff --git a/CHANGELOG.md b/CHANGELOG.md index 902a8a6162..a9b6c52220 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,28 @@ +## 16.13.0 (2023-03-02) + +### Feature + +- Added a default Component to show when the Listing block has no results, and another only for the ImageGallery variation. Both of them registered in the block registration config. @ionlizarazu [#3602](https://github.com/plone/volto/issues/3602) +- Add GHA Towncrier syntax checker @sneridagh [#4450](https://github.com/plone/volto/issues/4450) + +### Bugfix + +- On SSR-generated error pages, don't change the user's language to the default site language @tiberiuichim [#4425](https://github.com/plone/volto/issues/4425) + +### Internal + +- Expose a named export for the App component, separate its default wrappers as a separate `connectAppComponent` function. @tiberiuichim [#4413](https://github.com/plone/volto/issues/4413) +- Use latest plone/server breed images @sneridagh [#4454](https://github.com/plone/volto/issues/4454) + +### Documentation + +- Fix links, convert features to definition list, add link to issue for TODO. @stevepiercy [#4431](https://github.com/plone/volto/issues/4431) +- Update link to Yarn 3 Workspaces to avoid redirect to Yarn Classic 1.x. @stevepiercy [#4441](https://github.com/plone/volto/issues/4441) + + ## 16.12.0 (2023-02-21) ### Feature diff --git a/news/3602.feature b/news/3602.feature deleted file mode 100644 index acf4fae069..0000000000 --- a/news/3602.feature +++ /dev/null @@ -1 +0,0 @@ -Added a default Component to show when the Listing block has no results, and another only for the ImageGallery variation. Both of them registered in the block registration config. @ionlizarazu diff --git a/news/4413.internal b/news/4413.internal deleted file mode 100644 index 75b0b573b9..0000000000 --- a/news/4413.internal +++ /dev/null @@ -1 +0,0 @@ -Expose a named export for the App component, separate its default wrappers as a separate `connectAppComponent` function. @tiberiuichim diff --git a/news/4425.bugfix b/news/4425.bugfix deleted file mode 100644 index 59ce9dd624..0000000000 --- a/news/4425.bugfix +++ /dev/null @@ -1 +0,0 @@ -On SSR-generated error pages, don't change the user's language to the default site language @tiberiuichim diff --git a/news/4431.documentation b/news/4431.documentation deleted file mode 100644 index b89db2a531..0000000000 --- a/news/4431.documentation +++ /dev/null @@ -1 +0,0 @@ -Fix links, convert features to definition list, add link to issue for TODO. @stevepiercy diff --git a/news/4441.documentation b/news/4441.documentation deleted file mode 100644 index 545ac951b0..0000000000 --- a/news/4441.documentation +++ /dev/null @@ -1 +0,0 @@ -Update link to Yarn 3 Workspaces to avoid redirect to Yarn Classic 1.x. @stevepiercy diff --git a/news/4450.feature b/news/4450.feature deleted file mode 100644 index ae834b5e0e..0000000000 --- a/news/4450.feature +++ /dev/null @@ -1 +0,0 @@ -Add GHA Towncrier syntax checker @sneridagh diff --git a/news/4454.internal b/news/4454.internal deleted file mode 100644 index 252f249c29..0000000000 --- a/news/4454.internal +++ /dev/null @@ -1 +0,0 @@ -Use latest plone/server breed images @sneridagh diff --git a/package.json b/package.json index 793969442b..219cbae1b9 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "16.12.0", + "version": "16.13.0", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" diff --git a/packages/volto-slate/package.json b/packages/volto-slate/package.json index 300ba3bc9b..1275c1fb38 100644 --- a/packages/volto-slate/package.json +++ b/packages/volto-slate/package.json @@ -1,6 +1,6 @@ { "name": "@plone/volto-slate", - "version": "16.12.0", + "version": "16.13.0", "description": "Slate.js integration with Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", From e5416ce00c3c19e671b326ac98a1bd421db9d448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Fri, 3 Mar 2023 09:36:44 +0100 Subject: [PATCH 033/142] Teaser block in core (#3706) Co-authored-by: Steve Piercy Co-authored-by: David Glick --- cypress/tests/core/blocks/teaser.js | 49 ++++ cypress/tests/coresandbox/listingblock.js | 8 +- .../blocks/teaser-block-configuration.png | Bin 22668 -> 40930 bytes .../user-manual/blocks/teaser-block.png | Bin 14626 -> 32525 bytes docs/source/user-manual/blocks.md | 4 +- locales/ca/LC_MESSAGES/volto.po | 30 +++ locales/de/LC_MESSAGES/volto.po | 30 +++ locales/en/LC_MESSAGES/volto.po | 30 +++ locales/es/LC_MESSAGES/volto.po | 30 +++ locales/eu/LC_MESSAGES/volto.po | 30 +++ locales/fr/LC_MESSAGES/volto.po | 30 +++ locales/it/LC_MESSAGES/volto.po | 30 +++ locales/ja/LC_MESSAGES/volto.po | 30 +++ locales/nl/LC_MESSAGES/volto.po | 30 +++ locales/pt/LC_MESSAGES/volto.po | 30 +++ locales/pt_BR/LC_MESSAGES/volto.po | 30 +++ locales/ro/LC_MESSAGES/volto.po | 30 +++ locales/volto.pot | 32 ++- locales/zh_CN/LC_MESSAGES/volto.po | 30 +++ news/3706.feature | 1 + src/components/manage/Blocks/Teaser/Body.jsx | 30 +++ src/components/manage/Blocks/Teaser/Data.jsx | 71 ++++++ .../manage/Blocks/Teaser/DefaultBody.jsx | 89 +++++++ src/components/manage/Blocks/Teaser/Edit.jsx | 25 ++ src/components/manage/Blocks/Teaser/View.jsx | 9 + .../manage/Blocks/Teaser/adapter.js | 23 ++ src/components/manage/Blocks/Teaser/schema.js | 103 ++++++++ src/components/manage/Blocks/Teaser/utils.js | 44 ++++ .../manage/Blocks/Teaser/utils.test.jsx | 229 ++++++++++++++++++ src/config/Blocks.jsx | 28 +++ theme/themes/pastanaga/extras/blocks.less | 2 + theme/themes/pastanaga/extras/teaser.less | 166 +++++++++++++ 32 files changed, 1299 insertions(+), 4 deletions(-) create mode 100644 cypress/tests/core/blocks/teaser.js create mode 100644 news/3706.feature create mode 100644 src/components/manage/Blocks/Teaser/Body.jsx create mode 100644 src/components/manage/Blocks/Teaser/Data.jsx create mode 100644 src/components/manage/Blocks/Teaser/DefaultBody.jsx create mode 100644 src/components/manage/Blocks/Teaser/Edit.jsx create mode 100644 src/components/manage/Blocks/Teaser/View.jsx create mode 100644 src/components/manage/Blocks/Teaser/adapter.js create mode 100644 src/components/manage/Blocks/Teaser/schema.js create mode 100644 src/components/manage/Blocks/Teaser/utils.js create mode 100644 src/components/manage/Blocks/Teaser/utils.test.jsx create mode 100644 theme/themes/pastanaga/extras/teaser.less diff --git a/cypress/tests/core/blocks/teaser.js b/cypress/tests/core/blocks/teaser.js new file mode 100644 index 0000000000..60a4c13a4c --- /dev/null +++ b/cypress/tests/core/blocks/teaser.js @@ -0,0 +1,49 @@ +context('Blocks Acceptance Tests', () => { + beforeEach(() => { + cy.visit('/'); + cy.viewport('macbook-16'); + cy.createContent({ + contentType: 'Document', + contentId: 'document', + contentTitle: 'Document', + }); + cy.autologin(); + }); + + it('As editor I can add a (standalone) Teaser block', () => { + // GIVEN a Document with the title document and a Document to reference with the title Blue Orchidees + cy.createContent({ + contentType: 'Document', + contentId: 'blue-orchidees', + contentTitle: 'Blue Orchidees', + contentDescription: 'are growing on the mountain tops', + image: true, + path: '/document', + }); + cy.visit('/document/edit'); + // WHEN I create a Teaser block + cy.get('.block .slate-editor [contenteditable=true]').click(); + cy.get('.button .block-add-button').click({ force: true }); + cy.get('.blocks-chooser .mostUsed .button.teaser') + .contains('Teaser') + .click({ force: true }); + cy.get( + '.objectbrowser-field[aria-labelledby="fieldset-default-field-label-href"] button[aria-label="Open object browser"]', + ).click(); + cy.get('[aria-label="Select Blue Orchidees"]').dblclick(); + cy.wait(500); + cy.get('.align-buttons .ui.buttons button[aria-label="Center"]').click(); + cy.get('#toolbar-save').click(); + + // THEN I can see the Teaser block + cy.visit('/document'); + cy.get('.block.teaser').should('have.class', 'has--align--center'); + cy.get('.block.teaser .image-wrapper img') + .should('have.attr', 'src') + .and('include', '/document/blue-orchidees/@@images/preview_image-'); + cy.get('.block.teaser .content h2').contains('Blue Orchidees'); + cy.get('.block.teaser .content p').contains( + 'are growing on the mountain tops', + ); + }); +}); diff --git a/cypress/tests/coresandbox/listingblock.js b/cypress/tests/coresandbox/listingblock.js index a49dc6ad3e..01a665e515 100644 --- a/cypress/tests/coresandbox/listingblock.js +++ b/cypress/tests/coresandbox/listingblock.js @@ -43,7 +43,9 @@ context('Listing block tests', () => { cy.getSlate().click(); cy.get('button.block-add-button').click(); cy.get('.blocks-chooser .title').contains('Common').click(); - cy.get('.blocks-chooser .common').contains('Listing').click(); + cy.get('.blocks-chooser .common') + .contains('Listing') + .click({ force: true }); // select variation cy.get('#field-variation') @@ -91,7 +93,9 @@ context('Listing block tests', () => { cy.getSlate().click(); cy.get('button.block-add-button').click(); cy.get('.blocks-chooser .title').contains('Common').click(); - cy.get('.blocks-chooser .common').contains('Listing').click(); + cy.get('.blocks-chooser .common') + .contains('Listing') + .click({ force: true }); // select variation cy.get('#field-variation') diff --git a/docs/source/_static/user-manual/blocks/teaser-block-configuration.png b/docs/source/_static/user-manual/blocks/teaser-block-configuration.png index 84a7e4fb4f4884545372e5aa9f99afb79254a5db..55c21c78cda3581657188286b9bcf70b2f7ed014 100644 GIT binary patch literal 40930 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 RxQ7jr5|bA#eQogee*oDqpqT&w diff --git a/docs/source/user-manual/blocks.md b/docs/source/user-manual/blocks.md index ad2f3ed10a..9e4c744d4d 100644 --- a/docs/source/user-manual/blocks.md +++ b/docs/source/user-manual/blocks.md @@ -545,7 +545,7 @@ Target Title : The title is the title of the content item. -head title +Head title : The head title is a heading that appears above the title. Description @@ -554,6 +554,8 @@ Description Image override : The image override is either an existing image in your Plone site that can be selected by clicking the list icon, or an external URL of an image that can be typed into the text field and saved by clicking the right arrow when it appears after you start typing. +Alignment +: The alignment of the teaser image can be set to left (default), right, or top. (user-manual-teaser-grid-block-label)= diff --git a/locales/ca/LC_MESSAGES/volto.po b/locales/ca/LC_MESSAGES/volto.po index 95ef023613..c6806ec22e 100644 --- a/locales/ca/LC_MESSAGES/volto.po +++ b/locales/ca/LC_MESSAGES/volto.po @@ -296,6 +296,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -978,6 +979,7 @@ msgid "Descending" msgstr "Descendent" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1628,6 +1630,11 @@ msgstr "imatge" msgid "Image gallery" msgstr "Galeria d'imatges" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2302,6 +2309,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Obre en una pestanya nova" @@ -2396,6 +2404,11 @@ msgstr "Eines personals" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Responsables de la creació del contingut d'aquest article. Introduïu una llista de noms d'usuari, un per línia. El creador principal hauria de ser primer." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2666,6 +2679,11 @@ msgstr "Falta l'entrada necessària." msgid "Reset term title" msgstr "Restableix el títol" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3236,6 +3254,7 @@ msgstr "Etiquetes per afegir" msgid "Tags to remove" msgstr "Etiquetes per eliminar" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3261,6 +3280,11 @@ msgstr "Nombre objectiu d'objectes a la memòria per memòria cau" msgid "Target url path must start with a slash." msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3423,6 +3447,7 @@ msgid "Time" msgstr "Hora" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4122,6 +4147,11 @@ msgstr "quan" msgid "event_where" msgstr "On?" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/de/LC_MESSAGES/volto.po b/locales/de/LC_MESSAGES/volto.po index 752593787b..b75c33556e 100644 --- a/locales/de/LC_MESSAGES/volto.po +++ b/locales/de/LC_MESSAGES/volto.po @@ -293,6 +293,7 @@ msgstr "Alias wurde hinzugefügt" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -975,6 +976,7 @@ msgid "Descending" msgstr "Absteigend" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1625,6 +1627,11 @@ msgstr "Bild" msgid "Image gallery" msgstr "Bildergalerie" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "Bild überschreiben" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2299,6 +2306,7 @@ msgstr "Nur Kleinbuchstaben (a-z) ohne Umlaute oder Sonderzeichen, Zahlen (0-9) #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "In neuem Browser-Tab öffnen" @@ -2393,6 +2401,11 @@ msgstr "Persönliche Einstellungen" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Eine Liste von Personen, die an der Erstellung dieses Artikels beteiligt waren. Bitte geben Sie einen Benutzernamen pro Zeile ein. Der Hauptverantwortliche sollte zuerst genannt werden." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "Bitte wählen sie einen existierenden Inhalt als Quelle für dieses Element aus" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2663,6 +2676,11 @@ msgstr "Notwendige Eingabe fehlt." msgid "Reset term title" msgstr "Setze Titel zurück" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3233,6 +3251,7 @@ msgstr "Hinzuzufügende Tags" msgid "Tags to remove" msgstr "Zu entfernende Tags" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3258,6 +3277,11 @@ msgstr "Ziel-Anzahl von Objekten im Speicher pro Cache" msgid "Target url path must start with a slash." msgstr "Der Zielpfad muss mit einem Schrägstrich beginnen." +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3420,6 +3444,7 @@ msgid "Time" msgstr "Zeit" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4119,6 +4144,11 @@ msgstr "Datum" msgid "event_where" msgstr "Ort" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "Kopftitel" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/en/LC_MESSAGES/volto.po b/locales/en/LC_MESSAGES/volto.po index c016dd8240..b6762205e5 100644 --- a/locales/en/LC_MESSAGES/volto.po +++ b/locales/en/LC_MESSAGES/volto.po @@ -287,6 +287,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -969,6 +970,7 @@ msgid "Descending" msgstr "" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1619,6 +1621,11 @@ msgstr "" msgid "Image gallery" msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2293,6 +2300,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "" @@ -2387,6 +2395,11 @@ msgstr "" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "" +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2657,6 +2670,11 @@ msgstr "" msgid "Reset term title" msgstr "" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3227,6 +3245,7 @@ msgstr "" msgid "Tags to remove" msgstr "" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3252,6 +3271,11 @@ msgstr "" msgid "Target url path must start with a slash." msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3414,6 +3438,7 @@ msgid "Time" msgstr "" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4113,6 +4138,11 @@ msgstr "" msgid "event_where" msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/es/LC_MESSAGES/volto.po b/locales/es/LC_MESSAGES/volto.po index 8e2c45b45b..9fef3db528 100644 --- a/locales/es/LC_MESSAGES/volto.po +++ b/locales/es/LC_MESSAGES/volto.po @@ -298,6 +298,7 @@ msgstr "Alias añadido correctamente" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -980,6 +981,7 @@ msgid "Descending" msgstr "Descendente" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1630,6 +1632,11 @@ msgstr "Imagen" msgid "Image gallery" msgstr "Galería de imágenes" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2304,6 +2311,7 @@ msgstr "Solo letras minúsculas (a-z) sin tildes, números (0-9), y los caracter #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Abrir en un nueva pestaña" @@ -2398,6 +2406,11 @@ msgstr "Herramientas personales" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Las personas responsables de la creación del contenido de este elemento. Por favor, introduzca una lista de nombres de usuarios, uno por linea. El principal autor debe aparecer de primer lugar." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2668,6 +2681,11 @@ msgstr "Un campo requerido esta sin tomar en cuenta." msgid "Reset term title" msgstr "Limpiar el título del término" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3238,6 +3256,7 @@ msgstr "Categoría a agregar" msgid "Tags to remove" msgstr "Categoría a remover" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3263,6 +3282,11 @@ msgstr "Número objetivo de elementos en la memoria por caché" msgid "Target url path must start with a slash." msgstr "El camino de destino debe comenzar con /." +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3425,6 +3449,7 @@ msgid "Time" msgstr "Hora" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4124,6 +4149,11 @@ msgstr "Cuándo" msgid "event_where" msgstr "Dónde" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/eu/LC_MESSAGES/volto.po b/locales/eu/LC_MESSAGES/volto.po index 181828dac3..8ac00723de 100644 --- a/locales/eu/LC_MESSAGES/volto.po +++ b/locales/eu/LC_MESSAGES/volto.po @@ -294,6 +294,7 @@ msgstr "Aliasa ondo gehitu da" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -976,6 +977,7 @@ msgid "Descending" msgstr "Beheraka" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1626,6 +1628,11 @@ msgstr "Irudia" msgid "Image gallery" msgstr "Irudi galeria" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2300,6 +2307,7 @@ msgstr "Letra xeheak (a-z), karaktere berezi gabe, zenbakiak (0-9) eta "-", "_" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Fitxa berrian ireki" @@ -2394,6 +2402,11 @@ msgstr "Tresna pertsonalak" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Elementu honen edukia sortzearen arduradunak. Idatzi erabiltzaile-izen bat lerro bakoitzean. Egile nagusia lehenengoa izan beharko litzateke." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2664,6 +2677,11 @@ msgstr "Beharrezko balioak falta dira" msgid "Reset term title" msgstr "Berrezarri izenburua" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3234,6 +3252,7 @@ msgstr "Gehitu beharreko etiketak" msgid "Tags to remove" msgstr "Kendu beharreko etiketak" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3259,6 +3278,11 @@ msgstr "Katxe bakoitzaren elementu-kopurua" msgid "Target url path must start with a slash." msgstr "Helburuaren bidea / karakterearekin hasi behar da" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3421,6 +3445,7 @@ msgid "Time" msgstr "Ordua" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4120,6 +4145,11 @@ msgstr "Noiz" msgid "event_where" msgstr "Non" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/fr/LC_MESSAGES/volto.po b/locales/fr/LC_MESSAGES/volto.po index 051c376b02..9e99f2d228 100644 --- a/locales/fr/LC_MESSAGES/volto.po +++ b/locales/fr/LC_MESSAGES/volto.po @@ -304,6 +304,7 @@ msgstr "L'alias a été ajouté" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -986,6 +987,7 @@ msgid "Descending" msgstr "Descendant" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1636,6 +1638,11 @@ msgstr "Image" msgid "Image gallery" msgstr "Galerie d'images" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2310,6 +2317,7 @@ msgstr "Uniquement des caractères en minuscules (a-z) sans accents, chiffres (0 #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Ouvrir dans un nouvel onglet" @@ -2404,6 +2412,11 @@ msgstr "Outils personnelles" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Personnes responsables de la création du contenu de cet article. Veuillez entrer une liste de noms d'utilisateurs, un par ligne. Le créateur principal doit venir en premier." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2674,6 +2687,11 @@ msgstr "Un champ obligatoire est manquant" msgid "Reset term title" msgstr "Réinitialiser le titre" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3244,6 +3262,7 @@ msgstr "Mots clés à ajouter" msgid "Tags to remove" msgstr "Mots clés à supprimer" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3269,6 +3288,11 @@ msgstr "Nombre d'objets en mémoire par cache" msgid "Target url path must start with a slash." msgstr "Le chemin de destination d'URL doit commencer par une barre oblique." +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3431,6 +3455,7 @@ msgid "Time" msgstr "Temps" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4130,6 +4155,11 @@ msgstr "Quand" msgid "event_where" msgstr "Où" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/it/LC_MESSAGES/volto.po b/locales/it/LC_MESSAGES/volto.po index af8d24a1c4..3c7aa69e52 100644 --- a/locales/it/LC_MESSAGES/volto.po +++ b/locales/it/LC_MESSAGES/volto.po @@ -287,6 +287,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -969,6 +970,7 @@ msgid "Descending" msgstr "Decrescente" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1619,6 +1621,11 @@ msgstr "Immagine" msgid "Image gallery" msgstr "Galleria di immagini" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2293,6 +2300,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Apri in un nuovo tab" @@ -2387,6 +2395,11 @@ msgstr "Strumenti" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Persone responsabili della creazione del contenuto di questo elemento. Inserisci un elenco di nomi, uno per riga. L'autore principale dovrebbe essere messo al primo posto." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2657,6 +2670,11 @@ msgstr "Un campo richiesto è mancante." msgid "Reset term title" msgstr "Reimposta titolo del termine" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3227,6 +3245,7 @@ msgstr "Categorie da aggiungere" msgid "Tags to remove" msgstr "Categorie da rimuovere" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3252,6 +3271,11 @@ msgstr "Numero target di oggetti in memoria per cache" msgid "Target url path must start with a slash." msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3414,6 +3438,7 @@ msgid "Time" msgstr "Ora" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4113,6 +4138,11 @@ msgstr "Quando" msgid "event_where" msgstr "Dove" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/ja/LC_MESSAGES/volto.po b/locales/ja/LC_MESSAGES/volto.po index a8e118ed95..4879b4ffb2 100644 --- a/locales/ja/LC_MESSAGES/volto.po +++ b/locales/ja/LC_MESSAGES/volto.po @@ -295,6 +295,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -977,6 +978,7 @@ msgid "Descending" msgstr "降順" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1627,6 +1629,11 @@ msgstr "画像" msgid "Image gallery" msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2301,6 +2308,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "新しいタブで開く" @@ -2395,6 +2403,11 @@ msgstr "個人設定" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "このアイテムのコンテンツ作成責任者。リーダーを先頭にして、ユーザー名を1行に1名ずつ入力してください。" +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2665,6 +2678,11 @@ msgstr "必須" msgid "Reset term title" msgstr "" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3235,6 +3253,7 @@ msgstr "追加するタグ" msgid "Tags to remove" msgstr "削除をするタグ" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3260,6 +3279,11 @@ msgstr "キャッシュごとのメモリー上の最大オブジェクト数" msgid "Target url path must start with a slash." msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3422,6 +3446,7 @@ msgid "Time" msgstr "時刻" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4121,6 +4146,11 @@ msgstr "日時" msgid "event_where" msgstr "場所" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/nl/LC_MESSAGES/volto.po b/locales/nl/LC_MESSAGES/volto.po index d46cf17aa7..40b9a0c2b6 100644 --- a/locales/nl/LC_MESSAGES/volto.po +++ b/locales/nl/LC_MESSAGES/volto.po @@ -294,6 +294,7 @@ msgstr "Alias toegevoegd" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -976,6 +977,7 @@ msgid "Descending" msgstr "Aflopend" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1626,6 +1628,11 @@ msgstr "Afbeelding" msgid "Image gallery" msgstr "Afbeeldingsgallerij" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2300,6 +2307,7 @@ msgstr "Enkel kleine letters (a-z) zonder accenten, cijfers (0-9) en de karakter #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Openen in een nieuwe tab" @@ -2394,6 +2402,11 @@ msgstr "Persoonlijke tools" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Gebruikers die verantwoordelijk zijn voor de inhoud van dit item. De eindverantwoordelijke vermeld je als eerste." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2664,6 +2677,11 @@ msgstr "Verplichte waarde mist." msgid "Reset term title" msgstr "Title resetten" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3234,6 +3252,7 @@ msgstr "Toe te voegen tags" msgid "Tags to remove" msgstr "Te verwijderen tags" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3259,6 +3278,11 @@ msgstr "Aantal objecten van doel in geheugen per cache" msgid "Target url path must start with a slash." msgstr "URL pad van doel moet beginnen met een slash" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3421,6 +3445,7 @@ msgid "Time" msgstr "Tijd" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4120,6 +4145,11 @@ msgstr "Wanneer" msgid "event_where" msgstr "Waar" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/pt/LC_MESSAGES/volto.po b/locales/pt/LC_MESSAGES/volto.po index 8791945a97..7bf9d616b1 100644 --- a/locales/pt/LC_MESSAGES/volto.po +++ b/locales/pt/LC_MESSAGES/volto.po @@ -295,6 +295,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -977,6 +978,7 @@ msgid "Descending" msgstr "Descendente" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1627,6 +1629,11 @@ msgstr "Imagem" msgid "Image gallery" msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2301,6 +2308,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Abrir num novo separador" @@ -2395,6 +2403,11 @@ msgstr "" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Pessoas responsáveis pela criação de conteúdo deste item. Pro favor escreva uma lista de nomes de utilizador, um por linha. O criador principal deve estar em primeiro lugar." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2665,6 +2678,11 @@ msgstr "Falta informação obrigatória." msgid "Reset term title" msgstr "" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3235,6 +3253,7 @@ msgstr "Etiquetas a adicionar" msgid "Tags to remove" msgstr "Etiquetas a remover" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3260,6 +3279,11 @@ msgstr "" msgid "Target url path must start with a slash." msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3422,6 +3446,7 @@ msgid "Time" msgstr "" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4121,6 +4146,11 @@ msgstr "" msgid "event_where" msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/pt_BR/LC_MESSAGES/volto.po b/locales/pt_BR/LC_MESSAGES/volto.po index d011ec7915..e141cf9950 100644 --- a/locales/pt_BR/LC_MESSAGES/volto.po +++ b/locales/pt_BR/LC_MESSAGES/volto.po @@ -297,6 +297,7 @@ msgstr "Alternativa foi adicionada" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -979,6 +980,7 @@ msgid "Descending" msgstr "Descendente" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1629,6 +1631,11 @@ msgstr "Imagem" msgid "Image gallery" msgstr "Galeria de imagem" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2303,6 +2310,7 @@ msgstr "Apenas letras minúsculas (a-z) sem acentos, números (0-9), e os caract #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Abrir em uma nova aba" @@ -2397,6 +2405,11 @@ msgstr "Ferramentas pessoais" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Pessoas responsáveis pela criação do conteúdo deste item. Por favor, insira uma lista de nomes de usuário, um por linha. O autor principal deve vir primeiro." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2667,6 +2680,11 @@ msgstr "Falta informação obrigatória." msgid "Reset term title" msgstr "Redefinir o título do termo" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3237,6 +3255,7 @@ msgstr "Tags a serem adicionadas" msgid "Tags to remove" msgstr "Tags a serem removidas" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3262,6 +3281,11 @@ msgstr "Número de objetos na memória por cache" msgid "Target url path must start with a slash." msgstr "O caminho da URL de destino deve começar com uma barra." +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3424,6 +3448,7 @@ msgid "Time" msgstr "Hora" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4123,6 +4148,11 @@ msgstr "Quando" msgid "event_where" msgstr "Onde" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/ro/LC_MESSAGES/volto.po b/locales/ro/LC_MESSAGES/volto.po index 948b7f93ce..2ce98fa8d5 100644 --- a/locales/ro/LC_MESSAGES/volto.po +++ b/locales/ro/LC_MESSAGES/volto.po @@ -287,6 +287,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -969,6 +970,7 @@ msgid "Descending" msgstr "Descrescător" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1619,6 +1621,11 @@ msgstr "Imagine" msgid "Image gallery" msgstr "Galerie de imagini" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2293,6 +2300,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "Deschideți într-o fereastra nouă" @@ -2387,6 +2395,11 @@ msgstr "Instrumente personale" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "Persoane responsabile de crearea conținutului acestui articol. Vă rugăm să introduceți o listă cu numele de utilizator, unul pe fiecare linie. Creatorul principal ar trebui să vină pe primul loc." +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2657,6 +2670,11 @@ msgstr "Câmpul este obligatoriu." msgid "Reset term title" msgstr "Resetați titlul termenului" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3227,6 +3245,7 @@ msgstr "Etichete de adăugat" msgid "Tags to remove" msgstr "Etichete de eliminat" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3252,6 +3271,11 @@ msgstr "Numărul țintă de obiecte din memorie raportat la cache" msgid "Target url path must start with a slash." msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3414,6 +3438,7 @@ msgid "Time" msgstr "Oră" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4113,6 +4138,11 @@ msgstr "Data" msgid "event_where" msgstr "Locație" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/volto.pot b/locales/volto.pot index 913df8e339..61223a51ec 100644 --- a/locales/volto.pot +++ b/locales/volto.pot @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Plone\n" -"POT-Creation-Date: 2022-12-23T11:28:11.455Z\n" +"POT-Creation-Date: 2023-03-01T10:46:45.512Z\n" "Last-Translator: Plone i18n \n" "Language-Team: Plone i18n \n" "MIME-Version: 1.0\n" @@ -289,6 +289,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -971,6 +972,7 @@ msgid "Descending" msgstr "" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1621,6 +1623,11 @@ msgstr "" msgid "Image gallery" msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2295,6 +2302,7 @@ msgstr "" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "" @@ -2389,6 +2397,11 @@ msgstr "" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "" +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2659,6 +2672,11 @@ msgstr "" msgid "Reset term title" msgstr "" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3229,6 +3247,7 @@ msgstr "" msgid "Tags to remove" msgstr "" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3254,6 +3273,11 @@ msgstr "" msgid "Target url path must start with a slash." msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3416,6 +3440,7 @@ msgid "Time" msgstr "" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4115,6 +4140,11 @@ msgstr "" msgid "event_where" msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/locales/zh_CN/LC_MESSAGES/volto.po b/locales/zh_CN/LC_MESSAGES/volto.po index 87c2928252..5e39fce9ae 100644 --- a/locales/zh_CN/LC_MESSAGES/volto.po +++ b/locales/zh_CN/LC_MESSAGES/volto.po @@ -293,6 +293,7 @@ msgstr "别名已添加" #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar #: components/manage/Blocks/Maps/schema +#: components/manage/Blocks/Teaser/schema #: components/manage/Blocks/Video/schema # defaultMessage: Alignment msgid "Alignment" @@ -975,6 +976,7 @@ msgid "Descending" msgstr "降序" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/ContentTypes #: components/manage/Widgets/SchemaWidget #: components/manage/Widgets/SelectWidget @@ -1625,6 +1627,11 @@ msgstr "图像" msgid "Image gallery" msgstr "图像库" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Image override +msgid "Image override" +msgstr "" + #: components/manage/Blocks/Image/schema # defaultMessage: Image size msgid "Image size" @@ -2299,6 +2306,7 @@ msgstr "只允许不带读音号的小写字母(a-z),数字(0-9),和符号 #: components/manage/Blocks/Image/schema #: components/manage/Blocks/LeadImage/LeadImageSidebar +#: components/manage/Blocks/Teaser/schema # defaultMessage: Open in a new tab msgid "Open in a new tab" msgstr "在新标签中打开" @@ -2393,6 +2401,11 @@ msgstr "个人工具" msgid "Persons responsible for creating the content of this item. Please enter a list of user names, one per line. The principal creator should come first." msgstr "负责创建此条目内容的人员。请输入用户名列表,每行一个。主要创建者应放在首位。" +#: components/manage/Blocks/Teaser/DefaultBody +# defaultMessage: Please choose an existing content as source for this element +msgid "Please choose an existing content as source for this element" +msgstr "" + #: components/manage/Controlpanels/Controlpanels # defaultMessage: Please continue with the upgrade. msgid "Please continue with the upgrade." @@ -2663,6 +2676,11 @@ msgstr "缺少所需的输出。" msgid "Reset term title" msgstr "重新设置标题" +#: components/manage/Blocks/Teaser/Data +# defaultMessage: Reset the block +msgid "Reset the block" +msgstr "" + #: components/manage/Widgets/QuerystringWidget # defaultMessage: Results limit msgid "Results limit" @@ -3233,6 +3251,7 @@ msgstr "新增关键词" msgid "Tags to remove" msgstr "移除关键词" +#: components/manage/Blocks/Teaser/schema #: components/manage/Controlpanels/Aliases # defaultMessage: Target msgid "Target" @@ -3258,6 +3277,11 @@ msgstr "" msgid "Target url path must start with a slash." msgstr "目标url路径必须以斜杠开头。" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Teaser +msgid "Teaser" +msgstr "" + #: components/manage/Widgets/SchemaWidget # defaultMessage: Text msgid "Text" @@ -3420,6 +3444,7 @@ msgid "Time" msgstr "时间" #: components/manage/Blocks/HeroImageLeft/Edit +#: components/manage/Blocks/Teaser/schema #: components/manage/Contents/Contents #: components/manage/Contents/ContentsRenameModal #: components/manage/Controlpanels/ContentTypes @@ -4119,6 +4144,11 @@ msgstr "" msgid "event_where" msgstr "" +#: components/manage/Blocks/Teaser/schema +# defaultMessage: Head title +msgid "head_title" +msgstr "" + #: components/theme/PasswordReset/RequestPasswordReset # defaultMessage: Password reset confirmation sent msgid "heading_sent_password" diff --git a/news/3706.feature b/news/3706.feature new file mode 100644 index 0000000000..afcdeeef92 --- /dev/null +++ b/news/3706.feature @@ -0,0 +1 @@ +Add `Teaser` block @sneridagh diff --git a/src/components/manage/Blocks/Teaser/Body.jsx b/src/components/manage/Blocks/Teaser/Body.jsx new file mode 100644 index 0000000000..93504397d7 --- /dev/null +++ b/src/components/manage/Blocks/Teaser/Body.jsx @@ -0,0 +1,30 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import DefaultBody from './DefaultBody'; +import config from '@plone/volto/registry'; + +const TeaserBody = (props) => { + const { variation, data } = props; + + const hasType = data.href?.[0]?.['@type']; + + // Compatible with the previous version of the component registry + // and the Volto 16 one. + const BodyComponent = + (config?.getComponent && + hasType && + config.getComponent({ name: 'Teaser', dependencies: [hasType] }) + .component) || + variation?.template || + DefaultBody; + + return ; +}; + +TeaserBody.propTypes = { + data: PropTypes.objectOf(PropTypes.any).isRequired, + isEditMode: PropTypes.bool, + variation: PropTypes.string, +}; + +export default TeaserBody; diff --git a/src/components/manage/Blocks/Teaser/Data.jsx b/src/components/manage/Blocks/Teaser/Data.jsx new file mode 100644 index 0000000000..def9d23928 --- /dev/null +++ b/src/components/manage/Blocks/Teaser/Data.jsx @@ -0,0 +1,71 @@ +import React from 'react'; +import { defineMessages, useIntl } from 'react-intl'; +import { Button } from 'semantic-ui-react'; +import { BlockDataForm, Icon } from '@plone/volto/components'; +import { isEmpty } from 'lodash'; + +import trashSVG from '@plone/volto/icons/delete.svg'; + +const messages = defineMessages({ + resetTeaser: { + id: 'Reset the block', + defaultMessage: 'Reset the block', + }, +}); + +const TeaserData = (props) => { + const { block, blocksConfig, data, onChangeBlock } = props; + const intl = useIntl(); + + const reset = () => { + onChangeBlock(block, { + ...data, + href: '', + title: '', + description: '', + head_title: '', + }); + }; + + const isReseteable = + isEmpty(data.href) && !data.title && !data.description && !data.head_title; + + const HeaderActions = ( + + + + ); + + const schema = blocksConfig[data['@type']].blockSchema({ intl }); + const dataAdapter = blocksConfig[data['@type']].dataAdapter; + + return ( + { + dataAdapter({ + block, + data, + id, + onChangeBlock, + value, + }); + }} + onChangeBlock={onChangeBlock} + formData={data} + block={block} + blocksConfig={blocksConfig} + headerActions={HeaderActions} + /> + ); +}; + +export default TeaserData; diff --git a/src/components/manage/Blocks/Teaser/DefaultBody.jsx b/src/components/manage/Blocks/Teaser/DefaultBody.jsx new file mode 100644 index 0000000000..128d15f81f --- /dev/null +++ b/src/components/manage/Blocks/Teaser/DefaultBody.jsx @@ -0,0 +1,89 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Message } from 'semantic-ui-react'; +import { defineMessages, useIntl } from 'react-intl'; +import imageBlockSVG from '@plone/volto/components/manage/Blocks/Image/block-image.svg'; +import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers'; +import { getTeaserImageURL } from './utils'; +import { MaybeWrap } from '@plone/volto/components'; +import { UniversalLink } from '@plone/volto/components'; +import cx from 'classnames'; +import config from '@plone/volto/registry'; + +const messages = defineMessages({ + PleaseChooseContent: { + id: 'Please choose an existing content as source for this element', + defaultMessage: + 'Please choose an existing content as source for this element', + }, +}); + +const DefaultImage = (props) => {props.alt; + +const TeaserDefaultTemplate = (props) => { + const { className, data, isEditMode } = props; + const intl = useIntl(); + const href = data.href?.[0]; + const image = data.preview_image?.[0]; + const align = data?.styles?.align; + + const hasImageComponent = config.getComponent('Image').component; + const Image = config.getComponent('Image').component || DefaultImage; + const { openExternalLinkInNewTab } = config.settings; + const defaultImageSrc = + href && flattenToAppURL(getTeaserImageURL({ href, image, align })); + + return ( +
+ <> + {!href && isEditMode && ( + +
+ +

{intl.formatMessage(messages.PleaseChooseContent)}

+
+
+ )} + {href && ( + +
+ {(href.hasPreviewImage || href.image_field || image) && ( +
+ +
+ )} +
+ {data?.head_title && ( +
{data.head_title}
+ )} +

{data?.title}

+ {!data.hide_description &&

{data?.description}

} +
+
+
+ )} + +
+ ); +}; + +TeaserDefaultTemplate.propTypes = { + data: PropTypes.objectOf(PropTypes.any).isRequired, + isEditMode: PropTypes.bool, +}; + +export default TeaserDefaultTemplate; diff --git a/src/components/manage/Blocks/Teaser/Edit.jsx b/src/components/manage/Blocks/Teaser/Edit.jsx new file mode 100644 index 0000000000..64961374e0 --- /dev/null +++ b/src/components/manage/Blocks/Teaser/Edit.jsx @@ -0,0 +1,25 @@ +import React from 'react'; +import TeaserBody from './Body'; +import { SidebarPortal } from '@plone/volto/components'; +import TeaserData from './Data'; +import { withBlockExtensions } from '@plone/volto/helpers'; + +const TeaserEdit = (props) => { + const { data, onChangeBlock, block, selected } = props; + + return ( + <> + + + + + + ); +}; + +export default withBlockExtensions(TeaserEdit); diff --git a/src/components/manage/Blocks/Teaser/View.jsx b/src/components/manage/Blocks/Teaser/View.jsx new file mode 100644 index 0000000000..253be5b364 --- /dev/null +++ b/src/components/manage/Blocks/Teaser/View.jsx @@ -0,0 +1,9 @@ +import React from 'react'; +import TeaserBody from './Body'; +import { withBlockExtensions } from '@plone/volto/helpers'; + +const TeaserView = (props) => { + return ; +}; + +export default withBlockExtensions(TeaserView); diff --git a/src/components/manage/Blocks/Teaser/adapter.js b/src/components/manage/Blocks/Teaser/adapter.js new file mode 100644 index 0000000000..4f01bad5ef --- /dev/null +++ b/src/components/manage/Blocks/Teaser/adapter.js @@ -0,0 +1,23 @@ +import { isEmpty } from 'lodash'; + +export const TeaserBlockDataAdapter = ({ + block, + data, + id, + onChangeBlock, + value, +}) => { + let dataSaved = { + ...data, + [id]: value, + }; + if (id === 'href' && !isEmpty(value) && !data.title && !data.description) { + dataSaved = { + ...dataSaved, + title: value[0].Title, + description: value[0].Description, + head_title: value[0].head_title, + }; + } + onChangeBlock(block, dataSaved); +}; diff --git a/src/components/manage/Blocks/Teaser/schema.js b/src/components/manage/Blocks/Teaser/schema.js new file mode 100644 index 0000000000..66c243387d --- /dev/null +++ b/src/components/manage/Blocks/Teaser/schema.js @@ -0,0 +1,103 @@ +import { defineMessages } from 'react-intl'; +import { addStyling } from '@plone/volto/helpers/Extensions/withBlockSchemaEnhancer'; + +const messages = defineMessages({ + Target: { + id: 'Target', + defaultMessage: 'Target', + }, + imageOverride: { + id: 'Image override', + defaultMessage: 'Image override', + }, + openLinkInNewTab: { + id: 'Open in a new tab', + defaultMessage: 'Open in a new tab', + }, + title: { + id: 'Title', + defaultMessage: 'Title', + }, + description: { + id: 'Description', + defaultMessage: 'Description', + }, + head_title: { + id: 'head_title', + defaultMessage: 'Head title', + }, + teaser: { + id: 'Teaser', + defaultMessage: 'Teaser', + }, + align: { + id: 'Alignment', + defaultMessage: 'Alignment', + }, +}); + +export const TeaserSchema = ({ intl }) => { + const schema = { + title: intl.formatMessage(messages.teaser), + fieldsets: [ + { + id: 'default', + title: 'Default', + fields: ['href', 'title', 'head_title', 'description', 'preview_image'], + }, + ], + + properties: { + href: { + title: intl.formatMessage(messages.Target), + widget: 'object_browser', + mode: 'link', + selectedItemAttrs: [ + 'Title', + 'head_title', + 'Description', + 'hasPreviewImage', + 'image_field', + 'image_scales', + '@type', + ], + allowExternals: true, + }, + title: { + title: intl.formatMessage(messages.title), + }, + head_title: { + title: intl.formatMessage(messages.head_title), + }, + description: { + title: intl.formatMessage(messages.description), + widget: 'textarea', + }, + preview_image: { + title: intl.formatMessage(messages.imageOverride), + widget: 'object_browser', + mode: 'image', + allowExternals: true, + selectedItemAttrs: ['image_field', 'image_scales'], + }, + openLinkInNewTab: { + title: intl.formatMessage(messages.openLinkInNewTab), + type: 'boolean', + }, + }, + required: [], + }; + + addStyling({ schema, intl }); + + schema.properties.styles.schema.properties.align = { + widget: 'align', + title: intl.formatMessage(messages.align), + actions: ['left', 'right', 'center'], + default: 'left', + }; + + schema.properties.styles.schema.fieldsets[0].fields = ['align']; + + return schema; +}; diff --git a/src/components/manage/Blocks/Teaser/utils.js b/src/components/manage/Blocks/Teaser/utils.js new file mode 100644 index 0000000000..b820439a00 --- /dev/null +++ b/src/components/manage/Blocks/Teaser/utils.js @@ -0,0 +1,44 @@ +import { isInternalURL } from '@plone/volto/helpers'; +import config from '@plone/volto/registry'; + +export function getTeaserImageURL({ href, image, align }) { + // The default scale used in teasers is the 'teaser' scale + // except if it's customized otherwise in the teaser block settings + // or if the teaser is center (top) + const imageScale = + align === 'center' + ? 'great' + : config.blocks.blocksConfig['teaser'].imageScale || 'teaser'; + + if (image) { + // If the image is overriden locally in the teaser block + if (isInternalURL(image['@id'])) { + // If it's internal check if image_scales catalog info is present + if (image?.image_scales?.[image?.image_field]) { + return `${image['@id']}/${ + image.image_scales[image.image_field]?.[0].scales[imageScale] + ?.download || image.image_scales[image.image_field]?.[0].download + }`; + } else { + // If not, fallback to content scale URL shortcut + return `${image['@id']}/@@images/${image.image_field}/${imageScale}`; + } + } else { + // If it's external, return the plain URL + return image['@id']; + } + } else { + // If the image is not overriden + if (href?.image_scales?.[href?.image_field]) { + return `${href['@id']}/${ + href.image_scales[href.image_field]?.[0].scales[imageScale]?.download || + href.image_scales[href.image_field]?.[0].download + }`; + } else { + // If not, fallback to content scale URL shortcut + return `${href['@id']}/@@images/${ + href.image_field || 'preview_image' + }/${imageScale}`; + } + } +} diff --git a/src/components/manage/Blocks/Teaser/utils.test.jsx b/src/components/manage/Blocks/Teaser/utils.test.jsx new file mode 100644 index 0000000000..b9f4d52c32 --- /dev/null +++ b/src/components/manage/Blocks/Teaser/utils.test.jsx @@ -0,0 +1,229 @@ +import { getTeaserImageURL } from './utils'; +import config from '@plone/volto/registry'; + +beforeAll(() => { + config.blocks.blocksConfig.teaser = {}; + config.blocks.blocksConfig.teaser.imageScale = 'teaser'; +}); + +describe('getTeaserImageURL tests', () => { + it('getTeaserImageURL internal URL - no overriden', () => { + const align = 'left'; + const href = { + '@id': '/document', + image_field: 'preview_image', + image_scales: { + preview_image: [ + { + download: '@@images/default_original_URL', + scales: { + teaser: { + download: '@@images/teaser_scale_URL', + }, + }, + }, + ], + }, + }; + const image = undefined; + expect(getTeaserImageURL({ href, image, align })).toBe( + '/document/@@images/teaser_scale_URL', + ); + }); + + it('getTeaserImageURL internal URL - no overriden - no scale', () => { + const align = 'left'; + const href = { + '@id': '/document', + image_field: 'preview_image', + image_scales: { + preview_image: [ + { + download: '@@images/default_original_URL', + scales: {}, + }, + ], + }, + }; + const image = undefined; + expect(getTeaserImageURL({ href, image, align })).toBe( + '/document/@@images/default_original_URL', + ); + }); + + it('getTeaserImageURL internal URL - no overriden - no catalog image info', () => { + const align = 'left'; + const href = { + '@id': '/document', + image_field: 'image', + image_scales: { + preview_image: [ + { + download: '@@images/default_original_URL', + scales: {}, + }, + ], + }, + }; + const image = undefined; + expect(getTeaserImageURL({ href, image, align })).toBe( + '/document/@@images/image/teaser', + ); + }); + + it('getTeaserImageURL internal URL - no overriden - center', () => { + const align = 'center'; + const href = { + '@id': '/document', + image_field: 'preview_image', + image_scales: { + preview_image: [ + { + download: '@@images/default_original_URL', + scales: { + great: { + download: '@@images/great_scale_URL', + }, + teaser: { + download: '@@images/teaser_scale_URL', + }, + }, + }, + ], + }, + }; + const image = undefined; + expect(getTeaserImageURL({ href, image, align })).toBe( + '/document/@@images/great_scale_URL', + ); + }); + + it('getTeaserImageURL internal URL - no overriden - center - no great scale', () => { + const align = 'center'; + const href = { + '@id': '/document', + image_field: 'preview_image', + image_scales: { + preview_image: [ + { + download: '@@images/default_original_URL', + scales: { + teaser: { + download: '@@images/teaser_scale_URL', + }, + }, + }, + ], + }, + }; + const image = undefined; + expect(getTeaserImageURL({ href, image, align })).toBe( + '/document/@@images/default_original_URL', + ); + }); + + it('getTeaserImageURL internal URL - image overriden', () => { + const align = 'left'; + const href = { + '@id': '/document', + image_field: 'preview_image', + image_scales: { + preview_image: [ + { + download: '@@images/default_original_URL', + scales: { + teaser: { + download: '@@images/teaser_scale_URL', + }, + }, + }, + ], + }, + }; + const image = { + '@id': '/document/image', + image_field: 'image', + image_scales: { + image: [ + { + download: '@@images/overriden_image_default_original_URL', + scales: { + teaser: { + download: '@@images/overriden_image_teaser_scale_URL', + }, + }, + }, + ], + }, + }; + expect(getTeaserImageURL({ href, image, align })).toBe( + '/document/image/@@images/overriden_image_teaser_scale_URL', + ); + }); + + it('getTeaserImageURL internal URL - image overriden - center - no great scale', () => { + const align = 'center'; + const href = { + '@id': '/document', + image_field: 'preview_image', + image_scales: { + preview_image: [ + { + download: '@@images/default_original_URL', + scales: { + teaser: { + download: '@@images/teaser_scale_URL', + }, + }, + }, + ], + }, + }; + const image = { + '@id': '/document/image', + image_field: 'image', + image_scales: { + image: [ + { + download: '@@images/overriden_image_default_original_URL', + scales: { + teaser: { + download: '@@images/overriden_image_teaser_scale_URL', + }, + }, + }, + ], + }, + }; + expect(getTeaserImageURL({ href, image, align })).toBe( + '/document/image/@@images/overriden_image_default_original_URL', + ); + }); + + it('getTeaserImageURL internal URL - image overriden - external', () => { + const align = 'left'; + const href = { + '@id': '/document', + image_field: 'preview_image', + image_scales: { + preview_image: [ + { + download: '@@images/default_original_URL', + scales: { + teaser: { + download: '@@images/teaser_scale_URL', + }, + }, + }, + ], + }, + }; + const image = { + '@id': 'https://plone.org/document/image.png', + }; + + expect(getTeaserImageURL({ href, image, align })).toBe( + 'https://plone.org/document/image.png', + ); + }); +}); diff --git a/src/config/Blocks.jsx b/src/config/Blocks.jsx index b645b6a3ad..d7fe5a2b4b 100644 --- a/src/config/Blocks.jsx +++ b/src/config/Blocks.jsx @@ -42,6 +42,7 @@ import tableSVG from '@plone/volto/icons/table.svg'; import listingBlockSVG from '@plone/volto/icons/content-listing.svg'; import tocSVG from '@plone/volto/icons/list-bullet.svg'; import searchSVG from '@plone/volto/icons/zoom.svg'; +import imagesSVG from '@plone/volto/icons/images.svg'; import ImageGalleryListingBlockTemplate from '@plone/volto/components/manage/Blocks/Listing/ImageGallery'; import BlockSettingsSchema from '@plone/volto/components/manage/Blocks/Block/Schema'; @@ -73,6 +74,12 @@ import SearchBlockSchema from '@plone/volto/components/manage/Blocks/Search/sche import ToCVariations from '@plone/volto/components/manage/Blocks/ToC/variations'; +import TeaserViewBlock from '@plone/volto/components/manage/Blocks/Teaser/View'; +import TeaserEditBlock from '@plone/volto/components/manage/Blocks/Teaser/Edit'; +import TeaserBlockDefaultBody from '@plone/volto/components/manage/Blocks/Teaser/DefaultBody'; +import { TeaserSchema } from '@plone/volto/components/manage/Blocks/Teaser/schema'; +import { TeaserBlockDataAdapter } from '@plone/volto/components/manage/Blocks/Teaser/adapter'; + defineMessages({ title: { id: 'title', @@ -451,6 +458,27 @@ const blocksConfig = { }, }, }, + teaser: { + id: 'teaser', + title: 'Teaser', + icon: imagesSVG, + group: 'common', + view: TeaserViewBlock, + edit: TeaserEditBlock, + restricted: false, + mostUsed: true, + sidebarTab: 1, + blockSchema: TeaserSchema, + dataAdapter: TeaserBlockDataAdapter, + variations: [ + { + id: 'default', + isDefault: true, + title: 'Default', + template: TeaserBlockDefaultBody, + }, + ], + }, }; const requiredBlocks = ['title']; diff --git a/theme/themes/pastanaga/extras/blocks.less b/theme/themes/pastanaga/extras/blocks.less index eddd31fecd..c298319880 100644 --- a/theme/themes/pastanaga/extras/blocks.less +++ b/theme/themes/pastanaga/extras/blocks.less @@ -1176,3 +1176,5 @@ body.has-toolbar.has-sidebar-collapsed .ui.wrapper > .ui.inner.block.full { } } } + +@import 'teaser'; diff --git a/theme/themes/pastanaga/extras/teaser.less b/theme/themes/pastanaga/extras/teaser.less new file mode 100644 index 0000000000..ada561db6a --- /dev/null +++ b/theme/themes/pastanaga/extras/teaser.less @@ -0,0 +1,166 @@ +@teaser-images-aspect-ratio: var(--teaser-images-aspect-ratio, 16/9); +@teaser-images-object-position: var(--teaser-images-object-position, top left); + +.teaser-item { + display: flex; + color: rgba(0, 0, 0, 0.87); + + &.placeholder { + display: flex; + flex-direction: column; + align-items: center; + + img { + max-width: 300px; + height: auto; + align-self: center; + } + } + + p { + margin-bottom: 0; + text-align: left; + } + + &.default .image-wrapper { + margin-right: 25px; + + img { + max-width: 100%; + height: auto; + } + } +} + +.teaser-item.default { + .content { + width: 100%; + } +} + +.teaser-item .image-wrapper img { + width: 100%; + aspect-ratio: @teaser-images-aspect-ratio; + object-fit: cover; + object-position: @teaser-images-object-position; +} + +#page-document > .block.teaser { + padding: 25px 0; + + &.has--align--left, + &.has--align--right { + .teaser-item.default { + display: flex; + + .image-wrapper { + align-self: flex-start; + } + + @media only screen and (max-width: @largestMobileScreen) { + flex-direction: column !important; + + .image-wrapper { + margin-right: 0; + margin-bottom: 25px; + margin-left: 0; + + img { + width: 100%; + max-width: unset; + height: auto; + } + } + } + } + } + + &.has--align--left { + .teaser-item.default { + flex-direction: row; + + .image-wrapper { + margin-right: 20px; + margin-left: 0; + + @media only screen and (max-width: @largestMobileScreen) { + margin-right: 0; + margin-left: 0; + } + } + } + } + + &.has--align--right { + a .teaser-item.default { + flex-direction: row-reverse; + + .image-wrapper { + margin-right: 0; + margin-left: 20px; + + @media only screen and (max-width: @largestMobileScreen) { + margin-right: 0; + margin-left: 0; + } + } + } + } + + &.has--align--center { + .teaser-item.default { + display: block; + + a { + display: block; + } + + .image-wrapper { + margin-bottom: 25px; + } + } + } +} + +.block-editor-teaser.has--align--left .block.teaser, +.block-editor-teaser.has--align--right .block.teaser { + .teaser-item.default { + display: flex; + + .image-wrapper { + align-self: flex-start; + } + } +} + +.block-editor-teaser.has--align--left .block.teaser { + .teaser-item.default { + flex-direction: row; + + .image-wrapper { + margin-right: 20px; + margin-left: 0; + } + } +} + +.block-editor-teaser.has--align--right .block.teaser { + .teaser-item.default { + flex-direction: row-reverse; + + .image-wrapper { + margin-right: 0; + margin-left: 20px; + } + } +} + +.block-editor-teaser.has--align--center .block.teaser { + .teaser-item.default { + display: block; + + .image-wrapper { + margin: 0 0 25px 0; + } + } +} From 2b16db1bae6dd9a3331567fa600393b74ae9ab61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Fri, 3 Mar 2023 11:45:45 +0100 Subject: [PATCH 034/142] Release 16.14.0 (#4459) --- CHANGELOG.md | 7 +++++++ news/3706.feature | 1 - package.json | 2 +- packages/volto-slate/package.json | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) delete mode 100644 news/3706.feature diff --git a/CHANGELOG.md b/CHANGELOG.md index a9b6c52220..177e0acf57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ +## 16.14.0 (2023-03-03) + +### Feature + +- Add `Teaser` block @sneridagh [#3706](https://github.com/plone/volto/issues/3706) + + ## 16.13.0 (2023-03-02) ### Feature diff --git a/news/3706.feature b/news/3706.feature deleted file mode 100644 index afcdeeef92..0000000000 --- a/news/3706.feature +++ /dev/null @@ -1 +0,0 @@ -Add `Teaser` block @sneridagh diff --git a/package.json b/package.json index 219cbae1b9..054574179a 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "16.13.0", + "version": "16.14.0", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" diff --git a/packages/volto-slate/package.json b/packages/volto-slate/package.json index 1275c1fb38..ca624731aa 100644 --- a/packages/volto-slate/package.json +++ b/packages/volto-slate/package.json @@ -1,6 +1,6 @@ { "name": "@plone/volto-slate", - "version": "16.13.0", + "version": "16.14.0", "description": "Slate.js integration with Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", From b780de65a4f25d6c1d59b79675a19818c940f27d Mon Sep 17 00:00:00 2001 From: David Glick Date: Sat, 4 Mar 2023 01:01:41 -0800 Subject: [PATCH 035/142] Node 18 and webpack 5 support (#4086) Co-authored-by: Victor Fernandez de Alba Co-authored-by: Tiberiu Ichim --- .github/workflows/acceptance.yml | 95 +- .github/workflows/code-analysis.yml | 6 +- .github/workflows/unit.yml | 4 +- .storybook/main.js | 122 +- Makefile | 36 +- README.md | 29 +- __tests__/webpack-relative-resolver.test.js | 24 +- cypress.config.js | 2 +- cypress/support/commands.js | 14 +- cypress/support/guillotina.js | 4 +- cypress/support/reset-fixture.js | 4 +- cypress/support/upgradetests.js | 2 +- cypress/tests/core/basic/autologin.js | 2 +- cypress/tests/core/guillotina/autologin.js | 2 +- cypress/tests/coresandbox/autologin.js | 2 +- cypress/tests/guillotina/autologin.js | 2 +- cypress/tests/multilingual/autologin.js | 2 +- cypress/tests/workingCopy/autologin.js | 2 +- docker-compose.yml | 5 +- docs/source/getting-started/install.md | 12 +- docs/source/upgrade-guide/index.md | 23 + news/4086.breaking | 5 + package.json | 40 +- .../generators/addon/templates/Makefile | 8 +- .../generator-volto/generators/app/index.js | 17 +- .../generators/app/templates/Makefile | 10 +- .../generators/app/templates/package.json.tpl | 2 +- packages/generator-volto/package.json | 7 +- packages/generator-volto/yarn.lock | 253 +- razzle.config.js | 6 +- .../manage/Controlpanels/VersionOverview.jsx | 16 +- src/components/manage/Diff/DiffField.jsx | 12 +- .../theme/FormattedDate/FormattedDate.jsx | 6 +- src/express-middleware/sitemap.js | 2 +- src/helpers/Utils/Date.js | 6 +- src/helpers/Utils/Date.test.js | 4 +- src/helpers/index.js | 1 - webpack-plugins/webpack-relative-resolver.js | 52 +- webpack-plugins/webpack-root-resolver.js | 39 +- webpack-plugins/webpack-svg-plugin.js | 15 +- yarn.lock | 2117 ++++++----------- 41 files changed, 1206 insertions(+), 1806 deletions(-) create mode 100644 news/4086.breaking diff --git a/.github/workflows/acceptance.yml b/.github/workflows/acceptance.yml index 72ee3a5718..2457e48980 100644 --- a/.github/workflows/acceptance.yml +++ b/.github/workflows/acceptance.yml @@ -6,8 +6,9 @@ jobs: name: Core Basic timeout-minutes: 45 strategy: + fail-fast: false matrix: - node-version: [14.x, 16.x] + node-version: [16.x, 18.x] steps: - uses: actions/checkout@v3 @@ -22,7 +23,7 @@ jobs: - run: yarn --immutable - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -39,7 +40,7 @@ jobs: start: | make start-test-acceptance-server make start-test-acceptance-frontend - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -59,8 +60,9 @@ jobs: name: Core Blocks timeout-minutes: 35 strategy: + fail-fast: false matrix: - node-version: [14.x, 16.x] + node-version: [16.x, 18.x] steps: - uses: actions/checkout@v3 @@ -75,7 +77,7 @@ jobs: - run: yarn --immutable - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -92,7 +94,7 @@ jobs: start: | make start-test-acceptance-server make start-test-acceptance-frontend - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -112,8 +114,9 @@ jobs: name: Core Volto Slate timeout-minutes: 45 strategy: + fail-fast: false matrix: - node-version: [14.x, 16.x] + node-version: [16.x, 18.x] steps: - uses: actions/checkout@v3 @@ -128,7 +131,7 @@ jobs: - run: yarn --frozen-lockfile - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -145,7 +148,7 @@ jobs: start: | make start-test-acceptance-server make start-test-acceptance-frontend - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -164,8 +167,9 @@ jobs: runs-on: ubuntu-latest name: Core Basic - Plone 5 strategy: + fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] steps: - uses: actions/checkout@v3 @@ -180,7 +184,7 @@ jobs: - run: yarn --immutable - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -197,7 +201,7 @@ jobs: start: | make start-test-acceptance-server-5 make start-test-acceptance-frontend - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -217,9 +221,9 @@ jobs: name: Coresandbox timeout-minutes: 35 strategy: + fail-fast: false matrix: - node-version: [16.x] - python-version: [3.7] + node-version: [18.x] steps: - uses: actions/checkout@v3 @@ -232,32 +236,8 @@ jobs: - run: yarn --immutable - # python setup (temporary, while p.volto coresandbox changes are in a PR) - # - name: Set up Python ${{ matrix.python-version }} - # uses: actions/setup-python@v1 - # with: - # python-version: ${{ matrix.python-version }} - - # # python cache - # - uses: actions/cache@v1 - # with: - # path: ~/.cache/pip - # key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - # restore-keys: | - # ${{ runner.os }}-pip- - # # python install - # - run: pip install virtualenv - # - name: pip install - # working-directory: api - # run: pip install -r requirements.txt - # - name: buildout - # working-directory: api - # run: buildout - # env: - # CI: true - - name: Cypress Coresandbox Acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -274,7 +254,7 @@ jobs: start: | make start-test-acceptance-server-coresandbox make start-test-acceptance-frontend-coresandbox - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -294,8 +274,9 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 35 strategy: + fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] steps: - uses: actions/checkout@v3 @@ -310,7 +291,7 @@ jobs: - run: yarn --immutable - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_API: guillotina @@ -328,7 +309,7 @@ jobs: start: | make start-test-acceptance-server-guillotina make start-test-acceptance-frontend-guillotina - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:8081 http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:8081 http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -348,8 +329,9 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 35 strategy: + fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] steps: - uses: actions/checkout@v3 @@ -364,7 +346,7 @@ jobs: - run: yarn --immutable - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -381,7 +363,7 @@ jobs: start: | make start-test-acceptance-server-multilingual make start-test-acceptance-frontend-multilingual - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -401,8 +383,9 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 35 strategy: + fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] # python-version: [3.7] steps: - uses: actions/checkout@v3 @@ -442,7 +425,7 @@ jobs: # CI: true - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -459,7 +442,7 @@ jobs: start: | make start-test-acceptance-server-workingcopy make start-test-acceptance-frontend-workingcopy - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -479,8 +462,9 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 35 strategy: + fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] env: generator-directory: ./packages/generator-volto project-directory: ./my-volto-app @@ -530,7 +514,7 @@ jobs: working-directory: ${{env.project-directory}} - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -547,7 +531,7 @@ jobs: start: | make start-test-acceptance-server make start-test-acceptance-frontend-project - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 @@ -573,8 +557,9 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 35 strategy: + fail-fast: false matrix: - node-version: [16.x] + node-version: [18.x] steps: - uses: actions/checkout@v3 @@ -589,7 +574,7 @@ jobs: - run: yarn --immutable - name: Cypress acceptance tests - uses: cypress-io/github-action@v4 + uses: cypress-io/github-action@v5 env: BABEL_ENV: production CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} @@ -608,7 +593,7 @@ jobs: make start-test-acceptance-server make start-test-acceptance-frontend-seamless make start-test-acceptance-webserver-seamless - wait-on: 'npx wait-on --httpTimeout 20000 http-get://localhost:55001/plone http://localhost:3000 http://localhost' + wait-on: 'npx wait-on --httpTimeout 20000 http-get://127.0.0.1:55001/plone http://127.0.0.1:3000 http://localhost' # Upload Cypress screenshots - uses: actions/upload-artifact@v1 diff --git a/.github/workflows/code-analysis.yml b/.github/workflows/code-analysis.yml index a358cc3303..66ad61e73b 100644 --- a/.github/workflows/code-analysis.yml +++ b/.github/workflows/code-analysis.yml @@ -6,7 +6,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - uses: actions/checkout@v3 @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - uses: actions/checkout@v3 @@ -50,7 +50,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 3f75baa2ba..36880bd257 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -5,8 +5,9 @@ jobs: name: Core Unit Tests runs-on: ubuntu-latest strategy: + fail-fast: false matrix: - node-version: [14.x, 16.x] + node-version: [16.x, 18.x] steps: - uses: actions/checkout@v3 @@ -28,4 +29,3 @@ jobs: - uses: jackyef/bundlewatch-gh-action@master with: bundlewatch-github-token: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }} - diff --git a/.storybook/main.js b/.storybook/main.js index 877714c064..7109389c34 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -3,14 +3,10 @@ const fs = require('fs'); const path = require('path'); const makeLoaderFinder = require('razzle-dev-utils/makeLoaderFinder'); const fileLoaderFinder = makeLoaderFinder('file-loader'); - const projectRootPath = path.resolve('.'); -const createAddonsLoader = require('../create-addons-loader'); const lessPlugin = require('../webpack-plugins/webpack-less-plugin'); - const createConfig = require('../node_modules/razzle/config/createConfigAsync.js'); const razzleConfig = require(path.join(projectRootPath, 'razzle.config.js')); - const SVGLOADER = { test: /icons\/.*\.svg$/, use: [ @@ -21,16 +17,22 @@ const SVGLOADER = { loader: 'svgo-loader', options: { plugins: [ - { removeTitle: true }, - { convertPathData: false }, - { removeUselessStrokeAndFill: true }, - { removeViewBox: false }, + { + name: 'preset-default', + params: { + overrides: { + convertPathData: false, + removeViewBox: false, + }, + }, + }, + 'removeTitle', + 'removeUselessStrokeAndFill', ], }, }, ], }; - const defaultRazzleOptions = { verbose: false, debug: {}, @@ -46,98 +48,80 @@ const defaultRazzleOptions = { staticCssInDev: false, emitOnErrors: false, disableWebpackbar: false, - browserslist: [ - '>1%', - 'last 4 versions', - 'Firefox ESR', - 'not ie 11', - 'not dead', - ], + browserslist: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie 11', 'not dead'] }; - module.exports = { stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: ['@storybook/addon-links', '@storybook/addon-essentials'], staticDirs: ['./static'], - webpackFinal: async (config, { configType }) => { + webpackFinal: async (config, { + configType + }) => { // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION' // You can change the configuration based on that. // 'PRODUCTION' is used when building the static version of storybook. // Make whatever fine-grained changes you need let baseConfig; - baseConfig = await createConfig( - 'web', - 'dev', - { - // clearConsole: false, - modifyWebpackConfig: razzleConfig.modifyWebpackConfig, - plugins: razzleConfig.plugins, - }, - webpack, - false, - undefined, - [], - defaultRazzleOptions, - ); + baseConfig = await createConfig('web', 'dev', { + // clearConsole: false, + modifyWebpackConfig: razzleConfig.modifyWebpackConfig, + plugins: razzleConfig.plugins + }, webpack, false, undefined, [], defaultRazzleOptions); const AddonConfigurationRegistry = require('../addon-registry'); - const registry = new AddonConfigurationRegistry(projectRootPath); - - config = lessPlugin({ registry }).modifyWebpackConfig({ - env: { target: 'web', dev: 'dev' }, + config = lessPlugin({ + registry + }).modifyWebpackConfig({ + env: { + target: 'web', + dev: 'dev' + }, webpackConfig: config, webpackObject: webpack, - options: {}, + options: {} }); - // putting SVG loader on top, fix the fileloader manually (Volto plugin does not - // work) since it needs to go first + // Put the SVG loader on top and prevent the asset/resource rule + // from processing the app's SVGs config.module.rules.unshift(SVGLOADER); - const fileLoader = config.module.rules.find(fileLoaderFinder); - fileLoader.exclude = [/\.(config|variables|overrides)$/, /icons\/.*\.svg$/]; - - config.plugins.unshift( - new webpack.DefinePlugin({ - __DEVELOPMENT__: true, - __CLIENT__: true, - __SERVER__: false, - }), - ); - + const fileLoaderRule = config.module.rules.find(rule => rule.test.test('.svg')); + fileLoaderRule.exclude = /icons\/.*\.svg$/; + config.plugins.unshift(new webpack.DefinePlugin({ + __DEVELOPMENT__: true, + __CLIENT__: true, + __SERVER__: false + })); const resultConfig = { ...config, resolve: { ...config.resolve, - alias: { ...config.resolve.alias, ...baseConfig.resolve.alias }, - }, + alias: { + ...config.resolve.alias, + ...baseConfig.resolve.alias + } + } }; // Addons have to be loaded with babel - const addonPaths = registry.addonNames.map((addon) => - fs.realpathSync(registry.packages[addon].modulePath), - ); - resultConfig.module.rules[1].exclude = (input) => + const addonPaths = registry.addonNames.map(addon => fs.realpathSync(registry.packages[addon].modulePath)); + resultConfig.module.rules[1].exclude = input => // exclude every input from node_modules except from @plone/volto /node_modules\/(?!(@plone\/volto)\/)/.test(input) && // If input is in an addon, DON'T exclude it - !addonPaths.some((p) => input.includes(p)); - + !addonPaths.some(p => input.includes(p)); return resultConfig; }, - babel: async (options) => { + babel: async options => { return { ...options, - plugins: [ - ...options.plugins, - [ - './node_modules/babel-plugin-root-import/build/index.js', - { - rootPathSuffix: './src', - }, - ], - ], + plugins: [...options.plugins, ['./node_modules/babel-plugin-root-import/build/index.js', { + rootPathSuffix: './src' + }]] // any extra options you want to set }; }, -}; + core: { + builder: 'webpack5' + } +}; \ No newline at end of file diff --git a/Makefile b/Makefile index 226f1da0d2..6ef4a70b87 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,8 @@ NODEBIN = ./node_modules/.bin SCRIPTSPACKAGE = ./packages/scripts # Plone 5 legacy -DOCKER_IMAGE5=plone/plone-backend:5.2.9 -KGS5=plone.restapi==8.35.1 plone.volto==4.0.7 plone.rest==3.0.0 +DOCKER_IMAGE5=plone/plone-backend:5.2.10 +KGS5=plone.restapi==8.35.0 plone.volto==4.0.7 plone.rest==3.0.0 TESTING_ADDONS=plone.app.robotframework==2.0.0 plone.app.testing==7.0.0 # Sphinx variables @@ -86,7 +86,7 @@ build: .PHONY: build-frontend build-frontend: - yarn && RAZZLE_API_PATH=http://localhost:55001/plone yarn build + yarn && RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn build .PHONY: build-backend build-backend: ## Build Plone 5.2 @@ -203,7 +203,7 @@ start-test-all: ## Start Test .PHONY: start-test-frontend start-test-frontend: ## Start Test Volto Frontend @echo "$(GREEN)==> Start Test Volto Frontend$(RESET)" - RAZZLE_API_PATH=http://localhost:55001/plone yarn build && NODE_ENV=production yarn start:prod + RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn build && NODE_ENV=production yarn start:prod .PHONY: start-test-backend start-test-backend: ## Start Test Plone Backend (api folder) @@ -222,7 +222,7 @@ test-acceptance-server-old: .PHONY: start-test-acceptance-frontend-dev start-test-acceptance-frontend-dev: ## Start the Core Acceptance Frontend Fixture in dev mode - RAZZLE_API_PATH=http://localhost:55001/plone yarn start + RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn start ######### Core Acceptance tests @@ -232,7 +232,7 @@ start-test-acceptance-server test-acceptance-server: ## Start Test Acceptance Se .PHONY: start-test-acceptance-frontend start-test-acceptance-frontend: ## Start the Core Acceptance Frontend Fixture - RAZZLE_API_PATH=http://localhost:55001/plone yarn build && yarn start:prod + RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn build && yarn start:prod .PHONY: test-acceptance test-acceptance: ## Start Core Cypress Acceptance Tests @@ -244,7 +244,7 @@ test-acceptance-headless: ## Start Core Cypress Acceptance Tests in headless mod .PHONY: full-test-acceptance full-test-acceptance: ## Runs Core Full Acceptance Testing in headless mode - $(NODEBIN)/start-test "make start-test-acceptance-server" http-get://localhost:55001/plone "make start-test-acceptance-frontend" http://localhost:3000 "make test-acceptance-headless" + $(NODEBIN)/start-test "make start-test-acceptance-server" http-get://127.0.0.1:55001/plone "make start-test-acceptance-frontend" http://127.0.0.1:3000 "make test-acceptance-headless" ######### Seamless Core Acceptance tests @@ -262,13 +262,13 @@ start-test-acceptance-webserver-seamless: ## Start the seamless webserver .PHONY: full-test-acceptance-seamless full-test-acceptance-seamless: ## Runs Seamless Core Full Acceptance Testing in headless mode - $(NODEBIN)/start-test "make start-test-acceptance-server" http-get://localhost:55001/plone "make start-test-acceptance-frontend-seamless" http://localhost:3000 "make test-acceptance-headless" + $(NODEBIN)/start-test "make start-test-acceptance-server" http-get://127.0.0.1:55001/plone "make start-test-acceptance-frontend-seamless" http://127.0.0.1:3000 "make test-acceptance-headless" ######### Project Acceptance tests .PHONY: start-test-acceptance-frontend-project start-test-acceptance-frontend-project: ## Start the Project Acceptance Frontend Fixture - cd my-volto-app && RAZZLE_API_PATH=http://localhost:55001/plone yarn build && yarn start:prod + cd my-volto-app && RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn build && yarn start:prod ######### CoreSandbox Acceptance tests @@ -279,11 +279,11 @@ start-test-acceptance-server-coresandbox test-acceptance-server-coresandbox: ## .PHONY: start-test-acceptance-frontend-coresandbox start-test-acceptance-frontend-coresandbox: ## Start the CoreSandbox Acceptance Frontend Fixture - ADDONS=coresandbox RAZZLE_API_PATH=http://localhost:55001/plone yarn build && yarn start:prod + ADDONS=coresandbox RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn build && yarn start:prod .PHONY: start-test-acceptance-frontend-coresandbox-dev start-test-acceptance-frontend-coresandbox-dev: ## Start the CoreSandbox Acceptance Frontend Fixture in dev mode - ADDONS=coresandbox RAZZLE_API_PATH=http://localhost:55001/plone yarn start + ADDONS=coresandbox RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn start .PHONY: test-acceptance-coresandbox test-acceptance-coresandbox: ## Start CoreSandbox Cypress Acceptance Tests @@ -295,7 +295,7 @@ test-acceptance-coresandbox-headless: ## Start CoreSandbox Cypress Acceptance Te .PHONY: full-test-acceptance-coresandbox full-test-acceptance-coresandbox: ## Runs CoreSandbox Full Acceptance Testing in headless mode - $(NODEBIN)/start-test "make start-test-acceptance-server-coresandbox" http-get://localhost:55001/plone "make start-test-acceptance-frontend-coresandbox" http://localhost:3000 "make test-acceptance-coresandbox-headless" + $(NODEBIN)/start-test "make start-test-acceptance-server-coresandbox" http-get://127.0.0.1:55001/plone "make start-test-acceptance-frontend-coresandbox" http://127.0.0.1:3000 "make test-acceptance-coresandbox-headless" ######### Multilingual Acceptance tests @@ -305,7 +305,7 @@ start-test-acceptance-server-multilingual test-acceptance-server-multilingual: # .PHONY: start-test-acceptance-frontend-multilingual start-test-acceptance-frontend-multilingual: ## Start the Multilingual Acceptance Frontend Fixture - ADDONS=coresandbox:multilingualFixture RAZZLE_API_PATH=http://localhost:55001/plone yarn build && yarn start:prod + ADDONS=coresandbox:multilingualFixture RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn build && yarn start:prod .PHONY: test-acceptance-multilingual test-acceptance-multilingual: ## Start Multilingual Cypress Acceptance Tests @@ -317,7 +317,7 @@ test-acceptance-multilingual-headless: ## Start Multilingual Cypress Acceptance .PHONY: full-test-acceptance-multilingual full-test-acceptance-multilingual: ## Runs Multilingual Full Acceptance Testing in headless mode - $(NODEBIN)/start-test "make start-test-acceptance-server-multilingual" http-get://localhost:55001/plone "make start-test-acceptance-frontend-multilingual" http://localhost:3000 "make test-acceptance-multilingual-headless" + $(NODEBIN)/start-test "make start-test-acceptance-server-multilingual" http-get://127.0.0.1:55001/plone "make start-test-acceptance-frontend-multilingual" http://127.0.0.1:3000 "make test-acceptance-multilingual-headless" ######### WorkingCopy Acceptance tests @@ -328,7 +328,7 @@ start-test-acceptance-server-workingcopy test-acceptance-server-workingcopy : ## .PHONY: start-test-acceptance-frontend-workingcopy start-test-acceptance-frontend-workingcopy: ## Start the WorkingCopy Acceptance Frontend Fixture - ADDONS=coresandbox:workingCopyFixture RAZZLE_API_PATH=http://localhost:55001/plone yarn build && yarn start:prod + ADDONS=coresandbox:workingCopyFixture RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn build && yarn start:prod .PHONY: test-acceptance-workingcopy test-acceptance-workingcopy: ## Start WorkingCopy Cypress Acceptance Tests @@ -340,7 +340,7 @@ test-acceptance-workingcopy-headless: ## Start WorkingCopy Cypress Acceptance Te .PHONY: full-test-acceptance-workingcopy full-test-acceptance-workingcopy: ## Runs WorkingCopy Full Acceptance Testing in headless mode - $(NODEBIN)/start-test "make start-test-acceptance-server-workingcopy" http-get://localhost:55001/plone "make start-test-acceptance-frontend-workingcopy" http://localhost:3000 "make test-acceptance-workingcopy-headless" + $(NODEBIN)/start-test "make start-test-acceptance-server-workingcopy" http-get://127.0.0.1:55001/plone "make start-test-acceptance-frontend-workingcopy" http://127.0.0.1:3000 "make test-acceptance-workingcopy-headless" ######### Guillotina Acceptance tests @@ -350,7 +350,7 @@ start-test-acceptance-server-guillotina: ## Start Guillotina Test Acceptance Ser .PHONY: start-test-acceptance-frontend-guillotina start-test-acceptance-frontend-guillotina: ## Start the Guillotina Acceptance Frontend Fixture - ADDONS=volto-guillotina RAZZLE_API_PATH=http://localhost:8081/db/web RAZZLE_LEGACY_TRAVERSE=true yarn build && yarn start:prod + ADDONS=volto-guillotina RAZZLE_API_PATH=http://127.0.0.1:8081/db/web RAZZLE_LEGACY_TRAVERSE=true yarn build && yarn start:prod .PHONY: test-acceptance-guillotina test-acceptance-guillotina: ## Start the Guillotina Cypress Acceptance Tests @@ -362,7 +362,7 @@ test-acceptance-guillotina-headless: ## Start the Guillotina Cypress Acceptance .PHONY: full-test-acceptance-guillotina full-test-acceptance-guillotina: ## Runs the Guillotina Full Acceptance Testing in headless mode - $(NODEBIN)/start-test "make start-test-acceptance-server-guillotina" http-get://localhost:8081 "make start-test-acceptance-frontend-guillotina" http://localhost:3000 "make test-acceptance-guillotina-headless" + $(NODEBIN)/start-test "make start-test-acceptance-server-guillotina" http-get://127.0.0.1:8081 "make start-test-acceptance-frontend-guillotina" http://127.0.0.1:3000 "make test-acceptance-guillotina-headless" ######### Plone 5 Acceptance tests diff --git a/README.md b/README.md index d0c8275c42..c76079a98f 100644 --- a/README.md +++ b/README.md @@ -53,20 +53,16 @@ First get all the requirements installed on your system. ### Prerequisites -- [Node.js LTS (16.x)](https://nodejs.org/) +- [Node.js LTS (18.x)](https://nodejs.org/) - [Python](https://python.org/) - See below for specific versions. - [Docker](https://www.docker.com/get-started) (if using the Plone docker images) -*UPDATE 2022-10-25*: Since 2022-10-25, NodeJS 18 is in LTS state (https://github.com/nodejs/release#release-schedule). However, due to changes in internal SSL libraries, some Volto dependencies have been deprecated and need to be updated in order to continue working in NodeJS 18, mainly Webpack 4 (see: https://github.com/webpack/webpack/issues/14532#issuecomment-947525539 for further information). You can still use it, but NodeJS should be run under a special flag: `NODE_OPTIONS=--openssl-legacy-provider`. See also Volto's PR: https://github.com/plone/volto/pull/3699 for more information. - The versions of Python that are supported in Volto depend on the version of Plone that you use. | Plone | Python | Volto | |---|---|---| | 5.2 | 2.7, 3.6-3.8 | 15.0 | -| 6.0 (beta) | 3.8-3.10 | 16.0 (alpha) | - -At the time of this writing, Volto 16 is still in alpha status, and Plone 6 is in beta status. +| 6.0 | 3.8-3.11 | 16.0 | ### Create a Volto project using the generator @@ -90,7 +86,7 @@ cd myvoltoproject You can bootstrap a ready Docker Plone container with all the dependencies and ready for Volto use. We recommend to use the Plone docker builds based in `pip` [plone/plone-backend](https://github.com/plone/plone-backend) image: ```shell -docker run -it --rm --name=plone -p 8080:8080 -e SITE=Plone -e PROFILES="plone.volto:default-homepage" plone/plone-backend:6.0.0b3 +docker run -it --rm --name=plone -p 8080:8080 -e SITE=Plone -e PROFILES="plone.volto:default-homepage" plone/plone-backend:6.0.1 ``` or as an alternative if you have experience with Plone and you have all the @@ -105,7 +101,7 @@ make build-backend Volto is the default UI for Plone 6, so it will work for all Plone 6 released versions. -For the Plone 5 series, the latest released version of Plone 5 (with Python 3) is recommended (at the time of writing 5.2.9). +For the Plone 5 series, the latest released version of Plone 5 (with Python 3) is recommended (at the time of writing 5.2.10). #### KGS (known good set of versions) for backend packages @@ -113,14 +109,14 @@ On Plone 6, we recommend using the known good set (KGS) of package versions that On Plone 5, Volto is currently tested with the following packages pinned to specific versions, and we recommend using the same versions, which are: -- plone.restapi 8.30.0 -- plone.rest 2.0.0a5 -- plone.volto 4.0.0a13 +- plone.restapi 8.32.6 +- plone.rest 2.0.0 +- plone.volto 4.0.3 This would be the docker command to spawn a Plone 5 container with the right KGS versions: ```shell -docker run -it --rm --name=plone -p 8080:8080 -e SITE=Plone -e ADDONS="plone.restapi==8.30.0 plone.volto==4.0.0a13 plone.rest==2.0.0a5 plone.app.iterate==4.0.2 plone.app.vocabularies==4.3.0" -e PROFILES="plone.volto:default-homepage" plone/plone-backend +docker run -it --rm --name=plone -p 8080:8080 -e SITE=Plone -e ADDONS="plone.restapi==8.32.6 plone.volto==4.0.3 plone.rest==2.0.0" -e PROFILES="plone.volto:default-homepage" plone/plone-backend ``` ### Start Volto @@ -234,10 +230,11 @@ JavaScript-centered trainings. ## Node Support +- Node 18: Supported since Volto 17 - Node 16: Supported since Volto 14 -- Node 14: Supported since Volto 8.8.0 -- Node 12: Deprecated from Volto 16 onwards. It was supported since Volto 4 -- Node 10: Deprecated from Volto 13 onwards. It was supported since Volto 1 (and its predecessor "plone-react") +- Node 14: No longer supported. It was supported from Volto 8.8.0 - 16 +- Node 12: No longer supported. It was supported from Volto 4 - 15 +- Node 10: No longer supported. It was supported from Volto 1 - 12 ## Browser support @@ -272,7 +269,7 @@ yarn Either using a Docker command: ```shell -docker run -it --rm --name=plone -p 8080:8080 -e SITE=Plone -e PROFILES="plone.volto:default-homepage" plone/plone-backend:6.0.0b3 +docker run -it --rm --name=plone -p 8080:8080 -e SITE=Plone -e PROFILES="plone.volto:default-homepage" plone/plone-backend:6.0.1 ``` or using the convenience makefile command: diff --git a/__tests__/webpack-relative-resolver.test.js b/__tests__/webpack-relative-resolver.test.js index 41519c4c53..960d81a28a 100644 --- a/__tests__/webpack-relative-resolver.test.js +++ b/__tests__/webpack-relative-resolver.test.js @@ -120,10 +120,16 @@ describe('functions as a Webpack resolver plugin', () => { const resolved = []; const resolver = { - plugin(typ, resolveCallback) { - resolveCallback(req, () => flag.push(true)); + ensureHook(typ) { + return this; }, - doResolve(type, req, _, callback) { + getHook(typ) { + return this; + }, + tapAsync: (name, callback) => { + callback(req, {}); + }, + doResolve(type, req, _, resolveContext, callback) { flag.push(true); resolved.push(req.request); }, @@ -143,10 +149,16 @@ describe('functions as a Webpack resolver plugin', () => { const resolved = []; const resolver = { - plugin(typ, resolveCallback) { - resolveCallback(req, () => flag.push(true)); + ensureHook(typ) { + return this; + }, + getHook(typ) { + return this; + }, + tapAsync: (name, callback) => { + callback(req, {}, () => flag.push(true)); }, - doResolve(type, req, _, callback) { + doResolve(type, req, _, resolveContext, callback) { flag.push(true); resolved.push(req.request); }, diff --git a/cypress.config.js b/cypress.config.js index 8e6be41a2b..4f2286287f 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -5,7 +5,7 @@ module.exports = defineConfig({ chromeWebSecurity: false, projectId: 'hvviu4', e2e: { - baseUrl: 'http://localhost:3000', + baseUrl: 'http://127.0.0.1:3000', excludeSpecPattern: ['*~'], specPattern: 'cypress/tests/**/*.{js,jsx,ts,tsx}', }, diff --git a/cypress/support/commands.js b/cypress/support/commands.js index e97938364a..f950f973ac 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -2,7 +2,7 @@ import '@testing-library/cypress/add-commands'; import { getIfExists } from '../helpers'; import { ploneAuth } from './constants'; -const HOSTNAME = Cypress.env('BACKEND_HOST') || 'localhost'; +const HOSTNAME = Cypress.env('BACKEND_HOST') || '127.0.0.1'; const GUILLOTINA_API_URL = `http://${HOSTNAME}:8081/db/web`; const PLONE_SITE_ID = Cypress.env('SITE_ID') || 'plone'; const PLONE_API_URL = @@ -267,7 +267,7 @@ Cypress.Commands.add('getContent', ({ path = '' }) => { // --- Add DX Content-Type ---------------------------------------------------------- Cypress.Commands.add('addContentType', (name) => { let api_url, auth; - api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone'; + api_url = Cypress.env('API_PATH') || 'http://127.0.0.1:8080/Plone'; auth = ploneAuthObj; return cy @@ -288,7 +288,7 @@ Cypress.Commands.add('addContentType', (name) => { // --- Remove DX behavior ---------------------------------------------------------- Cypress.Commands.add('removeContentType', (name) => { let api_url, auth; - api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone'; + api_url = Cypress.env('API_PATH') || 'http://127.0.0.1:8080/Plone'; auth = ploneAuthObj; return cy @@ -307,7 +307,7 @@ Cypress.Commands.add('removeContentType', (name) => { // --- Add DX field ---------------------------------------------------------- Cypress.Commands.add('addSlateJSONField', (type, name) => { let api_url, auth; - api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone'; + api_url = Cypress.env('API_PATH') || 'http://127.0.0.1:8080/Plone'; auth = ploneAuthObj; return cy @@ -332,7 +332,7 @@ Cypress.Commands.add('addSlateJSONField', (type, name) => { // --- Remove DX field ---------------------------------------------------------- Cypress.Commands.add('removeSlateJSONField', (type, name) => { let api_url, auth; - api_url = Cypress.env('API_PATH') || 'http://localhost:8080/Plone'; + api_url = Cypress.env('API_PATH') || 'http://127.0.0.1:8080/Plone'; auth = ploneAuthObj; return cy @@ -360,7 +360,7 @@ Cypress.Commands.add( password = 'password', roles = ['Member', 'Reader', 'Editor'], groups = { - '@id': 'http://localhost:3000/@users', + '@id': 'http://127.0.0.1:3000/@users', items: [ { id: 'AuthenticatedUsers', @@ -444,7 +444,7 @@ Cypress.Commands.add( password = ploneAuth[1], roles = ['Member', 'Reader'], users = { - '@id': 'http://localhost:3000/@groups', + '@id': 'http://127.0.0.1:3000/@groups', items: [], items_total: 0, }, diff --git a/cypress/support/guillotina.js b/cypress/support/guillotina.js index 5300ff21cd..f8f9275e3f 100644 --- a/cypress/support/guillotina.js +++ b/cypress/support/guillotina.js @@ -3,7 +3,7 @@ export function setupGuillotina() { Authorization: 'Basic cm9vdDpyb290', 'Content-Type': 'application/json', }; - const api_url = 'http://localhost:8081/db'; + const api_url = 'http://127.0.0.1:8081/db'; cy.request({ method: 'POST', @@ -62,7 +62,7 @@ export function tearDownGuillotina({ allowFail = false } = {}) { Authorization: 'Basic cm9vdDpyb290', 'Content-Type': 'application/json', }; - const api_url = 'http://localhost:8081/db'; + const api_url = 'http://127.0.0.1:8081/db'; cy.request({ method: 'DELETE', diff --git a/cypress/support/reset-fixture.js b/cypress/support/reset-fixture.js index a9a5fad79c..ebe6fffaf6 100644 --- a/cypress/support/reset-fixture.js +++ b/cypress/support/reset-fixture.js @@ -1,5 +1,5 @@ function setup() { - const api_url = Cypress.env('API_PATH') || 'http://localhost:55001/plone'; + const api_url = Cypress.env('API_PATH') || 'http://127.0.0.1:55001/plone'; cy.request({ method: 'POST', url: `${api_url}/RobotRemote`, @@ -10,7 +10,7 @@ function setup() { } function teardown() { - const api_url = Cypress.env('API_PATH') || 'http://localhost:55001/plone'; + const api_url = Cypress.env('API_PATH') || 'http://127.0.0.1:55001/plone'; cy.request({ method: 'POST', url: `${api_url}/RobotRemote`, diff --git a/cypress/support/upgradetests.js b/cypress/support/upgradetests.js index 8d8d976636..03205a9c70 100644 --- a/cypress/support/upgradetests.js +++ b/cypress/support/upgradetests.js @@ -6,7 +6,7 @@ export const getsystemNeedsUpgrade = { plone_gs_metadata_version_file_system: '6008', plone_gs_metadata_version_installed: '6006', plone_restapi_version: '8.32.0', - plone_version: '6.0.0b3', + plone_version: '6.0.0', python_version: '3.9.14 (main, Sep 13 2022, 03:20:56) \n[GCC 10.2.1 20210110]', upgrade: true, diff --git a/cypress/tests/core/basic/autologin.js b/cypress/tests/core/basic/autologin.js index 214d03e478..2e3a5627ee 100644 --- a/cypress/tests/core/basic/autologin.js +++ b/cypress/tests/core/basic/autologin.js @@ -2,7 +2,7 @@ import { ploneAuth } from '../../../support/constants'; describe('Autologin Tests', () => { it('Autologin as an standalone test', function () { - const api_url = 'http://localhost:55001/plone'; + const api_url = 'http://127.0.0.1:55001/plone'; const user = ploneAuth[0]; const password = ploneAuth[1]; diff --git a/cypress/tests/core/guillotina/autologin.js b/cypress/tests/core/guillotina/autologin.js index 67eb37e9be..fce720381b 100644 --- a/cypress/tests/core/guillotina/autologin.js +++ b/cypress/tests/core/guillotina/autologin.js @@ -1,6 +1,6 @@ describe('Autologin Tests', () => { it('Autologin as an standalone test', function () { - const api_url = 'http://localhost:8081/db/web'; + const api_url = 'http://127.0.0.1:8081/db/web'; const user = 'admin'; const password = 'admin'; diff --git a/cypress/tests/coresandbox/autologin.js b/cypress/tests/coresandbox/autologin.js index 45c13788ca..bc4d02606d 100644 --- a/cypress/tests/coresandbox/autologin.js +++ b/cypress/tests/coresandbox/autologin.js @@ -2,7 +2,7 @@ import { ploneAuth } from '../../support/constants'; describe('Autologin Tests', () => { it('Autologin as an standalone test', function () { - const api_url = 'http://localhost:55001/plone'; + const api_url = 'http://127.0.0.1:55001/plone'; const user = ploneAuth[0]; const password = ploneAuth[1]; diff --git a/cypress/tests/guillotina/autologin.js b/cypress/tests/guillotina/autologin.js index 67eb37e9be..fce720381b 100644 --- a/cypress/tests/guillotina/autologin.js +++ b/cypress/tests/guillotina/autologin.js @@ -1,6 +1,6 @@ describe('Autologin Tests', () => { it('Autologin as an standalone test', function () { - const api_url = 'http://localhost:8081/db/web'; + const api_url = 'http://127.0.0.1:8081/db/web'; const user = 'admin'; const password = 'admin'; diff --git a/cypress/tests/multilingual/autologin.js b/cypress/tests/multilingual/autologin.js index 45c13788ca..bc4d02606d 100644 --- a/cypress/tests/multilingual/autologin.js +++ b/cypress/tests/multilingual/autologin.js @@ -2,7 +2,7 @@ import { ploneAuth } from '../../support/constants'; describe('Autologin Tests', () => { it('Autologin as an standalone test', function () { - const api_url = 'http://localhost:55001/plone'; + const api_url = 'http://127.0.0.1:55001/plone'; const user = ploneAuth[0]; const password = ploneAuth[1]; diff --git a/cypress/tests/workingCopy/autologin.js b/cypress/tests/workingCopy/autologin.js index 45c13788ca..bc4d02606d 100644 --- a/cypress/tests/workingCopy/autologin.js +++ b/cypress/tests/workingCopy/autologin.js @@ -2,7 +2,7 @@ import { ploneAuth } from '../../support/constants'; describe('Autologin Tests', () => { it('Autologin as an standalone test', function () { - const api_url = 'http://localhost:55001/plone'; + const api_url = 'http://127.0.0.1:55001/plone'; const user = ploneAuth[0]; const password = ploneAuth[1]; diff --git a/docker-compose.yml b/docker-compose.yml index c9dfff926e..82a49830b7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,14 +2,13 @@ version: '3.3' services: backend: - image: plone/plone-backend:6.0.0b2 + image: plone/plone-backend:6.0.1 # Plone 5.2 series can be used too - # image: plone/plone-backend:5.2.9 + # image: plone/plone-backend:5.2.10 ports: - '8080:8080' environment: - SITE=Plone - - 'ADDONS=plone.restapi==8.29.0 plone.volto==4.0.0a13 plone.rest==2.0.0a5' - 'PROFILES=plone.volto:default-homepage' labels: - traefik.enable=true diff --git a/docs/source/getting-started/install.md b/docs/source/getting-started/install.md index 92e9d4689d..1e8dfc2460 100644 --- a/docs/source/getting-started/install.md +++ b/docs/source/getting-started/install.md @@ -23,14 +23,10 @@ This chapter contains some legacy information that may be useful to Plone 5.2 de Volto can be installed in any operating system assuming that the following pre-requisites are met: -- [Node.js LTS (16.x)](https://nodejs.org/en/) +- [Node.js LTS (18.x)](https://nodejs.org/en/) - [Python](https://www.python.org/) - See below for specific versions. - [Docker](https://www.docker.com/get-started) (if using the Plone docker images) -```{note} -*UPDATE 2022-10-25*: Since 2022-10-25, NodeJS 18 is in LTS state (https://github.com/nodejs/release#release-schedule). However, due to changes in internal SSL libraries, some Volto dependencies have been deprecated and need to be updated in order to continue working in NodeJS 18, mainly Webpack 4 (see: https://github.com/webpack/webpack/issues/14532#issuecomment-947525539 for further information). You can still use it, but NodeJS should be run under a special flag: `NODE_OPTIONS=--openssl-legacy-provider`. See also Volto's PR: https://github.com/plone/volto/pull/3699 for more information. -``` - The versions of Python that are supported in Volto depend on the version of Plone that you use. | Plone | Python | Volto | @@ -93,8 +89,8 @@ it provides easy access to any NodeJS released version. 4. Install any active LTS version of NodeJS (https://github.com/nodejs/release#release-schedule): ```bash - nvm install 16 - nvm use 16 + nvm install 18 + nvm use 18 ``` 5. Test NodeJS: @@ -109,7 +105,7 @@ it provides easy access to any NodeJS released version. ```{note} Volto supports currently active NodeJS LTS versions based on [NodeJS - Releases page](https://github.com/nodejs/release#release-schedule), starting with Node 12 LTS. + Releases page](https://github.com/nodejs/release#release-schedule), starting with Node 16 LTS. ``` diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index 67566b973f..3c4cc5a11c 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -24,6 +24,29 @@ The generator will also "update" your project with the latest changes, and propo Thus it is safe to run it on top of your project and answer the prompts. ``` +(volto-upgrade-guide-17.x.x)= + +## Upgrading to Volto 17.x.x + +### Ending support for NodeJS 14 + +Long Term Support for NodeJS 14 by the NodeJS community ends in April 2023. +Volto 17 no longer supports NodeJS 14. +Please update your projects to a NodeJS LTS version, where either 16 or 18 is supported at the moment of this writing. +Version 18 is recommended. + +#### localhost now resolves to an IPv6 address + +NodeJS 18 prefers to resolve `localhost` to an IPv6 address instead of IPv4. +If you are setting `RAZZLE_API_PATH` to a URL that includes `localhost`, +change the hostname to `127.0.0.1` instead. + +### Webpack 5 + +Volto 17 now uses Webpack 5. +If you customized `razzle.config.js` for your project to change Webpack configuration +or use Webpack plugins, you might need to make adjustments. + (volto-upgrade-guide-16.x.x)= diff --git a/news/4086.breaking b/news/4086.breaking new file mode 100644 index 0000000000..bafa441d32 --- /dev/null +++ b/news/4086.breaking @@ -0,0 +1,5 @@ +Volto 17 drops support for NodeJS 14, and adds support for NodeJS 18. +Please see the [upgrade guide](https://6.dev-docs.plone.org/volto/upgrade-guide/index.html) +for more information. + +Volto 17 now uses Webpack 5. diff --git a/package.json b/package.json index 054574179a..8945121b80 100644 --- a/package.json +++ b/package.json @@ -222,7 +222,7 @@ ] }, "engines": { - "node": "^14 || ^16" + "node": "^16 || ^18" }, "dependencies": { "@babel/core": "^7.0.0", @@ -237,7 +237,7 @@ "@loadable/babel-plugin": "5.13.2", "@loadable/component": "5.14.1", "@loadable/server": "5.14.0", - "@loadable/webpack-plugin": "5.14.0", + "@loadable/webpack-plugin": "5.15.2", "@plone/scripts": "2.1.2", "@testing-library/cypress": "8.0.7", "@testing-library/jest-dom": "5.16.4", @@ -293,7 +293,7 @@ "hamburgers": "1.1.3", "history": "4.10.1", "hoist-non-react-statics": "3.3.2", - "html-webpack-plugin": "4.5.2", + "html-webpack-plugin": "5.5.0", "http-proxy-middleware": "2.0.1", "husky": "8.0.1", "identity-obj-proxy": "3.0.0", @@ -305,14 +305,14 @@ "jsonwebtoken": "8.3.0", "jwt-decode": "2.2.0", "less": "3.11.1", - "less-loader": "6.1.0", + "less-loader": "11.1.0", "linkify-it": "3.0.2", "lint-staged": "10.2.2", "locale": "0.1.0", "lodash": "4.17.21", "lodash-move": "1.1.1", - "lodash-webpack-plugin": "0.11.5", - "mini-css-extract-plugin": "0.9.0", + "lodash-webpack-plugin": "0.11.6", + "mini-css-extract-plugin": "2.7.2", "moment": "2.24.0", "object-assign": "4.1.1", "pofile": "1.0.10", @@ -320,7 +320,7 @@ "postcss-flexbugs-fixes": "5.0.2", "postcss-less": "6.0.0", "postcss-load-config": "3.1.4", - "postcss-loader": "4.3.0", + "postcss-loader": "7.0.2", "postcss-overrides": "3.1.4", "postcss-scss": "4.0.6", "prepend-http": "2", @@ -385,34 +385,36 @@ "slate-hyperscript": "0.81.3", "slate-react": "0.83.2", "start-server-and-test": "1.14.0", - "style-loader": "2", + "style-loader": "3.3.1", "stylelint": "14.0.1", "stylelint-config-idiomatic-order": "8.1.0", "stylelint-config-prettier": "8.0.1", "stylelint-prettier": "1.1.2", "superagent": "3.8.2", "svg-loader": "0.0.2", - "svgo": "1.3.2", - "svgo-loader": "2.2.1", + "svgo-loader": "3.0.3", + "terser-webpack-plugin": "5.3.6", "tlds": "1.203.1", "undoo": "0.5.0", "universal-cookie": "4.0.4", "universal-cookie-express": "4.0.3", "use-deep-compare-effect": "1.8.1", "uuid": "^8.3.2", - "webpack": "4.46.0", - "webpack-dev-server": "3.11.0", + "webpack": "5.75.0", + "webpack-dev-server": "4.11.1", "webpack-node-externals": "3.0.0", "xmlrpc": "1.3.2", "yarnhook": "0.5.1" }, "devDependencies": { - "@storybook/addon-actions": "^6.3.0", - "@storybook/addon-controls": "6.3.0", - "@storybook/addon-essentials": "^6.3.0", - "@storybook/addon-links": "^6.3.0", - "@storybook/react": "^6.3.0", - "babel-loader": "8.2.2", + "@storybook/addon-actions": "^6.5.15", + "@storybook/addon-controls": "6.5.15", + "@storybook/addon-essentials": "^6.5.15", + "@storybook/addon-links": "^6.5.15", + "@storybook/builder-webpack5": "^6.5.15", + "@storybook/manager-webpack5": "^6.5.15", + "@storybook/react": "^6.5.15", + "babel-loader": "9.1.0", "full-icu": "1.4.0", "identity-obj-proxy": "3.0.0", "jest": "26.6.3", @@ -434,7 +436,7 @@ "ua-parser-js": "0.7.28" }, "volta": { - "node": "16.17.1" + "node": "18.13.0" }, "packageManager": "yarn@3.2.3" } diff --git a/packages/generator-volto/generators/addon/templates/Makefile b/packages/generator-volto/generators/addon/templates/Makefile index 7a50357b0a..ba7c32fa89 100644 --- a/packages/generator-volto/generators/addon/templates/Makefile +++ b/packages/generator-volto/generators/addon/templates/Makefile @@ -12,14 +12,14 @@ MAKEFLAGS+=--no-builtin-rules # Project settings # Update the versions depending on your project requirements | Last Updated 2022-12-23 -DOCKER_IMAGE=plone/plone-backend:6.0 -KGS= +DOCKER_IMAGE=plone/plone-backend:6.0.1 +KGS=plone.volto==4.0.5 TESTING_ADDONS=plone.app.robotframework==2.0.0 plone.app.testing==7.0.0 NODEBIN = ./node_modules/.bin # Plone 5 legacy -DOCKER_IMAGE5=plone/plone-backend:5.2.9 -KGS5=plone.restapi==8.32.6 plone.volto==4.0.0 plone.rest==2.0.0 +DOCKER_IMAGE5=plone/plone-backend:5.2.10 +KGS5=plone.restapi==8.35.0 plone.volto==4.0.5 plone.rest==3.0.0 DIR=$(shell basename $$(pwd)) ADDON ?= "<%= addonName %>" diff --git a/packages/generator-volto/generators/app/index.js b/packages/generator-volto/generators/app/index.js index c5ba6fc47e..6d49e49bba 100644 --- a/packages/generator-volto/generators/app/index.js +++ b/packages/generator-volto/generators/app/index.js @@ -227,24 +227,19 @@ Run "npm install -g @plone/generator-volto" to update.`, this.destinationPath(base, 'package.json'), this.globals, ); - + this.fs.copyTpl( + this.templatePath('.gitignorefile'), + this.destinationPath(base, '.gitignore'), + this.globals, + ); this.fs.write(this.destinationPath(base, 'yarn.lock'), this.voltoYarnLock); this.fs.copy(this.templatePath(), this.destinationPath(base), { globOptions: { - ignore: ['**/*.tpl', '**/*~'], + ignore: ['**/*.tpl', '**/*~', '**/.gitignorefile'], dot: true, }, }); - - this.fs.copyTpl( - this.templatePath('.gitignorefile'), - this.destinationPath(base, '.gitignore'), - this.globals, - ); - - this.fs.delete(this.destinationPath(base, 'package.json.tpl')); - this.fs.delete(this.destinationPath(base, '.gitignorefile')); } install() { diff --git a/packages/generator-volto/generators/app/templates/Makefile b/packages/generator-volto/generators/app/templates/Makefile index f757f08206..78e10e03a8 100644 --- a/packages/generator-volto/generators/app/templates/Makefile +++ b/packages/generator-volto/generators/app/templates/Makefile @@ -16,8 +16,8 @@ TESTING_ADDONS=plone.app.robotframework==2.0.0 plone.app.testing==7.0.0 NODEBIN = ./node_modules/.bin # Plone 5 legacy -DOCKER_IMAGE5=plone/plone-backend:5.2.9 -KGS5=plone.restapi==8.32.6 plone.volto==4.0.0 plone.rest==2.0.0 +DOCKER_IMAGE5=plone/plone-backend:5.2.10 +KGS5=plone.restapi==8.35.0 plone.volto==4.0.5 plone.rest==3.0.0 # Project settings @@ -78,7 +78,7 @@ start-test-acceptance-server start-test-backend : ## Start Test Plone Backend .PHONY: start-test-acceptance-frontend start-test-acceptance-frontend: ## Start the Acceptance Frontend Fixture - RAZZLE_API_PATH=http://localhost:55001/plone yarn build && yarn start:prod + RAZZLE_API_PATH=http://127.0.0.1:55001/plone yarn build && yarn start:prod .PHONY: test-acceptance test-acceptance: ## Start Core Cypress Acceptance Tests @@ -90,7 +90,7 @@ test-acceptance-headless: ## Start Core Cypress Acceptance Tests in headless mod .PHONY: full-test-acceptance full-test-acceptance: ## Runs Core Full Acceptance Testing in headless mode - $(NODEBIN)/start-test "make start-test-acceptance-server" http-get://localhost:55001/plone "make start-test-acceptance-frontend" http://localhost:3000 "make test-acceptance-headless" + $(NODEBIN)/start-test "make start-test-acceptance-server" http-get://127.0.0.1:55001/plone "make start-test-acceptance-frontend" http://127.0.0.1:3000 "make test-acceptance-headless" .PHONY: test-acceptance test-acceptance-addon: ## Start Core Cypress Acceptance Tests for an addon @@ -102,4 +102,4 @@ test-acceptance-addon-headless: ## Start Core Cypress Acceptance Tests for an ad .PHONY: full-test-acceptance-addon full-test-acceptance-addon: ## Runs Core Full Acceptance Testing for an addon in headless mode - $(NODEBIN)/start-test "make start-test-acceptance-server" http-get://localhost:55001/plone "make start-test-acceptance-frontend" http://localhost:3000 "make test-acceptance-addon-headless" + $(NODEBIN)/start-test "make start-test-acceptance-server" http-get://127.0.0.1:55001/plone "make start-test-acceptance-frontend" http://127.0.0.1:3000 "make test-acceptance-addon-headless" diff --git a/packages/generator-volto/generators/app/templates/package.json.tpl b/packages/generator-volto/generators/app/templates/package.json.tpl index 304d309f6e..396775981a 100644 --- a/packages/generator-volto/generators/app/templates/package.json.tpl +++ b/packages/generator-volto/generators/app/templates/package.json.tpl @@ -126,7 +126,7 @@ "not dead" ], "engines": { - "node": "^14 || ^16" + "node": "^16 || ^18" }, "dependencies": <%- dependencies %>, "devDependencies": { diff --git a/packages/generator-volto/package.json b/packages/generator-volto/package.json index 54c8f88b29..1c2bba6e8c 100644 --- a/packages/generator-volto/package.json +++ b/packages/generator-volto/package.json @@ -96,7 +96,7 @@ } }, "engines": { - "node": "^12 || ^14 || ^16" + "node": "^16 || ^18" }, "dependencies": { "ansi-escapes": "2.0.0", @@ -129,5 +129,8 @@ "release-it": "^14.9.0", "yeoman-assert": "^3.1.0", "yeoman-test": "^6.1.0" + }, + "resolutions": { + "mem-fs-editor": "^9.5.0" } -} +} \ No newline at end of file diff --git a/packages/generator-volto/yarn.lock b/packages/generator-volto/yarn.lock index 90b197f68f..9e0129dc37 100644 --- a/packages/generator-volto/yarn.lock +++ b/packages/generator-volto/yarn.lock @@ -1278,7 +1278,7 @@ __metadata: languageName: node linkType: hard -"array-union@npm:^1.0.1, array-union@npm:^1.0.2": +"array-union@npm:^1.0.1": version: 1.0.2 resolution: "array-union@npm:1.0.2" dependencies: @@ -1375,13 +1375,6 @@ __metadata: languageName: node linkType: hard -"async@npm:0.9.x": - version: 0.9.2 - resolution: "async@npm:0.9.2" - checksum: 87dbf129292b8a6c32a4e07f43f462498162aa86f404a7e11f978dbfdf75cfb163c26833684bb07b9d436083cd604cbbf730a57bfcbe436c6ae1ed266cdc56bb - languageName: node - linkType: hard - "async@npm:^2.6.2": version: 2.6.3 resolution: "async@npm:2.6.3" @@ -1391,6 +1384,13 @@ __metadata: languageName: node linkType: hard +"async@npm:^3.2.3": + version: 3.2.4 + resolution: "async@npm:3.2.4" + checksum: 43d07459a4e1d09b84a20772414aa684ff4de085cbcaec6eea3c7a8f8150e8c62aa6cd4e699fe8ee93c3a5b324e777d34642531875a0817a35697522c1b02e89 + languageName: node + linkType: hard + "asynckit@npm:^0.4.0": version: 0.4.0 resolution: "asynckit@npm:0.4.0" @@ -1532,10 +1532,10 @@ __metadata: languageName: node linkType: hard -"binaryextensions@npm:^4.15.0": - version: 4.15.0 - resolution: "binaryextensions@npm:4.15.0" - checksum: 6c3cc8bc6852d94d3700dd8c2da742c83a5f95469465aac374c5064ac6b367307c164f717c5c4e85fd2acc37fd57d483e411977f3ea82065eccda7e24f0037e1 +"binaryextensions@npm:^4.16.0": + version: 4.18.0 + resolution: "binaryextensions@npm:4.18.0" + checksum: 6fe92a9004c5a7c08a8d49ac4087581043a0d195e76c288619c13e9232d0b80543f01da0037bb0f1b02830c174721fcad92bdfe76c84295cc8f308ee3b74d184 languageName: node linkType: hard @@ -1628,7 +1628,7 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.1": +"braces@npm:^3.0.1, braces@npm:^3.0.2": version: 3.0.2 resolution: "braces@npm:3.0.2" dependencies: @@ -1879,6 +1879,16 @@ __metadata: languageName: node linkType: hard +"chalk@npm:^4.0.2": + version: 4.1.2 + resolution: "chalk@npm:4.1.2" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: fe75c9d5c76a7a98d45495b91b2172fa3b7a09e0cc9370e5c8feb1c567b85c4288e2b3fded7cfdd7359ac28d6b3844feb8b82b8686842e93d23c827c417e83fc + languageName: node + linkType: hard + "chalk@npm:^4.1.0": version: 4.1.0 resolution: "chalk@npm:4.1.0" @@ -2658,15 +2668,6 @@ __metadata: languageName: node linkType: hard -"dir-glob@npm:^2.2.2": - version: 2.2.2 - resolution: "dir-glob@npm:2.2.2" - dependencies: - path-type: ^3.0.0 - checksum: 3aa48714a9f7845ffc30ab03a5c674fe760477cc55e67b0847333371549227d93953e6627ec160f75140c5bea5c5f88d13c01de79bd1997a588efbcf06980842 - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -2741,21 +2742,14 @@ __metadata: languageName: node linkType: hard -"ejs@npm:^2.6.1": - version: 2.7.4 - resolution: "ejs@npm:2.7.4" - checksum: a1d2bfc7d1f0b39e99ae19b20c9469a25aeddba1ffc225db098110b18d566f73772fcdcc740b108cfda7452276f67d7b64eb359f90285414c942f4ae70713371 - languageName: node - linkType: hard - -"ejs@npm:^3.1.5, ejs@npm:^3.1.6": - version: 3.1.6 - resolution: "ejs@npm:3.1.6" +"ejs@npm:^3.1.8": + version: 3.1.8 + resolution: "ejs@npm:3.1.8" dependencies: - jake: ^10.6.1 + jake: ^10.8.5 bin: - ejs: ./bin/cli.js - checksum: 81a9cdea0b4ded3b5a4b212b7c17e20bb07468f08394e2d519708d367957a70aef3d282a6d5d38bf6ad313ba25802b9193d4227f29b084d2ee0f28d115141d48 + ejs: bin/cli.js + checksum: 1d40d198ad52e315ccf37e577bdec06e24eefdc4e3c27aafa47751a03a0c7f0ec4310254c9277a5f14763c3cd4bbacce27497332b2d87c74232b9b1defef8efc languageName: node linkType: hard @@ -3284,7 +3278,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^2.0.2, fast-glob@npm:^2.2.6": +"fast-glob@npm:^2.0.2": version: 2.2.7 resolution: "fast-glob@npm:2.2.7" dependencies: @@ -3312,6 +3306,19 @@ __metadata: languageName: node linkType: hard +"fast-glob@npm:^3.2.9": + version: 3.2.12 + resolution: "fast-glob@npm:3.2.12" + dependencies: + "@nodelib/fs.stat": ^2.0.2 + "@nodelib/fs.walk": ^1.2.3 + glob-parent: ^5.1.2 + merge2: ^1.3.0 + micromatch: ^4.0.4 + checksum: 0b1990f6ce831c7e28c4d505edcdaad8e27e88ab9fa65eedadb730438cfc7cde4910d6c975d6b7b8dc8a73da4773702ebcfcd6e3518e73938bb1383badfe01c2 + languageName: node + linkType: hard + "fast-json-stable-stringify@npm:^2.0.0": version: 2.1.0 resolution: "fast-json-stable-stringify@npm:2.1.0" @@ -3766,6 +3773,15 @@ __metadata: languageName: node linkType: hard +"glob-parent@npm:^5.1.2": + version: 5.1.2 + resolution: "glob-parent@npm:5.1.2" + dependencies: + is-glob: ^4.0.1 + checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e + languageName: node + linkType: hard + "glob-to-regexp@npm:^0.3.0": version: 0.3.0 resolution: "glob-to-regexp@npm:0.3.0" @@ -3848,7 +3864,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:11.0.3, globby@npm:^11.0.3": +"globby@npm:11.0.3": version: 11.0.3 resolution: "globby@npm:11.0.3" dependencies: @@ -3878,6 +3894,20 @@ __metadata: languageName: node linkType: hard +"globby@npm:^11.1.0": + version: 11.1.0 + resolution: "globby@npm:11.1.0" + dependencies: + array-union: ^2.1.0 + dir-glob: ^3.0.1 + fast-glob: ^3.2.9 + ignore: ^5.2.0 + merge2: ^1.4.1 + slash: ^3.0.0 + checksum: b4be8885e0cfa018fc783792942d53926c35c50b3aefd3fdcfb9d22c627639dc26bd2327a40a0b74b074100ce95bb7187bfeae2f236856aa3de183af7a02aea6 + languageName: node + linkType: hard + "globby@npm:^8.0.1": version: 8.0.2 resolution: "globby@npm:8.0.2" @@ -3893,22 +3923,6 @@ __metadata: languageName: node linkType: hard -"globby@npm:^9.2.0": - version: 9.2.0 - resolution: "globby@npm:9.2.0" - dependencies: - "@types/glob": ^7.1.1 - array-union: ^1.0.2 - dir-glob: ^2.2.2 - fast-glob: ^2.2.6 - glob: ^7.1.3 - ignore: ^4.0.3 - pify: ^4.0.1 - slash: ^2.0.0 - checksum: 9b4cb70aa0b43bf89b18cf0e543695185e16d8dd99c17bdc6a1df0a9f88ff9dc8d2467aebace54c3842fc451a564882948c87a3b4fbdb1cacf3e05fd54b6ac5d - languageName: node - linkType: hard - "got@npm:11.8.2": version: 11.8.2 resolution: "got@npm:11.8.2" @@ -4261,7 +4275,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^4.0.3, ignore@npm:^4.0.6": +"ignore@npm:^4.0.6": version: 4.0.6 resolution: "ignore@npm:4.0.6" checksum: 248f82e50a430906f9ee7f35e1158e3ec4c3971451dd9f99c9bc1548261b4db2b99709f60ac6c6cac9333494384176cc4cc9b07acbe42d52ac6a09cad734d800 @@ -4275,6 +4289,13 @@ __metadata: languageName: node linkType: hard +"ignore@npm:^5.2.0": + version: 5.2.4 + resolution: "ignore@npm:5.2.4" + checksum: 3d4c309c6006e2621659311783eaea7ebcd41fe4ca1d78c91c473157ad6666a57a2df790fe0d07a12300d9aac2888204d7be8d59f9aaf665b1c7fcdb432517ef + languageName: node + linkType: hard + "import-cwd@npm:3.0.0": version: 3.0.0 resolution: "import-cwd@npm:3.0.0" @@ -4941,7 +4962,7 @@ __metadata: languageName: node linkType: hard -"isbinaryfile@npm:^4.0.0, isbinaryfile@npm:^4.0.8": +"isbinaryfile@npm:^4.0.8": version: 4.0.8 resolution: "isbinaryfile@npm:4.0.8" checksum: 606e3bb648d1a0dee23459d1d937bb2560e66a5281ec7c9ff50e585402d73321ac268d0f34cb7393125b3ebc4c7962d39e50a01cdb8904b52fce08b7ccd2bf9f @@ -5051,17 +5072,17 @@ __metadata: languageName: node linkType: hard -"jake@npm:^10.6.1": - version: 10.8.2 - resolution: "jake@npm:10.8.2" +"jake@npm:^10.8.5": + version: 10.8.5 + resolution: "jake@npm:10.8.5" dependencies: - async: 0.9.x - chalk: ^2.4.2 + async: ^3.2.3 + chalk: ^4.0.2 filelist: ^1.0.1 minimatch: ^3.0.4 bin: jake: ./bin/cli.js - checksum: b604c51863260e374ccd62cd0cfe0b659f72cb71beb7d5fb5137dd65b04cf9d5603abd01f9f6eaaac8f4182f396d6cfae01e0b0844c2215c9c1e200572307cf9 + checksum: 56c913ecf5a8d74325d0af9bc17a233bad50977438d44864d925bb6c45c946e0fee8c4c1f5fe2225471ef40df5222e943047982717ebff0d624770564d3c46ba languageName: node linkType: hard @@ -6104,63 +6125,26 @@ __metadata: languageName: node linkType: hard -"mem-fs-editor@npm:^6.0.0": - version: 6.0.0 - resolution: "mem-fs-editor@npm:6.0.0" - dependencies: - commondir: ^1.0.1 - deep-extend: ^0.6.0 - ejs: ^2.6.1 - glob: ^7.1.4 - globby: ^9.2.0 - isbinaryfile: ^4.0.0 - mkdirp: ^0.5.0 - multimatch: ^4.0.0 - rimraf: ^2.6.3 - through2: ^3.0.1 - vinyl: ^2.2.0 - checksum: ea2e27686a8d246ad50ec8ed0895d904fb19bd9cc58289b56783e5624ee9059174a4c0ff09e5a76274d69205f5a60d9df7dc746c94b0b4387379ae75b65f1a58 - languageName: node - linkType: hard - -"mem-fs-editor@npm:^7.0.1": - version: 7.1.0 - resolution: "mem-fs-editor@npm:7.1.0" - dependencies: - commondir: ^1.0.1 - deep-extend: ^0.6.0 - ejs: ^3.1.5 - glob: ^7.1.4 - globby: ^9.2.0 - isbinaryfile: ^4.0.0 - mkdirp: ^1.0.0 - multimatch: ^4.0.0 - rimraf: ^3.0.0 - through2: ^3.0.2 - vinyl: ^2.2.1 - checksum: caabbf53c9a06b22952774c213636472243cb0d59825e2c02d4b5007c24ed1f132ea2a22794eaea0c4b5b605492d2d18ca5020b7ac78e0e09519b68a6c316237 - languageName: node - linkType: hard - -"mem-fs-editor@npm:^9.0.0": - version: 9.0.1 - resolution: "mem-fs-editor@npm:9.0.1" +"mem-fs-editor@npm:^9.5.0": + version: 9.5.0 + resolution: "mem-fs-editor@npm:9.5.0" dependencies: - binaryextensions: ^4.15.0 + binaryextensions: ^4.16.0 commondir: ^1.0.1 deep-extend: ^0.6.0 - ejs: ^3.1.6 - globby: ^11.0.3 + ejs: ^3.1.8 + globby: ^11.1.0 isbinaryfile: ^4.0.8 + minimatch: ^3.1.2 multimatch: ^5.0.0 normalize-path: ^3.0.0 - textextensions: ^5.12.0 + textextensions: ^5.13.0 peerDependencies: mem-fs: ^2.1.0 peerDependenciesMeta: mem-fs: optional: true - checksum: 7853e32a80cad6ca3f97f769514c8533359669271f4f8c175a1546d7885af7b3ff5baf3942155c0204785e1162a4429df6c5dd5df98e4942b67bd1a626630b3e + checksum: 65919d02f596c14245cc75f0493e0221973753ce9bd490b6eb47026e7d64cb18cb17c8760441c65c56c51d83bf6fbc2e6c0a858fa162dfd2054ee3d0210d3579 languageName: node linkType: hard @@ -6182,7 +6166,7 @@ __metadata: languageName: node linkType: hard -"merge2@npm:^1.2.3, merge2@npm:^1.3.0": +"merge2@npm:^1.2.3, merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 @@ -6220,6 +6204,16 @@ __metadata: languageName: node linkType: hard +"micromatch@npm:^4.0.4": + version: 4.0.5 + resolution: "micromatch@npm:4.0.5" + dependencies: + braces: ^3.0.2 + picomatch: ^2.3.1 + checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc + languageName: node + linkType: hard + "mime-db@npm:1.44.0": version: 1.44.0 resolution: "mime-db@npm:1.44.0" @@ -6289,6 +6283,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:^3.1.2": + version: 3.1.2 + resolution: "minimatch@npm:3.1.2" + dependencies: + brace-expansion: ^1.1.7 + checksum: c154e566406683e7bcb746e000b84d74465b3a832c45d59912b9b55cd50dee66e5c4b1e5566dba26154040e51672f9aa450a9aef0c97cfc7336b78b7afb9540a + languageName: node + linkType: hard + "minimatch@npm:^5.0.1": version: 5.1.0 resolution: "minimatch@npm:5.1.0" @@ -6415,7 +6418,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^1.0.0, mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": +"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" bin: @@ -6459,19 +6462,6 @@ __metadata: languageName: node linkType: hard -"multimatch@npm:^4.0.0": - version: 4.0.0 - resolution: "multimatch@npm:4.0.0" - dependencies: - "@types/minimatch": ^3.0.3 - array-differ: ^3.0.0 - array-union: ^2.1.0 - arrify: ^2.0.1 - minimatch: ^3.0.4 - checksum: bdb6a98dad4e919d9a1a2a0db872f44fa2337315f2fd5827d91ae005cf22f4425782bdfa97c10b80d567f0cb3c226c31f4e85f8f6a4a4be4facf9af0de1bb0c2 - languageName: node - linkType: hard - "multimatch@npm:^5.0.0": version: 5.0.0 resolution: "multimatch@npm:5.0.0" @@ -7266,6 +7256,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^2.3.1": + version: 2.3.1 + resolution: "picomatch@npm:2.3.1" + checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf + languageName: node + linkType: hard + "pify@npm:^2.3.0": version: 2.3.0 resolution: "pify@npm:2.3.0" @@ -8892,10 +8889,10 @@ __metadata: languageName: node linkType: hard -"textextensions@npm:^5.12.0": - version: 5.12.0 - resolution: "textextensions@npm:5.12.0" - checksum: 251e91d85ff52fada81c8a46cea38c845e05d47712ee6b8e4edca3408669ec375a063a85ee7d9571d7bf1c7d99e1ccb7e034d4e47225846ffab0e580169ce4ad +"textextensions@npm:^5.13.0": + version: 5.15.0 + resolution: "textextensions@npm:5.15.0" + checksum: aa172e941e81b44e0d35fa217f758a0d8ba0342dac31539914225a2382b5792ef58bff3ec9009b9c85b0c0605f5a79a906bd97827a2e591d647137fcdbf867d3 languageName: node linkType: hard @@ -8924,7 +8921,7 @@ __metadata: languageName: node linkType: hard -"through2@npm:^3.0.0, through2@npm:^3.0.1, through2@npm:^3.0.2": +"through2@npm:^3.0.0, through2@npm:^3.0.1": version: 3.0.2 resolution: "through2@npm:3.0.2" dependencies: @@ -9376,7 +9373,7 @@ __metadata: languageName: node linkType: hard -"vinyl@npm:^2.0.1, vinyl@npm:^2.2.0, vinyl@npm:^2.2.1": +"vinyl@npm:^2.0.1": version: 2.2.1 resolution: "vinyl@npm:2.2.1" dependencies: diff --git a/razzle.config.js b/razzle.config.js index 992f8c17dc..34f84a95ce 100644 --- a/razzle.config.js +++ b/razzle.config.js @@ -99,15 +99,14 @@ const defaultModify = ({ runtimeChunk: true, splitChunks: { chunks: 'all', - name: dev, cacheGroups: { // We reset the default values set by webpack // So the chunks have all proper names (no random numbers) // The CSS gets bundled in one CSS chunk and it's consistent with // the `style-loader` load order, so no difference between // local (project CSS) and `node_modules` ones. - vendors: false, default: false, + defaultVendors: false, }, }, }); @@ -117,6 +116,7 @@ const defaultModify = ({ // Using the default provided (cssnano) by css-minimizer-webpack-plugin // should be enough see: // (https://github.com/clean-css/clean-css/discussions/1209) + delete options.webpackOptions.terserPluginOptions?.sourceMap; if (!dev) { config.optimization = Object.assign({}, config.optimization, { minimizer: [ @@ -317,7 +317,7 @@ const defaultModify = ({ : []; if (config.devServer) { - config.devServer.watchOptions.ignored = /node_modules\/(?!@plone\/volto)/; + config.devServer.static.watch.ignored = /node_modules\/(?!@plone\/volto)/; } return config; diff --git a/src/components/manage/Controlpanels/VersionOverview.jsx b/src/components/manage/Controlpanels/VersionOverview.jsx index 8cc6e81cd4..458350f461 100644 --- a/src/components/manage/Controlpanels/VersionOverview.jsx +++ b/src/components/manage/Controlpanels/VersionOverview.jsx @@ -7,14 +7,8 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import { isEmpty } from 'lodash'; -import { - version as voltoVersion, - name as voltoName, -} from '../../../../package.json'; -import { - version as projectVersion, - name as projectName, -} from '@root/../package.json'; +import voltoPackageJson from '../../../../package.json'; +import projectPackageJson from '@root/../package.json'; import { defineMessages, useIntl } from 'react-intl'; import config from '@plone/volto/registry'; @@ -26,6 +20,8 @@ const messages = defineMessages({ }, }); +const voltoVersion = voltoPackageJson.version; + const VersionOverview = ({ cmf_version, debug_mode, @@ -37,7 +33,7 @@ const VersionOverview = ({ }) => { const intl = useIntl(); const { addonsInfo } = config.settings; - const isProject = voltoName !== projectName; + const isProject = voltoPackageJson.name !== projectPackageJson.name; return ( <> @@ -50,7 +46,7 @@ const VersionOverview = ({ > {isProject ? (
  • - {projectName} {projectVersion} + {projectPackageJson.name} {projectPackageJson.version}
  • ) : null} {voltoVersion &&
  • Volto {voltoVersion}
  • } diff --git a/src/components/manage/Diff/DiffField.jsx b/src/components/manage/Diff/DiffField.jsx index 80530a0270..c2e0f16861 100644 --- a/src/components/manage/Diff/DiffField.jsx +++ b/src/components/manage/Diff/DiffField.jsx @@ -61,12 +61,12 @@ const DiffField = ({ break; case 'datetime': parts = diffWords( - new Intl.DateTimeFormat(language, readable_date_format).format( - new Date(one), - ), - new Intl.DateTimeFormat(language, readable_date_format).format( - new Date(two), - ), + new Intl.DateTimeFormat(language, readable_date_format) + .format(new Date(one)) + .replace('\u202F', ' '), + new Intl.DateTimeFormat(language, readable_date_format) + .format(new Date(two)) + .replace('\u202F', ' '), ); break; case 'json': diff --git a/src/components/theme/FormattedDate/FormattedDate.jsx b/src/components/theme/FormattedDate/FormattedDate.jsx index 314977d45d..0f9c0542cf 100644 --- a/src/components/theme/FormattedDate/FormattedDate.jsx +++ b/src/components/theme/FormattedDate/FormattedDate.jsx @@ -23,9 +23,9 @@ const FormattedDate = ({
    +
    {hasBlocksData(content) ? ( diff --git a/src/components/theme/View/NewsItemView.jsx b/src/components/theme/View/NewsItemView.jsx index 6415dda53f..0e16994429 100644 --- a/src/components/theme/View/NewsItemView.jsx +++ b/src/components/theme/View/NewsItemView.jsx @@ -21,7 +21,7 @@ import RenderBlocks from '@plone/volto/components/theme/View/RenderBlocks'; */ const NewsItemView = ({ content }) => hasBlocksData(content) ? ( -
    +
    ) : ( diff --git a/src/components/theme/View/__snapshots__/EventView.test.jsx.snap b/src/components/theme/View/__snapshots__/EventView.test.jsx.snap index 4bd487acd5..acf53acafc 100644 --- a/src/components/theme/View/__snapshots__/EventView.test.jsx.snap +++ b/src/components/theme/View/__snapshots__/EventView.test.jsx.snap @@ -2,7 +2,7 @@ exports[`renders an event view component with all props 1`] = `
    Date: Wed, 8 Mar 2023 03:38:35 -0800 Subject: [PATCH 053/142] Improvements to dev proxy (#4434) --- news/4434.feature | 8 ++++++++ src/config/index.js | 1 + src/express-middleware/devproxy.js | 6 ++++-- src/server.jsx | 1 + src/start-server.js | 6 ++++-- 5 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 news/4434.feature diff --git a/news/4434.feature b/news/4434.feature new file mode 100644 index 0000000000..0f5f181a52 --- /dev/null +++ b/news/4434.feature @@ -0,0 +1,8 @@ +Improvements to the dev API proxy: +- Prefer RAZZLE_INTERNAL_API_PATH over RAZZLE_API_PATH as the target of the proxy. + The target of the API proxy is now always logged on startup, even in production mode. +- Support proxying to a backend served over https. For this configuration it + might be necessary to set RAZZLE_DEV_PROXY_INSECURE=1 if the backend + certificate can't be verified. + +[davisagli] diff --git a/src/config/index.js b/src/config/index.js index a4dee4f99d..60985f5e26 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -89,6 +89,7 @@ let config = { // https://6.docs.plone.org/volto/deploying/seamless-mode.html devProxyToApiPath: process.env.RAZZLE_DEV_PROXY_API_PATH || + process.env.RAZZLE_INTERNAL_API_PATH || process.env.RAZZLE_API_PATH || 'http://localhost:8080/Plone', // Set it to '' for disabling the proxy // proxyRewriteTarget Set it for set a custom target for the proxy or overide the internal VHM rewrite diff --git a/src/express-middleware/devproxy.js b/src/express-middleware/devproxy.js index c2f2142d6b..d3411fdf89 100644 --- a/src/express-middleware/devproxy.js +++ b/src/express-middleware/devproxy.js @@ -75,12 +75,14 @@ export default function () { const { apiPathURL, instancePath } = getEnv(); const target = config.settings.proxyRewriteTarget || - `/VirtualHostBase/http/${apiPathURL.hostname}:${apiPathURL.port}${instancePath}/++api++/VirtualHostRoot`; + `/VirtualHostBase/${apiPathURL.protocol.slice(0, -1)}/${ + apiPathURL.hostname + }:${apiPathURL.port}${instancePath}/++api++/VirtualHostRoot`; return `${target}${path.replace('/++api++', '')}`; }, logLevel: process.env.DEBUG_HPM ? 'debug' : 'silent', - ...(config.settings?.proxyRewriteTarget?.startsWith('https') && { + ...(process.env.RAZZLE_DEV_PROXY_INSECURE && { changeOrigin: true, secure: false, }), diff --git a/src/server.jsx b/src/server.jsx index df5290aa5d..8fea05fd78 100644 --- a/src/server.jsx +++ b/src/server.jsx @@ -329,6 +329,7 @@ export const defaultReadCriticalCss = () => { // Exposed for the console bootstrap info messages server.apiPath = config.settings.apiPath; server.devProxyToApiPath = config.settings.devProxyToApiPath; +server.proxyRewriteTarget = config.settings.proxyRewriteTarget; server.publicURL = config.settings.publicURL; export default server; diff --git a/src/start-server.js b/src/start-server.js index 5ea7ea0bb4..ee34673e29 100644 --- a/src/start-server.js +++ b/src/start-server.js @@ -19,9 +19,11 @@ export default () => { } else { console.log(`API server (API_PATH) is set to: ${app.apiPath}`); } - if (__DEVELOPMENT__ && app.devProxyToApiPath) + if (app.devProxyToApiPath) console.log( - `Using internal proxy: ${app.publicURL} -> ${app.devProxyToApiPath}`, + `Proxying API requests from ${app.publicURL}/++api++ to ${ + app.devProxyToApiPath + }${app.proxyRewriteTarget || ''}`, ); console.log(`🎭 Volto started at ${bind_address}:${port} 🚀`); From a4766a7e6d2029d23c221f29c4c8536e5803929a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Wed, 8 Mar 2023 15:20:12 +0100 Subject: [PATCH 054/142] Release 16.15.0. Update Changelog. (#4485) --- CHANGELOG.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08a327a59e..04920603d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,31 @@ - Use a universal static path for both documentation and volto repos. @stevepiercy [#4376](https://github.com/plone/volto/issues/4376) +## 16.15.0 (2023-03-08) + +### Feature + +- Improvements to the dev API proxy: + - Prefer RAZZLE_INTERNAL_API_PATH over RAZZLE_API_PATH as the target of the proxy. + The target of the API proxy is now always logged on startup, even in production mode. + - Support proxying to a backend served over https. For this configuration it + might be necessary to set RAZZLE_DEV_PROXY_INSECURE=1 if the backend + certificate can't be verified. + + [davisagli] [#4434](https://github.com/plone/volto/issues/4434) + +### Bugfix + +- fix: newsitem and event views wrapper classNames @nzambello [#4443](https://github.com/plone/volto/issues/4443) +- Fix weird GHA failure on config option not supported @sneridagh [#4466](https://github.com/plone/volto/issues/4466) +- Fix history view dropdown for first entry, showing 'Revert to this version option' always @sneridagh [#4471](https://github.com/plone/volto/issues/4471) +- Fix order of row of long table in edit and view mode @iFlameing [#4473](https://github.com/plone/volto/issues/4473) + +### Documentation + +- Complete teaser docs, add new section in `Blocks`: `Core Blocks developers notes` @sneridagh [#4461](https://github.com/plone/volto/issues/4461) + + ## 16.14.0 (2023-03-03) ### Feature From 3ea85278c8145f215854eb925d8851a51f2f2771 Mon Sep 17 00:00:00 2001 From: Mauro Amico Date: Thu, 9 Mar 2023 10:54:00 +0100 Subject: [PATCH 055/142] Serve static assets with an efficient cache policy (#2216) Co-authored-by: nzambello Co-authored-by: Tiberiu Ichim Co-authored-by: Tiberiu Ichim --- CHANGELOG.md | 3 +++ src/config/server.js | 19 +++++++++++++++++++ src/express-middleware/static.js | 32 ++++++++++++++++++++++++++++++++ src/server.jsx | 7 ------- 4 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 src/express-middleware/static.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 04920603d3..a7e84ec14a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1115,6 +1115,9 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa ### Breaking +- Add directive to cache stable resources in browser or intermediate server for 365 days, + static resource that could change after a new deployment for 1 minute. @mamico + ### Feature - Added new components `Aliases` for aliases control in Volto. Alias management in both controlpanel and object view. @andreiggr @avoinea diff --git a/src/config/server.js b/src/config/server.js index 1698da1233..8e8d7e4b61 100644 --- a/src/config/server.js +++ b/src/config/server.js @@ -2,6 +2,7 @@ import imagesMiddleware from '@plone/volto/express-middleware/images'; import filesMiddleware from '@plone/volto/express-middleware/files'; import robotstxtMiddleware from '@plone/volto/express-middleware/robotstxt'; import sitemapMiddleware from '@plone/volto/express-middleware/sitemap'; +import staticsMiddleware from '@plone/volto/express-middleware/static'; import devProxyMiddleware from '@plone/volto/express-middleware/devproxy'; const settings = { @@ -11,10 +12,28 @@ const settings = { imagesMiddleware(), robotstxtMiddleware(), sitemapMiddleware(), + staticsMiddleware(), ], criticalCssPath: 'public/critical.css', readCriticalCss: null, // so it will be defaultReadCriticalCss extractScripts: { errorPages: false }, + staticFiles: [ + { + id: 'root_static', + match: /^\/static\/.*/, + headers: { + // stable resources never change. 31536000 seconds == 365 days + 'Cache-Control': 'public, max-age=31536000', + }, + }, + { + id: 'all', + match: /.*/, + headers: { + 'Cache-Control': 'public, max-age=60', + }, + }, + ], }; export default settings; diff --git a/src/express-middleware/static.js b/src/express-middleware/static.js new file mode 100644 index 0000000000..5e90754bc0 --- /dev/null +++ b/src/express-middleware/static.js @@ -0,0 +1,32 @@ +import express from 'express'; +import path from 'path'; +import config from '@plone/volto/registry'; + +const staticMiddleware = express.static( + process.env.BUILD_DIR + ? path.join(process.env.BUILD_DIR, 'public') + : process.env.RAZZLE_PUBLIC_DIR, + { + setHeaders: function (res, path) { + const pathLib = require('path'); + const base = pathLib.resolve(process.env.RAZZLE_PUBLIC_DIR); + const relpath = path.substr(base.length); + config.settings.serverConfig.staticFiles.some((elem) => { + if (relpath.match(elem.match)) { + for (const name in elem.headers) { + res.setHeader(name, elem.headers[name] || 'undefined'); + } + return true; + } + return false; + }); + }, + }, +); + +export default function () { + const middleware = express.Router(); + middleware.all('*', staticMiddleware); + middleware.id = 'staticResourcesProcessor'; + return middleware; +} diff --git a/src/server.jsx b/src/server.jsx index 8fea05fd78..a9858b9854 100644 --- a/src/server.jsx +++ b/src/server.jsx @@ -59,13 +59,6 @@ const supported = new locale.Locales(keys(languages), 'en'); const server = express() .disable('x-powered-by') - .use( - express.static( - process.env.BUILD_DIR - ? path.join(process.env.BUILD_DIR, 'public') - : process.env.RAZZLE_PUBLIC_DIR, - ), - ) .head('/*', function (req, res) { // Support for HEAD requests. Required by start-test utility in CI. res.send(''); From 176aa96cd697530cc4f36b09df35a89b72131614 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Thu, 9 Mar 2023 11:01:21 +0100 Subject: [PATCH 056/142] Changelog --- CHANGELOG.md | 5 ----- news/2216.feature | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) create mode 100644 news/2216.feature diff --git a/CHANGELOG.md b/CHANGELOG.md index a7e84ec14a..4d01600c40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1113,11 +1113,6 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa ## 16.0.0-alpha.34 (2022-09-17) -### Breaking - -- Add directive to cache stable resources in browser or intermediate server for 365 days, - static resource that could change after a new deployment for 1 minute. @mamico - ### Feature - Added new components `Aliases` for aliases control in Volto. Alias management in both controlpanel and object view. @andreiggr @avoinea diff --git a/news/2216.feature b/news/2216.feature new file mode 100644 index 0000000000..19ee35ab03 --- /dev/null +++ b/news/2216.feature @@ -0,0 +1 @@ +- Add directive to cache stable resources in browser or intermediate server for 365 days by default directly in the SSR Express server, static resource that could change after a new deployment for 1 minute. @mamico From 636149b2582dbb3492820b6a2f67eff53f84f967 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Thu, 9 Mar 2023 16:24:17 +0100 Subject: [PATCH 057/142] Release 17.0.0-alpha.1 --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ news/2216.feature | 1 - news/4141.feature | 1 - news/4434.feature | 8 -------- news/4443.bugfix | 1 - news/4461.documentation | 1 - news/4466.bugfix | 1 - news/4470.documentation | 1 - news/4471.bugfix | 1 - news/4473.bugfix | 1 - news/4475.bugfix | 1 - package.json | 2 +- packages/volto-slate/package.json | 2 +- 13 files changed, 31 insertions(+), 19 deletions(-) delete mode 100644 news/2216.feature delete mode 100644 news/4141.feature delete mode 100644 news/4434.feature delete mode 100644 news/4443.bugfix delete mode 100644 news/4461.documentation delete mode 100644 news/4466.bugfix delete mode 100644 news/4470.documentation delete mode 100644 news/4471.bugfix delete mode 100644 news/4473.bugfix delete mode 100644 news/4475.bugfix diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d01600c40..641578d18e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,35 @@ +## 17.0.0-alpha.1 (2023-03-09) + +### Feature + +- - Add directive to cache stable resources in browser or intermediate server for 365 days by default directly in the SSR Express server, static resource that could change after a new deployment for 1 minute. @mamico [#2216](https://github.com/plone/volto/issues/2216) +- Use popperjs in BlockChooser, move the markup to the bottom of the body tag. @sneridagh [#4141](https://github.com/plone/volto/issues/4141) +- Improvements to the dev API proxy: + - Prefer RAZZLE_INTERNAL_API_PATH over RAZZLE_API_PATH as the target of the proxy. + The target of the API proxy is now always logged on startup, even in production mode. + - Support proxying to a backend served over https. For this configuration it + might be necessary to set RAZZLE_DEV_PROXY_INSECURE=1 if the backend + certificate can't be verified. + + [davisagli] [#4434](https://github.com/plone/volto/issues/4434) + +### Bugfix + +- fix: newsitem and event views wrapper classNames @nzambello [#4443](https://github.com/plone/volto/issues/4443) +- Fix weird GHA failure on config option not supported @sneridagh [#4466](https://github.com/plone/volto/issues/4466) +- Fix history view dropdown for first entry, showing 'Revert to this version option' always @sneridagh [#4471](https://github.com/plone/volto/issues/4471) +- Fix order of row of long table in edit and view mode @iFlameing [#4473](https://github.com/plone/volto/issues/4473) +- Improve flaky test in autofocus Cypress tests @sneridagh [#4475](https://github.com/plone/volto/issues/4475) + +### Documentation + +- Complete teaser docs, add new section in `Blocks`: `Core Blocks developers notes` @sneridagh [#4461](https://github.com/plone/volto/issues/4461) +- Change from links to inline literals in `CHANGELOG.md` to fix linkcheckbroken. @stevepiercy [#4470](https://github.com/plone/volto/issues/4470) + + ## 17.0.0-alpha.0 (2023-03-04) ### Breaking diff --git a/news/2216.feature b/news/2216.feature deleted file mode 100644 index 19ee35ab03..0000000000 --- a/news/2216.feature +++ /dev/null @@ -1 +0,0 @@ -- Add directive to cache stable resources in browser or intermediate server for 365 days by default directly in the SSR Express server, static resource that could change after a new deployment for 1 minute. @mamico diff --git a/news/4141.feature b/news/4141.feature deleted file mode 100644 index 04f470f52c..0000000000 --- a/news/4141.feature +++ /dev/null @@ -1 +0,0 @@ -Use popperjs in BlockChooser, move the markup to the bottom of the body tag. @sneridagh diff --git a/news/4434.feature b/news/4434.feature deleted file mode 100644 index 0f5f181a52..0000000000 --- a/news/4434.feature +++ /dev/null @@ -1,8 +0,0 @@ -Improvements to the dev API proxy: -- Prefer RAZZLE_INTERNAL_API_PATH over RAZZLE_API_PATH as the target of the proxy. - The target of the API proxy is now always logged on startup, even in production mode. -- Support proxying to a backend served over https. For this configuration it - might be necessary to set RAZZLE_DEV_PROXY_INSECURE=1 if the backend - certificate can't be verified. - -[davisagli] diff --git a/news/4443.bugfix b/news/4443.bugfix deleted file mode 100644 index ba1f1a8c8a..0000000000 --- a/news/4443.bugfix +++ /dev/null @@ -1 +0,0 @@ -fix: newsitem and event views wrapper classNames @nzambello diff --git a/news/4461.documentation b/news/4461.documentation deleted file mode 100644 index cef8c89618..0000000000 --- a/news/4461.documentation +++ /dev/null @@ -1 +0,0 @@ -Complete teaser docs, add new section in `Blocks`: `Core Blocks developers notes` @sneridagh diff --git a/news/4466.bugfix b/news/4466.bugfix deleted file mode 100644 index 2facedcb3b..0000000000 --- a/news/4466.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix weird GHA failure on config option not supported @sneridagh diff --git a/news/4470.documentation b/news/4470.documentation deleted file mode 100644 index 930a5b495d..0000000000 --- a/news/4470.documentation +++ /dev/null @@ -1 +0,0 @@ -Change from links to inline literals in `CHANGELOG.md` to fix linkcheckbroken. @stevepiercy diff --git a/news/4471.bugfix b/news/4471.bugfix deleted file mode 100644 index eec2978aa9..0000000000 --- a/news/4471.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix history view dropdown for first entry, showing 'Revert to this version option' always @sneridagh diff --git a/news/4473.bugfix b/news/4473.bugfix deleted file mode 100644 index 4314fff4c5..0000000000 --- a/news/4473.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix order of row of long table in edit and view mode @iFlameing \ No newline at end of file diff --git a/news/4475.bugfix b/news/4475.bugfix deleted file mode 100644 index ea4f489eed..0000000000 --- a/news/4475.bugfix +++ /dev/null @@ -1 +0,0 @@ -Improve flaky test in autofocus Cypress tests @sneridagh diff --git a/package.json b/package.json index 16d320e489..1029401f03 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "17.0.0-alpha.0", + "version": "17.0.0-alpha.1", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" diff --git a/packages/volto-slate/package.json b/packages/volto-slate/package.json index 00e9108281..e4ad38ef6e 100644 --- a/packages/volto-slate/package.json +++ b/packages/volto-slate/package.json @@ -1,6 +1,6 @@ { "name": "@plone/volto-slate", - "version": "17.0.0-alpha.0", + "version": "17.0.0-alpha.1", "description": "Slate.js integration with Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", From 7e8ac32115c7defaa2e3ac50e6240412b0aac114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katja=20S=C3=BCss?= Date: Sat, 11 Mar 2023 09:53:20 +0100 Subject: [PATCH 058/142] Fix training urls (Remove /5/) (#4502) --- CHANGELOG.md | 2 +- README.md | 8 ++++---- api/README.rst | 2 +- docs/source/getting-started/others.md | 8 ++++---- news/4502.documentation | 1 + 5 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 news/4502.documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index 641578d18e..02e9f73734 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ diff --git a/README.md b/README.md index c76079a98f..8cdca13cbe 100644 --- a/README.md +++ b/README.md @@ -190,14 +190,14 @@ On the [Plone Trainings Website](https://training.plone.org) you'll find Volto-dedicated open training materials, plus React and other JavaScript-centered trainings. -- [Mastering Plone 6 Development](https://training.plone.org/5/mastering-plone/) +- [Mastering Plone 6 Development](https://training.plone.org/mastering-plone/) The comprehensive training on Plone 6 with best practice tips for developers and integrators. - [Volto](https://training.plone.org/5/volto/index.html) A detailed training on how to create your own website using Volto frontend. -- [Volto Hands-On](https://training.plone.org/5/voltohandson/index.html) -- [Volto Add-ons Development](https://training.plone.org/5/voltoaddons/index.html) +- [Volto Hands-On](https://training.plone.org/voltohandson/index.html) +- [Volto Add-ons Development](https://training.plone.org/voltoaddons/index.html) - [Plone Deployment](https://training.plone.org/5/plone-deployment/index.html) -- [React](https://training.plone.org/5/react/index.html) +- [React](https://training.plone.org/react/index.html) - [JavaScript For Plone Developers](https://training.plone.org/5/javascript/index.html) ## Talks diff --git a/api/README.rst b/api/README.rst index c249527cbc..3203aea283 100644 --- a/api/README.rst +++ b/api/README.rst @@ -45,7 +45,7 @@ are required for cryptography, image handling/scaling support and compression. You can find more up to date details on installing these necessary libraries for linux systems in the 'Mastering Plone' training at --> https://training.plone.org/5/mastering-plone/installation.html#installing-plone-backend +-> https://training.plone.org/mastering-plone/installation.html#installing-plone-backend For Windows you could try WSL (Windows subsystem for Linux) and for Mac OS X for example Homebrew to install these necessary support libraries. diff --git a/docs/source/getting-started/others.md b/docs/source/getting-started/others.md index da86287873..3b5fcf48ea 100644 --- a/docs/source/getting-started/others.md +++ b/docs/source/getting-started/others.md @@ -15,14 +15,14 @@ On the [Plone Trainings Website](https://training.plone.org) you'll find Volto-dedicated open training materials plus React and other Javascript-centered trainings. -- [Mastering Plone 6 Development](https://training.plone.org/5/mastering-plone/) +- [Mastering Plone 6 Development](https://training.plone.org/mastering-plone/) The comprehensive training on Plone 6 with best practice tips for developers and integrators. - [Volto](https://training.plone.org/5/volto/index.html) A detailed training on how to create your own website using Volto frontend. -- [Volto Hands-On](https://training.plone.org/5/voltohandson/index.html) -- [Volto Add-ons Development](https://training.plone.org/5/voltoaddons/index.html) +- [Volto Hands-On](https://training.plone.org/voltohandson/index.html) +- [Volto Add-ons Development](https://training.plone.org/voltoaddons/index.html) - [Plone Deployment](https://training.plone.org/5/plone-deployment/index.html) -- [React](https://training.plone.org/5/react/index.html) +- [React](https://training.plone.org/react/index.html) - [JavaScript For Plone Developers](https://training.plone.org/5/javascript/index.html) ## How does it work under the hood diff --git a/news/4502.documentation b/news/4502.documentation new file mode 100644 index 0000000000..cc20ee1c42 --- /dev/null +++ b/news/4502.documentation @@ -0,0 +1 @@ +Fix training urls @ksuess \ No newline at end of file From b5bafd5b2be339539f1a384dbe7137235b2506ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katja=20S=C3=BCss?= Date: Tue, 14 Mar 2023 11:01:00 +0100 Subject: [PATCH 059/142] Mark empty listings for optional hiding, per variation or globally (#4474) --- news/4393.feature | 1 + src/components/manage/Blocks/Listing/Edit.jsx | 5 - .../manage/Blocks/Listing/ListingBody.jsx | 138 ++++++++++-------- src/components/manage/Blocks/Listing/View.jsx | 4 - .../__snapshots__/ListingBody.test.jsx.snap | 4 +- 5 files changed, 81 insertions(+), 71 deletions(-) create mode 100644 news/4393.feature diff --git a/news/4393.feature b/news/4393.feature new file mode 100644 index 0000000000..977e5aec23 --- /dev/null +++ b/news/4393.feature @@ -0,0 +1 @@ +Add option to hide empty listing blocks @ksuess \ No newline at end of file diff --git a/src/components/manage/Blocks/Listing/Edit.jsx b/src/components/manage/Blocks/Listing/Edit.jsx index 9f3d632b75..f447211415 100644 --- a/src/components/manage/Blocks/Listing/Edit.jsx +++ b/src/components/manage/Blocks/Listing/Edit.jsx @@ -47,14 +47,9 @@ const Edit = React.memo( ? intl.formatMessage(messages.results) : intl.formatMessage(messages.items)); - const HeadlineTag = data.headlineTag || 'h2'; - return ( <>

    {placeholder}

    - {data.headline && ( - {data.headline} - )} { ? variation.noResultsComponent : config.blocks?.blocksConfig['listing'].noResultsComponent; - return listingItems?.length > 0 ? ( -
    - - {totalPages > 1 && ( -
    - { - !isEditMode && - listingRef.current.scrollIntoView({ behavior: 'smooth' }); - onPaginationChange(e, { activePage }); - }} - firstItem={null} - lastItem={null} - prevItem={{ - content: , - icon: true, - 'aria-disabled': !prevBatch, - className: !prevBatch ? 'disabled' : null, - }} - nextItem={{ - content: , - icon: true, - 'aria-disabled': !nextBatch, - className: !nextBatch ? 'disabled' : null, - }} + const HeadlineTag = data.headlineTag || 'h2'; + + return ( + <> + {data.headline && ( + 0, + })} + > + {data.headline} + + )} + {listingItems?.length > 0 ? ( +
    + + {totalPages > 1 && ( +
    + { + !isEditMode && + listingRef.current.scrollIntoView({ behavior: 'smooth' }); + onPaginationChange(e, { activePage }); + }} + firstItem={null} + lastItem={null} + prevItem={{ + content: , + icon: true, + 'aria-disabled': !prevBatch, + className: !prevBatch ? 'disabled' : null, + }} + nextItem={{ + content: , + icon: true, + 'aria-disabled': !nextBatch, + className: !nextBatch ? 'disabled' : null, + }} + /> +
    + )} +
    + ) : isEditMode ? ( +
    + {isFolderContentsListing && ( + + )} + {hasLoaded && NoResults && ( + + )} + + + + + +
    + ) : ( +
    + {hasLoaded && NoResults && ( + + )} + + + + +
    )} -
    - ) : isEditMode ? ( -
    - {isFolderContentsListing && ( - - )} - {hasLoaded && NoResults && ( - - )} - - - - - -
    - ) : ( -
    - {hasLoaded && NoResults && ( - - )} - - - - - -
    + ); }); diff --git a/src/components/manage/Blocks/Listing/View.jsx b/src/components/manage/Blocks/Listing/View.jsx index 5c69b38b0d..b70adfdf0b 100644 --- a/src/components/manage/Blocks/Listing/View.jsx +++ b/src/components/manage/Blocks/Listing/View.jsx @@ -7,15 +7,11 @@ import { ListingBlockBody as ListingBody } from '@plone/volto/components'; const View = (props) => { const { data, path, pathname, className } = props; - const HeadlineTag = data.headlineTag || 'h2'; return (
    - {data.headline && ( - {data.headline} - )}
    ); diff --git a/src/components/manage/Blocks/Listing/__snapshots__/ListingBody.test.jsx.snap b/src/components/manage/Blocks/Listing/__snapshots__/ListingBody.test.jsx.snap index d91cbc9314..e81db3c83f 100644 --- a/src/components/manage/Blocks/Listing/__snapshots__/ListingBody.test.jsx.snap +++ b/src/components/manage/Blocks/Listing/__snapshots__/ListingBody.test.jsx.snap @@ -1,7 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`renders a ListingBody component 1`] = ` -
    +
    Date: Tue, 14 Mar 2023 23:28:54 -0600 Subject: [PATCH 060/142] Add hamburger menu animation (#4433) Co-authored-by: David Glick --- news/4433.feature | 1 + package.json | 1 - theme/themes/pastanaga/extras/main.less | 81 ++++++++++++++++++++++++- yarn.lock | 8 --- 4 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 news/4433.feature diff --git a/news/4433.feature b/news/4433.feature new file mode 100644 index 0000000000..c0047b763a --- /dev/null +++ b/news/4433.feature @@ -0,0 +1 @@ +Add custom CSS animation to hamburger menu, to avoid third party dependency. @danalvrz \ No newline at end of file diff --git a/package.json b/package.json index 1029401f03..3d31a28ee5 100644 --- a/package.json +++ b/package.json @@ -290,7 +290,6 @@ "express": "4.17.3", "filesize": "6", "glob": "7.1.6", - "hamburgers": "1.1.3", "history": "4.10.1", "hoist-non-react-statics": "3.3.2", "html-webpack-plugin": "5.5.0", diff --git a/theme/themes/pastanaga/extras/main.less b/theme/themes/pastanaga/extras/main.less index 6aeb31658c..4d294b67ea 100644 --- a/theme/themes/pastanaga/extras/main.less +++ b/theme/themes/pastanaga/extras/main.less @@ -8,7 +8,6 @@ @import (multiple) '../../theme.config'; // Extras (third party libs) -@import (less) '~hamburgers/dist/hamburgers.css'; @import (less) '~react-toastify/dist/ReactToastify.css'; // Mixins @@ -494,6 +493,86 @@ fieldset.invisible { .hamburger-wrapper { position: relative; z-index: 5; + width: 70px; + height: 59px; + padding: 15px 15px; + + .hamburger { + position: relative; + width: 40px; + height: 24px; + padding: 0; + border: none; + background-color: transparent; + cursor: pointer; + transition: 0.3s ease-in-out; + } + + .hamburger::after { + position: absolute; + top: 0; + left: 0; + display: inline-block; + width: 100%; + height: 4px; + background-color: #000; + border-radius: 4px; + content: ''; + transition: 0.3s ease-in-out; + } + + .hamburger::before { + position: absolute; + top: 20px; + left: 0; + display: inline-block; + width: 100%; + height: 4px; + background-color: #000; + border-radius: 4px; + content: ''; + transition: 0.3s ease-in-out; + } + + .hamburger-inner { + position: absolute; + top: 10px; + left: 0; + display: inline-block; + width: 100%; + height: 4px; + border-radius: 4px; + transition: 0.3s ease-in-out; + } + + .hamburger.is-active::after, + .hamburger.is-active::before { + top: 10px; + left: 50%; + width: 0%; + } + + .hamburger-inner::after, + .hamburger-inner::before { + position: absolute; + top: 0; + left: 0; + display: block; + width: 100%; + height: 4px; + background-color: #000; + border-radius: 4px; + content: ''; + transition: 0.3s ease-in-out; + } + + .hamburger.is-active .hamburger-inner::after { + transform: rotate(45deg); + } + + .hamburger.is-active .hamburger-inner::before { + transform: rotate(-45deg); + } } .mobile-menu { diff --git a/yarn.lock b/yarn.lock index b79af047a6..b4f27635da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2700,7 +2700,6 @@ __metadata: filesize: 6 full-icu: 1.4.0 glob: 7.1.6 - hamburgers: 1.1.3 history: 4.10.1 hoist-non-react-statics: 3.3.2 html-webpack-plugin: 5.5.0 @@ -12460,13 +12459,6 @@ __metadata: languageName: node linkType: hard -"hamburgers@npm:1.1.3": - version: 1.1.3 - resolution: "hamburgers@npm:1.1.3" - checksum: 932c1cfa7c8c645d5f8778ee50b762f819be935a4c2275604570cd6043a0850a2f5638714a7ddd4b19d3e2e6ff91e161b08be750f9ce8a43a6d70926ce6a3eff - languageName: node - linkType: hard - "handle-thing@npm:^2.0.0": version: 2.0.1 resolution: "handle-thing@npm:2.0.1" From 70fec9804566dc5de6dd7996652d6b0d5297e014 Mon Sep 17 00:00:00 2001 From: David Glick Date: Wed, 15 Mar 2023 03:22:50 -0700 Subject: [PATCH 061/142] Combined dependency updates (#4520) --- news/4520.bugfix | 1 + package.json | 4 +- packages/generator-volto/package.json | 1 - packages/generator-volto/yarn.lock | 22 ++----- packages/scripts/yarn.lock | 27 +++------ yarn.lock | 82 +++++++-------------------- 6 files changed, 38 insertions(+), 99 deletions(-) create mode 100644 news/4520.bugfix diff --git a/news/4520.bugfix b/news/4520.bugfix new file mode 100644 index 0000000000..19630ab2e3 --- /dev/null +++ b/news/4520.bugfix @@ -0,0 +1 @@ +Patch updates for some dependencies. @davisagli diff --git a/package.json b/package.json index 3d31a28ee5..775e6bd938 100644 --- a/package.json +++ b/package.json @@ -301,7 +301,6 @@ "is-hotkey": "0.2.0", "is-url": "1.2.4", "jest-file": "1.0.0", - "jsonwebtoken": "8.3.0", "jwt-decode": "2.2.0", "less": "3.11.1", "less-loader": "11.1.0", @@ -399,7 +398,7 @@ "universal-cookie-express": "4.0.3", "use-deep-compare-effect": "1.8.1", "uuid": "^8.3.2", - "webpack": "5.75.0", + "webpack": "5.76.1", "webpack-dev-server": "4.11.1", "webpack-node-externals": "3.0.0", "xmlrpc": "1.3.2", @@ -418,6 +417,7 @@ "identity-obj-proxy": "3.0.0", "jest": "26.6.3", "jest-environment-jsdom": "^26", + "jsonwebtoken": "9.0.0", "react-error-overlay": "6.0.9", "react-is": "^16.13.1", "release-it": "^15.1.3", diff --git a/packages/generator-volto/package.json b/packages/generator-volto/package.json index 49f9944101..022f0bc334 100644 --- a/packages/generator-volto/package.json +++ b/packages/generator-volto/package.json @@ -108,7 +108,6 @@ "fs-extra": "3.0.0", "gitly": "2.0.3", "mkdirp-then": "1.2.0", - "ms": "1.0.0", "mz": "2.6.0", "ora": "1.2.0", "promise": "7.1.1", diff --git a/packages/generator-volto/yarn.lock b/packages/generator-volto/yarn.lock index 9e0129dc37..6e2114304e 100644 --- a/packages/generator-volto/yarn.lock +++ b/packages/generator-volto/yarn.lock @@ -682,7 +682,6 @@ __metadata: jest: ^24.8.0 lint-staged: ^9.4.3 mkdirp-then: 1.2.0 - ms: 1.0.0 mz: 2.6.0 ora: 1.2.0 prettier: 2.0.5 @@ -4150,9 +4149,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard @@ -5635,13 +5634,11 @@ __metadata: linkType: hard "json5@npm:^2.1.2": - version: 2.1.3 - resolution: "json5@npm:2.1.3" - dependencies: - minimist: ^1.2.5 + version: 2.2.3 + resolution: "json5@npm:2.2.3" bin: json5: lib/cli.js - checksum: b2de57a66520eca0fbb6c5ef59249b8308efb93fe89a8c75f5a6846e4f5f7d99a5a6f2e4db4d7a1c7047802dd816ed602a052d147a415d0e6b7f834885b62bc3 + checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 languageName: node linkType: hard @@ -6434,13 +6431,6 @@ __metadata: languageName: node linkType: hard -"ms@npm:1.0.0": - version: 1.0.0 - resolution: "ms@npm:1.0.0" - checksum: d8df74551552ffce335dcb07b77fae25573b6e83789cd58e04c6bd5652095390d55e5be54ec8e143b6dbb785b61615f6a314d5d8e1a141fdf53cf3596d8972b5 - languageName: node - linkType: hard - "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" diff --git a/packages/scripts/yarn.lock b/packages/scripts/yarn.lock index ed87c69c84..1c6cc01244 100644 --- a/packages/scripts/yarn.lock +++ b/packages/scripts/yarn.lock @@ -3244,9 +3244,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.0.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard @@ -3599,23 +3599,12 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.1.2": - version: 2.2.0 - resolution: "json5@npm:2.2.0" - dependencies: - minimist: ^1.2.5 - bin: - json5: lib/cli.js - checksum: e88fc5274bb58fc99547baa777886b069d2dd96d9cfc4490b305fd16d711dabd5979e35a4f90873cefbeb552e216b041a304fe56702bedba76e19bc7845f208d - languageName: node - linkType: hard - -"json5@npm:^2.2.1": - version: 2.2.1 - resolution: "json5@npm:2.2.1" +"json5@npm:^2.1.2, json5@npm:^2.2.1": + version: 2.2.3 + resolution: "json5@npm:2.2.3" bin: json5: lib/cli.js - checksum: 74b8a23b102a6f2bf2d224797ae553a75488b5adbaee9c9b6e5ab8b510a2fc6e38f876d4c77dea672d4014a44b2399e15f2051ac2b37b87f74c0c7602003543b + checksum: 2a7436a93393830bce797d4626275152e37e877b265e94ca69c99e3d20c2b9dab021279146a39cdb700e71b2dd32a4cebd1514cd57cee102b1af906ce5040349 languageName: node linkType: hard @@ -3843,7 +3832,7 @@ __metadata: languageName: node linkType: hard -"minimist@npm:^1.2.0, minimist@npm:^1.2.5": +"minimist@npm:^1.2.0": version: 1.2.6 resolution: "minimist@npm:1.2.6" checksum: d15428cd1e11eb14e1233bcfb88ae07ed7a147de251441d61158619dfb32c4d7e9061d09cab4825fdee18ecd6fce323228c8c47b5ba7cd20af378ca4048fb3fb diff --git a/yarn.lock b/yarn.lock index b4f27635da..6c08fb44f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2713,7 +2713,7 @@ __metadata: jest: 26.6.3 jest-environment-jsdom: ^26 jest-file: 1.0.0 - jsonwebtoken: 8.3.0 + jsonwebtoken: 9.0.0 jwt-decode: 2.2.0 less: 3.11.1 less-loader: 11.1.0 @@ -2816,7 +2816,7 @@ __metadata: use-deep-compare-effect: 1.8.1 use-trace-update: 1.3.2 uuid: ^8.3.2 - webpack: 5.75.0 + webpack: 5.76.1 webpack-dev-server: 4.11.1 webpack-node-externals: 3.0.0 why: 0.6.2 @@ -8335,9 +8335,9 @@ __metadata: linkType: hard "cookiejar@npm:^2.1.0": - version: 2.1.3 - resolution: "cookiejar@npm:2.1.3" - checksum: 88259983ebc52ceb23cdacfa48762b6a518a57872eff1c7ed01d214fff5cf492e2660d7d5c04700a28f1787a76811df39e8639f8e17670b3cf94ecd86e161f07 + version: 2.1.4 + resolution: "cookiejar@npm:2.1.4" + checksum: c4442111963077dc0e5672359956d6556a195d31cbb35b528356ce5f184922b99ac48245ac05ed86cf993f7df157c56da10ab3efdadfed79778a0d9b1b092d5b languageName: node linkType: hard @@ -12971,9 +12971,9 @@ __metadata: linkType: hard "http-cache-semantics@npm:^4.1.0": - version: 4.1.0 - resolution: "http-cache-semantics@npm:4.1.0" - checksum: 974de94a81c5474be07f269f9fd8383e92ebb5a448208223bfb39e172a9dbc26feff250192ecc23b9593b3f92098e010406b0f24bd4d588d631f80214648ed42 + version: 4.1.1 + resolution: "http-cache-semantics@npm:4.1.1" + checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236 languageName: node linkType: hard @@ -15265,20 +15265,15 @@ __metadata: languageName: node linkType: hard -"jsonwebtoken@npm:8.3.0": - version: 8.3.0 - resolution: "jsonwebtoken@npm:8.3.0" +"jsonwebtoken@npm:9.0.0": + version: 9.0.0 + resolution: "jsonwebtoken@npm:9.0.0" dependencies: - jws: ^3.1.5 - lodash.includes: ^4.3.0 - lodash.isboolean: ^3.0.3 - lodash.isinteger: ^4.0.4 - lodash.isnumber: ^3.0.3 - lodash.isplainobject: ^4.0.6 - lodash.isstring: ^4.0.1 - lodash.once: ^4.0.0 + jws: ^3.2.2 + lodash: ^4.17.21 ms: ^2.1.1 - checksum: b1225914e32bd44389872c9fbc1306eecad7e4aac031e33e39915b5ad687d92f10cd0dd0bcfc29cada26fb98fd04c6f39379b7d3634e173196cd1b239f663520 + semver: ^7.3.8 + checksum: b9181cecf9df99f1dc0253f91ba000a1aa4d91f5816d1608c0dba61a5623726a0bfe200b51df25de18c1a6000825d231ad7ce2788aa54fd48dcb760ad9eb9514 languageName: node linkType: hard @@ -15341,7 +15336,7 @@ __metadata: languageName: node linkType: hard -"jws@npm:^3.1.5": +"jws@npm:^3.2.2": version: 3.2.2 resolution: "jws@npm:3.2.2" dependencies: @@ -15762,34 +15757,6 @@ __metadata: languageName: node linkType: hard -"lodash.includes@npm:^4.3.0": - version: 4.3.0 - resolution: "lodash.includes@npm:4.3.0" - checksum: 71092c130515a67ab3bd928f57f6018434797c94def7f46aafa417771e455ce3a4834889f4267b17887d7f75297dfabd96231bf704fd2b8c5096dc4a913568b6 - languageName: node - linkType: hard - -"lodash.isboolean@npm:^3.0.3": - version: 3.0.3 - resolution: "lodash.isboolean@npm:3.0.3" - checksum: b70068b4a8b8837912b54052557b21fc4774174e3512ed3c5b94621e5aff5eb6c68089d0a386b7e801d679cd105d2e35417978a5e99071750aa2ed90bffd0250 - languageName: node - linkType: hard - -"lodash.isinteger@npm:^4.0.4": - version: 4.0.4 - resolution: "lodash.isinteger@npm:4.0.4" - checksum: 6034821b3fc61a2ffc34e7d5644bb50c5fd8f1c0121c554c21ac271911ee0c0502274852845005f8651d51e199ee2e0cfebfe40aaa49c7fe617f603a8a0b1691 - languageName: node - linkType: hard - -"lodash.isnumber@npm:^3.0.3": - version: 3.0.3 - resolution: "lodash.isnumber@npm:3.0.3" - checksum: 913784275b565346255e6ae6a6e30b760a0da70abc29f3e1f409081585875105138cda4a429ff02577e1bc0a7ae2a90e0a3079a37f3a04c3d6c5aaa532f4cab2 - languageName: node - linkType: hard - "lodash.isplainobject@npm:^4.0.6": version: 4.0.6 resolution: "lodash.isplainobject@npm:4.0.6" @@ -15797,13 +15764,6 @@ __metadata: languageName: node linkType: hard -"lodash.isstring@npm:^4.0.1": - version: 4.0.1 - resolution: "lodash.isstring@npm:4.0.1" - checksum: eaac87ae9636848af08021083d796e2eea3d02e80082ab8a9955309569cb3a463ce97fd281d7dc119e402b2e7d8c54a23914b15d2fc7fff56461511dc8937ba0 - languageName: node - linkType: hard - "lodash.memoize@npm:^4.1.2": version: 4.1.2 resolution: "lodash.memoize@npm:4.1.2" @@ -15818,7 +15778,7 @@ __metadata: languageName: node linkType: hard -"lodash.once@npm:^4.0.0, lodash.once@npm:^4.1.1": +"lodash.once@npm:^4.1.1": version: 4.1.1 resolution: "lodash.once@npm:4.1.1" checksum: d768fa9f9b4e1dc6453be99b753906f58990e0c45e7b2ca5a3b40a33111e5d17f6edf2f768786e2716af90a8e78f8f91431ab8435f761fef00f9b0c256f6d245 @@ -24945,9 +24905,9 @@ __metadata: languageName: node linkType: hard -"webpack@npm:5.75.0, webpack@npm:>=4.43.0 <6.0.0, webpack@npm:^5.9.0": - version: 5.75.0 - resolution: "webpack@npm:5.75.0" +"webpack@npm:5.76.1, webpack@npm:>=4.43.0 <6.0.0, webpack@npm:^5.9.0": + version: 5.76.1 + resolution: "webpack@npm:5.76.1" dependencies: "@types/eslint-scope": ^3.7.3 "@types/estree": ^0.0.51 @@ -24978,7 +24938,7 @@ __metadata: optional: true bin: webpack: bin/webpack.js - checksum: 2bcc5f3c195f375944e8af2f00bf2feea39cb9fda5f763b0d1b00077f1c51783db25c94d3fae96a07dead9fa085e6ae7474417e5ab31719c9776ea5969ceb83a + checksum: b01fe0bc2dbca0e10d290ddb0bf81e807a031de48028176e2b21afd696b4d3f25ab9accdad888ef4a1f7c7f4d41f13d5bf2395b7653fdf3e5e3dafa54e56dab2 languageName: node linkType: hard From 45ecca3222cf1a8672605f8b055dd80e300ca44d Mon Sep 17 00:00:00 2001 From: dobri1408 <50819975+dobri1408@users.noreply.github.com> Date: Wed, 15 Mar 2023 12:25:59 +0200 Subject: [PATCH 062/142] (fix): Paste button disappearing while coping from nested blocks (#4505) Co-authored-by: Tiberiu Ichim --- news/4505.bugfix | 1 + src/components/manage/Form/BlocksToolbar.jsx | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 news/4505.bugfix diff --git a/news/4505.bugfix b/news/4505.bugfix new file mode 100644 index 0000000000..bcefcf8101 --- /dev/null +++ b/news/4505.bugfix @@ -0,0 +1 @@ +(fix): Paste button disappearing while coping from nested blocks @dobri1408 diff --git a/src/components/manage/Form/BlocksToolbar.jsx b/src/components/manage/Form/BlocksToolbar.jsx index 87c3554f68..49a315d8c6 100644 --- a/src/components/manage/Form/BlocksToolbar.jsx +++ b/src/components/manage/Form/BlocksToolbar.jsx @@ -177,7 +177,11 @@ export class BlocksToolbarComponent extends React.Component { '' )} {selectedBlock && (blocksClipboard?.cut || blocksClipboard?.copy) && ( - + + )} {this.state.linkIntegrityBreakages.length > 0 ? (

    From 2a4c0dce31c8e83bf3cd895bc4d61a53d5c765ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Wed, 15 Mar 2023 18:27:01 +0100 Subject: [PATCH 073/142] 4433 as a breaking change, add upgrade guide (#4540) --- docs/source/upgrade-guide/index.md | 5 +++++ news/4433.breaking | 1 + news/4433.feature | 1 - 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 news/4433.breaking delete mode 100644 news/4433.feature diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index 30cb937c14..e31d31806a 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -59,6 +59,11 @@ This is better from the UI point of view, since any other element can take prece If you have customized the `BlockChooser` in any way could be that this now could interact with your customizations. +### Removed `hamburgers` library + +The `hamburgers` library was removed from core Volto, replaced by a much more lightweight approach. +If your theme or add-ons relied on it, add it again as a dependency in them, or adopt the CSS part that you are using in them. + (volto-upgrade-guide-16.x.x)= ## Upgrading to Volto 16.x.x diff --git a/news/4433.breaking b/news/4433.breaking new file mode 100644 index 0000000000..9fd7e71cb8 --- /dev/null +++ b/news/4433.breaking @@ -0,0 +1 @@ +Add custom CSS animation to hamburger menu. Removed `hamburgers` dependency. @danalvrz diff --git a/news/4433.feature b/news/4433.feature deleted file mode 100644 index c0047b763a..0000000000 --- a/news/4433.feature +++ /dev/null @@ -1 +0,0 @@ -Add custom CSS animation to hamburger menu, to avoid third party dependency. @danalvrz \ No newline at end of file From 889d25486971a866acad03408616a5c6313bdc82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Wed, 15 Mar 2023 19:35:06 +0100 Subject: [PATCH 074/142] Add upgrade guide for 4504 (#4542) --- docs/source/upgrade-guide/index.md | 6 ++++++ news/4542.documentation | 1 + 2 files changed, 7 insertions(+) create mode 100644 news/4542.documentation diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index e31d31806a..02cace9ff7 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -64,6 +64,12 @@ If you have customized the `BlockChooser` in any way could be that this now coul The `hamburgers` library was removed from core Volto, replaced by a much more lightweight approach. If your theme or add-ons relied on it, add it again as a dependency in them, or adopt the CSS part that you are using in them. +### Fixed i18n script by taking into account the real add-on order + +By fixing this, we are potentially breaking how the locales were applied, since now the order will be the correct. +Please check the translations of your project and add-ons and verify that the translations are still correct. +This could be specially true if you did translation overrides or two add-ons were using different translations for the same `msgid` or there were conflicting `msgid` in different add-ons. + (volto-upgrade-guide-16.x.x)= ## Upgrading to Volto 16.x.x diff --git a/news/4542.documentation b/news/4542.documentation new file mode 100644 index 0000000000..7ee1bc739a --- /dev/null +++ b/news/4542.documentation @@ -0,0 +1 @@ +Add upgrade guide for 4504 @sneridagh From 65fd8a737d4f4c07097703b83d49142e65f597e2 Mon Sep 17 00:00:00 2001 From: Rob Gietema Date: Wed, 15 Mar 2023 19:37:40 +0100 Subject: [PATCH 075/142] Make Drag and Drop list work with container-type inline-size. (#4497) --- news/4497.bugfix | 1 + .../manage/DragDropList/DragDropList.jsx | 105 +++++++++++------- 2 files changed, 64 insertions(+), 42 deletions(-) create mode 100644 news/4497.bugfix diff --git a/news/4497.bugfix b/news/4497.bugfix new file mode 100644 index 0000000000..521ca84511 --- /dev/null +++ b/news/4497.bugfix @@ -0,0 +1 @@ +Make Drag and Drop list work with container-type inline-size. @robgietema \ No newline at end of file diff --git a/src/components/manage/DragDropList/DragDropList.jsx b/src/components/manage/DragDropList/DragDropList.jsx index 0e78531429..c1e9d9ec03 100644 --- a/src/components/manage/DragDropList/DragDropList.jsx +++ b/src/components/manage/DragDropList/DragDropList.jsx @@ -3,7 +3,7 @@ import { isEmpty } from 'lodash'; import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable'; import { v4 as uuid } from 'uuid'; -const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex) => { +const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex, uid) => { // Because of the margin rendering rules, there is no easy // way to calculate the offset of the placeholder. // @@ -13,12 +13,16 @@ const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex) => { // // To get a placeholder that looks good in all cases, we // fill up the space between the previous and the next element. - const childrenArray = [...draggedDOM.parentNode.children]; + const queryAttr = 'data-rbd-droppable-id'; + const domQuery = `[${queryAttr}='${uid}']`; + const parentDOM = document.querySelector(domQuery); + + const childrenArray = [...parentDOM.children]; // Remove the source element childrenArray.splice(sourceIndex, 1); // Also remove the placeholder that the library always inserts at the end childrenArray.splice(-1, 1); - const parentRect = draggedDOM.parentNode.getBoundingClientRect(); + const parentRect = parentDOM.getBoundingClientRect(); const prevNode = childrenArray[destinationIndex - 1]; const nextNode = childrenArray[destinationIndex]; let top, bottom; @@ -40,9 +44,7 @@ const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex) => { return { clientY: top, clientHeight: bottom - top, - clientX: parseFloat( - window.getComputedStyle(draggedDOM.parentNode).paddingLeft, - ), + clientX: parseFloat(window.getComputedStyle(parentDOM).paddingLeft), clientWidth: draggedDOM.clientWidth, }; }; @@ -63,17 +65,22 @@ const DragDropList = (props) => { // queueing timed action const timer = useRef(null); - const onDragStart = React.useCallback((event) => { - clearTimeout(timer.current); - const queryAttr = 'data-rbd-draggable-id'; - const domQuery = `[${queryAttr}='${event.draggableId}']`; - const draggedDOM = document.querySelector(domQuery); - if (!draggedDOM) { - return; - } - const sourceIndex = event.source.index; - setPlaceholderProps(getPlaceholder(draggedDOM, sourceIndex, sourceIndex)); - }, []); + const onDragStart = React.useCallback( + (event) => { + clearTimeout(timer.current); + const queryAttr = 'data-rbd-draggable-id'; + const domQuery = `[${queryAttr}='${event.draggableId}']`; + const draggedDOM = document.querySelector(domQuery); + if (!draggedDOM) { + return; + } + const sourceIndex = event.source.index; + setPlaceholderProps( + getPlaceholder(draggedDOM, sourceIndex, sourceIndex, uid), + ); + }, + [uid], + ); const onDragEnd = React.useCallback( (result) => { @@ -84,30 +91,33 @@ const DragDropList = (props) => { [onMoveItem], ); - const onDragUpdate = React.useCallback((update) => { - clearTimeout(timer.current); - setPlaceholderProps({}); - if (!update.destination) { - return; - } - const draggableId = update.draggableId; - const queryAttr = 'data-rbd-draggable-id'; - const domQuery = `[${queryAttr}='${draggableId}']`; - const draggedDOM = document.querySelector(domQuery); - if (!draggedDOM) { - return; - } - const sourceIndex = update.source.index; - const destinationIndex = update.destination.index; - // Wait until the animations have finished, to make it look good. - timer.current = setTimeout( - () => - setPlaceholderProps( - getPlaceholder(draggedDOM, sourceIndex, destinationIndex), - ), - 250, - ); - }, []); + const onDragUpdate = React.useCallback( + (update) => { + clearTimeout(timer.current); + setPlaceholderProps({}); + if (!update.destination) { + return; + } + const draggableId = update.draggableId; + const queryAttr = 'data-rbd-draggable-id'; + const domQuery = `[${queryAttr}='${draggableId}']`; + const draggedDOM = document.querySelector(domQuery); + if (!draggedDOM) { + return; + } + const sourceIndex = update.source.index; + const destinationIndex = update.destination.index; + // Wait until the animations have finished, to make it look good. + timer.current = setTimeout( + () => + setPlaceholderProps( + getPlaceholder(draggedDOM, sourceIndex, destinationIndex, uid), + ), + 250, + ); + }, + [uid], + ); const AsDomComponent = as; return ( @@ -116,7 +126,18 @@ const DragDropList = (props) => { onDragUpdate={onDragUpdate} onDragEnd={onDragEnd} > - + { + const index = rubric.source.index; + return children({ + child: childList[index][1], + childId: childList[index][0], + index, + draginfo: provided, + }); + }} + > {(provided, snapshot) => ( Date: Wed, 15 Mar 2023 19:51:11 +0100 Subject: [PATCH 076/142] Update 16.16.0 and 16.17.0 releases changelog (#4544) --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02e9f73734..42c95bf61c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,35 @@ - Fix English and MyST grammar and syntax from PR #4285 @stevepiercy [#4331](https://github.com/plone/volto/issues/4331) - Use a universal static path for both documentation and volto repos. @stevepiercy [#4376](https://github.com/plone/volto/issues/4376) +## 16.17.0 (2023-03-15) + +### Feature + +- Add option to hide empty listing blocks @ksuess [#4393](https://github.com/plone/volto/issues/4393) + +### Bugfix + +- Added block prop to BlockDataForm in the Edit component of ToC. If block is not passed, OnChangeBlock will be called with undefined block id. @tedw87 [#4110](https://github.com/plone/volto/issues/4110) +- Fix focus steal in Form @tedw87 [#4230](https://github.com/plone/volto/issues/4230) +- Fixed paste issue in Table Block and added cypress test for pasting text in Table Block. [#4301](https://github.com/plone/volto/issues/4301) +- Fixed i18n script to avoid overwriting translations with an empty msgstr @danalvrz [#4316](https://github.com/plone/volto/issues/4316) +- bugfix: conditionally render all delete items in confirm widget [#4336](https://github.com/plone/volto/issues/4336) +- Make the Site Setup control panel responsive for small screen devices. @lord2anil [#4484](https://github.com/plone/volto/issues/4484) +- The menu for the contents page was unresponsive on mobile devices. Fixed this by changing the menu overflow to scroll. @sudhanshu1309 [#4492](https://github.com/plone/volto/issues/4492) +- (fix): Paste button disappearing while coping from nested blocks @dobri1408 [#4505](https://github.com/plone/volto/issues/4505) +- Fix flaky Cypress test introduced in #4521 @sneridagh [#4522](https://github.com/plone/volto/issues/4522) + +### Documentation + +- Fix training urls @ksuess [#4502](https://github.com/plone/volto/issues/4502) + + +## 16.16.0 (2023-03-09) + +### Feature + +- Add directive to cache stable resources in browser or intermediate server for 365 days by default directly in the SSR Express server, static resource that could change after a new deployment for 1 minute. @mamico [#2216](https://github.com/plone/volto/issues/2216) + ## 16.15.0 (2023-03-08) From 9687a74e81c3f9740fcb944cb3f726c1ba391caa Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Wed, 15 Mar 2023 20:08:22 +0100 Subject: [PATCH 077/142] Release 17.0.0-alpha.2 --- CHANGELOG.md | 32 +++++++++++++++++++++++++++++++ news/3997.bugfix | 1 - news/4110.bugfix | 1 - news/4230.bugfix | 1 - news/4301.bugfix | 1 - news/4316.bugfix | 1 - news/4336.bugfix | 1 - news/4393.feature | 1 - news/4433.breaking | 1 - news/4484.bugfix | 2 -- news/4492.bugfix | 1 - news/4495.breaking | 1 - news/4497.bugfix | 1 - news/4502.documentation | 1 - news/4505.bugfix | 1 - news/4520.bugfix | 1 - news/4522.bugfix | 1 - news/4542.documentation | 1 - package.json | 2 +- packages/volto-slate/package.json | 2 +- 20 files changed, 34 insertions(+), 20 deletions(-) delete mode 100644 news/3997.bugfix delete mode 100644 news/4110.bugfix delete mode 100644 news/4230.bugfix delete mode 100644 news/4301.bugfix delete mode 100644 news/4316.bugfix delete mode 100644 news/4336.bugfix delete mode 100644 news/4393.feature delete mode 100644 news/4433.breaking delete mode 100644 news/4484.bugfix delete mode 100644 news/4492.bugfix delete mode 100644 news/4495.breaking delete mode 100644 news/4497.bugfix delete mode 100644 news/4502.documentation delete mode 100644 news/4505.bugfix delete mode 100644 news/4520.bugfix delete mode 100644 news/4522.bugfix delete mode 100644 news/4542.documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index 42c95bf61c..3a4a695541 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,38 @@ +## 17.0.0-alpha.2 (2023-03-15) + +### Breaking + +- Add custom CSS animation to hamburger menu. Removed `hamburgers` dependency. @danalvrz [#4433](https://github.com/plone/volto/issues/4433) +- Improve i18n script ordering of addons, so that addons can override translations from their dependencies. @davisagli [#4495](https://github.com/plone/volto/issues/4495) + +### Feature + +- Add option to hide empty listing blocks @ksuess [#4393](https://github.com/plone/volto/issues/4393) + +### Bugfix + +- Update build dependencies (razzle and react-dev-utils) @davisagli [#3997](https://github.com/plone/volto/issues/3997) +- Added block prop to BlockDataForm in the Edit component of ToC. If block is not passed, OnChangeBlock will be called with undefined block id. @tedw87 [#4110](https://github.com/plone/volto/issues/4110) +- Fix focus steal in Form @tedw87 [#4230](https://github.com/plone/volto/issues/4230) +- Fixed paste issue in Table Block and added cypress test for pasting text in Table Block. [#4301](https://github.com/plone/volto/issues/4301) +- Fixed i18n script to avoid overwriting translations with an empty msgstr @danalvrz [#4316](https://github.com/plone/volto/issues/4316) +- bugfix: conditionally render all delete items in confirm widget [#4336](https://github.com/plone/volto/issues/4336) +- Make the Site Setup control panel responsive for small screen devices. @lord2anil [#4484](https://github.com/plone/volto/issues/4484) +- The menu for the contents page was unresponsive on mobile devices. Fixed this by changing the menu overflow to scroll. @sudhanshu1309 [#4492](https://github.com/plone/volto/issues/4492) +- Make Drag and Drop list work with container-type inline-size. @robgietema [#4497](https://github.com/plone/volto/issues/4497) +- (fix): Paste button disappearing while coping from nested blocks @dobri1408 [#4505](https://github.com/plone/volto/issues/4505) +- Patch updates for some dependencies. @davisagli [#4520](https://github.com/plone/volto/issues/4520) +- Fix flaky Cypress test introduced in #4521 @sneridagh [#4522](https://github.com/plone/volto/issues/4522) + +### Documentation + +- Fix training urls @ksuess [#4502](https://github.com/plone/volto/issues/4502) +- Add upgrade guide for 4504 @sneridagh [#4542](https://github.com/plone/volto/issues/4542) + + ## 17.0.0-alpha.1 (2023-03-09) ### Feature diff --git a/news/3997.bugfix b/news/3997.bugfix deleted file mode 100644 index 78fd386d0a..0000000000 --- a/news/3997.bugfix +++ /dev/null @@ -1 +0,0 @@ -Update build dependencies (razzle and react-dev-utils) @davisagli diff --git a/news/4110.bugfix b/news/4110.bugfix deleted file mode 100644 index 6d0a130901..0000000000 --- a/news/4110.bugfix +++ /dev/null @@ -1 +0,0 @@ -Added block prop to BlockDataForm in the Edit component of ToC. If block is not passed, OnChangeBlock will be called with undefined block id. @tedw87 \ No newline at end of file diff --git a/news/4230.bugfix b/news/4230.bugfix deleted file mode 100644 index a685d65a5d..0000000000 --- a/news/4230.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix focus steal in Form @tedw87 \ No newline at end of file diff --git a/news/4301.bugfix b/news/4301.bugfix deleted file mode 100644 index dacf3365a1..0000000000 --- a/news/4301.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed paste issue in Table Block and added cypress test for pasting text in Table Block. \ No newline at end of file diff --git a/news/4316.bugfix b/news/4316.bugfix deleted file mode 100644 index 4df1b112a6..0000000000 --- a/news/4316.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed i18n script to avoid overwriting translations with an empty msgstr @danalvrz \ No newline at end of file diff --git a/news/4336.bugfix b/news/4336.bugfix deleted file mode 100644 index e4fac0c50a..0000000000 --- a/news/4336.bugfix +++ /dev/null @@ -1 +0,0 @@ -bugfix: conditionally render all delete items in confirm widget \ No newline at end of file diff --git a/news/4393.feature b/news/4393.feature deleted file mode 100644 index 977e5aec23..0000000000 --- a/news/4393.feature +++ /dev/null @@ -1 +0,0 @@ -Add option to hide empty listing blocks @ksuess \ No newline at end of file diff --git a/news/4433.breaking b/news/4433.breaking deleted file mode 100644 index 9fd7e71cb8..0000000000 --- a/news/4433.breaking +++ /dev/null @@ -1 +0,0 @@ -Add custom CSS animation to hamburger menu. Removed `hamburgers` dependency. @danalvrz diff --git a/news/4484.bugfix b/news/4484.bugfix deleted file mode 100644 index aabce324d5..0000000000 --- a/news/4484.bugfix +++ /dev/null @@ -1,2 +0,0 @@ -Make the Site Setup control panel responsive for small screen devices. @lord2anil - diff --git a/news/4492.bugfix b/news/4492.bugfix deleted file mode 100644 index a510c9c955..0000000000 --- a/news/4492.bugfix +++ /dev/null @@ -1 +0,0 @@ -The menu for the contents page was unresponsive on mobile devices. Fixed this by changing the menu overflow to scroll. @sudhanshu1309 diff --git a/news/4495.breaking b/news/4495.breaking deleted file mode 100644 index 5aacb9fc94..0000000000 --- a/news/4495.breaking +++ /dev/null @@ -1 +0,0 @@ -Improve i18n script ordering of addons, so that addons can override translations from their dependencies. @davisagli diff --git a/news/4497.bugfix b/news/4497.bugfix deleted file mode 100644 index 521ca84511..0000000000 --- a/news/4497.bugfix +++ /dev/null @@ -1 +0,0 @@ -Make Drag and Drop list work with container-type inline-size. @robgietema \ No newline at end of file diff --git a/news/4502.documentation b/news/4502.documentation deleted file mode 100644 index cc20ee1c42..0000000000 --- a/news/4502.documentation +++ /dev/null @@ -1 +0,0 @@ -Fix training urls @ksuess \ No newline at end of file diff --git a/news/4505.bugfix b/news/4505.bugfix deleted file mode 100644 index bcefcf8101..0000000000 --- a/news/4505.bugfix +++ /dev/null @@ -1 +0,0 @@ -(fix): Paste button disappearing while coping from nested blocks @dobri1408 diff --git a/news/4520.bugfix b/news/4520.bugfix deleted file mode 100644 index 19630ab2e3..0000000000 --- a/news/4520.bugfix +++ /dev/null @@ -1 +0,0 @@ -Patch updates for some dependencies. @davisagli diff --git a/news/4522.bugfix b/news/4522.bugfix deleted file mode 100644 index 3fc94a0525..0000000000 --- a/news/4522.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix flaky Cypress test introduced in #4521 @sneridagh diff --git a/news/4542.documentation b/news/4542.documentation deleted file mode 100644 index 7ee1bc739a..0000000000 --- a/news/4542.documentation +++ /dev/null @@ -1 +0,0 @@ -Add upgrade guide for 4504 @sneridagh diff --git a/package.json b/package.json index 98ea10074e..3fb6c324a1 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "17.0.0-alpha.1", + "version": "17.0.0-alpha.2", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" diff --git a/packages/volto-slate/package.json b/packages/volto-slate/package.json index e4ad38ef6e..d6a6dc6f68 100644 --- a/packages/volto-slate/package.json +++ b/packages/volto-slate/package.json @@ -1,6 +1,6 @@ { "name": "@plone/volto-slate", - "version": "17.0.0-alpha.1", + "version": "17.0.0-alpha.2", "description": "Slate.js integration with Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", From 3797966d7c868b46121bc90d5baf2fa893515046 Mon Sep 17 00:00:00 2001 From: "Mohd. Yahya" <59670962+yahya-cloud@users.noreply.github.com> Date: Thu, 16 Mar 2023 01:02:20 +0530 Subject: [PATCH 078/142] url update and duplicate import deletion (#4523) Co-authored-by: Steve Piercy --- docs/source/blocks/settings.md | 1 - news/4523.documentation | 1 + packages/generator-volto/generators/app/templates/README.md | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 news/4523.documentation diff --git a/docs/source/blocks/settings.md b/docs/source/blocks/settings.md index e9d81009c5..e92e736042 100644 --- a/docs/source/blocks/settings.md +++ b/docs/source/blocks/settings.md @@ -26,7 +26,6 @@ import CardTeaserView from '@package/components/Blocks/CardTeaserView'; import DefaultColumnRenderer from '@package/components/Blocks/DefaultColumnRenderer'; import NumberColumnRenderer from '@package/components/Blocks/NumberColumnRenderer'; import ColoredColumnRenderer from '@package/components/Blocks/ColoredColumnRenderer'; -import CardTeaserView from '@package/components/Blocks/CardTeaserView'; import CustomSchemaEnhancer from '@package/components/Blocks/CustomSchemaEnhancer'; diff --git a/news/4523.documentation b/news/4523.documentation new file mode 100644 index 0000000000..9236a1fd29 --- /dev/null +++ b/news/4523.documentation @@ -0,0 +1 @@ +Deleted duplicate import and fixed training URLs. @yahya-cloud \ No newline at end of file diff --git a/packages/generator-volto/generators/app/templates/README.md b/packages/generator-volto/generators/app/templates/README.md index 1410a4d24e..9547b698b2 100644 --- a/packages/generator-volto/generators/app/templates/README.md +++ b/packages/generator-volto/generators/app/templates/README.md @@ -1,6 +1,6 @@ ## Documentation -A training on how to create your own website using Volto is available as part of the Plone training at [https://training.plone.org/5/volto/index.html](https://training.plone.org/5/volto/index.html). +[Volto Hands-On](https://training.plone.org/voltohandson/index.html) is a training on how to create your own website. ## Quick Start From 15b83f26e21b87acaf058fca0ac6016aa3b06f22 Mon Sep 17 00:00:00 2001 From: iRohitSingh <61353484+iRohitSingh@users.noreply.github.com> Date: Thu, 16 Mar 2023 02:48:44 +0530 Subject: [PATCH 079/142] Fix Search is case sensitive in Block chooser (#4527) Co-authored-by: David Glick --- news/4526.bugfix | 1 + src/components/manage/BlockChooser/BlockChooser.jsx | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 news/4526.bugfix diff --git a/news/4526.bugfix b/news/4526.bugfix new file mode 100644 index 0000000000..a4f5ed0bdb --- /dev/null +++ b/news/4526.bugfix @@ -0,0 +1 @@ +Fix Search is case sensitive in Block chooser @iRohitSingh \ No newline at end of file diff --git a/src/components/manage/BlockChooser/BlockChooser.jsx b/src/components/manage/BlockChooser/BlockChooser.jsx index 5c97683981..921d6b79a6 100644 --- a/src/components/manage/BlockChooser/BlockChooser.jsx +++ b/src/components/manage/BlockChooser/BlockChooser.jsx @@ -89,14 +89,18 @@ const BlockChooser = ({ function blocksAvailableFilter(blocks) { return blocks.filter( (block) => - getFormatMessage(block.title).toLowerCase().includes(filterValue) || + getFormatMessage(block.title) + .toLowerCase() + .includes(filterValue.toLowerCase()) || filterVariations(block)?.length, ); } function filterVariations(block) { return block.variations?.filter( (variation) => - getFormatMessage(variation.title).toLowerCase().includes(filterValue) && + getFormatMessage(variation.title) + .toLowerCase() + .includes(filterValue.toLowerCase()) && !variation.title.toLowerCase().includes('default'), ); } From ed7cb97d5ccead4bcaf175837196494067aa28d3 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 16 Mar 2023 03:48:08 -0700 Subject: [PATCH 080/142] Fix grammar in PR #4542 (#4555) --- docs/source/upgrade-guide/index.md | 6 +++--- news/4555.documentation | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 news/4555.documentation diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index 02cace9ff7..166f10263c 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -66,9 +66,9 @@ If your theme or add-ons relied on it, add it again as a dependency in them, or ### Fixed i18n script by taking into account the real add-on order -By fixing this, we are potentially breaking how the locales were applied, since now the order will be the correct. -Please check the translations of your project and add-ons and verify that the translations are still correct. -This could be specially true if you did translation overrides or two add-ons were using different translations for the same `msgid` or there were conflicting `msgid` in different add-ons. +By fixing this, we may break how the locales were applied, since the order will now be correct. +Please check the translations of your project and add-ons, and verify that the translations are still correct. +This could be especially true if you did translation overrides, two add-ons were using different translations for the same `msgid`, or there were conflicting `msgid`s in different add-ons. (volto-upgrade-guide-16.x.x)= diff --git a/news/4555.documentation b/news/4555.documentation new file mode 100644 index 0000000000..75b7876611 --- /dev/null +++ b/news/4555.documentation @@ -0,0 +1 @@ +Fix grammar in PR #4542. @stevepiercy From 48d7d62e8c5f122f6b6cae2860650e3547187ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Thu, 16 Mar 2023 11:55:12 +0100 Subject: [PATCH 081/142] Changelog for 16.17.1 (#4556) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a4a695541..e9fe55acd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,18 @@ - Fix English and MyST grammar and syntax from PR #4285 @stevepiercy [#4331](https://github.com/plone/volto/issues/4331) - Use a universal static path for both documentation and volto repos. @stevepiercy [#4376](https://github.com/plone/volto/issues/4376) + +## 16.17.1 (2023-03-16) + + ### Bugfix + + - Fix Search is case sensitive in Block chooser @iRohitSingh [#4526](https://github.com/plone/volto/issues/4526) + + ### Documentation + + - Deleted duplicate import and fixed training URLs. @yahya-cloud [#4523](https://github.com/plone/volto/issues/4523) + + ## 16.17.0 (2023-03-15) ### Feature From 0a0f319c2c75ca8ebed8fcf76e236087d5f4e86e Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 17 Mar 2023 22:42:48 -0700 Subject: [PATCH 082/142] Fix broken links at ReactJS (#4569) --- CHANGELOG.md | 4 ++-- docs/source/getting-started/roadmap.md | 2 +- news/4569.documentation | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 news/4569.documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index e9fe55acd8..81db5d5a22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2447,7 +2447,7 @@ See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information - Use Plone logo @ericof - Update favicon and related tags with best practices @sneridagh - Enable to be able to use the internal proxy in production as well @sneridagh -- Add runtime configuration for `@babel/plugin-transform-react-jsx` set to `automatic`. This enables the new JSX runtime: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html So no longer `import React from 'react'` is needed anymore. @sneridagh +- Add runtime configuration for `@babel/plugin-transform-react-jsx` set to `automatic`. This enables the new JSX runtime: https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html So no longer `import React from 'react'` is needed anymore. @sneridagh - Add `autocomplete` Widget component - It holds off the vocabulary endpoint pull until you search (more than 2 chars). Useful when dealing with huge vocabularies @sneridagh @reebalazs - Add new listing block option "fullobjects" per variation @ksuess - `FormFieldWrapper` accepts now strings and elements for description @nzambello @@ -2577,7 +2577,7 @@ See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information ### Feature -- Add runtime configuration for `@babel/plugin-transform-react-jsx` set to `automatic`. This enables the new JSX runtime: https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html So no longer `import React from 'react'` is needed anymore. +- Add runtime configuration for `@babel/plugin-transform-react-jsx` set to `automatic`. This enables the new JSX runtime: https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html So no longer `import React from 'react'` is needed anymore. - Update favicon and related tags with best practices @sneridagh ### Bugfix diff --git a/docs/source/getting-started/roadmap.md b/docs/source/getting-started/roadmap.md index 933ef0515f..3af14a07b0 100644 --- a/docs/source/getting-started/roadmap.md +++ b/docs/source/getting-started/roadmap.md @@ -28,7 +28,7 @@ As is the case with similar modern Javascript-based applications, you should kno - Modern Javascript development. Volto uses next-generation Javascript. Follow the [ES6 guide](https://flaviocopes.com/es6/) to get up to speed. - React knowledge - [basic level is - fine](https://reactjs.org/tutorial/tutorial.html) for the beginning, you'll progress + fine](https://react.dev/learn/tutorial-tic-tac-toe) for the beginning, you'll progress along the way. React itself is a simple and well documented framework. - A basic understanding of Javascript [CommonJS](https://flaviocopes.com/commonjs/), diff --git a/news/4569.documentation b/news/4569.documentation new file mode 100644 index 0000000000..a08842d90d --- /dev/null +++ b/news/4569.documentation @@ -0,0 +1 @@ +Fix broken links at ReactJS.org. @stevepiercy From d3865b3ac9e5c1213058373e6ecf5422060d7ab0 Mon Sep 17 00:00:00 2001 From: Mohammad Hussain <99530996+MAX-786@users.noreply.github.com> Date: Sun, 19 Mar 2023 02:55:53 +0530 Subject: [PATCH 083/142] Using Vale in CI for spellcheck (#4423) Co-authored-by: Steve Piercy --- .github/workflows/docs.yml | 10 ++++++++++ .gitignore | 1 + .vale.ini | 10 ++++++++++ news/4423.feature | 1 + styles/Vocab/Base/accept.txt | 0 styles/Vocab/Base/reject.txt | 0 styles/Vocab/Plone/accept.txt | 8 ++++++++ styles/Vocab/Plone/reject.txt | 0 8 files changed, 30 insertions(+) create mode 100644 .vale.ini create mode 100644 news/4423.feature create mode 100644 styles/Vocab/Base/accept.txt create mode 100644 styles/Vocab/Base/reject.txt create mode 100644 styles/Vocab/Plone/accept.txt create mode 100644 styles/Vocab/Plone/reject.txt diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index bf6a564301..d9aacb121b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -37,3 +37,13 @@ jobs: - name: Build HTML documentation run: make docs-html + + - uses: errata-ai/vale-action@reviewdog + with: + # debug: true + files: all + env: + # Required, set by GitHub actions automatically: + # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + diff --git a/.gitignore b/.gitignore index 971b10aee2..ebcc210125 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ selenium-screenshot-*.png /selenium/ cypress/videos/ cypress/screenshots +/styles/Microsoft # Local environment setup .env diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 0000000000..da6af903f2 --- /dev/null +++ b/.vale.ini @@ -0,0 +1,10 @@ +StylesPath = styles + +MinAlertLevel = suggestion + +Vocab = Base,Plone + +Packages = Microsoft + +[*.md] +BasedOnStyles = Vale, Microsoft diff --git a/news/4423.feature b/news/4423.feature new file mode 100644 index 0000000000..8901b62863 --- /dev/null +++ b/news/4423.feature @@ -0,0 +1 @@ +Add Vale to CI for spell and style checks. @MAX-786 diff --git a/styles/Vocab/Base/accept.txt b/styles/Vocab/Base/accept.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/styles/Vocab/Base/reject.txt b/styles/Vocab/Base/reject.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/styles/Vocab/Plone/accept.txt b/styles/Vocab/Plone/accept.txt new file mode 100644 index 0000000000..78bcf7537b --- /dev/null +++ b/styles/Vocab/Plone/accept.txt @@ -0,0 +1,8 @@ +`plone.restapi` +`plone.volto` +npm +Plone +Razzle +RichText +Volto +Zope diff --git a/styles/Vocab/Plone/reject.txt b/styles/Vocab/Plone/reject.txt new file mode 100644 index 0000000000..e69de29bb2 From 0da6bc8a212f1bcff2d659e071f5c3dcde3a3891 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Tue, 21 Mar 2023 00:32:13 -0700 Subject: [PATCH 084/142] Fix video warnings link errors (#4578) --- docs/source/_static/custom.css | 4 ++++ docs/source/getting-started/install.md | 2 +- docs/source/user-manual/copy-paste-blocks.md | 2 -- news/4578.documentation | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 news/4578.documentation diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css index aa980421c2..d792d49f36 100644 --- a/docs/source/_static/custom.css +++ b/docs/source/_static/custom.css @@ -240,3 +240,7 @@ span.guilabel, span.menuselection { font-style: italic; white-space: nowrap; } + +video { + width: 100%; +} diff --git a/docs/source/getting-started/install.md b/docs/source/getting-started/install.md index 1e8dfc2460..7dd17ff64b 100644 --- a/docs/source/getting-started/install.md +++ b/docs/source/getting-started/install.md @@ -23,7 +23,7 @@ This chapter contains some legacy information that may be useful to Plone 5.2 de Volto can be installed in any operating system assuming that the following pre-requisites are met: -- [Node.js LTS (18.x)](https://nodejs.org/en/) +- [Node.js LTS (18.x)](https://nodejs.org/en) - [Python](https://www.python.org/) - See below for specific versions. - [Docker](https://www.docker.com/get-started) (if using the Plone docker images) diff --git a/docs/source/user-manual/copy-paste-blocks.md b/docs/source/user-manual/copy-paste-blocks.md index 1f922e2f75..c62544700e 100644 --- a/docs/source/user-manual/copy-paste-blocks.md +++ b/docs/source/user-manual/copy-paste-blocks.md @@ -27,7 +27,6 @@ This feature can be used by selecting a start block and an end block while holdi This will select all the blocks between the start and end blocks, allowing you to copy, cut, or delete multiple blocks at once. ```{video} /_static/user-manual/blocks/block-copy-cut.mp4 - :width: 100% ``` @@ -42,5 +41,4 @@ You can click the paste option Paste icon Date: Tue, 21 Mar 2023 10:48:01 +0100 Subject: [PATCH 085/142] Update message Add-on control panel (#4574) --- locales/ca/LC_MESSAGES/volto.po | 2 +- locales/de/LC_MESSAGES/volto.po | 2 +- locales/en/LC_MESSAGES/volto.po | 2 +- locales/es/LC_MESSAGES/volto.po | 2 +- locales/eu/LC_MESSAGES/volto.po | 2 +- locales/fr/LC_MESSAGES/volto.po | 2 +- locales/it/LC_MESSAGES/volto.po | 2 +- locales/ja/LC_MESSAGES/volto.po | 2 +- locales/nl/LC_MESSAGES/volto.po | 2 +- locales/pt/LC_MESSAGES/volto.po | 2 +- locales/pt_BR/LC_MESSAGES/volto.po | 2 +- locales/ro/LC_MESSAGES/volto.po | 2 +- locales/volto.pot | 2 +- locales/zh_CN/LC_MESSAGES/volto.po | 2 +- news/4574.bugfix | 1 + src/components/manage/Controlpanels/AddonsControlpanel.jsx | 6 +++--- .../__snapshots__/AddonsControlpanel.test.jsx.snap | 4 ++-- 17 files changed, 20 insertions(+), 19 deletions(-) create mode 100644 news/4574.bugfix diff --git a/locales/ca/LC_MESSAGES/volto.po b/locales/ca/LC_MESSAGES/volto.po index dd9c9d8f9e..1133771312 100644 --- a/locales/ca/LC_MESSAGES/volto.po +++ b/locales/ca/LC_MESSAGES/volto.po @@ -93,7 +93,7 @@ msgid "Add (object list)" msgstr "" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Afegeix complements" diff --git a/locales/de/LC_MESSAGES/volto.po b/locales/de/LC_MESSAGES/volto.po index f3af5c2c05..8a717bc3d2 100644 --- a/locales/de/LC_MESSAGES/volto.po +++ b/locales/de/LC_MESSAGES/volto.po @@ -90,7 +90,7 @@ msgid "Add (object list)" msgstr "Hinzufügen" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Add-on hinzufügen" diff --git a/locales/en/LC_MESSAGES/volto.po b/locales/en/LC_MESSAGES/volto.po index d305b3ba72..30e4e39d71 100644 --- a/locales/en/LC_MESSAGES/volto.po +++ b/locales/en/LC_MESSAGES/volto.po @@ -84,7 +84,7 @@ msgid "Add (object list)" msgstr "" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "" diff --git a/locales/es/LC_MESSAGES/volto.po b/locales/es/LC_MESSAGES/volto.po index 45f795f134..5eaf110016 100644 --- a/locales/es/LC_MESSAGES/volto.po +++ b/locales/es/LC_MESSAGES/volto.po @@ -95,7 +95,7 @@ msgid "Add (object list)" msgstr "Añadir" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Añadir complementos" diff --git a/locales/eu/LC_MESSAGES/volto.po b/locales/eu/LC_MESSAGES/volto.po index 81f78b90f8..4f058ed3ab 100644 --- a/locales/eu/LC_MESSAGES/volto.po +++ b/locales/eu/LC_MESSAGES/volto.po @@ -91,7 +91,7 @@ msgid "Add (object list)" msgstr "Gehitu" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Gehitu gehigarriak" diff --git a/locales/fr/LC_MESSAGES/volto.po b/locales/fr/LC_MESSAGES/volto.po index 9870322dc1..5f9097b014 100644 --- a/locales/fr/LC_MESSAGES/volto.po +++ b/locales/fr/LC_MESSAGES/volto.po @@ -101,7 +101,7 @@ msgid "Add (object list)" msgstr "Ajouter (liste d'objets)" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Ajouter des modules" diff --git a/locales/it/LC_MESSAGES/volto.po b/locales/it/LC_MESSAGES/volto.po index c7d64a0ead..ee1c27901c 100644 --- a/locales/it/LC_MESSAGES/volto.po +++ b/locales/it/LC_MESSAGES/volto.po @@ -84,7 +84,7 @@ msgid "Add (object list)" msgstr "Aggiungi" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Aggiungi Add-ons" diff --git a/locales/ja/LC_MESSAGES/volto.po b/locales/ja/LC_MESSAGES/volto.po index b59f2e75bd..53ba075dea 100644 --- a/locales/ja/LC_MESSAGES/volto.po +++ b/locales/ja/LC_MESSAGES/volto.po @@ -92,7 +92,7 @@ msgid "Add (object list)" msgstr "" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "以下のリストに新しいアドオンが表示されるようにするには、それをビルドアウト設定(buildout.cfg)に追加し、ビルドアウトコマンド(bin/buildout)を実行した後に、サーバプロセスを再起動します。" diff --git a/locales/nl/LC_MESSAGES/volto.po b/locales/nl/LC_MESSAGES/volto.po index c5ea31fc2b..17eac461c8 100644 --- a/locales/nl/LC_MESSAGES/volto.po +++ b/locales/nl/LC_MESSAGES/volto.po @@ -91,7 +91,7 @@ msgid "Add (object list)" msgstr "Toevoegen (object lijst)" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Voeg modules toe" diff --git a/locales/pt/LC_MESSAGES/volto.po b/locales/pt/LC_MESSAGES/volto.po index 04e893f019..40dae41756 100644 --- a/locales/pt/LC_MESSAGES/volto.po +++ b/locales/pt/LC_MESSAGES/volto.po @@ -92,7 +92,7 @@ msgid "Add (object list)" msgstr "" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "" diff --git a/locales/pt_BR/LC_MESSAGES/volto.po b/locales/pt_BR/LC_MESSAGES/volto.po index 516c58d2e6..d4d8f10d1e 100644 --- a/locales/pt_BR/LC_MESSAGES/volto.po +++ b/locales/pt_BR/LC_MESSAGES/volto.po @@ -94,7 +94,7 @@ msgid "Add (object list)" msgstr "Adicionar" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Adicionar complementos" diff --git a/locales/ro/LC_MESSAGES/volto.po b/locales/ro/LC_MESSAGES/volto.po index eabec0fec6..88cc55fcdb 100644 --- a/locales/ro/LC_MESSAGES/volto.po +++ b/locales/ro/LC_MESSAGES/volto.po @@ -84,7 +84,7 @@ msgid "Add (object list)" msgstr "Adăugare (listă de obiecte)" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "Adăugare add-on-uri" diff --git a/locales/volto.pot b/locales/volto.pot index 2798937487..ad763942a7 100644 --- a/locales/volto.pot +++ b/locales/volto.pot @@ -86,7 +86,7 @@ msgid "Add (object list)" msgstr "" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "" diff --git a/locales/zh_CN/LC_MESSAGES/volto.po b/locales/zh_CN/LC_MESSAGES/volto.po index c463b10175..ac6774f8e8 100644 --- a/locales/zh_CN/LC_MESSAGES/volto.po +++ b/locales/zh_CN/LC_MESSAGES/volto.po @@ -90,7 +90,7 @@ msgid "Add (object list)" msgstr "添加(对象列表)" #: components/manage/Controlpanels/AddonsControlpanel -# defaultMessage: To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see +# defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" msgstr "添加附件" diff --git a/news/4574.bugfix b/news/4574.bugfix new file mode 100644 index 0000000000..e5013ab087 --- /dev/null +++ b/news/4574.bugfix @@ -0,0 +1 @@ +Update message add-on control panel: remove 'buildout', update reference. @ksuess \ No newline at end of file diff --git a/src/components/manage/Controlpanels/AddonsControlpanel.jsx b/src/components/manage/Controlpanels/AddonsControlpanel.jsx index a1f8a8b384..1248c90cbf 100644 --- a/src/components/manage/Controlpanels/AddonsControlpanel.jsx +++ b/src/components/manage/Controlpanels/AddonsControlpanel.jsx @@ -43,7 +43,7 @@ const messages = defineMessages({ addAddons: { id: 'Add Addons', defaultMessage: - 'To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see', + 'To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see', }, addonsSettings: { id: 'Add-ons Settings', @@ -380,11 +380,11 @@ class AddonsControlpanel extends Component {   diff --git a/src/components/manage/Controlpanels/__snapshots__/AddonsControlpanel.test.jsx.snap b/src/components/manage/Controlpanels/__snapshots__/AddonsControlpanel.test.jsx.snap index 220fa5bff8..78ea65bb56 100644 --- a/src/components/manage/Controlpanels/__snapshots__/AddonsControlpanel.test.jsx.snap +++ b/src/components/manage/Controlpanels/__snapshots__/AddonsControlpanel.test.jsx.snap @@ -31,10 +31,10 @@ exports[`AddonsControlpanel renders an addon control component 1`] = ` > Activate and deactivate add-ons in the lists below.

    - To make new add-ons show up here, add them to your buildout configuration, run buildout, and restart the server process. For detailed instructions see + To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see   From a44cfa2d28bc6c56bbf8d1ee8898ccc57b9ae77f Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Tue, 21 Mar 2023 22:44:13 +0530 Subject: [PATCH 086/142] =?UTF-8?q?InternalURl=20helper=20method=20should?= =?UTF-8?q?=20incorporate=20externalRoutes=20settings=20=E2=80=A6=20(#4560?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alin Voinea --- news/4559.bugfix | 1 + src/helpers/Url/Url.js | 22 +++++++++++++++++++--- src/helpers/Url/Url.test.js | 12 ++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 news/4559.bugfix diff --git a/news/4559.bugfix b/news/4559.bugfix new file mode 100644 index 0000000000..395e77aca0 --- /dev/null +++ b/news/4559.bugfix @@ -0,0 +1 @@ +InternalURl helper method should incorporate externalRoutes settings into consideration. @iFlameing \ No newline at end of file diff --git a/src/helpers/Url/Url.js b/src/helpers/Url/Url.js index c6bf7f2391..3038e4602d 100644 --- a/src/helpers/Url/Url.js +++ b/src/helpers/Url/Url.js @@ -7,6 +7,7 @@ import { last, memoize } from 'lodash'; import { urlRegex, telRegex, mailRegex } from './urlRegex'; import prependHttp from 'prepend-http'; import config from '@plone/volto/registry'; +import { matchPath } from 'react-router'; /** * Get base url. @@ -213,7 +214,17 @@ export function expandToBackendURL(path) { */ export function isInternalURL(url) { const { settings } = config; - return ( + + const isMatch = (config.settings.externalRoutes ?? []).find((route) => { + if (typeof route === 'object') { + return matchPath(flattenToAppURL(url), route.match); + } + return matchPath(flattenToAppURL(url), route); + }); + + const isExcluded = isMatch && Object.keys(isMatch)?.length > 0; + + const internalURL = url && (url.indexOf(settings.publicURL) !== -1 || (settings.internalApiPath && @@ -221,8 +232,13 @@ export function isInternalURL(url) { url.indexOf(settings.apiPath) !== -1 || url.charAt(0) === '/' || url.charAt(0) === '.' || - url.startsWith('#')) - ); + url.startsWith('#')); + + if (internalURL && isExcluded) { + return false; + } + + return internalURL; } /** diff --git a/src/helpers/Url/Url.test.js b/src/helpers/Url/Url.test.js index 597c307935..0c06f89d08 100644 --- a/src/helpers/Url/Url.test.js +++ b/src/helpers/Url/Url.test.js @@ -191,6 +191,7 @@ describe('Url', () => { expect(isInternalURL(href)).toBe(false); settings.internalApiPath = saved; }); + it('tells if an URL is internal if it is an anchor', () => { const href = '#anchor'; expect(isInternalURL(href)).toBe(true); @@ -211,6 +212,17 @@ describe('Url', () => { const href = undefined; expect(isInternalURL(href)).toBe(undefined); }); + it('tells if an URL is external if settings.externalroutes is persent.', () => { + const url = `https://localhost:3000/fb/my-page/contents`; + const blacklistedurl = '/blacklisted'; + settings.externalRoutes = [ + { title: 'My Page', match: '/fb' }, + '/blacklisted', + ]; + settings.publicURL = 'https://localhost:3000'; + expect(isInternalURL(url)).toBe(false); + expect(isInternalURL(blacklistedurl)).toBe(false); + }); }); describe('isUrl', () => { it('isUrl test', () => { From c9275b2d0b740cfc6ed7e99578e7debd1b35f3ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Wed, 22 Mar 2023 10:04:47 +0100 Subject: [PATCH 087/142] Update changelog relese 16.18.0 (#4596) --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81db5d5a22..1fe6548560 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,24 @@ - Use a universal static path for both documentation and volto repos. @stevepiercy [#4376](https://github.com/plone/volto/issues/4376) +## 16.18.0 (2023-03-22) + +### Feature + +- Add Vale to CI for spell and style checks. @MAX-786 [#4423](https://github.com/plone/volto/issues/4423) + +### Bugfix + +- Patch updates for some dependencies. @davisagli [#4520](https://github.com/plone/volto/issues/4520) +- InternalURl helper method should incorporate externalRoutes settings into consideration. @iFlameing [#4559](https://github.com/plone/volto/issues/4559) +- Update message add-on control panel: remove 'buildout', update reference. @ksuess [#4574](https://github.com/plone/volto/issues/4574) + +### Documentation + +- Fix broken links at ReactJS.org. @stevepiercy [#4569](https://github.com/plone/volto/issues/4569) +- Fix video warnings and link errors. @stevepiercy [#4578](https://github.com/plone/volto/issues/4578) + + ## 16.17.1 (2023-03-16) ### Bugfix From 0cca3b257b9fc98da773d3aa8f73a923458a9b59 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Wed, 22 Mar 2023 10:06:22 +0100 Subject: [PATCH 088/142] Release 17.0.0-alpha.3 --- CHANGELOG.md | 20 ++++++++++++++++++++ news/4423.feature | 1 - news/4523.documentation | 1 - news/4526.bugfix | 1 - news/4555.documentation | 1 - news/4559.bugfix | 1 - news/4569.documentation | 1 - news/4574.bugfix | 1 - news/4578.documentation | 1 - package.json | 2 +- packages/volto-slate/package.json | 2 +- 11 files changed, 22 insertions(+), 10 deletions(-) delete mode 100644 news/4423.feature delete mode 100644 news/4523.documentation delete mode 100644 news/4526.bugfix delete mode 100644 news/4555.documentation delete mode 100644 news/4559.bugfix delete mode 100644 news/4569.documentation delete mode 100644 news/4574.bugfix delete mode 100644 news/4578.documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fe6548560..074b7a462a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,26 @@ +## 17.0.0-alpha.3 (2023-03-22) + +### Feature + +- Add Vale to CI for spell and style checks. @MAX-786 [#4423](https://github.com/plone/volto/issues/4423) + +### Bugfix + +- Fix Search is case sensitive in Block chooser @iRohitSingh [#4526](https://github.com/plone/volto/issues/4526) +- InternalURl helper method should incorporate externalRoutes settings into consideration. @iFlameing [#4559](https://github.com/plone/volto/issues/4559) +- Update message add-on control panel: remove 'buildout', update reference. @ksuess [#4574](https://github.com/plone/volto/issues/4574) + +### Documentation + +- Deleted duplicate import and fixed training URLs. @yahya-cloud [#4523](https://github.com/plone/volto/issues/4523) +- Fix grammar in PR #4542. @stevepiercy [#4555](https://github.com/plone/volto/issues/4555) +- Fix broken links at ReactJS.org. @stevepiercy [#4569](https://github.com/plone/volto/issues/4569) +- Fix video warnings and link errors. @stevepiercy [#4578](https://github.com/plone/volto/issues/4578) + + ## 17.0.0-alpha.2 (2023-03-15) ### Breaking diff --git a/news/4423.feature b/news/4423.feature deleted file mode 100644 index 8901b62863..0000000000 --- a/news/4423.feature +++ /dev/null @@ -1 +0,0 @@ -Add Vale to CI for spell and style checks. @MAX-786 diff --git a/news/4523.documentation b/news/4523.documentation deleted file mode 100644 index 9236a1fd29..0000000000 --- a/news/4523.documentation +++ /dev/null @@ -1 +0,0 @@ -Deleted duplicate import and fixed training URLs. @yahya-cloud \ No newline at end of file diff --git a/news/4526.bugfix b/news/4526.bugfix deleted file mode 100644 index a4f5ed0bdb..0000000000 --- a/news/4526.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix Search is case sensitive in Block chooser @iRohitSingh \ No newline at end of file diff --git a/news/4555.documentation b/news/4555.documentation deleted file mode 100644 index 75b7876611..0000000000 --- a/news/4555.documentation +++ /dev/null @@ -1 +0,0 @@ -Fix grammar in PR #4542. @stevepiercy diff --git a/news/4559.bugfix b/news/4559.bugfix deleted file mode 100644 index 395e77aca0..0000000000 --- a/news/4559.bugfix +++ /dev/null @@ -1 +0,0 @@ -InternalURl helper method should incorporate externalRoutes settings into consideration. @iFlameing \ No newline at end of file diff --git a/news/4569.documentation b/news/4569.documentation deleted file mode 100644 index a08842d90d..0000000000 --- a/news/4569.documentation +++ /dev/null @@ -1 +0,0 @@ -Fix broken links at ReactJS.org. @stevepiercy diff --git a/news/4574.bugfix b/news/4574.bugfix deleted file mode 100644 index e5013ab087..0000000000 --- a/news/4574.bugfix +++ /dev/null @@ -1 +0,0 @@ -Update message add-on control panel: remove 'buildout', update reference. @ksuess \ No newline at end of file diff --git a/news/4578.documentation b/news/4578.documentation deleted file mode 100644 index 9a6645de55..0000000000 --- a/news/4578.documentation +++ /dev/null @@ -1 +0,0 @@ -Fix video warnings and link errors. @stevepiercy diff --git a/package.json b/package.json index 3fb6c324a1..ccc3202d9c 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "17.0.0-alpha.2", + "version": "17.0.0-alpha.3", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" diff --git a/packages/volto-slate/package.json b/packages/volto-slate/package.json index d6a6dc6f68..6b1160981d 100644 --- a/packages/volto-slate/package.json +++ b/packages/volto-slate/package.json @@ -1,6 +1,6 @@ { "name": "@plone/volto-slate", - "version": "17.0.0-alpha.2", + "version": "17.0.0-alpha.3", "description": "Slate.js integration with Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", From 4e800aa670aaba6ba3196e21c31e52760f7e287c Mon Sep 17 00:00:00 2001 From: Andrea Cecchi Date: Thu, 23 Mar 2023 16:27:40 +0100 Subject: [PATCH 089/142] Fix regexp that checks valid URLs and improve tests (#4601) --- news/4601.bugfix | 1 + src/helpers/FormValidation/FormValidation.js | 11 ++++- .../FormValidation/FormValidation.test.js | 41 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 news/4601.bugfix diff --git a/news/4601.bugfix b/news/4601.bugfix new file mode 100644 index 0000000000..cbb24473ca --- /dev/null +++ b/news/4601.bugfix @@ -0,0 +1 @@ +Fix regexp that checks valid URLs and improve tests [cekk] diff --git a/src/helpers/FormValidation/FormValidation.js b/src/helpers/FormValidation/FormValidation.js index 7c6d609f19..0c5fd28eac 100644 --- a/src/helpers/FormValidation/FormValidation.js +++ b/src/helpers/FormValidation/FormValidation.js @@ -65,7 +65,16 @@ const widgetValidation = { }, url: { isValidURL: (urlValue, urlObj, intlFunc) => { - const urlRegex = /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?|^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([_.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?|^((http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/gm; + var urlRegex = new RegExp( + '^(https?:\\/\\/)?' + // validate protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // validate domain name + '((\\d{1,3}\\.){3}\\d{1,3}))|' + // validate OR ip (v4) address + '(localhost)' + // validate OR localhost address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // validate port and path + '(\\?[;&a-z\\d%_.~+=-]*)?' + // validate query string + '(\\#[-a-z\\d_]*)?$', // validate fragment locator + 'i', + ); const isValid = urlRegex.test(urlValue); return !isValid ? intlFunc(messages.isValidURL) : null; }, diff --git a/src/helpers/FormValidation/FormValidation.test.js b/src/helpers/FormValidation/FormValidation.test.js index 56da3a43a3..df25ac0038 100644 --- a/src/helpers/FormValidation/FormValidation.test.js +++ b/src/helpers/FormValidation/FormValidation.test.js @@ -5,6 +5,7 @@ const schema = { properties: { username: { title: 'Username', type: 'string', description: '' }, email: { title: 'Email', type: 'string', widget: 'email', description: '' }, + url: { title: 'url', type: 'string', widget: 'url', description: '' }, }, fieldsets: [ { id: 'default', title: 'FIXME: User Data', fields: ['username'] }, @@ -87,5 +88,45 @@ describe('FormValidation', () => { }), ).toEqual({}); }); + it('validates incorrect url', () => { + formData.url = 'foo'; + expect( + FormValidation.validateFieldsPerFieldset({ + schema, + formData, + formatMessage, + }), + ).toEqual({ url: [messages.isValidURL.defaultMessage] }); + }); + it('validates url', () => { + formData.url = 'https://plone.org/'; + expect( + FormValidation.validateFieldsPerFieldset({ + schema, + formData, + formatMessage, + }), + ).toEqual({}); + }); + it('validates url with ip', () => { + formData.url = 'http://127.0.0.1:8080/Plone'; + expect( + FormValidation.validateFieldsPerFieldset({ + schema, + formData, + formatMessage, + }), + ).toEqual({}); + }); + it('validates url with localhost', () => { + formData.url = 'http://localhost:8080/Plone'; + expect( + FormValidation.validateFieldsPerFieldset({ + schema, + formData, + formatMessage, + }), + ).toEqual({}); + }); }); }); From fbd4fe5c4465dee265b4c1921a180bbacfe52b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katja=20S=C3=BCss?= Date: Thu, 23 Mar 2023 16:31:03 +0100 Subject: [PATCH 090/142] DefaultView (blocks disabled): Show field name as tip on hover of label (#4598) --- news/4598.feature | 1 + src/components/theme/View/DefaultView.jsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 news/4598.feature diff --git a/news/4598.feature b/news/4598.feature new file mode 100644 index 0000000000..7c7160922f --- /dev/null +++ b/news/4598.feature @@ -0,0 +1 @@ +DefaultView (view of fields for content types with blocks disabled): Show field name as tip on hover of label. @ksuess \ No newline at end of file diff --git a/src/components/theme/View/DefaultView.jsx b/src/components/theme/View/DefaultView.jsx index cf34ab3cf5..c2db9de92b 100644 --- a/src/components/theme/View/DefaultView.jsx +++ b/src/components/theme/View/DefaultView.jsx @@ -87,7 +87,7 @@ const DefaultView = (props) => { return f !== 'title' ? ( - + From 33962f130f25a92760848c07ab59bcd13a2ef37d Mon Sep 17 00:00:00 2001 From: David Glick Date: Thu, 23 Mar 2023 11:26:34 -0700 Subject: [PATCH 091/142] Update simple-git (#4546) --- packages/scripts/news/4546.breaking | 1 + packages/scripts/package.json | 3 +- packages/scripts/yarn.lock | 47 ++++++++++++----------------- yarn.lock | 6 ++-- 4 files changed, 24 insertions(+), 33 deletions(-) create mode 100644 packages/scripts/news/4546.breaking diff --git a/packages/scripts/news/4546.breaking b/packages/scripts/news/4546.breaking new file mode 100644 index 0000000000..468d189887 --- /dev/null +++ b/packages/scripts/news/4546.breaking @@ -0,0 +1 @@ +Remove dependency on `simple-git`. It is used by `mrs-developer` but not directly. @davisagli diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 95c68bb612..2936321d4f 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -68,8 +68,7 @@ "fs-extra": "10.1.0", "git-url-parse": "^11.6.0", "mrs-developer": "*", - "pofile": "1.0.10", - "simple-git": "3.15.0" + "pofile": "1.0.10" }, "devDependencies": { "release-it": "14.2.1" diff --git a/packages/scripts/yarn.lock b/packages/scripts/yarn.lock index 36c5d848fe..778e6ca55c 100644 --- a/packages/scripts/yarn.lock +++ b/packages/scripts/yarn.lock @@ -1941,7 +1941,6 @@ __metadata: mrs-developer: "*" pofile: 1.0.10 release-it: 14.2.1 - simple-git: 3.15.0 bin: addon: ./addon/index.js changelogupdater: ./changelogupdater.cjs @@ -2183,6 +2182,13 @@ __metadata: languageName: node linkType: hard +"async@npm:^3.2.4": + version: 3.2.4 + resolution: "async@npm:3.2.4" + checksum: 43d07459a4e1d09b84a20772414aa684ff4de085cbcaec6eea3c7a8f8150e8c62aa6cd4e699fe8ee93c3a5b324e777d34642531875a0817a35697522c1b02e89 + languageName: node + linkType: hard + "asynckit@npm:^0.4.0": version: 0.4.0 resolution: "asynckit@npm:0.4.0" @@ -2464,7 +2470,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.0.0": +"chalk@npm:^2.0.0, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -2577,13 +2583,6 @@ __metadata: languageName: node linkType: hard -"colors@npm:^1.4.0": - version: 1.4.0 - resolution: "colors@npm:1.4.0" - checksum: 98aa2c2418ad87dedf25d781be69dc5fc5908e279d9d30c34d8b702e586a0474605b3a189511482b9d5ed0d20c867515d22749537f7bc546256c6014f3ebdcec - languageName: node - linkType: hard - "combined-stream@npm:^1.0.8": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" @@ -2683,7 +2682,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.4": +"debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -3840,14 +3839,15 @@ __metadata: linkType: hard "mrs-developer@npm:*": - version: 1.6.0 - resolution: "mrs-developer@npm:1.6.0" + version: 2.1.0 + resolution: "mrs-developer@npm:2.1.0" dependencies: - colors: ^1.4.0 - simple-git: ^1.132.0 + async: ^3.2.4 + chalk: ^2.4.2 + simple-git: ^3.3.0 bin: missdev: src/command.js - checksum: 7154612bfa0f316b7a443bf4bc698bf46ba953900a5f134c67048974134a678218a0624e92c81ec1d84f5b923593b6a2c0d768a72d6ea4199fa769a30fe9530a + checksum: 11a47dee219fb4986a591195ea18d47602741f90d66ccb94378d619979c0bc52284590cc11f48da60fbbd463765904fc60a3800fb5f786caa9c5a5610cbece86 languageName: node linkType: hard @@ -4609,23 +4609,14 @@ __metadata: languageName: node linkType: hard -"simple-git@npm:3.15.0": - version: 3.15.0 - resolution: "simple-git@npm:3.15.0" +"simple-git@npm:^3.3.0": + version: 3.17.0 + resolution: "simple-git@npm:3.17.0" dependencies: "@kwsites/file-exists": ^1.1.1 "@kwsites/promise-deferred": ^1.1.1 debug: ^4.3.4 - checksum: 4733d1b769965a7608254c3a5b27532e02e60d4369bc9b397ce47159dd153344a3774739fd2602f693947ed64631b30145b970988fb007b5b779459e9abcdee8 - languageName: node - linkType: hard - -"simple-git@npm:^1.132.0": - version: 1.132.0 - resolution: "simple-git@npm:1.132.0" - dependencies: - debug: ^4.0.1 - checksum: 717d7cf7919ebe771b2562ed70c79c3971ac650d9577a15c47052472f8e549a088aea593b6a7245d73af0425a202106e6c236d35a73dc4c48dce99bf7b4f939a + checksum: 977a05cb0b5087296348b5afa682ce552f43234f5fd29b44c3d7f56b3682d10dcb03752a418e508aaffcbdb6ea2e304a3ef10095197d6743d2353adb85f32592 languageName: node linkType: hard diff --git a/yarn.lock b/yarn.lock index 520b246b8a..f5aa1197cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21874,13 +21874,13 @@ __metadata: linkType: hard "simple-git@npm:^3.3.0": - version: 3.15.1 - resolution: "simple-git@npm:3.15.1" + version: 3.17.0 + resolution: "simple-git@npm:3.17.0" dependencies: "@kwsites/file-exists": ^1.1.1 "@kwsites/promise-deferred": ^1.1.1 debug: ^4.3.4 - checksum: 2b97c3ba3c0709eded408013336bf1822be4171d965f3ab45f5bfc05ec690f9e488e11280bec8e2faa05d3039c4769e9d8197040a48dc5cf21cc5c7fa22fe77f + checksum: 977a05cb0b5087296348b5afa682ce552f43234f5fd29b44c3d7f56b3682d10dcb03752a418e508aaffcbdb6ea2e304a3ef10095197d6743d2353adb85f32592 languageName: node linkType: hard From 76bf09d6efcf5725c5834de95750b6adad356ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Fri, 31 Mar 2023 13:02:19 +0200 Subject: [PATCH 092/142] Set sameSite in `18N_LANGUAGE` cookie (#4627) --- news/4627.feature | 1 + src/actions/language/language.js | 1 + 2 files changed, 2 insertions(+) create mode 100644 news/4627.feature diff --git a/news/4627.feature b/news/4627.feature new file mode 100644 index 0000000000..dd91379ab9 --- /dev/null +++ b/news/4627.feature @@ -0,0 +1 @@ +Set sameSite in I18N_LANGUAGE cookie @sneridagh diff --git a/src/actions/language/language.js b/src/actions/language/language.js index 6ea855c8b2..e62d4be472 100644 --- a/src/actions/language/language.js +++ b/src/actions/language/language.js @@ -7,6 +7,7 @@ export function changeLanguageCookies(language, req) { const cookieOptions = getCookieOptions({ secure: req?.protocol?.startsWith('https') ? true : false, + sameSite: 'strict', }); if (!req) { From 010696643a2c04ce89d110fb15b1e18f9a428c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Fri, 31 Mar 2023 13:02:56 +0200 Subject: [PATCH 093/142] Pining of `pydata-sphinx-theme` and `sphinx-book-theme`, CI is complaining. (#4626) --- news/4626.documentation | 1 + requirements-docs.txt | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 news/4626.documentation diff --git a/news/4626.documentation b/news/4626.documentation new file mode 100644 index 0000000000..7898850040 --- /dev/null +++ b/news/4626.documentation @@ -0,0 +1 @@ +Fix documentation build, add pins @sneridagh diff --git a/requirements-docs.txt b/requirements-docs.txt index 7c4e331ab9..d4596cb251 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -5,7 +5,8 @@ lesscpy linkify-it-py myst-parser sphinx-autobuild -sphinx-book-theme +pydata-sphinx-theme<=0.8.99 +sphinx-book-theme==0.3.3 sphinx-copybutton sphinx-sitemap sphinx-togglebutton From 5808b787230d4049632a4d5b14c3b0a80cc86e77 Mon Sep 17 00:00:00 2001 From: David Glick Date: Fri, 31 Mar 2023 12:01:02 -0700 Subject: [PATCH 094/142] Trigger CI on pull_request event (#4629) I chatted with Maurits this afternoon as well, he agrees on the pull_request trigger. Let's see first how this works out and improve on what else we might find. Thanks for the extra feedback @wesleybl --- .github/workflows/acceptance.yml | 12 +++++++++++- .github/workflows/code-analysis.yml | 5 ++++- .github/workflows/unit.yml | 3 ++- news/4629.internal | 1 + 4 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 news/4629.internal diff --git a/.github/workflows/acceptance.yml b/.github/workflows/acceptance.yml index 41309bc3b6..cea3058c29 100644 --- a/.github/workflows/acceptance.yml +++ b/.github/workflows/acceptance.yml @@ -1,7 +1,8 @@ name: Acceptance Tests -on: [push] +on: [push, pull_request] jobs: core: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name runs-on: ubuntu-latest name: Core Basic timeout-minutes: 45 @@ -56,6 +57,7 @@ jobs: path: cypress/videos coreblocks: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name runs-on: ubuntu-latest name: Core Blocks timeout-minutes: 35 @@ -110,6 +112,7 @@ jobs: path: cypress/videos corevoltoslate: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name runs-on: ubuntu-latest name: Core Volto Slate timeout-minutes: 45 @@ -164,6 +167,7 @@ jobs: path: cypress/videos core5: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name runs-on: ubuntu-latest name: Core Basic - Plone 5 strategy: @@ -217,6 +221,7 @@ jobs: path: cypress/videos coresandbox: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name runs-on: ubuntu-latest name: Coresandbox timeout-minutes: 35 @@ -270,6 +275,7 @@ jobs: path: cypress/videos guillotina: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: Guillotina runs-on: ubuntu-latest timeout-minutes: 35 @@ -325,6 +331,7 @@ jobs: path: cypress/videos multilingual: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: Multilingual runs-on: ubuntu-latest timeout-minutes: 35 @@ -379,6 +386,7 @@ jobs: path: cypress/videos workingcopy: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: Working Copy runs-on: ubuntu-latest timeout-minutes: 35 @@ -458,6 +466,7 @@ jobs: path: cypress/videos generator: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: Project Generator runs-on: ubuntu-latest timeout-minutes: 35 @@ -553,6 +562,7 @@ jobs: working-directory: ${{env.generator-directory}} seamless: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: Seamless Mode runs-on: ubuntu-latest timeout-minutes: 35 diff --git a/.github/workflows/code-analysis.yml b/.github/workflows/code-analysis.yml index 66ad61e73b..9b4db344de 100644 --- a/.github/workflows/code-analysis.yml +++ b/.github/workflows/code-analysis.yml @@ -1,7 +1,8 @@ name: Code Analysis Check -on: [push] +on: [push, pull_request] jobs: prettier: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: Prettier runs-on: ubuntu-latest strategy: @@ -24,6 +25,7 @@ jobs: run: yarn run prettier eslint: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: ESlint runs-on: ubuntu-latest strategy: @@ -46,6 +48,7 @@ jobs: run: yarn run lint i18n: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: i18n runs-on: ubuntu-latest strategy: diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 36880bd257..97428e6fe3 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -1,7 +1,8 @@ name: Unit Tests -on: [push] +on: [push, pull_request] jobs: unit: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name name: Core Unit Tests runs-on: ubuntu-latest strategy: diff --git a/news/4629.internal b/news/4629.internal new file mode 100644 index 0000000000..869b4a6d24 --- /dev/null +++ b/news/4629.internal @@ -0,0 +1 @@ +Trigger CI workflows to run from external pull requests. @davisagli From dac283a02396bcd88360b923fa3f9747660b936f Mon Sep 17 00:00:00 2001 From: Fred van Dijk Date: Fri, 31 Mar 2023 21:05:03 +0200 Subject: [PATCH 095/142] developer process for first time contributing (#4617) Co-authored-by: Maurits van Rees --- .../developer-guidelines/contributing.md | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/docs/source/developer-guidelines/contributing.md b/docs/source/developer-guidelines/contributing.md index 42568ce6e6..04446bf2db 100644 --- a/docs/source/developer-guidelines/contributing.md +++ b/docs/source/developer-guidelines/contributing.md @@ -33,10 +33,32 @@ In your report, please specify a few things: ```{include} ./branch-policy.md ``` -## Create a pull request +## Sign and send us the Plone Contributors Agreement You must sign the [Plone Contributor Agreement](https://plone.org/foundation/contributors-agreement) to contribute code and documentation to any Plone project. -This means that we can NOT accept pull requests from you until you do this. +This means that we can NOT accept pull requests from you from any location until you do this. + + +## First Time Contributors: work from a fork + +When we have received the Plone Contributor Agreement and it has been process by a community member, you will be added to the Plone organisation and added to the Contributors Team on GitHub. +You can create issues, add comments to existing issues, and discuss the development of Plone with others. +Creating branches and editing code on our main repositories is restricted and granted to members who have been active in the Plone community for a while and have shown continued interest to contributing. + +- First, verify that your issue is valid by creating it and discussing it with other developers. +- Then, create a fork of the repo in your own workspace, work on your code and make commits. +- When you want to run our code quality checks, create a Pull Request from your repo/branch to the main repository. +- As a security measure, the first run of code Quality checks need to be [approved by a member in our Developers Team](https://docs.github.com/en/actions/managing-workflow-runs/approving-workflow-runs-from-public-forks) +- A Developer with full access to the workflow will need to review and approve your Pull request. + +Please be aware that as long as you are working from a fork, you are the only developer being able to commit to your branch. +Collaboration between developers on bigger pull requests is more efficient when these are done on branch on the main repo. +Therefore: as your first time contribution don't choose a too big problem to solve. +Pick something that you can fix or complete from start to end. + + + +## Documenting your changes All pull requests must include a `towncrier` news item. This is a file that is placed in the root of the repository directory at `/news`. @@ -57,7 +79,8 @@ strings as translatable as defined in the [i18n guide](../recipes/i18n.md). ## Code Quality All pull requests must pass tests, documentation builds, and other code quality checks. -Contributors are strongly encouraged to run these checks locally before creating a pull request. +Developers are strongly encouraged to run these checks locally before creating a pull request. +Contributors without full Developer access will need to create a Pull request first and get approval for their first PR from a Developer. These checks are enforced automatically on every pull request, so you might as well save time and frustration by doing these checks locally first. Specifically: From cb9dfd062cf0c51af23b30afeb10f51634e36327 Mon Sep 17 00:00:00 2001 From: Utkarsh Bhardwaj <67866657+utkkkarshhh@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:50:01 +0530 Subject: [PATCH 096/142] 3092 improve spellcheck (#4633) Co-authored-by: Steve Piercy --- news/3092.documentation | 1 + styles/Vocab/Plone/accept.txt | 2 ++ styles/Vocab/Plone/reject.txt | 5 +++++ 3 files changed, 8 insertions(+) create mode 100644 news/3092.documentation diff --git a/news/3092.documentation b/news/3092.documentation new file mode 100644 index 0000000000..2f1b9f34d6 --- /dev/null +++ b/news/3092.documentation @@ -0,0 +1 @@ +Added `JavaScript` and `NodeJS` as accepted spellings, and deviations of them as rejected spellings. @utkkkarshhh \ No newline at end of file diff --git a/styles/Vocab/Plone/accept.txt b/styles/Vocab/Plone/accept.txt index 78bcf7537b..0ff684308f 100644 --- a/styles/Vocab/Plone/accept.txt +++ b/styles/Vocab/Plone/accept.txt @@ -6,3 +6,5 @@ Razzle RichText Volto Zope +JavaScript +NodeJS diff --git a/styles/Vocab/Plone/reject.txt b/styles/Vocab/Plone/reject.txt index e69de29bb2..1deaa26744 100644 --- a/styles/Vocab/Plone/reject.txt +++ b/styles/Vocab/Plone/reject.txt @@ -0,0 +1,5 @@ +node +nodejs +javascript +js +Javascript \ No newline at end of file From ba40abf6b7ca48afabbef57b8623ba5329df273c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Mon, 3 Apr 2023 13:59:22 +0200 Subject: [PATCH 097/142] Update to latest Razzle - needed since #3997. This fixes the duplicated Razzles issue (#4640) --- .../generator-volto/generators/app/templates/package.json.tpl | 2 +- packages/generator-volto/news/4640.bugfix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 packages/generator-volto/news/4640.bugfix diff --git a/packages/generator-volto/generators/app/templates/package.json.tpl b/packages/generator-volto/generators/app/templates/package.json.tpl index eeea34b12f..8292f576f9 100644 --- a/packages/generator-volto/generators/app/templates/package.json.tpl +++ b/packages/generator-volto/generators/app/templates/package.json.tpl @@ -148,7 +148,7 @@ "@storybook/addon-essentials": "^6.3.0", "@storybook/addon-links": "^6.3.0", "@storybook/react": "^6.3.0", - "razzle": "4.2.17", + "razzle": "4.2.18", "stylelint": "14.0.1", "stylelint-config-idiomatic-order": "8.1.0", "stylelint-config-prettier": "8.0.1", diff --git a/packages/generator-volto/news/4640.bugfix b/packages/generator-volto/news/4640.bugfix new file mode 100644 index 0000000000..aecf02d3b1 --- /dev/null +++ b/packages/generator-volto/news/4640.bugfix @@ -0,0 +1 @@ +Update to latest Razzle - needed since #3997. This fixes the duplicated Razzles issue @sneridagh From bc564db6798c98c7ef94d1ffc32e1b3d94d516a5 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Mon, 3 Apr 2023 14:00:46 +0200 Subject: [PATCH 098/142] Release generate-volto 7.0.0-alpha.3 --- packages/generator-volto/CHANGELOG.md | 7 +++++++ packages/generator-volto/news/4640.bugfix | 1 - packages/generator-volto/package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 packages/generator-volto/news/4640.bugfix diff --git a/packages/generator-volto/CHANGELOG.md b/packages/generator-volto/CHANGELOG.md index e3b7cc11cd..b46cda34cd 100644 --- a/packages/generator-volto/CHANGELOG.md +++ b/packages/generator-volto/CHANGELOG.md @@ -8,6 +8,13 @@ +## 7.0.0-alpha.3 (2023-04-03) + +### Bugfix + +- Update to latest Razzle - needed since #3997. This fixes the duplicated Razzles issue @sneridagh [#4640](https://github.com/plone/volto/issues/4640) + + ## 7.0.0-alpha.2 (2023-03-05) ### Feature diff --git a/packages/generator-volto/news/4640.bugfix b/packages/generator-volto/news/4640.bugfix deleted file mode 100644 index aecf02d3b1..0000000000 --- a/packages/generator-volto/news/4640.bugfix +++ /dev/null @@ -1 +0,0 @@ -Update to latest Razzle - needed since #3997. This fixes the duplicated Razzles issue @sneridagh diff --git a/packages/generator-volto/package.json b/packages/generator-volto/package.json index 022f0bc334..3a9ac534fe 100644 --- a/packages/generator-volto/package.json +++ b/packages/generator-volto/package.json @@ -10,7 +10,7 @@ } ], "license": "MIT", - "version": "7.0.0-alpha.2", + "version": "7.0.0-alpha.3", "repository": { "type": "git", "url": "git+https://github.com/plone/generator-volto.git" From 169a01bbaa024518253b7993676dcc7f4dd3bec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Mon, 3 Apr 2023 17:20:37 +0200 Subject: [PATCH 099/142] Razzle upgrade notice in upgrade guide (#4641) Co-authored-by: Steve Piercy --- docs/source/upgrade-guide/index.md | 5 +++++ news/4641.documentation | 1 + 2 files changed, 6 insertions(+) create mode 100644 news/4641.documentation diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index 166f10263c..31bd17f7f9 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -47,6 +47,11 @@ Volto 17 now uses Webpack 5. If you customized `razzle.config.js` for your project to change Webpack configuration or use Webpack plugins, you might need to make adjustments. +### Razzle upgraded to version `4.2.18` + +Razzle has been upgraded to version `4.2.18`. +It is recommended that you update your project's dependency on Razzle to this version in order to avoid duplication. + ### `BlockChooser` component now uses `popperjs` internally Technically not a breaking, the API nor the component contract has changed, but it's worth noting this change in here. diff --git a/news/4641.documentation b/news/4641.documentation new file mode 100644 index 0000000000..335c2489fd --- /dev/null +++ b/news/4641.documentation @@ -0,0 +1 @@ +Razzle upgrade notice in upgrade guide @sneridagh From 72ba0818a7a9eb6a957d6f07f1f166a24b9f717a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Wed, 5 Apr 2023 10:32:22 +0200 Subject: [PATCH 100/142] Release notes for 16.19.0 (#4655) --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 074b7a462a..c492f428b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -112,6 +112,23 @@ - Use a universal static path for both documentation and volto repos. @stevepiercy [#4376](https://github.com/plone/volto/issues/4376) +## 16.19.0 (2023-04-04) + +### Feature + +- DefaultView (view of fields for content types with blocks disabled): Show field name as tip on hover of label. @ksuess [#4598](https://github.com/plone/volto/issues/4598) +- Set sameSite in I18N_LANGUAGE cookie @sneridagh [#4627](https://github.com/plone/volto/issues/4627) + +### Bugfix + +- Fix regexp that checks valid URLs and improve tests [cekk] [#4601](https://github.com/plone/volto/issues/4601) + +### Documentation + +- Added `JavaScript` and `NodeJS` as accepted spellings, and deviations of them as rejected spellings. @utkkkarshhh [#3092](https://github.com/plone/volto/issues/3092) +- Fix documentation build, add pins @sneridagh [#4626](https://github.com/plone/volto/issues/4626) + + ## 16.18.0 (2023-03-22) ### Feature From 267181c1eaeb450844392b3be13b1f0aa308f5ef Mon Sep 17 00:00:00 2001 From: iRohitSingh <61353484+iRohitSingh@users.noreply.github.com> Date: Wed, 5 Apr 2023 19:20:37 +0530 Subject: [PATCH 101/142] Fixed wrong localization on password reset page(#4656) (#4657) --- locales/ca/LC_MESSAGES/volto.po | 4 ++-- locales/de/LC_MESSAGES/volto.po | 8 ++++---- locales/en/LC_MESSAGES/volto.po | 4 ++-- locales/es/LC_MESSAGES/volto.po | 4 ++-- locales/eu/LC_MESSAGES/volto.po | 4 ++-- locales/fr/LC_MESSAGES/volto.po | 4 ++-- locales/it/LC_MESSAGES/volto.po | 4 ++-- locales/ja/LC_MESSAGES/volto.po | 4 ++-- locales/nl/LC_MESSAGES/volto.po | 4 ++-- locales/pt/LC_MESSAGES/volto.po | 4 ++-- locales/pt_BR/LC_MESSAGES/volto.po | 4 ++-- locales/ro/LC_MESSAGES/volto.po | 4 ++-- locales/volto.pot | 6 +++--- locales/zh_CN/LC_MESSAGES/volto.po | 4 ++-- news/4656.bugfix | 1 + src/components/theme/PasswordReset/PasswordReset.jsx | 2 +- .../theme/PasswordReset/RequestPasswordReset.jsx | 2 +- .../__snapshots__/RequestPasswordReset.test.jsx.snap | 2 +- 18 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 news/4656.bugfix diff --git a/locales/ca/LC_MESSAGES/volto.po b/locales/ca/LC_MESSAGES/volto.po index 1133771312..d204173163 100644 --- a/locales/ca/LC_MESSAGES/volto.po +++ b/locales/ca/LC_MESSAGES/volto.po @@ -2098,7 +2098,7 @@ msgid "My email is" msgstr "" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "El meu nom d'usuari és" @@ -4193,7 +4193,7 @@ msgid "label_my_email_is" msgstr "" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "El meu nom d'usuari és" diff --git a/locales/de/LC_MESSAGES/volto.po b/locales/de/LC_MESSAGES/volto.po index 8a717bc3d2..908ad7614d 100644 --- a/locales/de/LC_MESSAGES/volto.po +++ b/locales/de/LC_MESSAGES/volto.po @@ -2095,9 +2095,9 @@ msgid "My email is" msgstr "Meine E-Mail ist" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" -msgstr "Mein Benutzername ist" +msgstr "Mein Nutzername lautet" #: components/manage/Sharing/Sharing #: components/theme/ContactForm/ContactForm @@ -4190,9 +4190,9 @@ msgid "label_my_email_is" msgstr "Meine E-Mail ist" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" -msgstr "El meu nom d'usuari és" +msgstr "Mein Nutzername lautet" #: config/Blocks # defaultMessage: Lead Image Field diff --git a/locales/en/LC_MESSAGES/volto.po b/locales/en/LC_MESSAGES/volto.po index 30e4e39d71..40dc8bc6b1 100644 --- a/locales/en/LC_MESSAGES/volto.po +++ b/locales/en/LC_MESSAGES/volto.po @@ -2089,7 +2089,7 @@ msgid "My email is" msgstr "" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "" @@ -4184,7 +4184,7 @@ msgid "label_my_email_is" msgstr "" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "" diff --git a/locales/es/LC_MESSAGES/volto.po b/locales/es/LC_MESSAGES/volto.po index 5eaf110016..076b32ae41 100644 --- a/locales/es/LC_MESSAGES/volto.po +++ b/locales/es/LC_MESSAGES/volto.po @@ -2100,7 +2100,7 @@ msgid "My email is" msgstr "Mi dirección de correo electrónico es" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "Mi nombre de usuario es" @@ -4195,7 +4195,7 @@ msgid "label_my_email_is" msgstr "Mi dirección de correo es" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "Mi nombre de usuario es" diff --git a/locales/eu/LC_MESSAGES/volto.po b/locales/eu/LC_MESSAGES/volto.po index 4f058ed3ab..fc08930c3d 100644 --- a/locales/eu/LC_MESSAGES/volto.po +++ b/locales/eu/LC_MESSAGES/volto.po @@ -2096,7 +2096,7 @@ msgid "My email is" msgstr "Nire helbidea hauxe da" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "Nire erabiltzaile izena da" @@ -4191,7 +4191,7 @@ msgid "label_my_email_is" msgstr "Nire helbidea hauxe da: " #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "Nire erabiltzaile izena da" diff --git a/locales/fr/LC_MESSAGES/volto.po b/locales/fr/LC_MESSAGES/volto.po index 5f9097b014..786de2a3f2 100644 --- a/locales/fr/LC_MESSAGES/volto.po +++ b/locales/fr/LC_MESSAGES/volto.po @@ -2106,7 +2106,7 @@ msgid "My email is" msgstr "Mon email est" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "Mon nom d'utilisateur est" @@ -4201,7 +4201,7 @@ msgid "label_my_email_is" msgstr "Mon email est" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "Mon nom d'utilisateur est" diff --git a/locales/it/LC_MESSAGES/volto.po b/locales/it/LC_MESSAGES/volto.po index ee1c27901c..8139c852c5 100644 --- a/locales/it/LC_MESSAGES/volto.po +++ b/locales/it/LC_MESSAGES/volto.po @@ -2089,7 +2089,7 @@ msgid "My email is" msgstr "La mia email è" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "Il mio nome utente è" @@ -4184,7 +4184,7 @@ msgid "label_my_email_is" msgstr "La mia email è" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "Il mio nome utente è" diff --git a/locales/ja/LC_MESSAGES/volto.po b/locales/ja/LC_MESSAGES/volto.po index 53ba075dea..501902a95f 100644 --- a/locales/ja/LC_MESSAGES/volto.po +++ b/locales/ja/LC_MESSAGES/volto.po @@ -2097,7 +2097,7 @@ msgid "My email is" msgstr "" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "私のユーザー名は" @@ -4192,7 +4192,7 @@ msgid "label_my_email_is" msgstr "" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "私のユーザー名は" diff --git a/locales/nl/LC_MESSAGES/volto.po b/locales/nl/LC_MESSAGES/volto.po index 17eac461c8..53effede9e 100644 --- a/locales/nl/LC_MESSAGES/volto.po +++ b/locales/nl/LC_MESSAGES/volto.po @@ -2096,7 +2096,7 @@ msgid "My email is" msgstr "Mijn e-mail is" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "Mijn gebruikersnaam is" @@ -4191,7 +4191,7 @@ msgid "label_my_email_is" msgstr "Mijn e-mail is" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "Mijn gebruikersnaam is" diff --git a/locales/pt/LC_MESSAGES/volto.po b/locales/pt/LC_MESSAGES/volto.po index 40dae41756..6f2139d880 100644 --- a/locales/pt/LC_MESSAGES/volto.po +++ b/locales/pt/LC_MESSAGES/volto.po @@ -2097,7 +2097,7 @@ msgid "My email is" msgstr "" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "Meu nome de usuário é" @@ -4192,7 +4192,7 @@ msgid "label_my_email_is" msgstr "" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "Meu nome de usuário é" diff --git a/locales/pt_BR/LC_MESSAGES/volto.po b/locales/pt_BR/LC_MESSAGES/volto.po index d4d8f10d1e..0087d92fbe 100644 --- a/locales/pt_BR/LC_MESSAGES/volto.po +++ b/locales/pt_BR/LC_MESSAGES/volto.po @@ -2099,7 +2099,7 @@ msgid "My email is" msgstr "Meu e-mail é" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "Meu nome de usuário é" @@ -4194,7 +4194,7 @@ msgid "label_my_email_is" msgstr "Meu endereço de e-mail é" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "Meu nome de usuário é<<<<<<< HEAD" diff --git a/locales/ro/LC_MESSAGES/volto.po b/locales/ro/LC_MESSAGES/volto.po index 88cc55fcdb..45e761e855 100644 --- a/locales/ro/LC_MESSAGES/volto.po +++ b/locales/ro/LC_MESSAGES/volto.po @@ -2089,7 +2089,7 @@ msgid "My email is" msgstr "" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "Numele meu de utilizator este" @@ -4184,7 +4184,7 @@ msgid "label_my_email_is" msgstr "" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "Numele meu de utilizator este" diff --git a/locales/volto.pot b/locales/volto.pot index ad763942a7..660ab3fe0f 100644 --- a/locales/volto.pot +++ b/locales/volto.pot @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Plone\n" -"POT-Creation-Date: 2023-03-01T10:46:45.512Z\n" +"POT-Creation-Date: 2023-04-05T10:12:20.363Z\n" "Last-Translator: Plone i18n \n" "Language-Team: Plone i18n \n" "MIME-Version: 1.0\n" @@ -2091,7 +2091,7 @@ msgid "My email is" msgstr "" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "" @@ -4186,7 +4186,7 @@ msgid "label_my_email_is" msgstr "" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "" diff --git a/locales/zh_CN/LC_MESSAGES/volto.po b/locales/zh_CN/LC_MESSAGES/volto.po index ac6774f8e8..3d436e9e67 100644 --- a/locales/zh_CN/LC_MESSAGES/volto.po +++ b/locales/zh_CN/LC_MESSAGES/volto.po @@ -2095,7 +2095,7 @@ msgid "My email is" msgstr "我的邮箱是" #: components/theme/PasswordReset/PasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "My username is" msgstr "我的用户名是" @@ -4190,7 +4190,7 @@ msgid "label_my_email_is" msgstr "我的邮箱是" #: components/theme/PasswordReset/RequestPasswordReset -# defaultMessage: My username is +# defaultMessage: My user name is msgid "label_my_username_is" msgstr "我的用户名是" diff --git a/news/4656.bugfix b/news/4656.bugfix new file mode 100644 index 0000000000..06b9558589 --- /dev/null +++ b/news/4656.bugfix @@ -0,0 +1 @@ +Fixed wrong localization on password reset page @iRohitSingh \ No newline at end of file diff --git a/src/components/theme/PasswordReset/PasswordReset.jsx b/src/components/theme/PasswordReset/PasswordReset.jsx index ca822ed4b2..f676b2d3d0 100644 --- a/src/components/theme/PasswordReset/PasswordReset.jsx +++ b/src/components/theme/PasswordReset/PasswordReset.jsx @@ -31,7 +31,7 @@ const messages = defineMessages({ }, usernameTitle: { id: 'My username is', - defaultMessage: 'My username is', + defaultMessage: 'My user name is', }, emailTitle: { id: 'My email is', diff --git a/src/components/theme/PasswordReset/RequestPasswordReset.jsx b/src/components/theme/PasswordReset/RequestPasswordReset.jsx index 3154a95321..db429f94f3 100644 --- a/src/components/theme/PasswordReset/RequestPasswordReset.jsx +++ b/src/components/theme/PasswordReset/RequestPasswordReset.jsx @@ -32,7 +32,7 @@ const messages = defineMessages({ }, usernameTitle: { id: 'label_my_username_is', - defaultMessage: 'My username is', + defaultMessage: 'My user name is', }, emailTitle: { id: 'label_my_email_is', diff --git a/src/components/theme/PasswordReset/__snapshots__/RequestPasswordReset.test.jsx.snap b/src/components/theme/PasswordReset/__snapshots__/RequestPasswordReset.test.jsx.snap index 027cf7b048..0eaf6db99a 100644 --- a/src/components/theme/PasswordReset/__snapshots__/RequestPasswordReset.test.jsx.snap +++ b/src/components/theme/PasswordReset/__snapshots__/RequestPasswordReset.test.jsx.snap @@ -47,7 +47,7 @@ exports[`RequestPasswordReset renders a RequestPasswordReset component 1`] = ` className="mocked-default-widget" id="mocked-field-username" > - My username is + My user name is - No description
    From c40e772701e4f6771a541898621457ec45500859 Mon Sep 17 00:00:00 2001 From: Bittor Poza Date: Wed, 5 Apr 2023 17:56:48 +0200 Subject: [PATCH 102/142] Add current page parameter to the route in the listing and search block pagination (#4159) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Mikel Larreategi Co-authored-by: Víctor Fernández de Alba Co-authored-by: ionlizarazu --- news/4159.bugfix | 1 + .../Blocks/Listing/ListingBody.test.jsx | 20 +++ .../Blocks/Listing/withQuerystringResults.jsx | 3 +- .../manage/Blocks/Search/hocs/withSearch.jsx | 12 +- src/helpers/Utils/usePagination.js | 62 +++++++--- src/helpers/Utils/usePagination.test.js | 115 ++++++++++++++++++ 6 files changed, 193 insertions(+), 20 deletions(-) create mode 100644 news/4159.bugfix create mode 100644 src/helpers/Utils/usePagination.test.js diff --git a/news/4159.bugfix b/news/4159.bugfix new file mode 100644 index 0000000000..d9b9f18dfa --- /dev/null +++ b/news/4159.bugfix @@ -0,0 +1 @@ +Added current page parameter to route in listing and search block pagination - Fix: #3868 @bipoza \ No newline at end of file diff --git a/src/components/manage/Blocks/Listing/ListingBody.test.jsx b/src/components/manage/Blocks/Listing/ListingBody.test.jsx index d52c7df814..8a5c359972 100644 --- a/src/components/manage/Blocks/Listing/ListingBody.test.jsx +++ b/src/components/manage/Blocks/Listing/ListingBody.test.jsx @@ -36,6 +36,26 @@ test('renders a ListingBody component', () => { content: { data: { is_folderish: true, + blocks: { + '839ee00b-013b-4f4a-9b10-8867938fdac3': { + '@type': 'listing', + block: '839ee00b-013b-4f4a-9b10-8867938fdac3', + headlineTag: 'h2', + query: [], + querystring: { + b_size: '2', + query: [ + { + i: 'path', + o: 'plone.app.querystring.operation.string.absolutePath', + v: '/', + }, + ], + sort_order: 'ascending', + }, + variation: 'default', + }, + }, }, }, intl: { diff --git a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx index d675fc050a..c550cf93cb 100644 --- a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +++ b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx @@ -25,7 +25,7 @@ export default function withQuerystringResults(WrappedComponent) { const [initialPath] = React.useState(getBaseUrl(path)); const copyFields = ['limit', 'query', 'sort_on', 'sort_order', 'depth']; - + const { currentPage, setCurrentPage } = usePagination(data.block, 1); const adaptedQuery = Object.assign( variation?.fullobjects ? { fullobjects: 1 } : { metadata_fields: '_all' }, { @@ -37,7 +37,6 @@ export default function withQuerystringResults(WrappedComponent) { : {}, ), ); - const { currentPage, setCurrentPage } = usePagination(querystring, 1); const querystringResults = useSelector( (state) => state.querystringsearch.subrequests, ); diff --git a/src/components/manage/Blocks/Search/hocs/withSearch.jsx b/src/components/manage/Blocks/Search/hocs/withSearch.jsx index 5177dd6304..fd1842fbc1 100644 --- a/src/components/manage/Blocks/Search/hocs/withSearch.jsx +++ b/src/components/manage/Blocks/Search/hocs/withSearch.jsx @@ -144,12 +144,16 @@ const getSearchFields = (searchData) => { }; /** - * A HOC that will mirror the search block state to a hash location + * A hook that will mirror the search block state to a hash location */ const useHashState = () => { const location = useLocation(); const history = useHistory(); + /** + * Required to maintain parameter compatibility. + With this we will maintain support for receiving hash (#) and search (?) type parameters. + */ const oldState = React.useMemo(() => { return { ...qs.parse(location.search), @@ -165,7 +169,7 @@ const useHashState = () => { const setSearchData = React.useCallback( (searchData) => { - const newParams = qs.parse(location.hash); + const newParams = qs.parse(location.search); let changed = false; @@ -182,11 +186,11 @@ const useHashState = () => { if (changed) { history.push({ - hash: qs.stringify(newParams), + search: qs.stringify(newParams), }); } }, - [history, oldState, location.hash], + [history, oldState, location.search], ); return [current, setSearchData]; diff --git a/src/helpers/Utils/usePagination.js b/src/helpers/Utils/usePagination.js index acb12d2ac5..dc984e9932 100644 --- a/src/helpers/Utils/usePagination.js +++ b/src/helpers/Utils/usePagination.js @@ -1,25 +1,59 @@ -import React from 'react'; -import { isEqual } from 'lodash'; -import { usePrevious } from './usePrevious'; -import useDeepCompareEffect from 'use-deep-compare-effect'; +import React, { useRef, useEffect } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; +import qs from 'query-string'; +import { useSelector } from 'react-redux'; +import { slugify } from '@plone/volto/helpers/Utils/Utils'; + +/** + * @function useCreatePageQueryStringKey + * @description A hook that creates a key with an id if there are multiple blocks with pagination. + * @returns {string} Example: page || page_012345678 + */ +const useCreatePageQueryStringKey = (id) => { + const blockTypesWithPagination = ['search', 'listing']; + const blocks = useSelector((state) => state?.content?.data?.blocks) || []; + const blocksLayout = + useSelector((state) => state?.content?.data?.blocks_layout?.items) || []; + const displayedBlocks = blocksLayout?.map((item) => blocks[item]); + const hasMultiplePaginations = + displayedBlocks.filter((item) => + blockTypesWithPagination.includes(item['@type']), + ).length > 1 || false; + + return hasMultiplePaginations ? slugify(`page-${id}`) : 'page'; +}; /** * A pagination helper that tracks the query and resets pagination in case the * query changes. */ -export const usePagination = (query, defaultPage = 1) => { - const previousQuery = usePrevious(query); - const [currentPage, setCurrentPage] = React.useState(defaultPage); +export const usePagination = (id = null, defaultPage = 1) => { + const location = useLocation(); + const history = useHistory(); + const pageQueryStringKey = useCreatePageQueryStringKey(id); + const pageQueryParam = + qs.parse(location.search)[pageQueryStringKey] || defaultPage; + const [currentPage, setCurrentPage] = React.useState( + parseInt(pageQueryParam), + ); + const queryRef = useRef(qs.parse(location.search)?.query); - useDeepCompareEffect(() => { - setCurrentPage(defaultPage); - }, [query, previousQuery, defaultPage]); + useEffect(() => { + if (queryRef.current !== qs.parse(location.search)?.query) { + setCurrentPage(defaultPage); + queryRef.current = qs.parse(location.search)?.query; + } + const newParams = { + ...qs.parse(location.search), + [pageQueryStringKey]: currentPage, + }; + history.replace({ + search: qs.stringify(newParams), + }); + }, [currentPage, defaultPage, location.search, history, pageQueryStringKey]); return { - currentPage: - previousQuery && !isEqual(previousQuery, query) - ? defaultPage - : currentPage, + currentPage, setCurrentPage, }; }; diff --git a/src/helpers/Utils/usePagination.test.js b/src/helpers/Utils/usePagination.test.js new file mode 100644 index 0000000000..26924d78a0 --- /dev/null +++ b/src/helpers/Utils/usePagination.test.js @@ -0,0 +1,115 @@ +import { renderHook } from '@testing-library/react-hooks'; +import { usePagination } from './usePagination'; +import * as redux from 'react-redux'; +import routeData from 'react-router'; +import { slugify } from '@plone/volto/helpers/Utils/Utils'; + +const searchBlockId = '545b33de-92cf-4747-969d-68851837b317'; +const searchBlockId2 = '454b33de-92cf-4747-969d-68851837b713'; +const searchBlock = { + '@type': 'search', + query: { + b_size: '4', + query: [ + { + i: 'path', + o: 'plone.app.querystring.operation.string.relativePath', + v: '', + }, + ], + sort_order: 'ascending', + }, + showSearchInput: true, + showTotalResults: true, +}; +let state = { + content: { + data: { + blocks: { + [searchBlockId]: searchBlock, + }, + blocks_layout: { + items: [searchBlockId], + }, + }, + }, +}; + +let mockUseLocationValue = { + pathname: '/testroute', + search: '', +}; + +const setUp = (searchParam, numberOfSearches) => { + mockUseLocationValue.search = searchParam; + if (numberOfSearches > 1) { + state.content.data.blocks[searchBlockId2] = searchBlock; + state.content.data.blocks_layout.items.push(searchBlockId2); + } + return renderHook(({ id, defaultPage }) => usePagination(id, defaultPage), { + initialProps: { + id: searchBlockId, + defaultPage: 1, + }, + }); +}; + +describe(`Tests for usePagination, for the block ${searchBlockId}`, () => { + const useLocation = jest.spyOn(routeData, 'useLocation'); + const useHistory = jest.spyOn(routeData, 'useHistory'); + const useSelector = jest.spyOn(redux, 'useSelector'); + beforeEach(() => { + useLocation.mockReturnValue(mockUseLocationValue); + useHistory.mockReturnValue({ replace: jest.fn() }); + useSelector.mockImplementation((cb) => cb(state)); + }); + + it('1 paginated block with id and defaultPage 1 - shoud be 1', () => { + const { result } = setUp(); + expect(result.current.currentPage).toBe(1); + }); + + it('1 paginated block without params - shoud be 1', () => { + const { result } = setUp(); + expect(result.current.currentPage).toBe(1); + }); + + const param1 = '?page=2'; + it(`1 paginated block with params: ${param1} - shoud be 2`, () => { + const { result } = setUp(param1); + expect(result.current.currentPage).toBe(2); + }); + + const param2 = `?${slugify(`page-${searchBlockId}`)}=2`; + it(`2 paginated blocks with current block in the params: ${param2} - shoud be 2`, () => { + const { result } = setUp(param2, 2); + expect(result.current.currentPage).toBe(2); + }); + + const param3 = `?${slugify(`page-${searchBlockId2}`)}=2`; + it(`2 paginated blocks with the other block in the params: ${param3} - shoud be 1`, () => { + const { result } = setUp(param3, 2); + expect(result.current.currentPage).toBe(1); + }); + + const param4 = `?${slugify(`page-${searchBlockId}`)}=2&${slugify( + `page-${searchBlockId2}`, + )}=1`; + it(`2 paginated blocks with both blocks in the params, current 2: ${param4} - shoud be 2`, () => { + const { result } = setUp(param4, 2); + expect(result.current.currentPage).toBe(2); + }); + + const param5 = `?${slugify(`page-${searchBlockId}`)}=1&${slugify( + `page-${searchBlockId2}`, + )}=2`; + it(`2 paginated blocks with both blocks in the params, current 1: ${param5} - shoud be 1`, () => { + const { result } = setUp(param5, 2); + expect(result.current.currentPage).toBe(1); + }); + + it(`2 paginated blocks with wrong page param: ${param1} - shoud be 1`, () => { + const { result } = setUp(param1, 2); + expect(result.current.currentPage).toBe(1); + }); +}); From 9d767d43348a3d27633c5000bc362932e8016508 Mon Sep 17 00:00:00 2001 From: Rob Gietema Date: Thu, 6 Apr 2023 09:35:06 +0200 Subject: [PATCH 103/142] Added querystring search get option (#4658) --- news/4658.feature | 1 + .../querystringsearch/querystringsearch.js | 34 +++++++++++-------- src/config/index.js | 1 + 3 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 news/4658.feature diff --git a/news/4658.feature b/news/4658.feature new file mode 100644 index 0000000000..0c4c3cc11b --- /dev/null +++ b/news/4658.feature @@ -0,0 +1 @@ +Added querystring search get option. @robgietema \ No newline at end of file diff --git a/src/actions/querystringsearch/querystringsearch.js b/src/actions/querystringsearch/querystringsearch.js index 9dff75b72d..6b178436f7 100644 --- a/src/actions/querystringsearch/querystringsearch.js +++ b/src/actions/querystringsearch/querystringsearch.js @@ -31,24 +31,30 @@ export function getQueryStringResults(path, data, subrequest, page) { } } + const query = { + ...requestData, + ...(!requestData.b_size && { + b_size: settings.defaultPageSize, + }), + ...(page && { + b_start: requestData.b_size + ? data.b_size * (page - 1) + : settings.defaultPageSize * (page - 1), + }), + query: requestData?.query, + }; + return { type: GET_QUERYSTRING_RESULTS, subrequest, request: { - op: 'post', - path: `${path}/@querystring-search`, - data: { - ...requestData, - ...(!requestData.b_size && { - b_size: settings.defaultPageSize, - }), - ...(page && { - b_start: requestData.b_size - ? data.b_size * (page - 1) - : settings.defaultPageSize * (page - 1), - }), - query: requestData?.query, - }, + op: settings.querystringSearchGet ? 'get' : 'post', + path: `${path}/@querystring-search${ + settings.querystringSearchGet + ? `?query=${encodeURIComponent(JSON.stringify(query))}` + : '' + }`, + data: settings.querystringSearchGet ? null : query, }, }; } diff --git a/src/config/index.js b/src/config/index.js index 60985f5e26..6833ff56b8 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -180,6 +180,7 @@ let config = { styleClassNameConverters, hashLinkSmoothScroll: false, styleClassNameExtenders, + querystringSearchGet: false, }, experimental: { addBlockButton: { From 90363c2ff7dba330fdc705bf95195b2b848acff3 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Fri, 7 Apr 2023 11:12:21 +0200 Subject: [PATCH 104/142] Changelog --- packages/scripts/news/4316.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/scripts/news/4316.bugfix diff --git a/packages/scripts/news/4316.bugfix b/packages/scripts/news/4316.bugfix new file mode 100644 index 0000000000..0e012ad4f1 --- /dev/null +++ b/packages/scripts/news/4316.bugfix @@ -0,0 +1 @@ +Fixed i18n script to avoid overwriting translations with an empty msgstr @danalvrz From d8b665f387c2827757782123083a9918394c7d12 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Fri, 7 Apr 2023 11:12:44 +0200 Subject: [PATCH 105/142] Release @plone/scripts 3.0.0 --- packages/scripts/CHANGELOG.md | 11 +++++++++++ packages/scripts/news/4316.bugfix | 1 - packages/scripts/news/4546.breaking | 1 - packages/scripts/package.json | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) delete mode 100644 packages/scripts/news/4316.bugfix delete mode 100644 packages/scripts/news/4546.breaking diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 560a57ee9b..84c99079d7 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -8,6 +8,17 @@ +## 3.0.0 (2023-04-07) + +### Breaking + +- Remove dependency on `simple-git`. It is used by `mrs-developer` but not directly. @davisagli [#4546](https://github.com/plone/volto/issues/4546) + +### Bugfix + +- Fixed i18n script to avoid overwriting translations with an empty msgstr @danalvrz [#4316](https://github.com/plone/volto/issues/4316) + + ## 2.3.0 (2023-01-13) ### Feature diff --git a/packages/scripts/news/4316.bugfix b/packages/scripts/news/4316.bugfix deleted file mode 100644 index 0e012ad4f1..0000000000 --- a/packages/scripts/news/4316.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed i18n script to avoid overwriting translations with an empty msgstr @danalvrz diff --git a/packages/scripts/news/4546.breaking b/packages/scripts/news/4546.breaking deleted file mode 100644 index 468d189887..0000000000 --- a/packages/scripts/news/4546.breaking +++ /dev/null @@ -1 +0,0 @@ -Remove dependency on `simple-git`. It is used by `mrs-developer` but not directly. @davisagli diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 2936321d4f..6d8ed40cf6 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "2.3.0", + "version": "3.0.0", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" From 00029a2cb9fd9599fd1a1707aa5018a96d1e6873 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 8 Apr 2023 15:15:00 -0700 Subject: [PATCH 106/142] =?UTF-8?q?Update=20Volto=20contributing=20to=20al?= =?UTF-8?q?ign=20with=20and=20refer=20to=20the=20new=20Plone=20co=E2=80=A6?= =?UTF-8?q?=20(#4634)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../developer-guidelines/contributing.md | 81 ++++++++++--------- news/4634.documentation | 1 + 2 files changed, 42 insertions(+), 40 deletions(-) create mode 100644 news/4634.documentation diff --git a/docs/source/developer-guidelines/contributing.md b/docs/source/developer-guidelines/contributing.md index 04446bf2db..b2b7a445b6 100644 --- a/docs/source/developer-guidelines/contributing.md +++ b/docs/source/developer-guidelines/contributing.md @@ -7,11 +7,15 @@ myst: "keywords": "Volto, Plone, frontend, React, guidelines" --- +(contributing-to-volto-label)= + # Contributing to Volto -You may have an issue to report, make a feature request, report a security vulnerability, or you want to create a pull request. -You have come to the right place to learn how to do so. +First read {doc}`plone:contributing/index`. +Volto follows those guidelines with a few specific variations, as described in this chapter. + +(contributing-reporting-an-issue-or-making-a-feature-request-label)= ## Reporting an issue or making a feature request @@ -22,65 +26,60 @@ When in doubt, create one in the [CMFPlone issue tracker](https://github.com/plo In your report, please specify a few things: -- What are the steps to reproduce the problem? -- What do you expect when you follow those steps? -- What do you observe? -- Which Plone version are you using? -- Include relevant screenshots, error messages, and stack traces. +- What are the steps to reproduce the problem? +- What do you expect when you follow those steps? +- What do you observe? +- Which Plone version are you using? +- Include relevant screenshots, error messages, and stack traces. + + +(contributing-sign-and-return-the-plone-contributor-agreement-label)= + +## Sign and return the Plone Contributor Agreement + +The Volto Team reviews pull requests only from people with a GitHub account who have signed and returned the {ref}`Plone Contributor Agreement `, and subsequently been assigned to a Plone Team in GitHub. + + +(contributing-branch-policy-label)= ## Branch policy ```{include} ./branch-policy.md ``` -## Sign and send us the Plone Contributors Agreement -You must sign the [Plone Contributor Agreement](https://plone.org/foundation/contributors-agreement) to contribute code and documentation to any Plone project. -This means that we can NOT accept pull requests from you from any location until you do this. +(contributing-translations-label)= +## Translations -## First Time Contributors: work from a fork +All text that can be shown in a browser must be translatable. +Please mark all such strings as translatable as defined in the [i18n guide](../recipes/i18n.md). -When we have received the Plone Contributor Agreement and it has been process by a community member, you will be added to the Plone organisation and added to the Contributors Team on GitHub. -You can create issues, add comments to existing issues, and discuss the development of Plone with others. -Creating branches and editing code on our main repositories is restricted and granted to members who have been active in the Plone community for a while and have shown continued interest to contributing. -- First, verify that your issue is valid by creating it and discussing it with other developers. -- Then, create a fork of the repo in your own workspace, work on your code and make commits. -- When you want to run our code quality checks, create a Pull Request from your repo/branch to the main repository. -- As a security measure, the first run of code Quality checks need to be [approved by a member in our Developers Team](https://docs.github.com/en/actions/managing-workflow-runs/approving-workflow-runs-from-public-forks) -- A Developer with full access to the workflow will need to review and approve your Pull request. +(contributing-change-log-entry-label)= -Please be aware that as long as you are working from a fork, you are the only developer being able to commit to your branch. -Collaboration between developers on bigger pull requests is more efficient when these are done on branch on the main repo. -Therefore: as your first time contribution don't choose a too big problem to solve. -Pick something that you can fix or complete from start to end. +## Change log entry +Volto requires that you include a change log entry or news item with your contribution. +Your attribution must be in the format of `@github_username`. +```{seealso} +For details see {ref}`contributing-change-log-label`. +``` -## Documenting your changes -All pull requests must include a `towncrier` news item. -This is a file that is placed in the root of the repository directory at `/news`. -Its format must be `###.type`, where `###` is the referenced GitHub issue or pull request number, `.` is the literal extension delimiter, and `type` is one of the following strings. +(contributing-documenting-your-changes-label)= -- `breaking` for breaking changes -- `bugfix` for bug fixes -- `documentation` for documentation -- `feature` for new features -- `internal` for internal changes +## Documenting your changes If the feature includes a breaking change, you must include instructions for how to upgrade in the [upgrade guide](../upgrade-guide/index.md). -All text that can be shown in a browser must be translatable. Please mark all such -strings as translatable as defined in the [i18n guide](../recipes/i18n.md). +(contributing-code-quality-label)= -## Code Quality +## Code quality All pull requests must pass tests, documentation builds, and other code quality checks. -Developers are strongly encouraged to run these checks locally before creating a pull request. -Contributors without full Developer access will need to create a Pull request first and get approval for their first PR from a Developer. These checks are enforced automatically on every pull request, so you might as well save time and frustration by doing these checks locally first. Specifically: @@ -90,7 +89,9 @@ Specifically: - {doc}`./acceptance-tests` -If after reading this you become hesitant, don't worry. -You can always create a pull request, mark it as "Draft", and improve the above points later, requesting help from the community. +(contributing-final-advice-label)= + +## Final advice -Welcome to the Plone community, and thank you for contributing! +If you become hesitant after reading the foregoing, don't worry. +You can always create a pull request, mark it as "Draft", and improve these points later while requesting help from the community. diff --git a/news/4634.documentation b/news/4634.documentation new file mode 100644 index 0000000000..f3498b18ff --- /dev/null +++ b/news/4634.documentation @@ -0,0 +1 @@ +Update Volto contributing to align with and refer to the new Plone core code contributing requirements. @stevepiercy From a9b96f0399fba4d89a70edb4accea91af3f81d4d Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 9 Apr 2023 03:51:40 -0700 Subject: [PATCH 107/142] Move developer guidelines to contributing #4665 (#4666) --- CHANGELOG.md | 2 +- docs/source/cheatsheet.md | 2 +- docs/source/conf.py | 2 +- .../Quanta.pdf | Bin .../acceptance-tests.md | 0 .../accessibility-guidelines.md | 0 .../branch-policy.md | 0 .../design-principles.md | 0 .../icons.md | 0 .../contributing.md => contributing/index.md} | 44 +++++++++++++++--- .../language-features.md | 0 .../linting.md | 0 .../react.md | 0 .../redux.md | 0 .../routing.md | 0 .../style-guide.md | 0 .../testing.md | 0 .../typescript.md | 0 .../volto-core-addons.md | 0 docs/source/developer-guidelines/index.md | 38 --------------- docs/source/index.md | 2 +- news/4666.documentation | 1 + 22 files changed, 43 insertions(+), 48 deletions(-) rename docs/source/{developer-guidelines => contributing}/Quanta.pdf (100%) rename docs/source/{developer-guidelines => contributing}/acceptance-tests.md (100%) rename docs/source/{developer-guidelines => contributing}/accessibility-guidelines.md (100%) rename docs/source/{developer-guidelines => contributing}/branch-policy.md (100%) rename docs/source/{developer-guidelines => contributing}/design-principles.md (100%) rename docs/source/{developer-guidelines => contributing}/icons.md (100%) rename docs/source/{developer-guidelines/contributing.md => contributing/index.md} (65%) rename docs/source/{developer-guidelines => contributing}/language-features.md (100%) rename docs/source/{developer-guidelines => contributing}/linting.md (100%) rename docs/source/{developer-guidelines => contributing}/react.md (100%) rename docs/source/{developer-guidelines => contributing}/redux.md (100%) rename docs/source/{developer-guidelines => contributing}/routing.md (100%) rename docs/source/{developer-guidelines => contributing}/style-guide.md (100%) rename docs/source/{developer-guidelines => contributing}/testing.md (100%) rename docs/source/{developer-guidelines => contributing}/typescript.md (100%) rename docs/source/{developer-guidelines => contributing}/volto-core-addons.md (100%) delete mode 100644 docs/source/developer-guidelines/index.md create mode 100644 news/4666.documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index c492f428b4..a24ff4bb09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ - Deleted duplicate import and fixed training URLs. @yahya-cloud [#4523](https://github.com/plone/volto/issues/4523) - Fix grammar in PR #4542. @stevepiercy [#4555](https://github.com/plone/volto/issues/4555) -- Fix broken links at ReactJS.org. @stevepiercy [#4569](https://github.com/plone/volto/issues/4569) +- Fix broken links at `ReactJS.org`. @stevepiercy [#4569](https://github.com/plone/volto/issues/4569) - Fix video warnings and link errors. @stevepiercy [#4578](https://github.com/plone/volto/issues/4578) diff --git a/docs/source/cheatsheet.md b/docs/source/cheatsheet.md index dc7eb80d88..f7b8601d7d 100644 --- a/docs/source/cheatsheet.md +++ b/docs/source/cheatsheet.md @@ -14,7 +14,7 @@ myst: # Cheatsheet ```{seealso} -{doc}`plone:contributing/myst-reference` +{doc}`plone:contributing/documentation/myst-reference` ``` diff --git a/docs/source/conf.py b/docs/source/conf.py index 1421636d3f..679833e9a9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -119,7 +119,7 @@ "spelling_wordlist.txt", "**/CHANGES.rst", "**/LICENSE.rst", - "developer-guidelines/branch-policy.md", + "contributing/branch-policy.md", ] html_extra_path = [ diff --git a/docs/source/developer-guidelines/Quanta.pdf b/docs/source/contributing/Quanta.pdf similarity index 100% rename from docs/source/developer-guidelines/Quanta.pdf rename to docs/source/contributing/Quanta.pdf diff --git a/docs/source/developer-guidelines/acceptance-tests.md b/docs/source/contributing/acceptance-tests.md similarity index 100% rename from docs/source/developer-guidelines/acceptance-tests.md rename to docs/source/contributing/acceptance-tests.md diff --git a/docs/source/developer-guidelines/accessibility-guidelines.md b/docs/source/contributing/accessibility-guidelines.md similarity index 100% rename from docs/source/developer-guidelines/accessibility-guidelines.md rename to docs/source/contributing/accessibility-guidelines.md diff --git a/docs/source/developer-guidelines/branch-policy.md b/docs/source/contributing/branch-policy.md similarity index 100% rename from docs/source/developer-guidelines/branch-policy.md rename to docs/source/contributing/branch-policy.md diff --git a/docs/source/developer-guidelines/design-principles.md b/docs/source/contributing/design-principles.md similarity index 100% rename from docs/source/developer-guidelines/design-principles.md rename to docs/source/contributing/design-principles.md diff --git a/docs/source/developer-guidelines/icons.md b/docs/source/contributing/icons.md similarity index 100% rename from docs/source/developer-guidelines/icons.md rename to docs/source/contributing/icons.md diff --git a/docs/source/developer-guidelines/contributing.md b/docs/source/contributing/index.md similarity index 65% rename from docs/source/developer-guidelines/contributing.md rename to docs/source/contributing/index.md index b2b7a445b6..adc5e4d2aa 100644 --- a/docs/source/developer-guidelines/contributing.md +++ b/docs/source/contributing/index.md @@ -1,10 +1,10 @@ --- myst: html_meta: - "description": "A guide on how to contribute to Volto, the frontend for Plone." - "property=og:description": "A guide on how to contribute to Volto, the frontend for Plone." - "property=og:title": "Contributing to Volto" - "keywords": "Volto, Plone, frontend, React, guidelines" + "description": "How to contribute to Volto, the frontend for Plone." + "property=og:description": "How to contribute to Volto, the frontend for Plone." + "property=og:title": "How to contribute to Volto, the frontend for Plone." + "keywords": "Plone, Volto, contributing, developer, guidelines" --- (contributing-to-volto-label)= @@ -33,11 +33,11 @@ In your report, please specify a few things: - Include relevant screenshots, error messages, and stack traces. -(contributing-sign-and-return-the-plone-contributor-agreement-label)= +(contributing-volto-sign-and-return-the-plone-contributor-agreement-label)= ## Sign and return the Plone Contributor Agreement -The Volto Team reviews pull requests only from people with a GitHub account who have signed and returned the {ref}`Plone Contributor Agreement `, and subsequently been assigned to a Plone Team in GitHub. +The Volto Team reviews pull requests only from people with a GitHub account who have signed and returned the {ref}`Plone Contributor Agreement `, and subsequently been assigned to a Plone Team in GitHub. (contributing-branch-policy-label)= @@ -89,6 +89,38 @@ Specifically: - {doc}`./acceptance-tests` +(contributing-developer-guidelines-label)= + +## Developer guidelines + +Development and configuration of Volto is managed through your {ref}`choice of Plone installation method `. +You may choose to install Plone via {ref}`containers ` or from its {ref}`packages `. + +```{todo} +When referring to installation and configuration of Plone's backend, this part of the Volto documentation may have obsolete content. +The most current information for installing and configuring Plone is in {ref}`install-index-label`. +Please report any issues in the [Volto issue tracker](https://github.com/plone/volto/issues/). +``` + +```{toctree} +:maxdepth: 1 + +design-principles +style-guide +language-features +linting +react +redux +routing +icons +testing +acceptance-tests +accessibility-guidelines +typescript +volto-core-addons +``` + + (contributing-final-advice-label)= ## Final advice diff --git a/docs/source/developer-guidelines/language-features.md b/docs/source/contributing/language-features.md similarity index 100% rename from docs/source/developer-guidelines/language-features.md rename to docs/source/contributing/language-features.md diff --git a/docs/source/developer-guidelines/linting.md b/docs/source/contributing/linting.md similarity index 100% rename from docs/source/developer-guidelines/linting.md rename to docs/source/contributing/linting.md diff --git a/docs/source/developer-guidelines/react.md b/docs/source/contributing/react.md similarity index 100% rename from docs/source/developer-guidelines/react.md rename to docs/source/contributing/react.md diff --git a/docs/source/developer-guidelines/redux.md b/docs/source/contributing/redux.md similarity index 100% rename from docs/source/developer-guidelines/redux.md rename to docs/source/contributing/redux.md diff --git a/docs/source/developer-guidelines/routing.md b/docs/source/contributing/routing.md similarity index 100% rename from docs/source/developer-guidelines/routing.md rename to docs/source/contributing/routing.md diff --git a/docs/source/developer-guidelines/style-guide.md b/docs/source/contributing/style-guide.md similarity index 100% rename from docs/source/developer-guidelines/style-guide.md rename to docs/source/contributing/style-guide.md diff --git a/docs/source/developer-guidelines/testing.md b/docs/source/contributing/testing.md similarity index 100% rename from docs/source/developer-guidelines/testing.md rename to docs/source/contributing/testing.md diff --git a/docs/source/developer-guidelines/typescript.md b/docs/source/contributing/typescript.md similarity index 100% rename from docs/source/developer-guidelines/typescript.md rename to docs/source/contributing/typescript.md diff --git a/docs/source/developer-guidelines/volto-core-addons.md b/docs/source/contributing/volto-core-addons.md similarity index 100% rename from docs/source/developer-guidelines/volto-core-addons.md rename to docs/source/contributing/volto-core-addons.md diff --git a/docs/source/developer-guidelines/index.md b/docs/source/developer-guidelines/index.md deleted file mode 100644 index a96f92b02b..0000000000 --- a/docs/source/developer-guidelines/index.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -myst: - html_meta: - "description": "Developer Guidelines" - "property=og:description": "Developer Guidelines" - "property=og:title": "Developer Guidelines" - "keywords": "Developer, Guidelines" ---- - -# Developer guidelines - -Development and configuration of Volto is managed through your {ref}`choice of Plone installation method `. -You may choose to install Plone via {ref}`containers ` or from its {ref}`packages `. - -```{todo} -When referring to installation and configuration of Plone's backend, this part of the Volto documentation may have obsolete content. -The most current information for installing and configuring Plone is in {ref}`install-index-label`. -Please report any issues in the [Volto issue tracker](https://github.com/plone/volto/issues/). -``` - -```{toctree} -:maxdepth: 1 - -contributing -design-principles -style-guide -language-features -linting -react -redux -routing -icons -testing -acceptance-tests -accessibility-guidelines -typescript -volto-core-addons -``` diff --git a/docs/source/index.md b/docs/source/index.md index 222455dae2..ee7723015f 100644 --- a/docs/source/index.md +++ b/docs/source/index.md @@ -47,7 +47,7 @@ addons/index backend/index deploying/index upgrade-guide/index -developer-guidelines/index user-manual/index +contributing/index release-notes/index ``` diff --git a/news/4666.documentation b/news/4666.documentation new file mode 100644 index 0000000000..0ad620aa45 --- /dev/null +++ b/news/4666.documentation @@ -0,0 +1 @@ +Rename "Developer Guidelines" to "Contributing". @stevepiercy From c09c578e1c8f5fd3c33b8562a75c262485e6b099 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 9 Apr 2023 15:48:01 -0700 Subject: [PATCH 108/142] Make URL a literal string to fix broken link (#4667) --- CHANGELOG.md | 2 +- news/4667.documentation | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 news/4667.documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index a24ff4bb09..f47070e07f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -143,7 +143,7 @@ ### Documentation -- Fix broken links at ReactJS.org. @stevepiercy [#4569](https://github.com/plone/volto/issues/4569) +- Fix broken links at `ReactJS.org`. @stevepiercy [#4569](https://github.com/plone/volto/issues/4569) - Fix video warnings and link errors. @stevepiercy [#4578](https://github.com/plone/volto/issues/4578) diff --git a/news/4667.documentation b/news/4667.documentation new file mode 100644 index 0000000000..6ccff67f8b --- /dev/null +++ b/news/4667.documentation @@ -0,0 +1 @@ +Fix broken link to `ReactJS.org`. @stevepiercy From 2adb993a2d336ca37d55874da53f05df38b3dc32 Mon Sep 17 00:00:00 2001 From: dobri1408 <50819975+dobri1408@users.noreply.github.com> Date: Tue, 11 Apr 2023 18:21:52 +0300 Subject: [PATCH 109/142] fix sitemap.xml.gz is not compressed #4622 (v2) (#4663) Co-authored-by: Alin Voinea --- news/4663.bugfix | 1 + src/express-middleware/sitemap.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 news/4663.bugfix diff --git a/news/4663.bugfix b/news/4663.bugfix new file mode 100644 index 0000000000..708a1987dc --- /dev/null +++ b/news/4663.bugfix @@ -0,0 +1 @@ +fix sitemap.xml.gz not is not compressed @dobri1408 diff --git a/src/express-middleware/sitemap.js b/src/express-middleware/sitemap.js index 6525b540af..f593219456 100644 --- a/src/express-middleware/sitemap.js +++ b/src/express-middleware/sitemap.js @@ -5,7 +5,6 @@ export const sitemap = function (req, res, next) { generateSitemap(req).then((sitemap) => { if (Buffer.isBuffer(sitemap)) { res.set('Content-Type', 'application/x-gzip'); - res.set('Content-Encoding', 'gzip'); res.set('Content-Disposition', 'attachment; filename="sitemap.xml.gz"'); res.send(sitemap); } else { From 9f56f2e051a563dbb844dbb023239be009a66e52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roger=20Boixader=20G=C3=BCell?= Date: Tue, 11 Apr 2023 17:24:32 +0200 Subject: [PATCH 110/142] docs: improve creating view documentation (#4636) Co-authored-by: Steve Piercy --- docs/source/recipes/creating-views.md | 77 ++++++++++++--------------- news/4636.documentation | 1 + 2 files changed, 36 insertions(+), 42 deletions(-) create mode 100644 news/4636.documentation diff --git a/docs/source/recipes/creating-views.md b/docs/source/recipes/creating-views.md index a087fa1201..39e51b9e8a 100644 --- a/docs/source/recipes/creating-views.md +++ b/docs/source/recipes/creating-views.md @@ -142,13 +142,18 @@ called `layoutViews` which registers all the layout views. We will add the `full ```js import { FullView } from './components'; -export const views = { - ...defaultViews, - layoutViews: { - ...defaultViews.layoutViews, - full_view: FullView, - }, -}; +export default function applyConfig(config) { + const defaultViews = config.views + // Add here your project's configuration here by modifying `config` accordingly + config.views = { + ...defaultViews, + layoutViews: { + ...defaultViewslayoutViews, + full_view: FullView, + }, + }; + return config; +} ``` ## Registering a new view called Album View @@ -290,45 +295,33 @@ And in `config.js`: * Add your config changes here. * @module config * @example - * export const settings = { - * ...defaultSettings, - * port: 4300, - * listBlockTypes: { - * ...defaultSettings.listBlockTypes, - * 'my-list-item', - * } + * export default function applyConfig(config) { + * config.settings = { + * ...config.settings, + * port: 4300, + * listBlockTypes: { + * ...config.settings.listBlockTypes, + * 'my-list-item', + * } * } */ -import { - settings as defaultSettings, - views as defaultViews, - widgets as defaultWidgets, - blocks as defaultBlocks, -} from '@plone/volto/config'; - +// All your imports required for the config here BEFORE this line +import '@plone/volto/config'; import { AlbumView, FullView } from './components'; -export const settings = { - ...defaultSettings, -}; - -export const views = { - ...defaultViews, - layoutViews: { - ...defaultViews.layoutViews, - album_view: AlbumView, - full_view: FullView, - }, -}; - -export const widgets = { - ...defaultWidgets, -}; - -export const blocks = { - ...defaultBlocks, -}; +export default function applyConfig(config) { + const defaultViews = config.views + // Add here your project's configuration here by modifying `config` accordingly + config.views = { + ...defaultViews, + layoutViews: { + ...defaultViews.layoutViews, + album_view: AlbumView, + full_view: FullView, + }, + }; + return config; +} -export default SummaryView; ``` diff --git a/news/4636.documentation b/news/4636.documentation new file mode 100644 index 0000000000..e0b90b54be --- /dev/null +++ b/news/4636.documentation @@ -0,0 +1 @@ +Improve creating views documentation page. @rboixaderg \ No newline at end of file From ef3f6f84760af9f3d6bd57ff2c43c55032421eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Tue, 11 Apr 2023 17:25:19 +0200 Subject: [PATCH 111/142] Load a theme via a `theme` key in `volto.config.js` or in `package.json` (#4625) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Steve Piercy Co-authored-by: Katja Süss --- addon-registry.js | 34 +++ create-theme-addons-loader.js | 79 ++++++ docs/source/addons/index.md | 1 + docs/source/addons/theme.md | 230 ++++++++++++++++++ docs/source/configuration/volto-config-js.md | 55 ++++- .../theming/using-third-party-themes.md | 2 + news/4625.feature | 2 + razzle.config.js | 23 ++ 8 files changed, 420 insertions(+), 6 deletions(-) create mode 100644 create-theme-addons-loader.js create mode 100644 docs/source/addons/theme.md create mode 100644 news/4625.feature diff --git a/addon-registry.js b/addon-registry.js index 666c0bcd04..b502977ee8 100644 --- a/addon-registry.js +++ b/addon-registry.js @@ -130,6 +130,11 @@ class AddonConfigurationRegistry { this.packages = {}; this.customizations = new Map(); + // Theme from a package.json key, from volto.config.js or from an ENV VAR + // Programatically via volto.config.js wins or the ENV VAR if present + this.theme = + packageJson.theme || this.voltoConfigJS.theme || process.env.THEME; + this.initDevelopmentPackages(); this.initPublishedPackages(); this.initAddonsFromEnvVar(); @@ -354,6 +359,35 @@ class AddonConfigurationRegistry { .filter((e) => e); } + getCustomThemeAddons() { + const customThemeAddonsInfo = { + variables: [], + main: [], + }; + + this.getAddonDependencies().forEach((addon) => { + const normalizedAddonName = addon.split(':')[0]; + // We have two possible insertion points, variables and main + + const customThemeVariables = `${this.packages[normalizedAddonName].modulePath}/theme/_variables.scss`; + const customThemeMain = `${this.packages[normalizedAddonName].modulePath}/theme/_main.scss`; + if ( + fs.existsSync(customThemeVariables) && + normalizedAddonName !== this.theme + ) { + customThemeAddonsInfo.variables.push(normalizedAddonName); + } + if ( + fs.existsSync(customThemeMain) && + normalizedAddonName !== this.theme + ) { + customThemeAddonsInfo.main.push(normalizedAddonName); + } + }); + + return customThemeAddonsInfo; + } + /** * Returns a mapping name:diskpath to be uses in webpack's resolve aliases */ diff --git a/create-theme-addons-loader.js b/create-theme-addons-loader.js new file mode 100644 index 0000000000..41da132b44 --- /dev/null +++ b/create-theme-addons-loader.js @@ -0,0 +1,79 @@ +const path = require('path'); +const fs = require('fs'); +const tmp = require('tmp'); +const cryptoRandomString = require('crypto-random-string'); + +const titleCase = (w) => w.slice(0, 1).toUpperCase() + w.slice(1, w.length); + +/* + * Transforms a package name to javascript variable name + */ +function nameFromPackage(name) { + name = + name.replace(/[@~./\\:\s]/gi, '') || + cryptoRandomString({ length: 10, characters: 'abcdefghijk' }); + return name + .split('-') + .map((w, i) => (i > 0 ? titleCase(w) : w)) + .join(''); +} + +/* + * Creates a static file with code necessary to load the addons configuration + * + */ +function getAddonsLoaderCode(name, customThemeAddons = []) { + let buf = `/* +This file is autogenerated. Don't change it directly. +Add a ./theme/_${name}.scss in your add-on to load your theme customizations in the current theme. +*/ + +`; + customThemeAddons.forEach((addon) => { + const customization = `${addon}/theme/${name}`; + const line = `@import '${customization}';\n`; + buf += line; + }); + + return buf; +} + +module.exports = ({ main, variables }) => { + // const addonsThemeLoaderVariablesPath = path.join( + // process.cwd(), + // 'src', + // '_variables.scss', + // ); + // const addonsThemeLoaderMainPath = path.join( + // process.cwd(), + // 'src', + // '_main.scss', + // ); + + // const addonsThemeLoaderVariablesPath = path.join( + // process.cwd(), + // 'src', + // '_variables.scss', + // ); + // const addonsThemeLoaderMainPath = path.join( + // process.cwd(), + // 'src', + // '_main.scss', + // ); + + const addonsThemeLoaderVariablesPath = tmp.tmpNameSync({ postfix: '.scss' }); + const addonsThemeLoaderMainPath = tmp.tmpNameSync({ postfix: '.scss' }); + fs.writeFileSync( + addonsThemeLoaderVariablesPath, + new Buffer.from(getAddonsLoaderCode('variables', variables)), + ); + fs.writeFileSync( + addonsThemeLoaderMainPath, + new Buffer.from(getAddonsLoaderCode('main', main)), + ); + + return [addonsThemeLoaderVariablesPath, addonsThemeLoaderMainPath]; +}; + +module.exports.getAddonsLoaderCode = getAddonsLoaderCode; +module.exports.nameFromPackage = nameFromPackage; diff --git a/docs/source/addons/index.md b/docs/source/addons/index.md index cf456c215b..b692529aa5 100644 --- a/docs/source/addons/index.md +++ b/docs/source/addons/index.md @@ -14,6 +14,7 @@ myst: i18n best-practices +theme ``` There are several advanced scenarios where we might want to have more control diff --git a/docs/source/addons/theme.md b/docs/source/addons/theme.md new file mode 100644 index 0000000000..c3ec9ae413 --- /dev/null +++ b/docs/source/addons/theme.md @@ -0,0 +1,230 @@ +--- +myst: + html_meta: + "description": "Create a theme add-on" + "property=og:description": "Create a theme add-on" + "property=og:title": "Create a theme add-on" + "keywords": "Volto, Plone, Semantic UI, CSS, Volto theme" +--- + +# Create a Volto theme add-on + +We can create a Volto Add-on that acts as a Volto theme Add-on, so we can detach it from the project files. +The advantage is that you convert the project Volto theme in a pluggable one, so you can deploy the same theme in different projects. +You can even have themes depending on conditions that you could inject on build time. +This is the purpose of `volto.config.js`, the ability of declaring `add-ons` and the active `theme` programatically. See {ref}`volto-config-js` for more information. +For convenience, it can also be set via a `THEME` environment variable. + +1. Add a `theme` key in your `volto.config.js` file in the root of your project: + +```js +module.exports = { + addons: [], + theme: 'volto-my-theme' +}; +``` + +or add a key in your `package.json` project: + +```json +"theme": "volto-my-theme" +``` + +or via a `THEME` variable: + +```shell +THEME='volto-my-theme' yarn start +``` + +2. Create a directory `src/theme` in your add-on, then add this file `theme.config`, replacing `` with your add-on name: + +```less +/******************************* + Theme Selection +*******************************/ + +/* To override a theme for an individual element specify theme name below */ + +/* Global */ +@site : 'pastanaga'; +@reset : 'pastanaga'; + +/* Elements */ +@button : 'pastanaga'; +@container : 'pastanaga'; +@divider : 'pastanaga'; +@flag : 'pastanaga'; +@header : 'pastanaga'; +@icon : 'pastanaga'; +@image : 'pastanaga'; +@input : 'pastanaga'; +@label : 'pastanaga'; +@list : 'pastanaga'; +@loader : 'pastanaga'; +@placeholder : 'pastanaga'; +@rail : 'pastanaga'; +@reveal : 'pastanaga'; +@segment : 'pastanaga'; +@step : 'pastanaga'; + +/* Collections */ +@breadcrumb : 'pastanaga'; +@form : 'pastanaga'; +@grid : 'pastanaga'; +@menu : 'pastanaga'; +@message : 'pastanaga'; +@table : 'pastanaga'; + +/* Modules */ +@accordion : 'pastanaga'; +@checkbox : 'pastanaga'; +@dimmer : 'pastanaga'; +@dropdown : 'pastanaga'; +@embed : 'pastanaga'; +@modal : 'pastanaga'; +@nag : 'pastanaga'; +@popup : 'pastanaga'; +@progress : 'pastanaga'; +@rating : 'pastanaga'; +@search : 'pastanaga'; +@shape : 'pastanaga'; +@sidebar : 'pastanaga'; +@sticky : 'pastanaga'; +@tab : 'pastanaga'; +@transition : 'pastanaga'; + +/* Views */ +@ad : 'pastanaga'; +@card : 'pastanaga'; +@comment : 'pastanaga'; +@feed : 'pastanaga'; +@item : 'pastanaga'; +@statistic : 'pastanaga'; + +/* Extras */ +@main : 'pastanaga'; +@custom : 'pastanaga'; + +/******************************* + Folders +*******************************/ + +/* Path to theme packages */ +@themesFolder : '~volto-themes'; + +/* Path to site override folder */ +@siteFolder : "/theme"; + +/******************************* + Import Theme +*******************************/ + +@import (multiple) "~semantic-ui-less/theme.less"; +@fontPath : "~volto-themes/@{theme}/assets/fonts"; + +.loadAddonOverrides() { + @import (optional) "@{siteFolder}/@{addon}/@{addontype}s/@{addonelement}.overrides"; +} + +/* End Config */ +``` + +3. Declare the theme as an add-on by adding its name to the value for the `addons` key in either `volto.config.js` or `package.json` of your project. +4. After starting Volto, the theme should be active. + Now you can add overrides to the default theme in `src/theme`, same as you would in a project. +5. Now you can safely delete your project's `theme` folder, since the one in the add-on will take precedence and a project can only have one active theme at a time. + +## Using your own theming escape hatch + +Volto theming uses SemanticUI theming capabilities to define and extend a theme for your site. +However, while maintaining and playing well with the Semantic UI Volto base, using a traditional CSS approach can be done using the LESS preprocessor-based `extras` escape hatch. + +At the same time, one can either discard or complement the extras escape hatch and add your own, by customizing the `theme.js` module in Volto. + +```js +import 'semantic-ui-less/semantic.less'; +import '@plone/volto/../theme/themes/pastanaga/extras/extras.less'; + +// You can add more entry points for theming +import '@kitconcept/volto-light-theme/theme/main.scss'; +``` + +Customizing it is a special use case in Volto: add a `./@root/theme.js` file structure in your `customizations` folder in your add-on or project. + +You may want to do this to create a complete new theming experience adapted to your way of doing things that do not match the current Volto theming experience. +For example, if you want to use another preprocessor in the theme, like SCSS. +Maybe because your client forces you to have another entirely base of pre-made components based on another library other than Semantic UI: +See {ref}`volto-custom-theming-strategy` for an example of a custom theme escape hatch. + +While building your own escape hatch for theming, you can use the preprocessor of your choice (in the example, SCSS) while maintaining the "base" Volto theme, but customizing it using the resultant CSS. + +You can see an example of such a theme in: https://github.com/kitconcept/volto-light-theme + +## Modify a custom theme from another add-on + +Sometimes you have a custom theme that you want to reuse through all your projects, but with some differences, maintaining the base. +Usually, the only option would be to use an add-on that adds more CSS to the base theme, using imports that will load after the theme. +However, there is a problem with this approach. +You cannot use existing theme variables, including breakpoints, on these new styles. +Similarly, it gets somewhat detached from the normal flow of the loaded theme. +The same applies for add-ons, as they are detached from the current theme. +One could use a SemanticUI approach for making this work, but it's SemanticUI bound. + +```{warning} +This is only possible when using your own escape hatch, and works only with SCSS-based themes, and not with SemanticUI themes, since it enables a couple of entry points that only support SCSS files. +For an example of how it could be used, see: https://github.com/kitconcept/volto-light-theme +``` + +If your custom escape hatch defines a custom theme using SCSS, you can take advantage of this feature. +Although not limited to this, it would be possible to extend this feature to add more entry points, using another preprocessor or theming approach. + +This feature enables two entry points: variables and main. +From your add-on code, you can extend an existing theme by creating a file corresponding to each entry point: + +* `./src/theme/_variables.scss` +* `./src/theme/_main.scss` + +### Variables (`addonsThemeCustomizationsVariables`) + +Use this entry point file to modify the original variables of the current loaded theme by adding the entry point before the theme variable definitions. +In the theme, it should be imported as shown below: + +```scss hl_lines="2" +@import 'addonsThemeCustomizationsVariables'; +@import 'variables'; +@import 'typography'; +@import 'utils'; +@import 'layout'; +``` + +```{warning} +Following SCSS best practices, your theme variables should be "overridable" using the `!default` flag. +This assigns a value to a variable _only_ if that variable isn't defined or its value is [`null`](https://sass-lang.com/documentation/values/null). +Otherwise, the existing value will be used. +For more information, see https://sass-lang.com/documentation/variables#default-values +``` + +Volto will not only load your add-on entry point files, but it will also detect all the add-ons that have these entry point files and import them grouped under a single file. +It will also automatically add an `addonsThemeCustomizationsVariables` alias that can be referenced from the theme as shown above. + +### Main (`addonsThemeCustomizationsMain`) + +This entry point is intended to add your own style definitions, complementing those in the theme. +You should add it after all the CSS of your theme: + +```scss hl_lines="6" +@import 'blocks/search'; +@import 'blocks/listing'; + +@import 'temp'; + +@import 'addonsThemeCustomizationsMain'; + +/* No CSS beyond this point */ +``` + +Volto will also detect all the add-ons that have these entry point files, and import them grouped under a single file, and will automatically add an `addonsThemeCustomizationsMain` alias that can be referenced from the theme as shown above. + +```{note} +It will only work in combination with the theme declaration in `volto.config.js` or in `package.json`. +``` diff --git a/docs/source/configuration/volto-config-js.md b/docs/source/configuration/volto-config-js.md index 56bbcf417d..9320c3c6d5 100644 --- a/docs/source/configuration/volto-config-js.md +++ b/docs/source/configuration/volto-config-js.md @@ -1,8 +1,25 @@ -# Dynamic Volto Addons Configuration +--- +myst: + html_meta: + "description": "Dynamic Volto Addons Configuration programmatically via volto.config.js" + "property=og:description": "Dynamic Volto Addons Configuration programmatically via volto.config.js" + "property=og:title": "Dynamic Volto Addons Configuration" + "keywords": "Volto, Plone, frontend, React, config" +--- -There are some cases where defining the Volto addons your project is going to use is not enough, and you need more control over it. For example, when you have several builds under the umbrella of the same project that share the core of the code, but each build have special requirements, like other CSS, customizations, {term}`shadowing` or the features of other addons available. +(volto-config-js)= -There is a scapehatch `volto.config.js`. This module exports an object and can have arbitrary code depending on your needs: +# Programatically define the active add-ons and theme + +Volto allows you to define the active `add-ons` and `theme` via a file in the root of your project called `volto.config.js`. + +## Dynamic Volto Addons Configuration + +There are some cases where defining the Volto addons your project is going to use via `package.json` `addons` key is not enough, and you need more control over it. +For example, when you have several builds under the umbrella of the same project that share the core of the code, but each build have special requirements, like other CSS, customizations, {term}`shadowing` or the features of other addons available. + +This is an example of a `volto.config.js` file. +This module exports an object and can have arbitrary code depending on your needs: ```js let addons = []; @@ -10,12 +27,38 @@ if (process.env.MY_SPECIAL_CUSTOM_BUILD) { addons = ['volto-custom-addon']; } +if (process.env.MY_SPECIAL_SECOND_CUSTOM_BUILD) { + addons = ['volto-custom-addon', 'volto-custom-addon-additional']; +} + module.exports = { - addons: addons, + addons, }; - ``` -In the case above, we delegate to the presence of an environment variable (MY_SPECIAL_CUSTOM_BUILD) the use of the list of addons specified. +In the case above, we delegate to the presence of an environment variable (`MY_SPECIAL_CUSTOM_BUILD`) the use of the list of addons specified. This list, sums up to the one defined in `package.json` (it does not override it), and the addons added are placed at the end of the addons list, so the config in there is applied after the ones in the `package.json`. + +## Dynamic Volto active theme configuration + +The same applies for the active theme: + +```js +let addons = []; +let theme; +if (process.env.MY_SPECIAL_CUSTOM_BUILD) { + addons = ['volto-custom-addon']; + theme = 'volto-my-theme'; +} + +if (process.env.MY_SPECIAL_SECOND_CUSTOM_BUILD) { + addons = ['volto-custom-addon-alternative', 'volto-custom-addon-additional']; + theme = 'volto-my-alternate-theme'; +} + +module.exports = { + addons, + theme +}; +``` diff --git a/docs/source/theming/using-third-party-themes.md b/docs/source/theming/using-third-party-themes.md index ea8a8f0279..bc545302ca 100644 --- a/docs/source/theming/using-third-party-themes.md +++ b/docs/source/theming/using-third-party-themes.md @@ -7,6 +7,8 @@ myst: "keywords": "Volto, Plone, frontend, React, Semantic UI, semantic-ui, third, party, libraries, themes" --- +(volto-custom-theming-strategy)= + # Using third party libraries and themes other than `semantic-ui` You can use Volto with third party libraries or themes written in SASS and avoid applying `semantic-ui` on public facing views. diff --git a/news/4625.feature b/news/4625.feature new file mode 100644 index 0000000000..b7f9654fa6 --- /dev/null +++ b/news/4625.feature @@ -0,0 +1,2 @@ +Support for declaring a theme in `volto.config.js` or in `package.json` +Add two entry points to allow extension of a theme from other add-ons. @sneridagh diff --git a/razzle.config.js b/razzle.config.js index 34f84a95ce..78ad60f619 100644 --- a/razzle.config.js +++ b/razzle.config.js @@ -8,6 +8,7 @@ const fs = require('fs'); const RootResolverPlugin = require('./webpack-plugins/webpack-root-resolver'); const RelativeResolverPlugin = require('./webpack-plugins/webpack-relative-resolver'); const createAddonsLoader = require('./create-addons-loader'); +const createThemeAddonsLoader = require('./create-theme-addons-loader'); const AddonConfigurationRegistry = require('./addon-registry'); const CircularDependencyPlugin = require('circular-dependency-plugin'); const TerserPlugin = require('terser-webpack-plugin'); @@ -245,6 +246,28 @@ const defaultModify = ({ 'lodash-es': path.dirname(require.resolve('lodash')), }; + const [ + addonsThemeLoaderVariablesPath, + addonsThemeLoaderMainPath, + ] = createThemeAddonsLoader(registry.getCustomThemeAddons()); + + // Automatic Theme Loading + if (registry.theme) { + // The themes should be located in `src/theme` + const themePath = registry.packages[registry.theme].modulePath; + const themeConfigPath = `${themePath}/theme/theme.config`; + config.resolve.alias['../../theme.config$'] = themeConfigPath; + config.resolve.alias['../../theme.config'] = themeConfigPath; + + // We create an alias for each custom theme insertion point (variables, main) + config.resolve.alias[ + 'addonsThemeCustomizationsVariables' + ] = addonsThemeLoaderVariablesPath; + config.resolve.alias[ + 'addonsThemeCustomizationsMain' + ] = addonsThemeLoaderMainPath; + } + config.performance = { maxAssetSize: 10000000, maxEntrypointSize: 10000000, From cafad1c570195023a82007e31207c78f97ca4177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katja=20S=C3=BCss?= Date: Tue, 11 Apr 2023 17:26:38 +0200 Subject: [PATCH 112/142] Support RelationList field with StaticCatalogVocabulary and SelectWidget. (#4614) Co-authored-by: Steve Piercy --- docs/source/recipes/widget.md | 102 +++++++++++++++++- news/4614.feature | 1 + src/components/manage/Widgets/SelectUtils.js | 2 +- .../manage/Widgets/SelectWidget.jsx | 2 +- src/config/Widgets.jsx | 1 + 5 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 news/4614.feature diff --git a/docs/source/recipes/widget.md b/docs/source/recipes/widget.md index ebb232d0d5..6b2e81d185 100644 --- a/docs/source/recipes/widget.md +++ b/docs/source/recipes/widget.md @@ -146,14 +146,112 @@ const applyConfig = (config) => { Based on this setup, Volto will render this field with the `TokenWidget`. -```{seealso} -See [storybook](https://6.dev-docs.plone.org/storybook) with available widgets. +(widget-relation-field-label)= + +## Relation fields + +A relation field is either a single relation field to hold at most one content object, `RelationChoice`, or a multi relation field, `RelationList`, that can hold more than one content object. + +Relation fields can be edited and rendered with the `Select` widget. +The restriction on content types, workflow states, and so on can be done with a `StaticCatalogVocabulary`. + +There are other vocabulary types and other widgets, including the `ObjectBrowser` widget. + +(widget-relation-field-single-label)= + +### Single relation field + +Relation field (`RelationChoice`) with a named `StaticCatalogVocabulary` and `Select` widget: + +```python +relationchoice_field_named_staticcatalogvocabulary = RelationChoice( + title="RelationChoice – named StaticCatalogVocabulary – Select widget", + description="field/relation: relationchoice_field_named_staticcatalogvocabulary", + vocabulary="relationchoice_field_named_staticcatalogvocabulary", + required=False, +) +directives.widget( + "relationchoice_field_named_staticcatalogvocabulary", + frontendOptions={ + "widget": "select", + }, +) ``` +It is recommended to define the vocabulary as a named `StaticCatalogVocabulary` with the field/relation name as its name. +This allows the {guilabel}`relations` control panel to respect the defined restrictions to potential relation targets. + +{file}`vocabularies.py` +```python +from plone.app.vocabularies.catalog import StaticCatalogVocabulary +from zope.interface import provider +from zope.schema.interfaces import IVocabularyFactory + +@provider(IVocabularyFactory) +def ExamplesVocabularyFactory(context=None): + return StaticCatalogVocabulary( + { + "portal_type": ["example"], + "review_state": "published", + "sort_on": "sortable_title", + } + ) +``` + +{file}`configure.zcml` +```xml + +``` + +The `Select` widget is currently the default for `RelationChoice` fields with vocabulary. +Therefore the directive can be omitted. + +```python +relationchoice_field_named_staticcatalogvocabulary = RelationChoice( + title="RelationChoice – named StaticCatalogVocabulary – Select widget", + description="field/relation: relationchoice_field_named_staticcatalogvocabulary", + vocabulary="relationchoice_field_named_staticcatalogvocabulary", + required=False, +) +``` + +(widget-relation-field-multi-label)= + +### Multi relation field + +Multi relation field (`RelationList`) with a named `StaticCatalogVocabulary`and `Select` widget: + +```python +relationlist_field_named_staticcatalogvocabulary = RelationList( + title="RelationList – named StaticCatalogVocabulary – Select widget", + description="field/relation: relationlist_field_named_staticcatalogvocabulary", + value_type=RelationChoice( + vocabulary="relationlist_field_named_staticcatalogvocabulary", + ), + required=False, +) +directives.widget( + "relationlist_field_named_staticcatalogvocabulary", + frontendOptions={ + "widget": "select", + }, +) +``` + + ## Widget `isDisabled` Props We can disable the input of a widget by passing props `isDisabled: true`. + +## Available widgets + +See [Storybook](https://6.docs.plone.org/storybook) with available widgets. + + ## Write a new widget ```{note} diff --git a/news/4614.feature b/news/4614.feature new file mode 100644 index 0000000000..286f2fe464 --- /dev/null +++ b/news/4614.feature @@ -0,0 +1 @@ +Support RelationList field with named StaticCatalogVocabulary and SelectWidget. @ksuess \ No newline at end of file diff --git a/src/components/manage/Widgets/SelectUtils.js b/src/components/manage/Widgets/SelectUtils.js index eec6f2f82b..7d0129f3fa 100644 --- a/src/components/manage/Widgets/SelectUtils.js +++ b/src/components/manage/Widgets/SelectUtils.js @@ -54,7 +54,7 @@ export function normalizeSingleSelectOption(value, intl) { throw new Error(`Unknown value type of select widget: ${value}`); } - const token = value.token ?? value.value ?? 'no-value'; + const token = value.token ?? value.value ?? value.UID ?? 'no-value'; const label = (value.title && value.title !== 'None' ? value.title : undefined) ?? value.label ?? diff --git a/src/components/manage/Widgets/SelectWidget.jsx b/src/components/manage/Widgets/SelectWidget.jsx index 05bd609602..0045a2568f 100644 --- a/src/components/manage/Widgets/SelectWidget.jsx +++ b/src/components/manage/Widgets/SelectWidget.jsx @@ -202,7 +202,7 @@ class SelectWidget extends Component { const isMulti = this.props.isMulti ? this.props.isMulti - : id === 'roles' || id === 'groups'; + : id === 'roles' || id === 'groups' || this.props.type === 'array'; return ( diff --git a/src/config/Widgets.jsx b/src/config/Widgets.jsx index 9dcf7f7cb2..c111cf75ae 100644 --- a/src/config/Widgets.jsx +++ b/src/config/Widgets.jsx @@ -98,6 +98,7 @@ export const widgetMapping = { select_querystring_field: SelectMetadataWidget, autocomplete: SelectAutoComplete, color_picker: ColorPickerWidget, + select: SelectWidget, }, vocabulary: { 'plone.app.vocabularies.Catalog': ObjectBrowserWidget, From c29abc0f5b2f4b0524ba5be521c464f24d15e8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Wed, 12 Apr 2023 09:28:54 +0200 Subject: [PATCH 113/142] Update to latest backend versions (#4682) --- Makefile | 8 ++++---- api/buildout.cfg | 2 +- api/versions.cfg | 2 +- news/4682.internal | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 news/4682.internal diff --git a/Makefile b/Makefile index 6ef4a70b87..16e1c6f4ab 100644 --- a/Makefile +++ b/Makefile @@ -13,15 +13,15 @@ MAKEFLAGS+=--no-builtin-rules # Project settings INSTANCE_PORT=8080 -DOCKER_IMAGE=plone/server-dev:6.0.2 -DOCKER_IMAGE_ACCEPTANCE=plone/server-acceptance:6.0.2 -KGS= +DOCKER_IMAGE=plone/server-dev:6.0.3 +DOCKER_IMAGE_ACCEPTANCE=plone/server-acceptance:6.0.3 +KGS=plone.restapi==8.36.0 NODEBIN = ./node_modules/.bin SCRIPTSPACKAGE = ./packages/scripts # Plone 5 legacy DOCKER_IMAGE5=plone/plone-backend:5.2.10 -KGS5=plone.restapi==8.35.0 plone.volto==4.0.7 plone.rest==3.0.0 +KGS5=plone.restapi==8.36.0 plone.volto==4.0.7 plone.rest==3.0.0 TESTING_ADDONS=plone.app.robotframework==2.0.0 plone.app.testing==7.0.0 # Sphinx variables diff --git a/api/buildout.cfg b/api/buildout.cfg index feb689d278..1579cd7ac4 100644 --- a/api/buildout.cfg +++ b/api/buildout.cfg @@ -1,7 +1,7 @@ [buildout] index = https://pypi.org/simple/ extends = - http://dist.plone.org/release/6.0.2/versions.cfg + http://dist.plone.org/release/6.0.3/versions.cfg version-constraints.cfg versions.cfg parts = instance plonesite site-packages test robot-server diff --git a/api/versions.cfg b/api/versions.cfg index d404ee2ec3..abdae1715b 100644 --- a/api/versions.cfg +++ b/api/versions.cfg @@ -5,7 +5,7 @@ async-generator = 1.10 collective.folderishtypes = 3.0.0 collective.recipe.plonesite = 1.12.0 h11 = 0.12.0 -plone.restapi = 8.35.1 +plone.restapi = 8.36.0 plone.volto = 4.0.7 prompt-toolkit = 2.0.10 pyOpenSSL = 21.0.0 diff --git a/news/4682.internal b/news/4682.internal new file mode 100644 index 0000000000..2199a45343 --- /dev/null +++ b/news/4682.internal @@ -0,0 +1 @@ +Update to p.restapi 8.36.0 and Plone 6.0.3 @sneridagh From 2c93620c3e9382024f3ecf676ff8446e33b278d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Wed, 12 Apr 2023 09:56:58 +0200 Subject: [PATCH 114/142] Release changelog notes for 16.20.0 (#4684) --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f47070e07f..068593d101 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -112,6 +112,33 @@ - Use a universal static path for both documentation and volto repos. @stevepiercy [#4376](https://github.com/plone/volto/issues/4376) +## 16.20.0 (2023-04-12) + +### Feature + +- Support RelationList field with named StaticCatalogVocabulary and SelectWidget. @ksuess [#4614](https://github.com/plone/volto/issues/4614) +- Support for declaring a theme in `volto.config.js` or in `package.json` + Add two entry points to allow extension of a theme from other add-ons. @sneridagh [#4625](https://github.com/plone/volto/issues/4625) +- Added querystring search get option. @robgietema [#4658](https://github.com/plone/volto/issues/4658) + +### Bugfix + +- Added current page parameter to route in listing and search block pagination - Fix: #3868 @bipoza [#4159](https://github.com/plone/volto/issues/4159) +- Fixed wrong localization on password reset page @iRohitSingh [#4656](https://github.com/plone/volto/issues/4656) +- fix sitemap.xml.gz not is not compressed @dobri1408 [#4663](https://github.com/plone/volto/issues/4663) + +### Internal + +- Update to p.restapi 8.36.0 and Plone 6.0.3 @sneridagh [#4682](https://github.com/plone/volto/issues/4682) + +### Documentation + +- Update Volto contributing to align with and refer to the new Plone core code contributing requirements. @stevepiercy [#4634](https://github.com/plone/volto/issues/4634) +- Improve creating views documentation page. @rboixaderg [#4636](https://github.com/plone/volto/issues/4636) +- Rename "Developer Guidelines" to "Contributing". @stevepiercy [#4666](https://github.com/plone/volto/issues/4666) +- Fix broken link to `ReactJS.org`. @stevepiercy [#4667](https://github.com/plone/volto/issues/4667) + + ## 16.19.0 (2023-04-04) ### Feature From 81759da8ae9b47d23d223ae2616003287be9399a Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Wed, 12 Apr 2023 09:58:23 +0200 Subject: [PATCH 115/142] Release 17.0.0-alpha.4 --- CHANGELOG.md | 34 +++++++++++++++++++++++++++++++ news/3092.documentation | 1 - news/4159.bugfix | 1 - news/4598.feature | 1 - news/4601.bugfix | 1 - news/4614.feature | 1 - news/4625.feature | 2 -- news/4626.documentation | 1 - news/4627.feature | 1 - news/4629.internal | 1 - news/4634.documentation | 1 - news/4636.documentation | 1 - news/4641.documentation | 1 - news/4656.bugfix | 1 - news/4658.feature | 1 - news/4663.bugfix | 1 - news/4666.documentation | 1 - news/4667.documentation | 1 - news/4682.internal | 1 - package.json | 2 +- packages/volto-slate/package.json | 2 +- 21 files changed, 36 insertions(+), 21 deletions(-) delete mode 100644 news/3092.documentation delete mode 100644 news/4159.bugfix delete mode 100644 news/4598.feature delete mode 100644 news/4601.bugfix delete mode 100644 news/4614.feature delete mode 100644 news/4625.feature delete mode 100644 news/4626.documentation delete mode 100644 news/4627.feature delete mode 100644 news/4629.internal delete mode 100644 news/4634.documentation delete mode 100644 news/4636.documentation delete mode 100644 news/4641.documentation delete mode 100644 news/4656.bugfix delete mode 100644 news/4658.feature delete mode 100644 news/4663.bugfix delete mode 100644 news/4666.documentation delete mode 100644 news/4667.documentation delete mode 100644 news/4682.internal diff --git a/CHANGELOG.md b/CHANGELOG.md index 068593d101..1d14467538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,40 @@ +## 17.0.0-alpha.4 (2023-04-12) + +### Feature + +- DefaultView (view of fields for content types with blocks disabled): Show field name as tip on hover of label. @ksuess [#4598](https://github.com/plone/volto/issues/4598) +- Support RelationList field with named StaticCatalogVocabulary and SelectWidget. @ksuess [#4614](https://github.com/plone/volto/issues/4614) +- Support for declaring a theme in `volto.config.js` or in `package.json` + Add two entry points to allow extension of a theme from other add-ons. @sneridagh [#4625](https://github.com/plone/volto/issues/4625) +- Set sameSite in I18N_LANGUAGE cookie @sneridagh [#4627](https://github.com/plone/volto/issues/4627) +- Added querystring search get option. @robgietema [#4658](https://github.com/plone/volto/issues/4658) + +### Bugfix + +- Added current page parameter to route in listing and search block pagination - Fix: #3868 @bipoza [#4159](https://github.com/plone/volto/issues/4159) +- Fix regexp that checks valid URLs and improve tests [cekk] [#4601](https://github.com/plone/volto/issues/4601) +- Fixed wrong localization on password reset page @iRohitSingh [#4656](https://github.com/plone/volto/issues/4656) +- fix sitemap.xml.gz not is not compressed @dobri1408 [#4663](https://github.com/plone/volto/issues/4663) + +### Internal + +- Trigger CI workflows to run from external pull requests. @davisagli [#4629](https://github.com/plone/volto/issues/4629) +- Update to p.restapi 8.36.0 and Plone 6.0.3 @sneridagh [#4682](https://github.com/plone/volto/issues/4682) + +### Documentation + +- Added `JavaScript` and `NodeJS` as accepted spellings, and deviations of them as rejected spellings. @utkkkarshhh [#3092](https://github.com/plone/volto/issues/3092) +- Fix documentation build, add pins @sneridagh [#4626](https://github.com/plone/volto/issues/4626) +- Update Volto contributing to align with and refer to the new Plone core code contributing requirements. @stevepiercy [#4634](https://github.com/plone/volto/issues/4634) +- Improve creating views documentation page. @rboixaderg [#4636](https://github.com/plone/volto/issues/4636) +- Razzle upgrade notice in upgrade guide @sneridagh [#4641](https://github.com/plone/volto/issues/4641) +- Rename "Developer Guidelines" to "Contributing". @stevepiercy [#4666](https://github.com/plone/volto/issues/4666) +- Fix broken link to `ReactJS.org`. @stevepiercy [#4667](https://github.com/plone/volto/issues/4667) + + ## 17.0.0-alpha.3 (2023-03-22) ### Feature diff --git a/news/3092.documentation b/news/3092.documentation deleted file mode 100644 index 2f1b9f34d6..0000000000 --- a/news/3092.documentation +++ /dev/null @@ -1 +0,0 @@ -Added `JavaScript` and `NodeJS` as accepted spellings, and deviations of them as rejected spellings. @utkkkarshhh \ No newline at end of file diff --git a/news/4159.bugfix b/news/4159.bugfix deleted file mode 100644 index d9b9f18dfa..0000000000 --- a/news/4159.bugfix +++ /dev/null @@ -1 +0,0 @@ -Added current page parameter to route in listing and search block pagination - Fix: #3868 @bipoza \ No newline at end of file diff --git a/news/4598.feature b/news/4598.feature deleted file mode 100644 index 7c7160922f..0000000000 --- a/news/4598.feature +++ /dev/null @@ -1 +0,0 @@ -DefaultView (view of fields for content types with blocks disabled): Show field name as tip on hover of label. @ksuess \ No newline at end of file diff --git a/news/4601.bugfix b/news/4601.bugfix deleted file mode 100644 index cbb24473ca..0000000000 --- a/news/4601.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix regexp that checks valid URLs and improve tests [cekk] diff --git a/news/4614.feature b/news/4614.feature deleted file mode 100644 index 286f2fe464..0000000000 --- a/news/4614.feature +++ /dev/null @@ -1 +0,0 @@ -Support RelationList field with named StaticCatalogVocabulary and SelectWidget. @ksuess \ No newline at end of file diff --git a/news/4625.feature b/news/4625.feature deleted file mode 100644 index b7f9654fa6..0000000000 --- a/news/4625.feature +++ /dev/null @@ -1,2 +0,0 @@ -Support for declaring a theme in `volto.config.js` or in `package.json` -Add two entry points to allow extension of a theme from other add-ons. @sneridagh diff --git a/news/4626.documentation b/news/4626.documentation deleted file mode 100644 index 7898850040..0000000000 --- a/news/4626.documentation +++ /dev/null @@ -1 +0,0 @@ -Fix documentation build, add pins @sneridagh diff --git a/news/4627.feature b/news/4627.feature deleted file mode 100644 index dd91379ab9..0000000000 --- a/news/4627.feature +++ /dev/null @@ -1 +0,0 @@ -Set sameSite in I18N_LANGUAGE cookie @sneridagh diff --git a/news/4629.internal b/news/4629.internal deleted file mode 100644 index 869b4a6d24..0000000000 --- a/news/4629.internal +++ /dev/null @@ -1 +0,0 @@ -Trigger CI workflows to run from external pull requests. @davisagli diff --git a/news/4634.documentation b/news/4634.documentation deleted file mode 100644 index f3498b18ff..0000000000 --- a/news/4634.documentation +++ /dev/null @@ -1 +0,0 @@ -Update Volto contributing to align with and refer to the new Plone core code contributing requirements. @stevepiercy diff --git a/news/4636.documentation b/news/4636.documentation deleted file mode 100644 index e0b90b54be..0000000000 --- a/news/4636.documentation +++ /dev/null @@ -1 +0,0 @@ -Improve creating views documentation page. @rboixaderg \ No newline at end of file diff --git a/news/4641.documentation b/news/4641.documentation deleted file mode 100644 index 335c2489fd..0000000000 --- a/news/4641.documentation +++ /dev/null @@ -1 +0,0 @@ -Razzle upgrade notice in upgrade guide @sneridagh diff --git a/news/4656.bugfix b/news/4656.bugfix deleted file mode 100644 index 06b9558589..0000000000 --- a/news/4656.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed wrong localization on password reset page @iRohitSingh \ No newline at end of file diff --git a/news/4658.feature b/news/4658.feature deleted file mode 100644 index 0c4c3cc11b..0000000000 --- a/news/4658.feature +++ /dev/null @@ -1 +0,0 @@ -Added querystring search get option. @robgietema \ No newline at end of file diff --git a/news/4663.bugfix b/news/4663.bugfix deleted file mode 100644 index 708a1987dc..0000000000 --- a/news/4663.bugfix +++ /dev/null @@ -1 +0,0 @@ -fix sitemap.xml.gz not is not compressed @dobri1408 diff --git a/news/4666.documentation b/news/4666.documentation deleted file mode 100644 index 0ad620aa45..0000000000 --- a/news/4666.documentation +++ /dev/null @@ -1 +0,0 @@ -Rename "Developer Guidelines" to "Contributing". @stevepiercy diff --git a/news/4667.documentation b/news/4667.documentation deleted file mode 100644 index 6ccff67f8b..0000000000 --- a/news/4667.documentation +++ /dev/null @@ -1 +0,0 @@ -Fix broken link to `ReactJS.org`. @stevepiercy diff --git a/news/4682.internal b/news/4682.internal deleted file mode 100644 index 2199a45343..0000000000 --- a/news/4682.internal +++ /dev/null @@ -1 +0,0 @@ -Update to p.restapi 8.36.0 and Plone 6.0.3 @sneridagh diff --git a/package.json b/package.json index ccc3202d9c..236b585cce 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "17.0.0-alpha.3", + "version": "17.0.0-alpha.4", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" diff --git a/packages/volto-slate/package.json b/packages/volto-slate/package.json index 6b1160981d..08660d8a77 100644 --- a/packages/volto-slate/package.json +++ b/packages/volto-slate/package.json @@ -1,6 +1,6 @@ { "name": "@plone/volto-slate", - "version": "17.0.0-alpha.3", + "version": "17.0.0-alpha.4", "description": "Slate.js integration with Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", From c18898d767fae646af47c4b14aae914ac0deb387 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Thu, 13 Apr 2023 03:13:36 -0700 Subject: [PATCH 116/142] Fix training links (#4635) --- README.md | 13 +++++-------- docs/source/getting-started/install.md | 3 ++- docs/source/getting-started/others.md | 13 +++++-------- news/4635.documentation | 1 + 4 files changed, 13 insertions(+), 17 deletions(-) create mode 100644 news/4635.documentation diff --git a/README.md b/README.md index 8cdca13cbe..050d127c8b 100644 --- a/README.md +++ b/README.md @@ -186,19 +186,16 @@ You can find the latest (in-progress) documentation in [https://6.dev-docs.plone ## Training -On the [Plone Trainings Website](https://training.plone.org) you'll find -Volto-dedicated open training materials, plus React and other -JavaScript-centered trainings. +On the [Plone Training website](https://training.plone.org), you'll find Volto-dedicated training materials, plus other JavaScript-centered trainings. - [Mastering Plone 6 Development](https://training.plone.org/mastering-plone/) The comprehensive training on Plone 6 with best practice tips for developers and integrators. -- [Volto](https://training.plone.org/5/volto/index.html) - A detailed training on how to create your own website using Volto frontend. - [Volto Hands-On](https://training.plone.org/voltohandson/index.html) - [Volto Add-ons Development](https://training.plone.org/voltoaddons/index.html) -- [Plone Deployment](https://training.plone.org/5/plone-deployment/index.html) -- [React](https://training.plone.org/react/index.html) -- [JavaScript For Plone Developers](https://training.plone.org/5/javascript/index.html) +- [Effective Volto](https://training.plone.org/effective-volto/index.html) +- [Plone Deployment](https://training.plone.org/plone-deployment/index.html) +- [Volto](https://2022.training.plone.org/volto/index.html) (archived) +- [JavaScript For Plone Developers](https://2022.training.plone.org/javascript/index.html) (archived) ## Talks diff --git a/docs/source/getting-started/install.md b/docs/source/getting-started/install.md index 7dd17ff64b..911f9582f7 100644 --- a/docs/source/getting-started/install.md +++ b/docs/source/getting-started/install.md @@ -188,7 +188,8 @@ docker run -it --rm --name=plone \ ``` ```{tip} -This setup is meant only for demonstration and quick testing purposes (since it destroys the container on exit (--rm)). In case you need production ready deployment, check the latest [Plone Deployment Training](https://training.plone.org/5/plone-deployment/index.html). +This setup is meant only for demonstration and quick testing purposes, since it destroys the container on exit (`--rm`). +In case you need production-ready deployment, check the latest [Plone Deployment Training](https://training.plone.org/plone-deployment/index.html). ``` ```{note} diff --git a/docs/source/getting-started/others.md b/docs/source/getting-started/others.md index 3b5fcf48ea..4cdb8f4dd2 100644 --- a/docs/source/getting-started/others.md +++ b/docs/source/getting-started/others.md @@ -11,19 +11,16 @@ myst: ## Plone Trainings -On the [Plone Trainings Website](https://training.plone.org) you'll find -Volto-dedicated open training materials plus React and other -Javascript-centered trainings. +On the [Plone Training website](https://training.plone.org), you'll find Volto-dedicated training materials, plus other JavaScript-centered trainings. - [Mastering Plone 6 Development](https://training.plone.org/mastering-plone/) The comprehensive training on Plone 6 with best practice tips for developers and integrators. -- [Volto](https://training.plone.org/5/volto/index.html) - A detailed training on how to create your own website using Volto frontend. - [Volto Hands-On](https://training.plone.org/voltohandson/index.html) - [Volto Add-ons Development](https://training.plone.org/voltoaddons/index.html) -- [Plone Deployment](https://training.plone.org/5/plone-deployment/index.html) -- [React](https://training.plone.org/react/index.html) -- [JavaScript For Plone Developers](https://training.plone.org/5/javascript/index.html) +- [Effective Volto](https://training.plone.org/effective-volto/index.html) +- [Plone Deployment](https://training.plone.org/plone-deployment/index.html) +- [Volto](https://2022.training.plone.org/volto/index.html) (archived) +- [JavaScript For Plone Developers](https://2022.training.plone.org/javascript/index.html) (archived) ## How does it work under the hood diff --git a/news/4635.documentation b/news/4635.documentation new file mode 100644 index 0000000000..128db286a2 --- /dev/null +++ b/news/4635.documentation @@ -0,0 +1 @@ +Update links for 2022 Training archive. @stevepiercy From de57cf2efcfe796074a7cfb7ae9647de2419d1fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Thu, 13 Apr 2023 14:44:58 +0200 Subject: [PATCH 117/142] Force the resolution of the `react-error-overlay` package to `6.0.9` (#4687) --- .../generator-volto/generators/app/templates/package.json.tpl | 3 +++ packages/generator-volto/news/4687.bugfix | 1 + 2 files changed, 4 insertions(+) create mode 100644 packages/generator-volto/news/4687.bugfix diff --git a/packages/generator-volto/generators/app/templates/package.json.tpl b/packages/generator-volto/generators/app/templates/package.json.tpl index 8292f576f9..648853b627 100644 --- a/packages/generator-volto/generators/app/templates/package.json.tpl +++ b/packages/generator-volto/generators/app/templates/package.json.tpl @@ -154,5 +154,8 @@ "stylelint-config-prettier": "8.0.1", "stylelint-prettier": "1.1.2" }, + "resolutions": { + "react-error-overlay": "6.0.9" + }, "packageManager": "yarn@3.2.3" } diff --git a/packages/generator-volto/news/4687.bugfix b/packages/generator-volto/news/4687.bugfix new file mode 100644 index 0000000000..239d969597 --- /dev/null +++ b/packages/generator-volto/news/4687.bugfix @@ -0,0 +1 @@ +Force the resolution of the `react-error-overlay` package to `6.0.9` @sneridagh From 110f8323b73bbf9c0def9db93971d5d15f89bf33 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Thu, 13 Apr 2023 14:46:07 +0200 Subject: [PATCH 118/142] Release generate-volto 7.0.0-alpha.4 --- packages/generator-volto/CHANGELOG.md | 7 +++++++ packages/generator-volto/news/4687.bugfix | 1 - packages/generator-volto/package.json | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) delete mode 100644 packages/generator-volto/news/4687.bugfix diff --git a/packages/generator-volto/CHANGELOG.md b/packages/generator-volto/CHANGELOG.md index b46cda34cd..d2e320b45a 100644 --- a/packages/generator-volto/CHANGELOG.md +++ b/packages/generator-volto/CHANGELOG.md @@ -8,6 +8,13 @@ +## 7.0.0-alpha.4 (2023-04-13) + +### Bugfix + +- Force the resolution of the `react-error-overlay` package to `6.0.9` @sneridagh [#4687](https://github.com/plone/volto/issues/4687) + + ## 7.0.0-alpha.3 (2023-04-03) ### Bugfix diff --git a/packages/generator-volto/news/4687.bugfix b/packages/generator-volto/news/4687.bugfix deleted file mode 100644 index 239d969597..0000000000 --- a/packages/generator-volto/news/4687.bugfix +++ /dev/null @@ -1 +0,0 @@ -Force the resolution of the `react-error-overlay` package to `6.0.9` @sneridagh diff --git a/packages/generator-volto/package.json b/packages/generator-volto/package.json index 3a9ac534fe..b35a36f5e8 100644 --- a/packages/generator-volto/package.json +++ b/packages/generator-volto/package.json @@ -10,7 +10,7 @@ } ], "license": "MIT", - "version": "7.0.0-alpha.3", + "version": "7.0.0-alpha.4", "repository": { "type": "git", "url": "git+https://github.com/plone/generator-volto.git" From 7a3c07cd9db3b2eba5feb9b9abb3ad71762ac25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Fri, 14 Apr 2023 10:08:20 +0200 Subject: [PATCH 119/142] Revert "Add current page parameter to the route in the listing and search block pagination (#4159)" (#4695) --- .../Blocks/Listing/ListingBody.test.jsx | 20 --- .../Blocks/Listing/withQuerystringResults.jsx | 3 +- .../manage/Blocks/Search/hocs/withSearch.jsx | 12 +- src/helpers/Utils/usePagination.js | 62 +++------- src/helpers/Utils/usePagination.test.js | 115 ------------------ 5 files changed, 20 insertions(+), 192 deletions(-) delete mode 100644 src/helpers/Utils/usePagination.test.js diff --git a/src/components/manage/Blocks/Listing/ListingBody.test.jsx b/src/components/manage/Blocks/Listing/ListingBody.test.jsx index 8a5c359972..d52c7df814 100644 --- a/src/components/manage/Blocks/Listing/ListingBody.test.jsx +++ b/src/components/manage/Blocks/Listing/ListingBody.test.jsx @@ -36,26 +36,6 @@ test('renders a ListingBody component', () => { content: { data: { is_folderish: true, - blocks: { - '839ee00b-013b-4f4a-9b10-8867938fdac3': { - '@type': 'listing', - block: '839ee00b-013b-4f4a-9b10-8867938fdac3', - headlineTag: 'h2', - query: [], - querystring: { - b_size: '2', - query: [ - { - i: 'path', - o: 'plone.app.querystring.operation.string.absolutePath', - v: '/', - }, - ], - sort_order: 'ascending', - }, - variation: 'default', - }, - }, }, }, intl: { diff --git a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx index c550cf93cb..d675fc050a 100644 --- a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +++ b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx @@ -25,7 +25,7 @@ export default function withQuerystringResults(WrappedComponent) { const [initialPath] = React.useState(getBaseUrl(path)); const copyFields = ['limit', 'query', 'sort_on', 'sort_order', 'depth']; - const { currentPage, setCurrentPage } = usePagination(data.block, 1); + const adaptedQuery = Object.assign( variation?.fullobjects ? { fullobjects: 1 } : { metadata_fields: '_all' }, { @@ -37,6 +37,7 @@ export default function withQuerystringResults(WrappedComponent) { : {}, ), ); + const { currentPage, setCurrentPage } = usePagination(querystring, 1); const querystringResults = useSelector( (state) => state.querystringsearch.subrequests, ); diff --git a/src/components/manage/Blocks/Search/hocs/withSearch.jsx b/src/components/manage/Blocks/Search/hocs/withSearch.jsx index fd1842fbc1..5177dd6304 100644 --- a/src/components/manage/Blocks/Search/hocs/withSearch.jsx +++ b/src/components/manage/Blocks/Search/hocs/withSearch.jsx @@ -144,16 +144,12 @@ const getSearchFields = (searchData) => { }; /** - * A hook that will mirror the search block state to a hash location + * A HOC that will mirror the search block state to a hash location */ const useHashState = () => { const location = useLocation(); const history = useHistory(); - /** - * Required to maintain parameter compatibility. - With this we will maintain support for receiving hash (#) and search (?) type parameters. - */ const oldState = React.useMemo(() => { return { ...qs.parse(location.search), @@ -169,7 +165,7 @@ const useHashState = () => { const setSearchData = React.useCallback( (searchData) => { - const newParams = qs.parse(location.search); + const newParams = qs.parse(location.hash); let changed = false; @@ -186,11 +182,11 @@ const useHashState = () => { if (changed) { history.push({ - search: qs.stringify(newParams), + hash: qs.stringify(newParams), }); } }, - [history, oldState, location.search], + [history, oldState, location.hash], ); return [current, setSearchData]; diff --git a/src/helpers/Utils/usePagination.js b/src/helpers/Utils/usePagination.js index dc984e9932..acb12d2ac5 100644 --- a/src/helpers/Utils/usePagination.js +++ b/src/helpers/Utils/usePagination.js @@ -1,59 +1,25 @@ -import React, { useRef, useEffect } from 'react'; -import { useHistory, useLocation } from 'react-router-dom'; -import qs from 'query-string'; -import { useSelector } from 'react-redux'; -import { slugify } from '@plone/volto/helpers/Utils/Utils'; - -/** - * @function useCreatePageQueryStringKey - * @description A hook that creates a key with an id if there are multiple blocks with pagination. - * @returns {string} Example: page || page_012345678 - */ -const useCreatePageQueryStringKey = (id) => { - const blockTypesWithPagination = ['search', 'listing']; - const blocks = useSelector((state) => state?.content?.data?.blocks) || []; - const blocksLayout = - useSelector((state) => state?.content?.data?.blocks_layout?.items) || []; - const displayedBlocks = blocksLayout?.map((item) => blocks[item]); - const hasMultiplePaginations = - displayedBlocks.filter((item) => - blockTypesWithPagination.includes(item['@type']), - ).length > 1 || false; - - return hasMultiplePaginations ? slugify(`page-${id}`) : 'page'; -}; +import React from 'react'; +import { isEqual } from 'lodash'; +import { usePrevious } from './usePrevious'; +import useDeepCompareEffect from 'use-deep-compare-effect'; /** * A pagination helper that tracks the query and resets pagination in case the * query changes. */ -export const usePagination = (id = null, defaultPage = 1) => { - const location = useLocation(); - const history = useHistory(); - const pageQueryStringKey = useCreatePageQueryStringKey(id); - const pageQueryParam = - qs.parse(location.search)[pageQueryStringKey] || defaultPage; - const [currentPage, setCurrentPage] = React.useState( - parseInt(pageQueryParam), - ); - const queryRef = useRef(qs.parse(location.search)?.query); +export const usePagination = (query, defaultPage = 1) => { + const previousQuery = usePrevious(query); + const [currentPage, setCurrentPage] = React.useState(defaultPage); - useEffect(() => { - if (queryRef.current !== qs.parse(location.search)?.query) { - setCurrentPage(defaultPage); - queryRef.current = qs.parse(location.search)?.query; - } - const newParams = { - ...qs.parse(location.search), - [pageQueryStringKey]: currentPage, - }; - history.replace({ - search: qs.stringify(newParams), - }); - }, [currentPage, defaultPage, location.search, history, pageQueryStringKey]); + useDeepCompareEffect(() => { + setCurrentPage(defaultPage); + }, [query, previousQuery, defaultPage]); return { - currentPage, + currentPage: + previousQuery && !isEqual(previousQuery, query) + ? defaultPage + : currentPage, setCurrentPage, }; }; diff --git a/src/helpers/Utils/usePagination.test.js b/src/helpers/Utils/usePagination.test.js deleted file mode 100644 index 26924d78a0..0000000000 --- a/src/helpers/Utils/usePagination.test.js +++ /dev/null @@ -1,115 +0,0 @@ -import { renderHook } from '@testing-library/react-hooks'; -import { usePagination } from './usePagination'; -import * as redux from 'react-redux'; -import routeData from 'react-router'; -import { slugify } from '@plone/volto/helpers/Utils/Utils'; - -const searchBlockId = '545b33de-92cf-4747-969d-68851837b317'; -const searchBlockId2 = '454b33de-92cf-4747-969d-68851837b713'; -const searchBlock = { - '@type': 'search', - query: { - b_size: '4', - query: [ - { - i: 'path', - o: 'plone.app.querystring.operation.string.relativePath', - v: '', - }, - ], - sort_order: 'ascending', - }, - showSearchInput: true, - showTotalResults: true, -}; -let state = { - content: { - data: { - blocks: { - [searchBlockId]: searchBlock, - }, - blocks_layout: { - items: [searchBlockId], - }, - }, - }, -}; - -let mockUseLocationValue = { - pathname: '/testroute', - search: '', -}; - -const setUp = (searchParam, numberOfSearches) => { - mockUseLocationValue.search = searchParam; - if (numberOfSearches > 1) { - state.content.data.blocks[searchBlockId2] = searchBlock; - state.content.data.blocks_layout.items.push(searchBlockId2); - } - return renderHook(({ id, defaultPage }) => usePagination(id, defaultPage), { - initialProps: { - id: searchBlockId, - defaultPage: 1, - }, - }); -}; - -describe(`Tests for usePagination, for the block ${searchBlockId}`, () => { - const useLocation = jest.spyOn(routeData, 'useLocation'); - const useHistory = jest.spyOn(routeData, 'useHistory'); - const useSelector = jest.spyOn(redux, 'useSelector'); - beforeEach(() => { - useLocation.mockReturnValue(mockUseLocationValue); - useHistory.mockReturnValue({ replace: jest.fn() }); - useSelector.mockImplementation((cb) => cb(state)); - }); - - it('1 paginated block with id and defaultPage 1 - shoud be 1', () => { - const { result } = setUp(); - expect(result.current.currentPage).toBe(1); - }); - - it('1 paginated block without params - shoud be 1', () => { - const { result } = setUp(); - expect(result.current.currentPage).toBe(1); - }); - - const param1 = '?page=2'; - it(`1 paginated block with params: ${param1} - shoud be 2`, () => { - const { result } = setUp(param1); - expect(result.current.currentPage).toBe(2); - }); - - const param2 = `?${slugify(`page-${searchBlockId}`)}=2`; - it(`2 paginated blocks with current block in the params: ${param2} - shoud be 2`, () => { - const { result } = setUp(param2, 2); - expect(result.current.currentPage).toBe(2); - }); - - const param3 = `?${slugify(`page-${searchBlockId2}`)}=2`; - it(`2 paginated blocks with the other block in the params: ${param3} - shoud be 1`, () => { - const { result } = setUp(param3, 2); - expect(result.current.currentPage).toBe(1); - }); - - const param4 = `?${slugify(`page-${searchBlockId}`)}=2&${slugify( - `page-${searchBlockId2}`, - )}=1`; - it(`2 paginated blocks with both blocks in the params, current 2: ${param4} - shoud be 2`, () => { - const { result } = setUp(param4, 2); - expect(result.current.currentPage).toBe(2); - }); - - const param5 = `?${slugify(`page-${searchBlockId}`)}=1&${slugify( - `page-${searchBlockId2}`, - )}=2`; - it(`2 paginated blocks with both blocks in the params, current 1: ${param5} - shoud be 1`, () => { - const { result } = setUp(param5, 2); - expect(result.current.currentPage).toBe(1); - }); - - it(`2 paginated blocks with wrong page param: ${param1} - shoud be 1`, () => { - const { result } = setUp(param1, 2); - expect(result.current.currentPage).toBe(1); - }); -}); From 115fe384a3f469096d6aa4b42ba67047ad649000 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Fri, 14 Apr 2023 10:27:49 +0200 Subject: [PATCH 120/142] Changelog --- news/4695.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/4695.bugfix diff --git a/news/4695.bugfix b/news/4695.bugfix new file mode 100644 index 0000000000..4ac844f4f7 --- /dev/null +++ b/news/4695.bugfix @@ -0,0 +1 @@ +Revert "Add current page parameter to the route in the listing and search block pagination (#4159)" @sneridagh From 80e87c501825b8289223944d1e70348b187f3ff6 Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Fri, 14 Apr 2023 14:04:29 +0530 Subject: [PATCH 121/142] Fix Move to top of folder ordering in folder content view (#4691) --- news/4690.bugfix | 1 + src/components/manage/Contents/Contents.jsx | 25 ++++++++++++--------- 2 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 news/4690.bugfix diff --git a/news/4690.bugfix b/news/4690.bugfix new file mode 100644 index 0000000000..c7cd77a16e --- /dev/null +++ b/news/4690.bugfix @@ -0,0 +1 @@ +Fix Move to top of folder ordering in folder content view @iFlameing \ No newline at end of file diff --git a/src/components/manage/Contents/Contents.jsx b/src/components/manage/Contents/Contents.jsx index 744c794711..0e928dfc20 100644 --- a/src/components/manage/Contents/Contents.jsx +++ b/src/components/manage/Contents/Contents.jsx @@ -797,17 +797,20 @@ class Contents extends Component { onMoveToTop(event, { value }) { const id = this.state.items[value]['@id']; value = this.state.currentPage * this.state.pageSize + value; - this.props.orderContent( - getBaseUrl(this.props.pathname), - id.replace(/^.*\//, ''), - -value, - ); - this.setState( - { - currentPage: 0, - }, - () => this.fetchContents(), - ); + this.props + .orderContent( + getBaseUrl(this.props.pathname), + id.replace(/^.*\//, ''), + -value, + ) + .then(() => { + this.setState( + { + currentPage: 0, + }, + () => this.fetchContents(), + ); + }); } /** From fa2b6d4c1e12448a503c7c85056efe206381eee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Re=C3=A9?= Date: Fri, 14 Apr 2023 12:42:02 +0200 Subject: [PATCH 122/142] Fix search block in edit mode re-queries multiple blocks with an empty search text (#4694) --- news/4697.bugfix | 1 + .../manage/Blocks/Search/SearchBlockEdit.jsx | 9 ++--- .../manage/Blocks/Search/hocs/withSearch.jsx | 35 +++++++++++++------ 3 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 news/4697.bugfix diff --git a/news/4697.bugfix b/news/4697.bugfix new file mode 100644 index 0000000000..f167deca5d --- /dev/null +++ b/news/4697.bugfix @@ -0,0 +1 @@ +Fix search block in edit mode re-queries multiple blocks with an empty search text @reebalazs diff --git a/src/components/manage/Blocks/Search/SearchBlockEdit.jsx b/src/components/manage/Blocks/Search/SearchBlockEdit.jsx index 3f5b57bf91..0a3f222e9b 100644 --- a/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +++ b/src/components/manage/Blocks/Search/SearchBlockEdit.jsx @@ -1,5 +1,4 @@ -import React from 'react'; -import useDeepCompareEffect from 'use-deep-compare-effect'; +import React, { useEffect } from 'react'; import { defineMessages } from 'react-intl'; import { compose } from 'redux'; @@ -60,9 +59,11 @@ const SearchBlockEdit = (props) => { }; const { query = {} } = data || {}; - useDeepCompareEffect(() => { + // We don't need deep compare here, as this is just json serializable data. + const deepQuery = JSON.stringify(query); + useEffect(() => { onTriggerSearch(); - }, [query, onTriggerSearch]); + }, [deepQuery, onTriggerSearch]); return ( <> diff --git a/src/components/manage/Blocks/Search/hocs/withSearch.jsx b/src/components/manage/Blocks/Search/hocs/withSearch.jsx index 5177dd6304..332d6feb4f 100644 --- a/src/components/manage/Blocks/Search/hocs/withSearch.jsx +++ b/src/components/manage/Blocks/Search/hocs/withSearch.jsx @@ -114,15 +114,19 @@ function normalizeState({ block: id, }; - // TODO: need to check if SearchableText facet is not already in the query - // Ideally the searchtext functionality should be restructured as being just - // another facet - params.query = params.query.reduce( - // Remove SearchableText from query - (acc, kvp) => (kvp.i === 'SearchableText' ? acc : [...acc, kvp]), - [], - ); + // Note Ideally the searchtext functionality should be restructured as being just + // another facet. But right now it's the same. This means that if a searchText + // is provided, it will override the SearchableText facet. + // If there is no searchText, the SearchableText in the query remains in effect. + // TODO eventually the searchText should be a distinct facet from SearchableText, and + // the two conditions could be combined, in comparison to the current state, when + // one overrides the other. if (searchText) { + params.query = params.query.reduce( + // Remove SearchableText from query + (acc, kvp) => (kvp.i === 'SearchableText' ? acc : [...acc, kvp]), + [], + ); params.query.push({ i: 'SearchableText', o: 'plone.app.querystring.operation.string.contains', @@ -278,8 +282,14 @@ const withSearch = (options) => (WrappedComponent) => { const timeoutRef = React.useRef(); const facetSettings = data?.facets; + const deepQuery = JSON.stringify(data.query); const onTriggerSearch = React.useCallback( - (toSearchText, toSearchFacets, toSortOn, toSortOrder) => { + ( + toSearchText = undefined, + toSearchFacets = undefined, + toSortOn = undefined, + toSortOrder = undefined, + ) => { if (timeoutRef.current) clearTimeout(timeoutRef.current); timeoutRef.current = setTimeout( () => { @@ -287,7 +297,7 @@ const withSearch = (options) => (WrappedComponent) => { id, query: data.query || {}, facets: toSearchFacets || facets, - searchText: toSearchText, + searchText: toSearchText || searchText, sortOn: toSortOn || sortOn, sortOrder: toSortOrder || sortOrder, facetSettings, @@ -301,11 +311,14 @@ const withSearch = (options) => (WrappedComponent) => { toSearchFacets ? inputDelay / 3 : inputDelay, ); }, + // eslint-disable-next-line react-hooks/exhaustive-deps [ - data.query, + // Use deep comparison of data.query + deepQuery, facets, id, setLocationSearchData, + searchText, sortOn, sortOrder, facetSettings, From ba727b3ab7c20a962182d2ed28acec26373f06cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Re=C3=A9?= Date: Fri, 14 Apr 2023 15:26:10 +0200 Subject: [PATCH 123/142] Generate a split sitemap (also fix robots.txt) (#4639) --- news/4638.bugfix | 1 + src/express-middleware/sitemap.js | 39 ++++++++++++++++++++++++-- src/helpers/Robots/Robots.js | 15 ++++++---- src/helpers/Sitemap/Sitemap.js | 46 +++++++++++++++++++++++++++++-- 4 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 news/4638.bugfix diff --git a/news/4638.bugfix b/news/4638.bugfix new file mode 100644 index 0000000000..75b0f1490d --- /dev/null +++ b/news/4638.bugfix @@ -0,0 +1 @@ +Generate a split sitemap @reebalazs diff --git a/src/express-middleware/sitemap.js b/src/express-middleware/sitemap.js index f593219456..8b05884bb3 100644 --- a/src/express-middleware/sitemap.js +++ b/src/express-middleware/sitemap.js @@ -1,11 +1,34 @@ import express from 'express'; -import { generateSitemap } from '@plone/volto/helpers/Sitemap/Sitemap'; +import { + generateSitemap, + generateSitemapIndex, + SITEMAP_BATCH_SIZE, +} from '@plone/volto/helpers/Sitemap/Sitemap'; export const sitemap = function (req, res, next) { - generateSitemap(req).then((sitemap) => { + let start = 0; + let size = undefined; + const { batch: batchStr } = req.params; + if (batchStr !== undefined) { + const batch = parseInt(batchStr); + if (isNaN(batch) || batch === 0 || '' + batch !== batchStr) { + res.status(404); + // Some data, such as the internal API address, may be sensitive to be published + res.send( + `Invalid sitemap name, use sitemap.xml.gz, or batched sitemapN.xml.gz where N is a positive integer.`, + ); + return; + } + start = SITEMAP_BATCH_SIZE * (batch - 1); + size = SITEMAP_BATCH_SIZE; + } + generateSitemap(req, start, size).then((sitemap) => { if (Buffer.isBuffer(sitemap)) { res.set('Content-Type', 'application/x-gzip'); - res.set('Content-Disposition', 'attachment; filename="sitemap.xml.gz"'); + res.set( + 'Content-Disposition', + `attachment; filename="sitemap${batchStr || ''}.xml.gz"`, + ); res.send(sitemap); } else { // {"errno":-111, "code":"ECONNREFUSED", "host": ...} @@ -16,10 +39,20 @@ export const sitemap = function (req, res, next) { }); }; +export const sitemapIndex = function (req, res, next) { + generateSitemapIndex(req).then((sitemapIndex) => { + res.set('Content-Type', 'application/xml'); + res.set('Content-Disposition', 'attachment; filename="sitemap-index.xml"'); + res.send(sitemapIndex); + }); +}; + export default function () { const middleware = express.Router(); middleware.all('**/sitemap.xml.gz', sitemap); + middleware.all('**/sitemap:batch.xml.gz', sitemap); + middleware.all('**/sitemap-index.xml', sitemapIndex); middleware.id = 'sitemap.xml.gz'; return middleware; } diff --git a/src/helpers/Robots/Robots.js b/src/helpers/Robots/Robots.js index 040e4b2ea0..38a7e5527f 100644 --- a/src/helpers/Robots/Robots.js +++ b/src/helpers/Robots/Robots.js @@ -15,12 +15,9 @@ import { addHeadersFactory } from '@plone/volto/helpers/Proxy/Proxy'; */ export const generateRobots = (req) => new Promise((resolve) => { - //const url = `${req.protocol}://${req.get('Host')}`; - const request = superagent.get( - `${ - config.settings.internalApiPath ?? config.settings.apiPath - }/robots.txt`, - ); + const internalUrl = + config.settings.internalApiPath ?? config.settings.apiPath; + const request = superagent.get(`${internalUrl}/robots.txt`); request.set('Accept', 'text/plain'); const authToken = req.universalCookies.get('auth_token'); if (authToken) { @@ -31,6 +28,12 @@ export const generateRobots = (req) => if (error) { resolve(text || error); } else { + // Plone has probably returned the sitemap link with the internal url. + // If so, let's replace it with the current one. + const url = `${req.protocol}://${req.get('Host')}`; + text = text.replace(internalUrl, url); + // Replace the sitemap with the sitemap index. + text = text.replace('sitemap.xml.gz', 'sitemap-index.xml'); resolve(text); } }); diff --git a/src/helpers/Sitemap/Sitemap.js b/src/helpers/Sitemap/Sitemap.js index ac2629e61f..64cc8dadb2 100644 --- a/src/helpers/Sitemap/Sitemap.js +++ b/src/helpers/Sitemap/Sitemap.js @@ -11,19 +11,23 @@ import { addHeadersFactory } from '@plone/volto/helpers/Proxy/Proxy'; import config from '@plone/volto/registry'; +export const SITEMAP_BATCH_SIZE = 5000; + /** * Generate sitemap * @function generateSitemap * @param {Object} _req Request object * @return {string} Generated sitemap */ -export const generateSitemap = (_req) => +export const generateSitemap = (_req, start = 0, size = undefined) => new Promise((resolve) => { const { settings } = config; const APISUFIX = settings.legacyTraverse ? '' : '/++api++'; const apiPath = settings.internalApiPath ?? settings.apiPath; const request = superagent.get( - `${apiPath}${APISUFIX}/@search?metadata_fields=modified&b_size=100000000&use_site_search_settings=1`, + `${apiPath}${APISUFIX}/@search?metadata_fields=modified&b_start=${start}&b_size=${ + size !== undefined ? size : 100000000 + }&use_site_search_settings=1`, ); request.set('Accept', 'application/json'); request.use(addHeadersFactory(_req)); @@ -50,3 +54,41 @@ export const generateSitemap = (_req) => } }); }); + +/** + * Generate sitemap + * @function generateSitemapIndex + * @param {Object} _req Request object + * @return {string} Generated sitemap index + */ +export const generateSitemapIndex = (_req) => + new Promise((resolve) => { + const { settings } = config; + const APISUFIX = settings.legacyTraverse ? '' : '/++api++'; + const apiPath = settings.internalApiPath ?? settings.apiPath; + const request = superagent.get( + `${apiPath}${APISUFIX}/@search?metadata_fields=modified&b_size=0&use_site_search_settings=1`, + ); + request.set('Accept', 'application/json'); + const authToken = _req.universalCookies.get('auth_token'); + if (authToken) { + request.set('Authorization', `Bearer ${authToken}`); + } + request.end((error, { body } = {}) => { + if (error) { + resolve(body || error); + } else { + const items = Array.from( + { length: Math.ceil(body.items_total / SITEMAP_BATCH_SIZE) }, + (_, i) => + ` + ${toPublicURL('/sitemap' + (i + 1) + '.xml.gz')} + `, + ); + const result = ` + +${items.join('\n')}\n`; + resolve(result); + } + }); + }); From 45848776b874e4bb36b0cb9caf505c991061e2a5 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Fri, 14 Apr 2023 15:32:42 +0200 Subject: [PATCH 124/142] Release 17.0.0-alpha.5 --- CHANGELOG.md | 14 ++++++++++++++ news/4635.documentation | 1 - news/4638.bugfix | 1 - news/4690.bugfix | 1 - news/4695.bugfix | 1 - news/4697.bugfix | 1 - package.json | 2 +- packages/volto-slate/package.json | 2 +- 8 files changed, 16 insertions(+), 7 deletions(-) delete mode 100644 news/4635.documentation delete mode 100644 news/4638.bugfix delete mode 100644 news/4690.bugfix delete mode 100644 news/4695.bugfix delete mode 100644 news/4697.bugfix diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d14467538..85d1cd052e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,20 @@ +## 17.0.0-alpha.5 (2023-04-14) + +### Bugfix + +- Generate a split sitemap @reebalazs [#4638](https://github.com/plone/volto/issues/4638) +- Fix Move to top of folder ordering in folder content view @iFlameing [#4690](https://github.com/plone/volto/issues/4690) +- Revert "Add current page parameter to the route in the listing and search block pagination (#4159)" @sneridagh [#4695](https://github.com/plone/volto/issues/4695) +- Fix search block in edit mode re-queries multiple blocks with an empty search text @reebalazs [#4697](https://github.com/plone/volto/issues/4697) + +### Documentation + +- Update links for 2022 Training archive. @stevepiercy [#4635](https://github.com/plone/volto/issues/4635) + + ## 17.0.0-alpha.4 (2023-04-12) ### Feature diff --git a/news/4635.documentation b/news/4635.documentation deleted file mode 100644 index 128db286a2..0000000000 --- a/news/4635.documentation +++ /dev/null @@ -1 +0,0 @@ -Update links for 2022 Training archive. @stevepiercy diff --git a/news/4638.bugfix b/news/4638.bugfix deleted file mode 100644 index 75b0f1490d..0000000000 --- a/news/4638.bugfix +++ /dev/null @@ -1 +0,0 @@ -Generate a split sitemap @reebalazs diff --git a/news/4690.bugfix b/news/4690.bugfix deleted file mode 100644 index c7cd77a16e..0000000000 --- a/news/4690.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix Move to top of folder ordering in folder content view @iFlameing \ No newline at end of file diff --git a/news/4695.bugfix b/news/4695.bugfix deleted file mode 100644 index 4ac844f4f7..0000000000 --- a/news/4695.bugfix +++ /dev/null @@ -1 +0,0 @@ -Revert "Add current page parameter to the route in the listing and search block pagination (#4159)" @sneridagh diff --git a/news/4697.bugfix b/news/4697.bugfix deleted file mode 100644 index f167deca5d..0000000000 --- a/news/4697.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix search block in edit mode re-queries multiple blocks with an empty search text @reebalazs diff --git a/package.json b/package.json index 236b585cce..2f0d798a35 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "17.0.0-alpha.4", + "version": "17.0.0-alpha.5", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" diff --git a/packages/volto-slate/package.json b/packages/volto-slate/package.json index 08660d8a77..0fb36fb86f 100644 --- a/packages/volto-slate/package.json +++ b/packages/volto-slate/package.json @@ -1,6 +1,6 @@ { "name": "@plone/volto-slate", - "version": "17.0.0-alpha.4", + "version": "17.0.0-alpha.5", "description": "Slate.js integration with Volto", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", From d6acb0861502d27c095ff3c2746df022dd104b42 Mon Sep 17 00:00:00 2001 From: Victor Fernandez de Alba Date: Fri, 14 Apr 2023 15:33:22 +0200 Subject: [PATCH 125/142] Release changelog notes for 16.20.1 --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85d1cd052e..672827abe5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -160,6 +160,16 @@ - Use a universal static path for both documentation and volto repos. @stevepiercy [#4376](https://github.com/plone/volto/issues/4376) +## 16.20.1 (2023-04-14) + +### Bugfix + +- Generate a split sitemap @reebalazs [#4638](https://github.com/plone/volto/issues/4638) +- Fix Move to top of folder ordering in folder content view @iFlameing [#4690](https://github.com/plone/volto/issues/4690) +- Revert "Add current page parameter to the route in the listing and search block pagination (#4159)" @sneridagh [#4695](https://github.com/plone/volto/issues/4695) +- Fix search block in edit mode re-queries multiple blocks with an empty search text @reebalazs [#4697](https://github.com/plone/volto/issues/4697) + + ## 16.20.0 (2023-04-12) ### Feature From cca057b189fce0d40a8fefb708c0f542d0211a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Tue, 18 Apr 2023 09:32:20 +0200 Subject: [PATCH 126/142] Refactor faulty reorder elements in ObjectBrowserList widget (#4703) --- news/4703.bugfix | 1 + src/components/manage/Widgets/ObjectListWidget.jsx | 11 +++-------- src/helpers/Utils/Utils.js | 8 ++++---- src/helpers/index.js | 1 + 4 files changed, 9 insertions(+), 12 deletions(-) create mode 100644 news/4703.bugfix diff --git a/news/4703.bugfix b/news/4703.bugfix new file mode 100644 index 0000000000..d0b7241188 --- /dev/null +++ b/news/4703.bugfix @@ -0,0 +1 @@ +Fix faulty D&D elements in ObjectBrowserList widget @sneridagh diff --git a/src/components/manage/Widgets/ObjectListWidget.jsx b/src/components/manage/Widgets/ObjectListWidget.jsx index c2d5481551..859d5915bf 100644 --- a/src/components/manage/Widgets/ObjectListWidget.jsx +++ b/src/components/manage/Widgets/ObjectListWidget.jsx @@ -2,7 +2,7 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { Accordion, Button, Segment } from 'semantic-ui-react'; import { DragDropList, FormFieldWrapper, Icon } from '@plone/volto/components'; -import { applySchemaDefaults } from '@plone/volto/helpers'; +import { applySchemaDefaults, reorderArray } from '@plone/volto/helpers'; import ObjectWidget from '@plone/volto/components/manage/Widgets/ObjectWidget'; import upSVG from '@plone/volto/icons/up-key.svg'; @@ -164,13 +164,8 @@ const ObjectListWidget = (props) => { if (!destination) { return; } - - const first = value[source.index]; - const second = value[destination.index]; - value[destination.index] = first; - value[source.index] = second; - - onChange(id, value); + const newValue = reorderArray(value, source.index, destination.index); + onChange(id, newValue); return true; }} > diff --git a/src/helpers/Utils/Utils.js b/src/helpers/Utils/Utils.js index 672ec6d3c1..abdef7d307 100644 --- a/src/helpers/Utils/Utils.js +++ b/src/helpers/Utils/Utils.js @@ -258,11 +258,11 @@ export const removeFromArray = (array, index) => { }; /** - * Reorder array + * Moves an item from origin to target inside an array in an immutable way * @param {Array} array Array with data - * @param {number} origin Index of item to be reordered - * @param {number} target Index of item to be reordered to - * @returns {Array} Array with reordered elements + * @param {number} origin Index of item to be moved from + * @param {number} target Index of item to be moved to + * @returns {Array} Resultant array */ export const reorderArray = (array, origin, target) => { const result = Array.from(array); diff --git a/src/helpers/index.js b/src/helpers/index.js index 25a8de5f49..fd48c86bb4 100644 --- a/src/helpers/index.js +++ b/src/helpers/index.js @@ -85,6 +85,7 @@ export { hasApiExpander, replaceItemOfArray, cloneDeepSchema, + reorderArray, } from '@plone/volto/helpers/Utils/Utils'; export { messages } from './MessageLabels/MessageLabels'; export { From 48671635cf8aaa41084e6e1efa5f50467c5a954d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Re=C3=A9?= Date: Tue, 18 Apr 2023 09:33:02 +0200 Subject: [PATCH 127/142] Fix robot.txt - the sitemap link should respect x-forwarded headers (#4704) --- news/4638.bugfix | 1 + src/helpers/Robots/Robots.js | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 news/4638.bugfix diff --git a/news/4638.bugfix b/news/4638.bugfix new file mode 100644 index 0000000000..972338ec30 --- /dev/null +++ b/news/4638.bugfix @@ -0,0 +1 @@ +Fix robot.txt - the sitemap link should respect x-forwarded headers @reebalazs diff --git a/src/helpers/Robots/Robots.js b/src/helpers/Robots/Robots.js index 38a7e5527f..bc0f2bd620 100644 --- a/src/helpers/Robots/Robots.js +++ b/src/helpers/Robots/Robots.js @@ -28,9 +28,24 @@ export const generateRobots = (req) => if (error) { resolve(text || error); } else { + // It appears that express does not take the x-forwarded headers into + // consideration, so we do it ourselves. + const { + 'x-forwarded-proto': forwardedProto, + 'x-forwarded-host': forwardedHost, + 'x-forwarded-port': forwardedPort, + } = req.headers; + const proto = forwardedProto ?? req.protocol; + const host = forwardedHost ?? req.get('Host'); + const portNum = forwardedPort ?? req.get('Port'); + const port = + (proto === 'https' && '' + portNum === '443') || + (proto === 'http' && '' + portNum === '80') + ? '' + : `:${portNum}`; // Plone has probably returned the sitemap link with the internal url. // If so, let's replace it with the current one. - const url = `${req.protocol}://${req.get('Host')}`; + const url = `${proto}://${host}${port}`; text = text.replace(internalUrl, url); // Replace the sitemap with the sitemap index. text = text.replace('sitemap.xml.gz', 'sitemap-index.xml'); From 40bcf43b42b200e45f755be477caeff96ea591a7 Mon Sep 17 00:00:00 2001 From: Alok Kumar Date: Tue, 18 Apr 2023 16:03:33 +0530 Subject: [PATCH 128/142] =?UTF-8?q?Fix=20Move=20to=20top=20of=20folder=20o?= =?UTF-8?q?rdering=20in=20folder=20content=20view=20by=20searchin=E2=80=A6?= =?UTF-8?q?=20(#4709)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cypress/tests/core/basic/folder-contents.js | 85 +++++++++++++++++++++ news/4690.bugfix | 1 + src/components/manage/Contents/Contents.jsx | 30 ++++---- 3 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 news/4690.bugfix diff --git a/cypress/tests/core/basic/folder-contents.js b/cypress/tests/core/basic/folder-contents.js index 1aa45e1dac..3be1299b51 100644 --- a/cypress/tests/core/basic/folder-contents.js +++ b/cypress/tests/core/basic/folder-contents.js @@ -128,4 +128,89 @@ describe('Folder Contents Tests', () => { cy.waitForResourceToLoad('@breadcrumbs'); cy.get('thead tr').contains('Creator'); }); + it('Move items to top of folder and bottom of folder', () => { + // creating a Document + cy.createContent({ + contentType: 'Document', + contentId: 'child', + contentTitle: 'My Child', + path: 'my-folder', + }); + + // doing copy paste for dummy data + cy.get('svg[class="icon unchecked"]').click(); + cy.get('svg[class="icon copy"]').click(); + var genArr = Array.from({ length: 56 }, (v, k) => k + 1); + cy.wrap(genArr).each((index) => { + cy.get('svg[class="icon paste"]').click({ force: true }); + }); + cy.wait(2000); // just for clearing of toast + + // after adding 56 page I need to add a final page to move around. + // when I add a page + cy.get('#toolbar-add').click(); + cy.get('#toolbar-add-document').click(); + cy.getSlateTitle() + .focus() + .click() + .type('last and first page') + .contains('last and first page'); + + // then a new page has been created + cy.get('#toolbar-save').click(); + cy.url().should( + 'eq', + Cypress.config().baseUrl + '/my-folder/last-and-first-page', + ); + cy.visit('my-folder/contents'); + cy.get('.contents-pagination .menu').findByText('2').click(); + + cy.get( + 'tr[aria-label="/my-folder/last-and-first-page"] svg[class="icon dropdown-popup-trigger"]', + ).click(); + cy.findByText('Move to top of folder').click(); + cy.url().should('eq', Cypress.config().baseUrl + '/my-folder/contents'); + cy.wait(1000); // waiting for settling of odering or search return + + // Checking if move to top of folder works or not. + cy.get('table tbody tr:first-child a span').findByText( + 'last and first page', + ); + cy.get( + 'tr[aria-label="/my-folder/last-and-first-page"] svg[class="icon dropdown-popup-trigger"]', + ).click(); + cy.findByText('Move to bottom of folder').click(); + + // Checking whether moving to bottom of folder works or not. + cy.get('.contents-pagination .menu').findByText('2').click(); + cy.get('table tbody tr:last-child a span').findByText( + 'last and first page', + ); + + // Now doing for filtering by searhing content and moving them + cy.visit('my-folder/contents'); + cy.url().should('eq', Cypress.config().baseUrl + '/my-folder/contents'); + cy.get('.ui.small.transparent.input input').type('last'); + cy.get( + 'tr[aria-label="/my-folder/last-and-first-page"] svg[class="icon dropdown-popup-trigger"]', + ).click(); + // cy.intercept('GET', '/plone/++api++/my-folder/@search').as('getSearch'); // I don't know proper way to wait + cy.findByText('Move to top of folder').click(); + cy.get('.search.item button').click(); + + // Checking if move to top of folder works or not. + cy.get('table tbody tr:first-child a span').findByText( + 'last and first page', + ); + cy.get( + 'tr[aria-label="/my-folder/last-and-first-page"] svg[class="icon dropdown-popup-trigger"]', + ).click(); + cy.findByText('Move to bottom of folder').click(); + cy.get('.contents-pagination .menu').findByText('2').click(); + + // Checking whether moving to bottom of folder works or not. + cy.get('table tbody tr:last-child a span').findByText( + 'last and first page', + ); + }); }); diff --git a/news/4690.bugfix b/news/4690.bugfix new file mode 100644 index 0000000000..4729717efa --- /dev/null +++ b/news/4690.bugfix @@ -0,0 +1 @@ +Fix Move to top of folder ordering in folder content view by searching also @iFlameing diff --git a/src/components/manage/Contents/Contents.jsx b/src/components/manage/Contents/Contents.jsx index 0e928dfc20..291ed46c62 100644 --- a/src/components/manage/Contents/Contents.jsx +++ b/src/components/manage/Contents/Contents.jsx @@ -796,12 +796,11 @@ class Contents extends Component { */ onMoveToTop(event, { value }) { const id = this.state.items[value]['@id']; - value = this.state.currentPage * this.state.pageSize + value; this.props .orderContent( getBaseUrl(this.props.pathname), id.replace(/^.*\//, ''), - -value, + 'top', ) .then(() => { this.setState( @@ -821,18 +820,21 @@ class Contents extends Component { * @returns {undefined} */ onMoveToBottom(event, { value }) { - this.onOrderItem( - this.state.items[value]['@id'], - value, - this.state.items.length - 1 - value, - false, - ); - this.onOrderItem( - this.state.items[value]['@id'], - value, - this.state.items.length - 1 - value, - true, - ); + const id = this.state.items[value]['@id']; + this.props + .orderContent( + getBaseUrl(this.props.pathname), + id.replace(/^.*\//, ''), + 'bottom', + ) + .then(() => { + this.setState( + { + currentPage: 0, + }, + () => this.fetchContents(), + ); + }); } /** From b9ce7b1cf4ed23476fdf7d86cf7df1aca30e646f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katja=20S=C3=BCss?= Date: Wed, 19 Apr 2023 13:04:59 +0200 Subject: [PATCH 129/142] Translate add-on control panel (cleaned up PR) (#4620) obviously no objections --- locales/de/LC_MESSAGES/volto.po | 34 ++++++++++++++++----------------- news/4582.bugfix | 1 + 2 files changed, 18 insertions(+), 17 deletions(-) create mode 100644 news/4582.bugfix diff --git a/locales/de/LC_MESSAGES/volto.po b/locales/de/LC_MESSAGES/volto.po index 908ad7614d..63169c89a6 100644 --- a/locales/de/LC_MESSAGES/volto.po +++ b/locales/de/LC_MESSAGES/volto.po @@ -60,7 +60,7 @@ msgstr "Aktionen" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Activate and deactivate add-ons in the lists below. msgid "Activate and deactivate" -msgstr "Aktiviern und Deaktivieren" +msgstr "Aktivieren und Deaktivieren" #: components/manage/Rules/Rules # defaultMessage: Active @@ -92,7 +92,7 @@ msgstr "Hinzufügen" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: To make new add-ons show up here, add them to your configuration, build, and restart the server process. For detailed instructions see msgid "Add Addons" -msgstr "Add-on hinzufügen" +msgstr "Hier werden verfügbare und installierte Backend-Add-ons gezeigt. Informationen wie Weitere hinzugefügt werden können, finden sich hier:" #: components/manage/Toolbar/Types # defaultMessage: Add Content… @@ -232,7 +232,7 @@ msgstr "Erweiterungen" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Add-ons Settings msgid "Add-ons Settings" -msgstr "Einstellungen Add-ons" +msgstr "Add-ons" #: components/manage/Rules/Rules # defaultMessage: Added @@ -247,12 +247,12 @@ msgstr "Zusätzliches Datum" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Addon could not be installed msgid "Addon could not be installed" -msgstr "Erweiterung konnte nicht installiert werden" +msgstr "Erweiterung konnte nicht aktiviert werden" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Addon could not be uninstalled msgid "Addon could not be uninstalled" -msgstr "Erweiterung konnte nicht deinstalliert werden" +msgstr "Erweiterung konnte nicht deaktiviert werden" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Addon could not be upgraded @@ -262,12 +262,12 @@ msgstr "Erweiterung konnte nicht aktualisiert werden" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Addon installed succesfuly msgid "Addon installed succesfuly" -msgstr "Erweiterungen erfolgreich installiert" +msgstr "Erweiterungen erfolgreich aktiviert" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Addon uninstalled succesfuly msgid "Addon uninstalled succesfuly" -msgstr "Erweiterung erfolgreich deinstalliert" +msgstr "Erweiterung erfolgreich deaktiviert" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Addon upgraded succesfuly @@ -1693,22 +1693,22 @@ msgstr "Zeile davor einfügen" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Install msgid "Install" -msgstr "Installieren" +msgstr "aktivieren" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Installed msgid "Installed" -msgstr "Installiert" +msgstr "aktiviert" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Installed version msgid "Installed version" -msgstr "Installierte Version" +msgstr "Aktivierte Version" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Installing a third party add-on msgid "Installing a third party add-on" -msgstr "Eine Erweiterung installieren" +msgstr "Eine Erweiterung aktivieren" #: components/manage/Widgets/RecurrenceWidget/RecurrenceWidget # defaultMessage: days @@ -1831,7 +1831,7 @@ msgstr "Letzte verfügbare Konfiguration" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Latest version msgid "Latest version" -msgstr "Letzte Version" +msgstr "Verfügbare Version" #: components/manage/Controlpanels/ContentTypesActions # defaultMessage: Layout @@ -2243,7 +2243,7 @@ msgstr "Keine Auswahl" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: This addon does not provide an uninstall profile. msgid "No uninstall profile" -msgstr "Kein Deinstallationsprofil" +msgstr "Kein Deaktivierungsprofil" #: helpers/MessageLabels/MessageLabels # defaultMessage: No user found @@ -3626,7 +3626,7 @@ msgstr "Vereinigt" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Uninstall msgid "Uninstall" -msgstr "Deinstallieren" +msgstr "deaktivieren" #: components/manage/Blocks/Block/DefaultView #: components/manage/Blocks/Block/Edit @@ -3658,12 +3658,12 @@ msgstr "Update" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Update installed addons msgid "Update installed addons" -msgstr "Installierte Erweiterungen aktualisieren" +msgstr "Aktivierte Erweiterungen aktualisieren" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Update installed addons: msgid "Update installed addons:" -msgstr "Installierte Erweiterungen:" +msgstr "Aktivierte Erweiterungen:" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Updates available @@ -4531,7 +4531,7 @@ msgstr "Toggle" #: components/manage/Controlpanels/AddonsControlpanel # defaultMessage: Update from version {origin} to {destination} msgid "upgradeVersions" -msgstr "Aktualisieren von Version {origin} zu Version {destination}" +msgstr "Von Version {origin} zu Version {destination} aktualisieren" #: helpers/MessageLabels/MessageLabels # defaultMessage: Input must be valid url (www.something.com or http(s)://www.something.com) diff --git a/news/4582.bugfix b/news/4582.bugfix new file mode 100644 index 0000000000..2a2383ed8f --- /dev/null +++ b/news/4582.bugfix @@ -0,0 +1 @@ +Update add-on control panel tranlsations: install -> activate. @ksuess From 0e62195bf5dade82fb01a5d37b4e003a66e990b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Katja=20S=C3=BCss?= Date: Wed, 19 Apr 2023 13:06:14 +0200 Subject: [PATCH 130/142] (Synchronize redundant block id in listing block on pasting) Fix duplicating listing block (#4239) Obvoiusly no objections anymore. --- docs/source/blocks/ssr.md | 4 +-- news/4234.bugfix | 1 + src/components/manage/Blocks/Listing/Edit.jsx | 14 --------- .../manage/Blocks/Listing/getAsyncData.js | 12 +++++-- .../Blocks/Listing/withQuerystringResults.jsx | 31 +++++++++++-------- .../manage/Blocks/Search/SearchBlockView.jsx | 3 +- 6 files changed, 33 insertions(+), 32 deletions(-) create mode 100644 news/4234.bugfix diff --git a/docs/source/blocks/ssr.md b/docs/source/blocks/ssr.md index 933dccb1c6..a1f231c53c 100644 --- a/docs/source/blocks/ssr.md +++ b/docs/source/blocks/ssr.md @@ -21,10 +21,10 @@ configuration, pointing to a function that returns a list of promises. For example: ```js -export default ({ dispatch, data, path }) => { +export default ({ dispatch, id, data, path }) => { return [ dispatch( - getQueryStringResults(path, { ...data, fullobjects: 1 }, data.block), + getQueryStringResults(path, { ...data, fullobjects: 1 }, id), ), ]; }; diff --git a/news/4234.bugfix b/news/4234.bugfix new file mode 100644 index 0000000000..26eb1934a1 --- /dev/null +++ b/news/4234.bugfix @@ -0,0 +1 @@ +Fix duplicating listing block by removing block uid from blocks data. @ksuess \ No newline at end of file diff --git a/src/components/manage/Blocks/Listing/Edit.jsx b/src/components/manage/Blocks/Listing/Edit.jsx index f447211415..29fefe54cc 100644 --- a/src/components/manage/Blocks/Listing/Edit.jsx +++ b/src/components/manage/Blocks/Listing/Edit.jsx @@ -26,21 +26,7 @@ const messages = defineMessages({ const Edit = React.memo( (props) => { const { data, onChangeBlock, block, selected, pathname } = props; - const intl = useIntl(); - - // componentDidMount - React.useEffect(() => { - if (!data.query) { - onChangeBlock(block, { - ...data, - query: [], - block, - }); - } - /* eslint-disable react-hooks/exhaustive-deps */ - }, []); - const placeholder = data.placeholder || (data?.querystring?.query?.length diff --git a/src/components/manage/Blocks/Listing/getAsyncData.js b/src/components/manage/Blocks/Listing/getAsyncData.js index 7d4ffe3662..c5f463f1dd 100644 --- a/src/components/manage/Blocks/Listing/getAsyncData.js +++ b/src/components/manage/Blocks/Listing/getAsyncData.js @@ -1,7 +1,13 @@ import { getQueryStringResults } from '@plone/volto/actions'; import { resolveBlockExtensions } from '@plone/volto/helpers'; -export default ({ dispatch, data, path, blocksConfig }) => { +const getListingBlockAsyncData = ({ + dispatch, + id, + data, + path, + blocksConfig, +}) => { const { resolvedExtensions } = resolveBlockExtensions(data, blocksConfig); return [ @@ -14,8 +20,10 @@ export default ({ dispatch, data, path, blocksConfig }) => { ? { fullobjects: 1 } : { metadata_fields: '_all' }), }, - data.block, + id, ), ), ]; }; + +export default getListingBlockAsyncData; diff --git a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx index d675fc050a..1b552e674b 100644 --- a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +++ b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx @@ -14,11 +14,16 @@ function getDisplayName(WrappedComponent) { export default function withQuerystringResults(WrappedComponent) { function WithQuerystringResults(props) { - const { data = {}, properties: content, path, variation } = props; + const { + data = {}, + id = data.block, + properties: content, + path, + variation, + } = 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 { block } = data; const { b_size = settings.defaultPageSize } = querystring; // batchsize // save the path so it won't trigger dispatch on eager router location change @@ -45,32 +50,32 @@ export default function withQuerystringResults(WrappedComponent) { const folderItems = content?.is_folderish ? content.items : []; const hasQuery = querystring?.query?.length > 0; - const hasLoaded = hasQuery ? !querystringResults?.[block]?.loading : true; + const hasLoaded = hasQuery ? !querystringResults?.[id]?.loading : true; const listingItems = - querystring?.query?.length > 0 && querystringResults?.[block] - ? querystringResults?.[block]?.items || [] + querystring?.query?.length > 0 && querystringResults?.[id] + ? querystringResults?.[id]?.items || [] : folderItems; const showAsFolderListing = !hasQuery && content?.items_total > b_size; const showAsQueryListing = - hasQuery && querystringResults?.[block]?.total > b_size; + hasQuery && querystringResults?.[id]?.total > b_size; const totalPages = showAsFolderListing ? Math.ceil(content.items_total / b_size) : showAsQueryListing - ? Math.ceil(querystringResults[block].total / b_size) + ? Math.ceil(querystringResults[id].total / b_size) : 0; const prevBatch = showAsFolderListing ? content.batching?.prev : showAsQueryListing - ? querystringResults[block].batching?.prev + ? querystringResults[id].batching?.prev : null; const nextBatch = showAsFolderListing ? content.batching?.next : showAsQueryListing - ? querystringResults[block].batching?.next + ? querystringResults[id].batching?.next : null; const isImageGallery = @@ -80,7 +85,7 @@ export default function withQuerystringResults(WrappedComponent) { useDeepCompareEffect(() => { if (hasQuery) { dispatch( - getQueryStringResults(initialPath, adaptedQuery, block, currentPage), + getQueryStringResults(initialPath, adaptedQuery, id, currentPage), ); } else if (isImageGallery && !hasQuery) { // when used as image gallery, it doesn't need a query to list children @@ -98,14 +103,14 @@ export default function withQuerystringResults(WrappedComponent) { }, ], }, - block, + id, ), ); } else { dispatch(getContent(initialPath, null, null, currentPage)); } }, [ - block, + id, isImageGallery, adaptedQuery, hasQuery, @@ -118,7 +123,7 @@ export default function withQuerystringResults(WrappedComponent) { setCurrentPage(activePage)} - total={querystringResults?.[block]?.total} + total={querystringResults?.[id]?.total} batch_size={b_size} currentPage={currentPage} totalPages={totalPages} diff --git a/src/components/manage/Blocks/Search/SearchBlockView.jsx b/src/components/manage/Blocks/Search/SearchBlockView.jsx index 49135a6fe6..55580cd79a 100644 --- a/src/components/manage/Blocks/Search/SearchBlockView.jsx +++ b/src/components/manage/Blocks/Search/SearchBlockView.jsx @@ -57,7 +57,7 @@ const applyDefaults = (data, root) => { }; const SearchBlockView = (props) => { - const { data, searchData, mode = 'view', variation } = props; + const { id, data, searchData, mode = 'view', variation } = props; const Layout = variation.view; @@ -89,6 +89,7 @@ const SearchBlockView = (props) => { setSelectedView={setSelectedView} > Date: Thu, 20 Apr 2023 01:15:31 -0700 Subject: [PATCH 131/142] Don't decode querystring while adding apiExpanders (#4719) Co-authored-by: Victor Fernandez de Alba --- .github/workflows/unit.yml | 3 ++- news/4718.bugfix | 1 + src/middleware/Api.test.js | 54 ++++++++++++++++++++++++++++++++++++++ src/middleware/api.js | 2 +- 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 news/4718.bugfix diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 97428e6fe3..3bad45b9aa 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -16,7 +16,8 @@ jobs: - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node-version }} + # remove workaround for 18.x once https://github.com/nodejs/node/issues/47563 is fixed + node-version: ${{ matrix.node-version == '18.x' && '18.15.0' || matrix.node-version }} cache: yarn # node install diff --git a/news/4718.bugfix b/news/4718.bugfix new file mode 100644 index 0000000000..f31527f057 --- /dev/null +++ b/news/4718.bugfix @@ -0,0 +1 @@ +Fix fetching API paths with urlencoded characters in the querystring. @davisagli diff --git a/src/middleware/Api.test.js b/src/middleware/Api.test.js index b508947b29..c67966eef1 100644 --- a/src/middleware/Api.test.js +++ b/src/middleware/Api.test.js @@ -53,6 +53,60 @@ describe('api middleware helpers', () => { ); expect(result).toEqual('/de/mypage/@navigation?expand.navigation.depth=3'); }); + it('addExpandersToPath - Path matching, preserve query', () => { + config.settings.apiExpanders = [ + { + match: '/de/mypage', + GET_CONTENT: ['mycustomexpander', 'mycustomexpander2'], + }, + ]; + + const result = addExpandersToPath( + '/de/mypage/@navigation?expand.navigation.depth=3', + GET_CONTENT, + ); + expect(result).toEqual( + '/de/mypage/@navigation?expand=mycustomexpander,mycustomexpander2&expand.navigation.depth=3', + ); + }); + it('addExpandersToPath - Path matching, preserve query with multiple', () => { + config.settings.apiExpanders = [ + { + match: '/de/mypage', + GET_CONTENT: ['mycustomexpander', 'mycustomexpander2'], + }, + ]; + + const result = addExpandersToPath( + '/de/mypage/@navigation?expand.navigation.depth=3&expand.other=2', + GET_CONTENT, + ); + expect(result).toEqual( + '/de/mypage/@navigation?expand=mycustomexpander,mycustomexpander2&expand.navigation.depth=3&expand.other=2', + ); + }); + it('addExpandersToPath - Path not matching, preserve encoded query', () => { + config.settings.apiExpanders = [ + { + match: '/de/otherpath', + GET_CONTENT: ['mycustomexpander'], + }, + ]; + + const result = addExpandersToPath('/de/mypage?query=a%26b', GET_CONTENT); + expect(result).toEqual('/de/mypage?query=a%26b'); + }); + it('addExpandersToPath - Path matching, preserve encoded query', () => { + config.settings.apiExpanders = [ + { + match: '/de/mypage', + GET_CONTENT: ['mycustomexpander'], + }, + ]; + + const result = addExpandersToPath('/de/mypage?query=a%26b', GET_CONTENT); + expect(result).toEqual('/de/mypage?expand=mycustomexpander&query=a%26b'); + }); it('addExpandersToPath - Two custom expanders from settings', () => { config.settings.apiExpanders = [ { diff --git a/src/middleware/api.js b/src/middleware/api.js index bd1c094698..84abb6bf4a 100644 --- a/src/middleware/api.js +++ b/src/middleware/api.js @@ -43,7 +43,7 @@ export function addExpandersToPath(path, type, isAnonymous) { const { url, query: { expand, ...query }, - } = qs.parseUrl(path); + } = qs.parseUrl(path, { decode: false }); const expandersFromConfig = apiExpanders .filter((expand) => matchPath(url, expand.match) && expand[type]) From 9fc595528d82f01b8ddb27e337fb680affb294e2 Mon Sep 17 00:00:00 2001 From: Piero Nicolli Date: Sat, 22 Apr 2023 17:16:28 +0200 Subject: [PATCH 132/142] Security upgrade for momentjs (#4715) 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/4715.internal | 1 + package.json | 2 +- yarn.lock | 11 ++--------- 3 files changed, 4 insertions(+), 10 deletions(-) create mode 100644 news/4715.internal diff --git a/news/4715.internal b/news/4715.internal new file mode 100644 index 0000000000..65b82d7d56 --- /dev/null +++ b/news/4715.internal @@ -0,0 +1 @@ +Security upgrade for momentjs diff --git a/package.json b/package.json index 2f0d798a35..154e3efd0a 100644 --- a/package.json +++ b/package.json @@ -311,7 +311,7 @@ "lodash-move": "1.1.1", "lodash-webpack-plugin": "0.11.6", "mini-css-extract-plugin": "2.7.2", - "moment": "2.24.0", + "moment": "2.29.4", "object-assign": "4.1.1", "pofile": "1.0.10", "postcss": "8.4.13", diff --git a/yarn.lock b/yarn.lock index f5aa1197cb..4ec82cce7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2715,7 +2715,7 @@ __metadata: lodash-move: 1.1.1 lodash-webpack-plugin: 0.11.6 mini-css-extract-plugin: 2.7.2 - moment: 2.24.0 + moment: 2.29.4 object-assign: 4.1.1 pofile: 1.0.10 postcss: 8.4.13 @@ -16592,14 +16592,7 @@ __metadata: languageName: node linkType: hard -"moment@npm:2.24.0": - version: 2.24.0 - resolution: "moment@npm:2.24.0" - checksum: 9cd93a251a2b33cb1b532eade0e496a2a7547faa6cfe37a283ee7bf69e202cd7c8ab0673d66883b5b29aed051353176dc0e6684f04073a75b0a155c500be1580 - languageName: node - linkType: hard - -"moment@npm:2.x, moment@npm:>=1.6.0": +"moment@npm:2.29.4, moment@npm:2.x, moment@npm:>=1.6.0": version: 2.29.4 resolution: "moment@npm:2.29.4" checksum: 0ec3f9c2bcba38dc2451b1daed5daded747f17610b92427bebe1d08d48d8b7bdd8d9197500b072d14e326dd0ccf3e326b9e3d07c5895d3d49e39b6803b76e80e From 89e290c341c157f222bd36cd3c8b22fcd52458e9 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sat, 22 Apr 2023 11:29:53 -0700 Subject: [PATCH 133/142] Use new URL 6.docs.plone.org (#4726) --- CHANGELOG.md | 24 ++++++++++++------------ CONTRIBUTING.md | 2 +- README.md | 8 ++++---- docs/source/contributing/style-guide.md | 2 +- docs/source/upgrade-guide/index.md | 2 +- news/4726.documentation | 1 + packages/generator-volto/CHANGELOG.md | 2 +- packages/scripts/CHANGELOG.md | 4 ++-- packages/scripts/README.md | 2 +- packages/volto-testing/CHANGELOG.md | 2 +- 10 files changed, 25 insertions(+), 24 deletions(-) create mode 100644 news/4726.documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index 672827abe5..d90827b8d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -625,7 +625,7 @@ - Enable the use of yarn 3 in the build by default @sneridagh - The `ContentsBreadcrumbs` component now renders the whole language name of the language root folder (if any) instead of just the `id` (before: `de`, now: `Deutsch`) @sneridagh -See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. +See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ### Feature @@ -1122,7 +1122,7 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa - Moved all sentry-related code from Volto to the `@plone-collective/volto-sentry` package. @tiberiuichim - The listing block icon has been improved to avoid confusion with the normal text list. @sneridagh -See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. +See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ### Feature @@ -1233,7 +1233,7 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa - Sentry integration is now lazy-loaded. The `sentryOptions` key from the `settings` registry becomes a callable that passes resolved sentry libraries. @tiberiuichim - See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. + See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ### Feature @@ -1297,7 +1297,7 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa - Upgrade to Razzle 4 @davisagli - Jest downgraded from 27 to 26 @davisagli -See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. +See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ### Internal @@ -1337,7 +1337,7 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa ### Breaking - `react-window` no longer a Volto dependency @sneridagh - See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. + See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ### Bugfix @@ -1376,7 +1376,7 @@ See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more informa ### Breaking - Move Layout constants to `config.views.layoutViewsNamesMapping`. Complete the list. i18n the list. Improve Display component. @sneridagh - See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. + See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ### Feature @@ -1422,7 +1422,7 @@ Undo html_static_path configuration in `plone/documentation`, and restore image ### Breaking - Main workflow change menu changed from Pastanaga UI simplification to classic Plone implementation. @sneridagh - See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. + See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ### Feature @@ -1518,7 +1518,7 @@ Undo html_static_path configuration in `plone/documentation`, and restore image - change password-reset url to be consistent with Plone configuration @erral - Simplify over the existing Component Registry API. The `component` key has been flattened for simplification and now it's mapped directly to the `component` argument of `registerComponent`. @sneridagh -See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. +See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ### Feature @@ -2096,14 +2096,14 @@ Use next release instead: https://github.com/plone/volto/releases/tag/16.0.0-alp ### Breaking - Upgrade `react-cookie` to the latest version. @sneridagh @robgietema - See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. + See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. - Language Switcher no longer takes care of the change of the language on the Redux Store. This responsibility has been unified in the API Redux middleware @sneridagh - Markup change in `LinkView` component. - Rename `core-sandbox` to `coresandbox` for sake of consistency @sneridagh - Extend the original intent and rename `RAZZLE_TESTING_ADDONS` to `ADDONS`. @sneridagh - See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. + See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. - Lazyload Draft.js library. See the upgrade guide on how that impacts you, in case you have extended the rich text editor configuration @tiberiuichim @kreafox - See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. + See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. - Deprecating `lang` cookie in favor of Plone official one `I18N_LANGUAGE` @sneridagh ### Feature @@ -5049,7 +5049,7 @@ https://6.docs.plone.org/volto/upgrade-guide/index.html - Added item type as a tooltip in contents @nzambello - Added Italian translations and translated array, token and select widget. @giuliaghisini - Added uploading image preview in FileWidget @iFlameing -- Allow custom express middleware declared with `settings.expressMiddleware`. See [Custom Express middleware](https://6.dev-docs.plone.org/volto/recipes/express.html) @tiberiuichim +- Allow custom express middleware declared with `settings.expressMiddleware`. See [Custom Express middleware](https://6.docs.plone.org/volto/recipes/express.html) @tiberiuichim ### Bugfix diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 330fc2cddb..21c3b21d4c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,3 @@ # Contributing to Volto -See [Contributing to Volto](https://6.dev-docs.plone.org/volto/developer-guidelines/contributing.html). +See [Contributing to Volto](https://6.docs.plone.org/volto/developer-guidelines/contributing.html). diff --git a/README.md b/README.md index 050d127c8b..7c32093b7f 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ Please create a new [issue](https://github.com/plone/volto/issues/new) or [pull ## Documentation -You can find the latest (in-progress) documentation in [https://6.dev-docs.plone.org/](https://6.dev-docs.plone.org/volto/index.html) +You can find the latest (in-progress) documentation in [https://6.docs.plone.org/](https://6.docs.plone.org/volto/index.html) ## Training @@ -242,7 +242,7 @@ We do not guarantee that deprecated browsers (e.g., Internet Explorer 11) are su ## Upgrades -You can find the upgrade guide here: https://6.dev-docs.plone.org/volto/upgrade-guide/index.html +You can find the upgrade guide here: https://6.docs.plone.org/volto/upgrade-guide/index.html ## Volto Development @@ -317,11 +317,11 @@ yarn test Here you can find a guide on how acceptance testing is done in Volto: -https://6.dev-docs.plone.org/volto/developer-guidelines/acceptance-tests.html +https://6.docs.plone.org/volto/developer-guidelines/acceptance-tests.html ## Translations -If you would like contribute to translate Volto into several languages, please, read the [Internationalization (i18n) guide](https://6.dev-docs.plone.org/volto/recipes/i18n.html). +If you would like contribute to translate Volto into several languages, please, read the [Internationalization (i18n) guide](https://6.docs.plone.org/volto/recipes/i18n.html). ## Contributors diff --git a/docs/source/contributing/style-guide.md b/docs/source/contributing/style-guide.md index 7e2100b9af..112ed410aa 100644 --- a/docs/source/contributing/style-guide.md +++ b/docs/source/contributing/style-guide.md @@ -27,7 +27,7 @@ Volto adopted some time ago [Storybook](https://storybook.js.org), a tool that i Not all Volto's visual components are covered yet in Storybook, but it has already a good foundation. -You can find the current Storybook build in: https://6.dev-docs.plone.org/storybook +You can find the current Storybook build in: https://6.docs.plone.org/storybook ## Quanta, the design system for Plone 6 diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index 31bd17f7f9..f33ea1d1d8 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -568,7 +568,7 @@ If you are extending an existing one, you should add it as a normal `schemaEnhan ``` ```{seealso} -See https://6.dev-docs.plone.org/volto/blocks/block-style-wrapper.html for more documentation. +See https://6.docs.plone.org/volto/blocks/block-style-wrapper.html for more documentation. ``` ### Sentry integration moved from Volto core to add-on diff --git a/news/4726.documentation b/news/4726.documentation new file mode 100644 index 0000000000..b37c62ee68 --- /dev/null +++ b/news/4726.documentation @@ -0,0 +1 @@ +Use new URL `6.docs.plone.org`. @stevepiercy diff --git a/packages/generator-volto/CHANGELOG.md b/packages/generator-volto/CHANGELOG.md index d2e320b45a..4696e00b0b 100644 --- a/packages/generator-volto/CHANGELOG.md +++ b/packages/generator-volto/CHANGELOG.md @@ -3,7 +3,7 @@ diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 84c99079d7..6722cb2121 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -3,7 +3,7 @@ @@ -91,7 +91,7 @@ - Removed `Razzle` as dependency, leave only the `babel-preset-razzle` one which is enough. - See https://6.dev-docs.plone.org/volto/upgrade-guide/index.html for more information. + See https://6.docs.plone.org/volto/upgrade-guide/index.html for more information. ## 1.6.0 (2022-08-05) diff --git a/packages/scripts/README.md b/packages/scripts/README.md index c4b9ec0d59..3c85d2d2c1 100644 --- a/packages/scripts/README.md +++ b/packages/scripts/README.md @@ -6,7 +6,7 @@ This package is a library of scripts that are useful to automate certain tasks w It scans and detects i18n messages from the code and adds them to the i18n machinery. -See https://6.dev-docs.plone.org/volto/recipes/i18n.html for more information. +See https://6.docs.plone.org/volto/recipes/i18n.html for more information. This script is installed in the `node_modules/.bin` directory and can be called via `yarn i18n` or directly in the `scripts` `package.json` part. diff --git a/packages/volto-testing/CHANGELOG.md b/packages/volto-testing/CHANGELOG.md index ff65a00722..c2077bdbf7 100644 --- a/packages/volto-testing/CHANGELOG.md +++ b/packages/volto-testing/CHANGELOG.md @@ -3,7 +3,7 @@ From a50f1286465412979010db1eaca2324415d46978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Fern=C3=A1ndez=20de=20Alba?= Date: Mon, 24 Apr 2023 15:45:11 +0200 Subject: [PATCH 134/142] Release notes from 16.20.2, 16.20.3, 16.20.4 (#4729) --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d90827b8d3..9f3fb8ba73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -160,6 +160,33 @@ - Use a universal static path for both documentation and volto repos. @stevepiercy [#4376](https://github.com/plone/volto/issues/4376) +## 16.20.4 (2023-04-20) + +### Bugfix + +- Fix fetching API paths with urlencoded characters in the querystring. @davisagli [#4718](https://github.com/plone/volto/issues/4718) + +### Internal + +- Security upgrade for momentjs [#4716](https://github.com/plone/volto/issues/4716) + + +## 16.20.3 (2023-04-18) + +### Bugfix + +- Revert inadvertently included files from another PR in #4710 @sneridagh [#4713](https://github.com/plone/volto/issues/4713) + + +## 16.20.2 (2023-04-18) + +### Bugfix + +- Fix robot.txt - the sitemap link should respect x-forwarded headers @reebalazs [#4638](https://github.com/plone/volto/issues/4638) +- Fix Move to top of folder ordering in folder content view by searching also @iFlameing [#4690](https://github.com/plone/volto/issues/4690) +- Fix faulty D&D elements in ObjectBrowserList widget @sneridagh [#4703](https://github.com/plone/volto/issues/4703) + + ## 16.20.1 (2023-04-14) ### Bugfix From 28fb4d20a8b099968e141788139b508e4ea4356c Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 24 Apr 2023 13:47:46 -0700 Subject: [PATCH 135/142] Tidy up from synch with 16.x.x (#4728) --- docs/source/getting-started/install.md | 21 +++++++++++++++++---- docs/source/getting-started/others.md | 3 +-- docs/source/recipes/creating-project.md | 5 +++-- news/4728.documentation | 1 + 4 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 news/4728.documentation diff --git a/docs/source/getting-started/install.md b/docs/source/getting-started/install.md index 911f9582f7..cb405dac88 100644 --- a/docs/source/getting-started/install.md +++ b/docs/source/getting-started/install.md @@ -219,15 +219,28 @@ You may choose to install the canary version, which is the latest alpha release, 1. Open a terminal and execute: - ```bash + ```shell npm install -g yo @plone/generator-volto + # install latest stable release yo @plone/volto + # or install latest alpha release + yo @plone/volto --canary ``` -See the [Creating a project](../recipes/creating-project) page for more -advanced options that can be passed to the generator. + See {doc}`../recipes/creating-project` for more advanced options that can be passed to the generator. + +2. Answer the questions when prompted, and provide the name of the new app (folder) to be created. + For the sake of this documentation, provide `myvoltoproject` as the project name. + + ````{note} + You can run the generator with parameters to tailor your requirements. + + ```shell + yo @plone/volto --help + ``` -2. Answer the questions when prompted, and provide the name of the new app (folder) to be created. For the sake of this documentation, provide `myvoltoproject` as the project name. + or take a look at the [README](https://github.com/plone/volto/blob/master/packages/generator-volto/README.md) for more information. + ```` 3. Change directory to the newly created folder `myvoltoapp` (or the one you've chosen): ```bash diff --git a/docs/source/getting-started/others.md b/docs/source/getting-started/others.md index 4cdb8f4dd2..a0b0ed82c2 100644 --- a/docs/source/getting-started/others.md +++ b/docs/source/getting-started/others.md @@ -30,8 +30,7 @@ You can watch the talk during the World Plone Day 2021: ## Presentations at Plone Conferences (PloneConf) and other events -In recent years the react based Volto frontend for Plone has been presented in more and more talks at -our yearly Conferences: +In recent years the React based Volto frontend for Plone has been presented in more and more talks at our yearly Conferences. ### PloneConf 2022 diff --git a/docs/source/recipes/creating-project.md b/docs/source/recipes/creating-project.md index c577cedd35..03e0bd47b0 100644 --- a/docs/source/recipes/creating-project.md +++ b/docs/source/recipes/creating-project.md @@ -15,7 +15,7 @@ In addition to bootstrapping stand-alone Volto projects, it can also bootstrap V 1. Open a terminal and execute: - ```bash + ```shell npm install -g yo @plone/generator-volto # Install the latest and stable release of Volto with the following command yo @plone/volto @@ -29,7 +29,8 @@ In addition to bootstrapping stand-alone Volto projects, it can also bootstrap V yo @plone/volto --addon=volto-form-block ``` -2. Answer the questions when prompted, and provide the name of the new app (folder) to be created. For the sake of this documentation, provide `myvoltoproject` as the project name then. +2. Answer the questions when prompted, and provide the name of the new app (folder) to be created. + For the sake of this documentation, provide `myvoltoproject` as the project name then. ````{note} You can run the generator with parameters to tailor your requirements. diff --git a/news/4728.documentation b/news/4728.documentation new file mode 100644 index 0000000000..c06faf93be --- /dev/null +++ b/news/4728.documentation @@ -0,0 +1 @@ +Synch stuff from `16.x.x` branch that should have been in `master` as well. @stevepiercy From dd5cb0181f12090324f0c2f0f4103f0a6fb408fb Mon Sep 17 00:00:00 2001 From: David Glick Date: Fri, 5 May 2023 08:51:10 -0700 Subject: [PATCH 136/142] Fix whitespace in locales created by the generator (#4737) --- .../app/templates/locales/de/LC_MESSAGES/volto.po | 11 +---------- .../app/templates/locales/es/LC_MESSAGES/volto.po | 5 ++--- .../app/templates/locales/eu/LC_MESSAGES/volto.po | 4 +++- .../app/templates/locales/fr/LC_MESSAGES/volto.po | 13 +++---------- .../app/templates/locales/it/LC_MESSAGES/volto.po | 2 ++ .../app/templates/locales/ja/LC_MESSAGES/volto.po | 4 ++-- .../app/templates/locales/nl/LC_MESSAGES/volto.po | 15 --------------- .../app/templates/locales/pt/LC_MESSAGES/volto.po | 5 ++--- .../templates/locales/pt_BR/LC_MESSAGES/volto.po | 4 ++-- .../app/templates/locales/ro/LC_MESSAGES/volto.po | 2 -- .../generators/app/templates/locales/volto.pot | 2 ++ packages/generator-volto/news/4737.bugfix | 1 + 12 files changed, 20 insertions(+), 48 deletions(-) create mode 100644 packages/generator-volto/news/4737.bugfix diff --git a/packages/generator-volto/generators/app/templates/locales/de/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/de/LC_MESSAGES/volto.po index c820db7482..49d2e20662 100644 --- a/packages/generator-volto/generators/app/templates/locales/de/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/de/LC_MESSAGES/volto.po @@ -1,13 +1,4 @@ -# Translation of plone.pot to German -# Jan Ulrich Hasecke , 2003-2010. -# Simon Eisenmann , 2003. -# Hanno Schlichting , 2003-2008. -# Dominik Bittl , 2005. -# Christian Ullrich , 2005. -# Thomas Lotze , 2005-2008. -# Sven Deichmann , 2008-2010. -# Harald Friessnegger , 2011. -# Andreas Jung , 2012 +# Translation of volto.pot to German msgid "" msgstr "" "Project-Id-Version: Plone\n" diff --git a/packages/generator-volto/generators/app/templates/locales/es/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/es/LC_MESSAGES/volto.po index a89bace6f0..784b64fb17 100644 --- a/packages/generator-volto/generators/app/templates/locales/es/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/es/LC_MESSAGES/volto.po @@ -1,6 +1,3 @@ -# Gettext Message File for Plone -# Translators: -# Leonardo J. Caballero G. , 2019. msgid "" msgstr "" "Project-Id-Version: Plone\n" @@ -20,3 +17,5 @@ msgstr "" "Preferred-Encodings: utf-8\n" "Domain: volto\n" "X-Is-Fallback-For: es-ar es-bo es-cl es-co es-cr es-do es-ec es-es es-sv es-gt es-hn es-mx es-ni es-pa es-py es-pe es-pr es-us es-uy es-ve\n" + + diff --git a/packages/generator-volto/generators/app/templates/locales/eu/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/eu/LC_MESSAGES/volto.po index 066e3e8de9..984adca72e 100644 --- a/packages/generator-volto/generators/app/templates/locales/eu/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/eu/LC_MESSAGES/volto.po @@ -1,4 +1,4 @@ -# Translation of plone.pot to EU +# Translation of volto.pot to EU msgid "" msgstr "" "Project-Id-Version: Plone\n" @@ -15,3 +15,5 @@ msgstr "" "Language-Code: eu\n" "Language-Name: eu\n" "Preferred-Encodings: utf-8 latin1\n" + + diff --git a/packages/generator-volto/generators/app/templates/locales/fr/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/fr/LC_MESSAGES/volto.po index afed0b8a27..f6050e4530 100644 --- a/packages/generator-volto/generators/app/templates/locales/fr/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/fr/LC_MESSAGES/volto.po @@ -1,13 +1,4 @@ -# Translation of plone.pot to French -# French Translation Team , 2003-2006. -# Sebastien Douche , 2005-2007. -# Encolpe Degoute , 2006, 2007, 2008. -# Gilles Lenfant , 2008. -# Encolpe Degoute , 2008. -# Vincent Fretin , 2009. -# Kevin Deldycke , 2009. -# JeanMichel FRANCOIS , 2010. -# Denis Bitouzé , 2019. +# Translation of volto.pot to French msgid "" msgstr "" "Project-Id-Version: Plone\n" @@ -25,3 +16,5 @@ msgstr "" "Language-Name: French\n" "Preferred-Encodings: utf-8 latin1\n" "X-Is-Fallback-For: fr-be fr-ca fr-lu fr-mc fr-ch fr-fr\n" + + diff --git a/packages/generator-volto/generators/app/templates/locales/it/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/it/LC_MESSAGES/volto.po index fbc3cc0274..12b9a47628 100644 --- a/packages/generator-volto/generators/app/templates/locales/it/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/it/LC_MESSAGES/volto.po @@ -10,3 +10,5 @@ msgstr "" "Content-Type: \n" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" + + diff --git a/packages/generator-volto/generators/app/templates/locales/ja/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/ja/LC_MESSAGES/volto.po index 3b04a25584..a543785fbf 100644 --- a/packages/generator-volto/generators/app/templates/locales/ja/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/ja/LC_MESSAGES/volto.po @@ -1,5 +1,3 @@ -# Manabu TERADA 2019 -# Peacock 2019 msgid "" msgstr "" "Project-Id-Version: Plone\n" @@ -17,3 +15,5 @@ msgstr "" "Language-Name: Japanese\n" "Preferred-Encodings: utf-8\n" "X-Is-Fallback-For: ja-jp\n" + + diff --git a/packages/generator-volto/generators/app/templates/locales/nl/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/nl/LC_MESSAGES/volto.po index 1a240e59ff..a9816b4cea 100644 --- a/packages/generator-volto/generators/app/templates/locales/nl/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/nl/LC_MESSAGES/volto.po @@ -1,18 +1,3 @@ -# Translators: -# Fred van Dijk , 2016 -# Coen van der Kamp , 2015 -# Danny Bloemendaal , 2007 -# Diederik Veeze , 2015 -# Duco Dokter , 2007 -# Esther Ladage , 2005 -# Jean-Paul Ladage , 2017 -# Kees Hink , 2010 -# Maarten Kling , 2013 -# Mark van Lent , 2007 -# Mirella van Teulingen , 2005 -# Reinout van Rees , 2008 -# Roel Bruggink , 2009 -# Wietze Helmantel , 2007 msgid "" msgstr "" "Project-Id-Version: PlonenPOT-Creation-Date: 2017-04-27T19:30:59.079Z\n" diff --git a/packages/generator-volto/generators/app/templates/locales/pt/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/pt/LC_MESSAGES/volto.po index 84ccaf6942..3713b40e7d 100644 --- a/packages/generator-volto/generators/app/templates/locales/pt/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/pt/LC_MESSAGES/volto.po @@ -1,6 +1,3 @@ -# Translators: -# Emanuel de Jesus , 2019 -# msgid "" msgstr "" "Project-Id-Version: Plone\n" @@ -18,3 +15,5 @@ msgstr "" "Language-Code: pt\n" "Language-Name: Portuguese\n" "Preferred-Encodings: utf-8\n" + + diff --git a/packages/generator-volto/generators/app/templates/locales/pt_BR/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/pt_BR/LC_MESSAGES/volto.po index 2895094452..d788679fdc 100644 --- a/packages/generator-volto/generators/app/templates/locales/pt_BR/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/pt_BR/LC_MESSAGES/volto.po @@ -1,5 +1,3 @@ -# Translators: -# Léu Almeida , 2019 msgid "" msgstr "" "Project-Id-Version: Plone\n" @@ -16,3 +14,5 @@ msgstr "" "Language-Code: pt-br\n" "Language-Name: Português do Brasil\n" "Preferred-Encodings: utf-8\n" + + diff --git a/packages/generator-volto/generators/app/templates/locales/ro/LC_MESSAGES/volto.po b/packages/generator-volto/generators/app/templates/locales/ro/LC_MESSAGES/volto.po index 8ad5875b09..42c60f4d17 100644 --- a/packages/generator-volto/generators/app/templates/locales/ro/LC_MESSAGES/volto.po +++ b/packages/generator-volto/generators/app/templates/locales/ro/LC_MESSAGES/volto.po @@ -1,5 +1,3 @@ -# Translation of plone.pot to Romanian -# Alin Voinea , 2020. msgid "" msgstr "" "Project-Id-Version: Plone\n" diff --git a/packages/generator-volto/generators/app/templates/locales/volto.pot b/packages/generator-volto/generators/app/templates/locales/volto.pot index 8ff7bce29b..430c431165 100644 --- a/packages/generator-volto/generators/app/templates/locales/volto.pot +++ b/packages/generator-volto/generators/app/templates/locales/volto.pot @@ -12,3 +12,5 @@ msgstr "" "Language-Name: English\n" "Preferred-Encodings: utf-8\n" "Domain: volto\n" + + diff --git a/packages/generator-volto/news/4737.bugfix b/packages/generator-volto/news/4737.bugfix new file mode 100644 index 0000000000..e229208dff --- /dev/null +++ b/packages/generator-volto/news/4737.bugfix @@ -0,0 +1 @@ +Fix whitespace in empty locales created by the generator. @davisagli From 52b758874710893ebc40a7e9d8b228e7d7fe6971 Mon Sep 17 00:00:00 2001 From: nilootpal Date: Sat, 6 May 2023 20:34:02 +0530 Subject: [PATCH 137/142] Closes issue #4567 (#4570) Co-authored-by: Steve Piercy --- news/4567.internal | 2 ++ src/components/theme/Icon/Icon.jsx | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 news/4567.internal diff --git a/news/4567.internal b/news/4567.internal new file mode 100644 index 0000000000..05b356b1c6 --- /dev/null +++ b/news/4567.internal @@ -0,0 +1,2 @@ +Change conditional checking to optional chaining for a theme icon @nilootpal + diff --git a/src/components/theme/Icon/Icon.jsx b/src/components/theme/Icon/Icon.jsx index bf0fc2e872..47c688a38e 100644 --- a/src/components/theme/Icon/Icon.jsx +++ b/src/components/theme/Icon/Icon.jsx @@ -44,8 +44,8 @@ const Icon = ({ ariaHidden, }) => ( Date: Tue, 9 May 2023 18:44:47 +0530 Subject: [PATCH 138/142] added documentation regarding the static middleware #4518 (#4736) Co-authored-by: Steve Piercy --- docs/source/recipes/express.md | 71 +++++++++++++++++++++++++++++++++- news/4518.documentation | 1 + 2 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 news/4518.documentation diff --git a/docs/source/recipes/express.md b/docs/source/recipes/express.md index 9c15e107f8..0195efb933 100644 --- a/docs/source/recipes/express.md +++ b/docs/source/recipes/express.md @@ -45,6 +45,75 @@ if (__SERVER__) { Now the [test-middleware](http://localhost:3000/test-middleware) page can be visited and it will return the simple string and not the usual Volto pages. +## Static middleware + +The `staticMiddleware` is for serving static files such as style sheets and client-side JavaScript files from the `BUILD_DIR/PUBLIC` or `PUBLIC_DIR` directory. +It uses the `express.static()` function to serve static files, and the `setHeaders()` function to add response headers to the files that it serves. + +```js +import { settings as defaultSettings } from '@plone/volto/config'; +import express from 'express'; + +const settings = { ...defaultSettings }; +if (__SERVER__) { + const customStaticMiddleware = express.static('test/static/files'); + + function setCustomHeaders(req, res, next) { + res.setHeader('Cache-Control', 'public, max-age=3600'); + next(); + } + + customStaticMiddleware.setHeaders = setCustomHeaders; + customStaticMiddleware.id = 'custom-static-middleware'; + + settings.expressMiddleware = [ + ...defaultSettings.expressMiddleware, + customStaticMiddleware, + ]; +} +``` + +### Function `setHeaders(path)` + +The `setHeaders()` function is used to update the response headers for a file. +It takes the path of the file being served as an argument, and adds the response headers to that file. +It uses the `config` object specified in `config.settings.serverConfig.staticFiles` to determine which response headers should be added to the file. + +### Configuration + +The `config.settings.staticFiles` is an array of objects with three properties: + +`id` +: a string identifier for the static file rule + +`match` +: a regular expression that evaluates the path of the requested resource + +`headers` +: an object containing the headers added if the match is successful + +The following example shows how to add the response header `Cache-Control: public, max-age=3600` to a file named {file}`styles.css` located in the `BUILD_DIR/PUBLIC` directory: + +```js +import { + settings as defaultSettings, +} from '@plone/volto/config'; + +const settings = { ...defaultSettings }; +settings.staticFiles = [ + ...defaultSettings.staticFiles, { + id: 'styles_css', + match: /^\/styles\.css$/, + headers: { + 'Cache-Control': 'public, max-age=3600', + }, + } +] +``` + +The rules are checked in sequential order, and the search stops at the first match. +The default rules add headers that set the browser cache to 365 days for resources under the `/static` path and 60 seconds for all other paths. + Notice the use of the ``__SERVER__`` condition. Because the code in a Volto project's ``config.js`` gets executed by both the server and the client (browser), the server-side libraries need to "excluded" with conditions. @@ -54,4 +123,4 @@ See [ExpressJS](https://expressjs.com/) website for more documentation. ```{note} Addon authors should add the ``id`` property to the middleware so that it can be identified and manipulated in Volto projects configuration. -``` +``` \ No newline at end of file diff --git a/news/4518.documentation b/news/4518.documentation new file mode 100644 index 0000000000..cb7f8b7a28 --- /dev/null +++ b/news/4518.documentation @@ -0,0 +1 @@ +Added documentation regarding the static middleware. @BhardwajAditya-github \ No newline at end of file From 104b80e4dfc0eceee77e8b85a7c94bd18d971931 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Wed, 10 May 2023 03:23:24 -0700 Subject: [PATCH 139/142] Fix link in Volto, remove from linkcheck ignore in Documentation v6.0 (#4742) --- CHANGELOG.md | 2 +- news/4742.documentation | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 news/4742.documentation diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f3fb8ba73..8295c62725 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -322,7 +322,7 @@ ### Documentation -- Complete teaser docs, add new section in `Blocks`: `Core Blocks developers notes` @sneridagh [#4461](https://github.com/plone/volto/issues/4461) +- Complete teaser docs, add new section in `Blocks`: `Core Blocks developers notes` @sneridagh [#4461](https://github.com/plone/volto/pull/4461) ## 16.14.0 (2023-03-03) diff --git a/news/4742.documentation b/news/4742.documentation new file mode 100644 index 0000000000..a99a3b78c4 --- /dev/null +++ b/news/4742.documentation @@ -0,0 +1 @@ +Fix link in Volto, remove from linkcheck ignore in Documentation. @stevepiercy From c230e7d6632a90b5d2e7616e730217af857ae421 Mon Sep 17 00:00:00 2001 From: dobri1408 <50819975+dobri1408@users.noreply.github.com> Date: Wed, 10 May 2023 17:05:19 +0300 Subject: [PATCH 140/142] (fix):Object.normaliseMail: Cannot read properties of null (#4558) --- news/4558.bugfix | 1 + src/helpers/Url/Url.js | 11 ++++++++--- src/helpers/Url/Url.test.js | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 news/4558.bugfix diff --git a/news/4558.bugfix b/news/4558.bugfix new file mode 100644 index 0000000000..59b2af9e28 --- /dev/null +++ b/news/4558.bugfix @@ -0,0 +1 @@ +(fix):Object.normaliseMail: Cannot read properties of null @dobri1408 diff --git a/src/helpers/Url/Url.js b/src/helpers/Url/Url.js index 3038e4602d..d8795f66f9 100644 --- a/src/helpers/Url/Url.js +++ b/src/helpers/Url/Url.js @@ -280,14 +280,14 @@ export function isTelephone(text) { } export function normaliseMail(email) { - if (email.toLowerCase().startsWith('mailto:')) { + if (email?.toLowerCase()?.startsWith('mailto:')) { return email; } return `mailto:${email}`; } export function normalizeTelephone(tel) { - if (tel.toLowerCase().startsWith('tel:')) { + if (tel?.toLowerCase()?.startsWith('tel:')) { return tel; } return `tel:${tel}`; @@ -310,12 +310,17 @@ export function checkAndNormalizeUrl(url) { res.url = URLUtils.normalizeTelephone(url); } else { //url - if (!res.url.startsWith('/') && !res.url.startsWith('#')) { + if ( + res.url?.length >= 0 && + !res.url.startsWith('/') && + !res.url.startsWith('#') + ) { res.url = URLUtils.normalizeUrl(url); if (!URLUtils.isUrl(res.url)) { res.isValid = false; } } + if (res.url === undefined || res.url === null) res.isValid = false; } return res; } diff --git a/src/helpers/Url/Url.test.js b/src/helpers/Url/Url.test.js index 0c06f89d08..b9e2233004 100644 --- a/src/helpers/Url/Url.test.js +++ b/src/helpers/Url/Url.test.js @@ -14,6 +14,9 @@ import { removeProtocol, addAppURL, expandToBackendURL, + checkAndNormalizeUrl, + normaliseMail, + normalizeTelephone, } from './Url'; beforeEach(() => { @@ -61,6 +64,17 @@ describe('Url', () => { it('return empty string if no url is empty string', () => { expect(getBaseUrl('')).toBe(''); }); + it('return a null/undefined mailto adress ', () => { + expect(normaliseMail(null)).toBe('mailto:null'); + expect(normaliseMail(undefined)).toBe('mailto:undefined'); + }); + it('return a null/undefined telephone number', () => { + expect(normalizeTelephone(null)).toBe('tel:null'); + expect(normalizeTelephone(undefined)).toBe('tel:undefined'); + }); + it('null returns an invalid link', () => { + expect(checkAndNormalizeUrl(null).isValid).toBe(false); + }); }); describe('getView', () => { From 990ce923390f4f00ab78baef5f1965ad1b101588 Mon Sep 17 00:00:00 2001 From: anil rundla <97228857+lord2anil@users.noreply.github.com> Date: Wed, 10 May 2023 19:39:32 +0530 Subject: [PATCH 141/142] Apply suggestion from browser for password field (#4524) Co-authored-by: David Glick --- news/3990.bugfix | 1 + src/components/theme/Login/Login.jsx | 1 + src/components/theme/Login/__snapshots__/Login.test.jsx.snap | 1 + 3 files changed, 3 insertions(+) create mode 100644 news/3990.bugfix diff --git a/news/3990.bugfix b/news/3990.bugfix new file mode 100644 index 0000000000..fed2312d0f --- /dev/null +++ b/news/3990.bugfix @@ -0,0 +1 @@ +Apply suggestion from browser for password field @lord2anil \ No newline at end of file diff --git a/src/components/theme/Login/Login.jsx b/src/components/theme/Login/Login.jsx index 8689580e58..90f22acce7 100644 --- a/src/components/theme/Login/Login.jsx +++ b/src/components/theme/Login/Login.jsx @@ -239,6 +239,7 @@ class Login extends Component {
    Date: Wed, 10 May 2023 19:54:15 +0530 Subject: [PATCH 142/142] fix: unresponsive add page (#4507) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Steve Piercy Co-authored-by: Víctor Fernández de Alba --- news/4506.bugfix | 1 + theme/themes/pastanaga/extras/sidebar.less | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 news/4506.bugfix diff --git a/news/4506.bugfix b/news/4506.bugfix new file mode 100644 index 0000000000..9e1c31dbf3 --- /dev/null +++ b/news/4506.bugfix @@ -0,0 +1 @@ +The tabs for the add page was unresponsive on mobile devices. Fixed this by changing flex-wrap property. @sudhanshu1309 diff --git a/theme/themes/pastanaga/extras/sidebar.less b/theme/themes/pastanaga/extras/sidebar.less index 3310cd779c..f34c08476a 100644 --- a/theme/themes/pastanaga/extras/sidebar.less +++ b/theme/themes/pastanaga/extras/sidebar.less @@ -489,3 +489,7 @@ margin-left: 5px; } } + +.formtabs { + flex-wrap: wrap; +}