diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 987ac42c7c..20ddb58092 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,12 +17,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10'] + python-version: ['3.12'] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: 'pip' diff --git a/.github/workflows/readme-link-check.yml b/.github/workflows/readme-link-check.yml index 82f938140f..41b0b13f34 100644 --- a/.github/workflows/readme-link-check.yml +++ b/.github/workflows/readme-link-check.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby 3.2 uses: ruby/setup-ruby@v1 with: diff --git a/apps/plone/package.json b/apps/plone/package.json index b14ff7d6c9..0fa1eae05c 100644 --- a/apps/plone/package.json +++ b/apps/plone/package.json @@ -141,33 +141,44 @@ "@loadable/component": "5.14.1", "@loadable/server": "5.14.0", "@plone/registry": "workspace:*", + "@plone/scripts": "workspace:*", "@plone/volto": "workspace:*", "@plone/volto-slate": "workspace:*", + "@redux-devtools/extension": "^3.3.0", "classnames": "2.2.6", "connected-react-router": "6.8.0", "debug": "4.3.2", + "decorate-component-with-props": "1.2.1", + "dependency-graph": "0.10.0", "detect-browser": "5.1.0", "diff": "3.5.0", "express": "4.17.3", "filesize": "6", "github-slugger": "1.4.0", "history": "4.10.1", + "hoist-non-react-statics": "3.3.2", "http-proxy-middleware": "2.0.1", + "image-extensions": "1.1.0", "immutable": "3", "is-hotkey": "0.2.0", + "is-url": "1.2.4", "jotai": "2.0.3", "jwt-decode": "2.2.0", + "linkify-it": "3.0.2", "locale": "0.1.0", "lodash": "4.17.21", + "lodash-move": "1.1.1", "moment": "2.29.4", + "object-assign": "4.1.1", "prepend-http": "2", "pretty-bytes": "5.3.0", "prismjs": "1.27.0", + "process": "^0.11.10", "promise-file-reader": "1.0.2", "prop-types": "15.7.2", "query-string": "7.1.0", "rc-time-picker": "3.7.3", - "react": "17.0.2", + "react": "18.2.0", "react-anchor-link-smooth-scroll": "1.0.12", "react-animate-height": "2.0.17", "react-beautiful-dnd": "13.0.0", @@ -176,16 +187,16 @@ "react-detect-click-outside": "1.1.1", "react-dnd": "5.0.0", "react-dnd-html5-backend": "5.0.1", - "react-dom": "17.0.2", + "react-dom": "18.2.0", "react-dropzone": "11.1.0", "react-fast-compare": "2.0.4", "react-image-gallery": "1.2.7", "react-intersection-observer": "9.1.0", "react-intl": "3.8.0", - "react-intl-redux": "2.2.0", + "react-intl-redux": "2.3.0", "react-medium-image-zoom": "3.0.15", - "react-portal": "4.2.1", - "react-redux": "7.2.4", + "react-popper": "^2.3.0", + "react-redux": "8.1.2", "react-router": "5.2.0", "react-router-config": "5.1.1", "react-router-dom": "5.2.0", @@ -193,23 +204,22 @@ "react-select": "4.3.1", "react-select-async-paginate": "0.5.3", "react-share": "2.3.1", - "react-side-effect": "2.1.0", + "react-side-effect": "2.1.2", "react-simple-code-editor": "0.7.1", "react-sortable-hoc": "2.0.0", - "react-test-renderer": "17.0.2", - "react-toastify": "5.4.1", + "react-test-renderer": "18.2.0", + "react-toastify": "5.5.0", "react-transition-group": "4.4.5", "react-virtualized": "9.22.3", - "redux": "4.1.0", - "redux-actions": "2.6.5", + "redux": "4.2.1", + "redux-actions": "3.0.0", "redux-connect": "10.0.0", - "@redux-devtools/extension": "^3.3.0", - "redux-localstorage-simple": "2.3.1", + "redux-localstorage-simple": "2.5.1", "redux-mock-store": "1.5.4", - "redux-thunk": "2.3.0", + "redux-thunk": "2.4.2", "rrule": "2.7.1", "semantic-ui-less": "2.4.1", - "semantic-ui-react": "2.0.3", + "semantic-ui-react": "2.1.5", "serialize-javascript": "3.1.0", "slate": "0.100.0", "slate-hyperscript": "0.100.0", @@ -219,36 +229,66 @@ "undoo": "0.5.0", "universal-cookie": "4.0.4", "universal-cookie-express": "4.0.3", + "url": "^0.11.3", "use-deep-compare-effect": "1.8.1", "uuid": "^8.3.2", "volto-volto-project": "workspace:*" }, "devDependencies": { + "@babel/core": "^7.0.0", + "@babel/eslint-parser": "7.22.15", "@babel/plugin-proposal-export-default-from": "7.18.10", "@babel/plugin-proposal-export-namespace-from": "7.18.9", "@babel/plugin-proposal-json-strings": "7.18.6", "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", "@babel/plugin-proposal-throw-expressions": "7.18.6", "@babel/plugin-syntax-export-namespace-from": "7.8.3", + "@babel/runtime": "7.20.6", + "@babel/types": "7.20.5", + "@jest/globals": "^29.7.0", "@loadable/babel-plugin": "5.13.2", "@loadable/webpack-plugin": "5.15.2", "@plone/scripts": "workspace:*", - "@storybook/addon-actions": "^6.3.0", - "@storybook/addon-controls": "6.3.0", - "@storybook/addon-essentials": "^6.3.0", - "@storybook/addon-links": "^6.3.0", + "@plone/types": "workspace:*", + "@plone/volto-coresandbox": "workspace:*", + "@sinonjs/fake-timers": "^6.0.1", + "@storybook/addon-actions": "^6.5.15", + "@storybook/addon-controls": "6.5.15", + "@storybook/addon-docs": "^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.3.0", - "@typescript-eslint/eslint-plugin": "6.7.0", - "@typescript-eslint/parser": "6.7.0", + "@storybook/react": "^6.5.15", + "@testing-library/cypress": "10.0.1", + "@testing-library/jest-dom": "6.4.2", + "@testing-library/react": "14.2.0", + "@testing-library/react-hooks": "8.0.1", + "@types/jest": "^29.5.8", + "@types/lodash": "^4.14.201", + "@types/react": "^18", + "@types/react-dom": "^18", + "@types/react-router-dom": "^5.3.3", + "@types/react-test-renderer": "18.0.7", + "@types/uuid": "^9.0.2", + "@typescript-eslint/eslint-plugin": "7.1.1", + "@typescript-eslint/parser": "7.1.1", "autoprefixer": "10.4.8", + "axe-core": "4.4.2", + "babel-loader": "9.1.0", "babel-plugin-add-module-exports": "0.2.1", "babel-plugin-lodash": "3.3.4", "babel-plugin-react-intl": "5.1.17", "babel-plugin-root-import": "6.1.0", + "babel-preset-razzle": "4.2.18", + "bundlewatch": "0.3.3", + "circular-dependency-plugin": "5.2.2", "css-loader": "5.2.7", - "eslint": "^8.57.0", + "cypress": "13.6.6", + "cypress-axe": "1.5.0", + "cypress-file-upload": "5.0.8", + "deep-freeze": "0.0.1", + "eslint": "8.49.0", "eslint-config-prettier": "9.1.0", "eslint-config-react-app": "7.0.1", "eslint-import-resolver-alias": "1.1.2", @@ -258,10 +298,21 @@ "eslint-plugin-prettier": "5.1.3", "eslint-plugin-react": "7.33.2", "eslint-plugin-react-hooks": "4.6.0", + "full-icu": "1.4.0", "glob": "7.1.6", + "html-webpack-plugin": "5.5.0", + "identity-obj-proxy": "3.0.0", + "jest": "26.6.3", + "jest-environment-jsdom": "^26", + "jest-file": "1.0.0", "jest-junit": "8.0.0", + "jsdom": "^16.7.0", + "jsonwebtoken": "9.0.0", "less": "3.11.1", "less-loader": "11.1.0", + "lodash-webpack-plugin": "0.11.6", + "mini-css-extract-plugin": "2.7.2", + "moment-locales-webpack-plugin": "1.2.0", "mrs-developer": "^2.1.1", "postcss": "8.4.31", "postcss-flexbugs-fixes": "5.0.2", @@ -272,17 +323,33 @@ "postcss-scss": "4.0.6", "prettier": "3.2.5", "razzle": "4.2.18", + "razzle-dev-utils": "4.2.18", + "razzle-plugin-scss": "4.2.18", + "react-docgen-typescript-plugin": "^1.0.5", + "react-error-overlay": "6.0.9", + "react-is": "^18.2.0", + "release-it": "^17.1.1", + "semver": "^7.5.4", "start-server-and-test": "1.14.0", "style-loader": "3.3.1", - "stylelint": "^16.2.1", + "stylelint": "16.2.1", "stylelint-config-idiomatic-order": "10.0.0", "stylelint-prettier": "5.0.0", "svg-loader": "0.0.2", "svgo-loader": "3.0.3", + "terser-webpack-plugin": "5.3.6", + "tmp": "0.2.1", "ts-jest": "^26.4.2", "ts-loader": "9.4.4", "tsconfig": "*", - "typescript": "5.2.2" + "typescript": "5.2.2", + "use-trace-update": "1.3.2", + "wait-on": "6.0.0", + "webpack": "5.76.1", + "webpack-bundle-analyzer": "4.10.1", + "webpack-dev-server": "4.11.1", + "webpack-node-externals": "3.0.0", + "why": "0.6.2" }, "theme": "volto-volto-project" -} +} \ No newline at end of file diff --git a/docs/source/configuration/volto-slate/configuration-settings.md b/docs/source/configuration/volto-slate/configuration-settings.md index 97276b804f..47c388200e 100644 --- a/docs/source/configuration/volto-slate/configuration-settings.md +++ b/docs/source/configuration/volto-slate/configuration-settings.md @@ -253,6 +253,10 @@ You can opt out of this feature by setting its value to `false`. slate.useLinkedHeadings = false ``` +```{versionchanged} Volto 17.0.0-alpha.28 +This feature is still enabled by default, but has a condition to show only for authenticated users. +``` + (editor-configuration-blocks-initialBlocksFocus-label)= ## `blocks.initialBlocksFocus` diff --git a/docs/source/configuration/volto-slate/index.md b/docs/source/configuration/volto-slate/index.md index 98272cf87b..d8f51c4726 100644 --- a/docs/source/configuration/volto-slate/index.md +++ b/docs/source/configuration/volto-slate/index.md @@ -11,7 +11,7 @@ myst: # `volto-slate` -`volto-slate` is an interactive default text editor for Volto, developed on top of {term}`Slate`. +`volto-slate` is an interactive default text editor for Volto, developed on top of {term}`Slate` and integrated into the core system. It offers enhanced WYSIWYG functionality and behavior. See a [brief elevator pitch for `volto-slate`](https://www.youtube.com/watch?v=SOz-rk5e4_w). @@ -23,8 +23,18 @@ Some examples of the kind of strong integration we have in mind: - The text block accepts drag-and-drop images, and it will upload them as Volto image blocks. - `volto-slate` has a {guilabel}`Table` button with the familiar {guilabel}`size` input, but it creates a table block. -Although this add-on is in an early alpha stage, we have solved most of the big issues. -The API has stabilized, and we have already started several add-ons based on it, including [`volto-slate-metadata-mentions`](https://github.com/eea/volto-slate-metadata-mentions/) and [`volto-slate-zotero`](https://github.com/eea/volto-slate-zotero). +The `volto-slate` API has stabilized, and we have already started several add-ons based on it, including [`volto-slate-metadata-mentions`](https://github.com/eea/volto-slate-metadata-mentions/) and [`volto-slate-zotero`](https://github.com/eea/volto-slate-zotero). + +```{versionadded} 16.0.0-alpha.15 +`volto-slate` added to Volto core as the default text block. +``` + +```{deprecated} 16.0.0-alpha.15 +`text` text block based on `draftJS` is now deprecated and will be removed from core in Volto 18. +``` + +To migrate existing projects to `volto-slate`, check the [Upgrade Guide](https://6.docs.plone.org/volto/upgrade-guide/index.html#volto-slate-is-now-in-core) documentation. + (volto-slate-why-another-wysiywg-editor-label)= @@ -53,4 +63,4 @@ Some of the main reasons that drove us to create `volto-slate`, instead of enhan api configuration-settings writing-plugins -``` +``` \ No newline at end of file diff --git a/docs/source/release-notes/index.md b/docs/source/release-notes/index.md index e3e05ba00a..b55351be71 100644 --- a/docs/source/release-notes/index.md +++ b/docs/source/release-notes/index.md @@ -17,6 +17,37 @@ myst: +## 18.0.0-alpha.22 (2024-03-19) + +### Bugfix + +- Correctly sort facet values if they are numbers @erral [#5864](https://github.com/plone/volto/issues/5864) +- Cross-package manager Volto path resolver in `webpack-relative-resolver` @sneridagh [#5893](https://github.com/plone/volto/issues/5893) + +### Documentation + +- `Volto 18.0.0-alpha.21` and `volto-update-deps` documentation @sneridagh [#5892](https://github.com/plone/volto/issues/5892) + +## 18.0.0-alpha.21 (2024-03-18) + +### Breaking + +- Moved `devDependencies` and `dependencies` to where they belong. @sneridagh [#5879](https://github.com/plone/volto/issues/5879) + +### Feature + +- Match props passed to the BlockView if reused from the BlockEdit @sneridagh [#5876](https://github.com/plone/volto/issues/5876) +- Added download link to filename in file widget @sabrina-bongiovanni [#5880](https://github.com/plone/volto/issues/5880) + +### Internal + +- Bump all the versions in GitHub workflows. @stevepiercy [#5873](https://github.com/plone/volto/issues/5873) + +### Documentation + +- Update `volto-slate` configuration documentation to indicate it is now part of Volto core. @MostafaMagdyy [#5342](https://github.com/plone/volto/issues/5342) +- Modified `slate.useLinkedHeadings` documentation to mention feature is disabled for authenticated users after #5225 changes. @ichim-david [#5885](https://github.com/plone/volto/issues/5885) + ## 18.0.0-alpha.20 (2024-03-14) ### Bugfix diff --git a/docs/source/upgrade-guide/index.md b/docs/source/upgrade-guide/index.md index f419bd0e93..620c5ea125 100644 --- a/docs/source/upgrade-guide/index.md +++ b/docs/source/upgrade-guide/index.md @@ -28,6 +28,73 @@ Thus it is safe to run it on top of your project and answer the prompts. ## Upgrading to Volto 18.x.x +### Volto's internal `dependencies` and `devDependencies` are now properly sorted out + +Volto internal `dependencies` and `devDependencies` have been correctly sorted out. +This means that Volto no longer will force `devDependencies` as `dependencies` just to make sure that they get installed in Volto projects. +This provoked undesired hoisting problems, and forced the build to not behave correctly in some situations. +This also aligns with the best practices in the JavaScript world, and will make the packagers work better. + +This change means that your projects will now have to declare all their dependencies. +For this purpose, we have developed a {ref}`new utility ` that synchronizes the `dependencies` and `devDependencies` of your projects with those in Volto core. +It is mandatory that you run the utility to make Volto version 18.0.0-alpha.21 or later work in your projects. +This opens the door to use {term}`pnpm` in projects, too, and other goodies. + +(upgrade-guide-new-dependencies-synchronizer-label)= + +### New dependencies synchronizer + +```{versionadded} 18.0.0-alpha.21 +``` + +```{versionadded} @plone/scripts 3.6.1 +``` + +Volto now has a script to ease the upgrades in Volto projects, called `volto-update-deps`. +It's included as part of the `@plone/scripts` package. +This script synchronizes the local dependencies of your project with those in Volto core. +It preserves your dependencies. + +To run the procedure, in your project's `package.json`, update the `@plone/volto` version to the one to which you want to upgrade, such as `18.0.0-alpha.21`. +Then update the version of `@plone/scripts` to at least version `3.6.1`. +The following example shows the minimum valid versions to use under the `dependencies` key. + +```json +dependencies: { + "@plone/volto": "18.0.0-alpha.21", + "@plone/scripts": "^3.6.1" +} +``` + +Then run `yarn` in your project to update the packages. + +```shell +yarn +``` + +After this, the `volto-update-deps` script will be available in your environment. +Now you can run the script to syncrhonize dependencies: + +```shell +yarn volto-update-deps +``` + +It should synchronize the versions in your project's `dependencies` and `devDependencies` with those in Volto core. +It will add the missing ones, and update the current ones. +It will preserve the existing ones. +It is recommended that you check the resultant changes to assess that everything is fine. +Run yarn again to update the versions. + +```shell +yarn +``` + +Verify that your project works well by running the development server. + +```shell +yarn start +``` + ### Volto runs now on React 18.2.0 We have updated Volto to use React 18. diff --git a/packages/generator-volto/CHANGELOG.md b/packages/generator-volto/CHANGELOG.md index f546772910..cf0371e2ea 100644 --- a/packages/generator-volto/CHANGELOG.md +++ b/packages/generator-volto/CHANGELOG.md @@ -8,6 +8,22 @@ +## 9.0.0-alpha.13 (2024-03-18) + +### Bugfix + +- Improve the generator by getting the `@plone/types` version from GH @sneridagh [#5889](https://github.com/plone/volto/issues/5889) + +## 9.0.0-alpha.12 (2024-03-18) + +### Feature + +- Copy over the `dependencies` and `devDependencies` from Volto in the generated project given the version provided @sneridagh [#5879](https://github.com/plone/volto/issues/5879) + +### Internal + +- Bump @plone/scripts and @plone/types to latests @sneridagh [#5888](https://github.com/plone/volto/issues/5888) + ## 9.0.0-alpha.11 (2024-03-14) ### Bugfix diff --git a/packages/generator-volto/__tests__/test_app.js b/packages/generator-volto/__tests__/test_app.js index ac99fdc044..66377d3e98 100644 --- a/packages/generator-volto/__tests__/test_app.js +++ b/packages/generator-volto/__tests__/test_app.js @@ -11,15 +11,22 @@ jest.mock('https', () => ({ const Stream = require('stream'); let streamStream = new Stream(); cb(streamStream); - - const json = JSON.stringify({ - name: '@plone/volto', - 'dist-tags': { - latest: '16.3.0', - alpha: '16.0.0-alpha.53', - rc: '16.0.0-rc.3', - }, - }); + let json; + if (!url.includes('packages/volto/package.json')) { + json = JSON.stringify({ + name: '@plone/volto', + 'dist-tags': { + latest: '16.3.0', + alpha: '16.0.0-alpha.53', + rc: '16.0.0-rc.3', + }, + }); + } else { + json = JSON.stringify({ + dependencies: {}, + devDependencies: {}, + }); + } streamStream.emit('data', json); streamStream.emit('end'); diff --git a/packages/generator-volto/generators/app/index.js b/packages/generator-volto/generators/app/index.js index 1a52239ebe..db1ddbc563 100644 --- a/packages/generator-volto/generators/app/index.js +++ b/packages/generator-volto/generators/app/index.js @@ -3,6 +3,8 @@ const chalk = require('chalk'); const Generator = require('yeoman-generator'); const _ = require('lodash'); const utils = require('./utils'); +const fs = require('fs'); +const fsp = require('fs').promises; // bring in the deprecated install method from the yeoman-generator/lib/actions/install.js _.extend(Generator.prototype, require('yeoman-generator/lib/actions/install')); @@ -149,8 +151,44 @@ Run "npm install -g @plone/generator-volto" to update.`, let props; + // dependencies + let VoltoPackageJSON; + let PloneTypesVersion; + if (voltoVersion === '*') { + VoltoPackageJSON = JSON.parse( + fs.readFileSync(`packages/volto/package.json`, 'utf8'), + ); + voltoVersion = VoltoPackageJSON.version; + PloneTypesVersion = await utils.getPloneTypesVersion('main'); + } else { + VoltoPackageJSON = await utils.getVoltoPackageJSON(voltoVersion); + PloneTypesVersion = await utils.getPloneTypesVersion(voltoVersion); + } + + const VoltoDependencies = VoltoPackageJSON.dependencies; + const VoltoDevDependencies = VoltoPackageJSON.devDependencies; + const dependencies = { '@plone/volto': voltoVersion, + // TODO: find a better way to specify the version of the core dependencies + // Since they grab "workspace: *" from the volto package.json + '@plone/scripts': '^3.6.0', + ...Object.fromEntries( + Object.entries(VoltoDependencies).filter( + ([key]) => !key.startsWith('@plone'), + ), + ), + }; + + const devDependencies = { + // TODO: find a better way to specify the version of the core devDependencies + // Since they grab "workspace: *" from the volto package.json + '@plone/types': PloneTypesVersion, + ...Object.fromEntries( + Object.entries(VoltoDevDependencies).filter( + ([key]) => !key.startsWith('@plone'), + ), + ), }; // Project name @@ -234,7 +272,16 @@ Run "npm install -g @plone/generator-volto" to update.`, } // Dependencies - this.globals.dependencies = JSON.stringify(dependencies, null, 4); + this.globals.dependencies = JSON.stringify( + utils.orderedDependencies(dependencies), + null, + 4, + ); + this.globals.devDependencies = JSON.stringify( + utils.orderedDependencies(devDependencies), + null, + 4, + ); } writing() { @@ -269,9 +316,13 @@ Run "npm install -g @plone/generator-volto" to update.`, } } - end() { + async end() { const base = currentDir === this.globals.projectName ? '.' : this.globals.projectName; + + // Delete the unfamous "package.json.tpl" + await fsp.unlink(path.join(base, 'package.json.tpl')); + this.composeWith(require.resolve('../addon'), { addonName: this.opts.defaultAddonName ? this.opts.defaultAddonName diff --git a/packages/generator-volto/generators/app/templates/package.json.tpl b/packages/generator-volto/generators/app/templates/package.json.tpl index 584ee5cae9..78daeed5e5 100644 --- a/packages/generator-volto/generators/app/templates/package.json.tpl +++ b/packages/generator-volto/generators/app/templates/package.json.tpl @@ -22,6 +22,7 @@ "cypress:run": "test-acceptance-headless", "start:prod": "NODE_ENV=production node build/server.js", "i18n": "rm -rf build/messages && NODE_ENV=production i18n", + "volto-update-deps": "volto-update-deps", "storybook": "start-storybook -p 6006", "build-storybook": "build-storybook" }, @@ -75,52 +76,7 @@ "node": "^18 || ^20" }, "dependencies": <%- dependencies %>, - "devDependencies": { - "@plone/scripts": "^3.5.0", - "@plone/types": "^1.0.0-alpha.5", - "@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/builder-webpack5": "^6.5.15", - "@storybook/manager-webpack5": "^6.5.15", - "@storybook/react": "^6.3.0", - "@testing-library/cypress": "10.0.1", - "@testing-library/jest-dom": "6.4.2", - "@testing-library/react": "14.2.0", - "@testing-library/react-hooks": "8.0.1", - "@types/jest": "^29.5.8", - "@types/lodash": "^4.14.201", - "@types/react": "^18", - "@types/react-dom": "^18", - "@types/react-router-dom": "^5.3.3", - "@types/uuid": "^9.0.8", - "@typescript-eslint/eslint-plugin": "7.2.0", - "@typescript-eslint/parser": "7.2.0", - "cypress": "13.6.6", - "cypress-axe": "1.5.0", - "cypress-file-upload": "5.0.8", - "eslint": "8.49.0", - "eslint-config-prettier": "9.1.0", - "eslint-config-react-app": "7.0.1", - "eslint-import-resolver-alias": "1.1.2", - "eslint-plugin-import": "2.29.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-prettier": "5.1.3", - "eslint-plugin-react": "7.33.2", - "eslint-plugin-react-hooks": "4.6.0", - "jest-junit": "8.0.0", - "mrs-developer": "^2.1.1", - "postcss": "8.4.13", - "prettier": "3.2.5", - "razzle": "4.2.18", - "stylelint": "^16.2.1", - "stylelint-config-idiomatic-order": "10.0.0", - "stylelint-prettier": "5.0.0", - "ts-jest": "^26.4.2", - "ts-loader": "9.4.4", - "typescript": "5.4.2" - }, + "devDependencies": <%- devDependencies %>, "resolutions": { "@pmmmwh/react-refresh-webpack-plugin": "0.5.11", "react-error-overlay": "6.0.9", diff --git a/packages/generator-volto/generators/app/utils.js b/packages/generator-volto/generators/app/utils.js index dd130de45f..09b78e5212 100644 --- a/packages/generator-volto/generators/app/utils.js +++ b/packages/generator-volto/generators/app/utils.js @@ -88,8 +88,60 @@ async function getLatestCanaryVoltoVersion() { }); } +async function getVoltoPackageJSON(tag) { + const url = `https://raw.githubusercontent.com/plone/volto/${tag}/packages/volto/package.json`; + const requestContent = await new Promise((resolve, reject) => { + https + .get(url, {}, (resp) => { + let data = ''; + resp.on('data', (chunk) => { + data += chunk; + }); + resp.on('end', () => { + resolve(data); + }); + }) + .on('error', (err) => { + reject(err); + }); + }); + return JSON.parse(requestContent); +} + +async function getPloneTypesVersion(tag) { + const url = `https://raw.githubusercontent.com/plone/volto/${tag}/packages/types/package.json`; + const requestContent = await new Promise((resolve, reject) => { + https + .get(url, {}, (resp) => { + let data = ''; + resp.on('data', (chunk) => { + data += chunk; + }); + resp.on('end', () => { + resolve(data); + }); + }) + .on('error', (err) => { + reject(err); + }); + }); + return JSON.parse(requestContent).version; +} + +function orderedDependencies(dependencies) { + return Object.keys(dependencies) + .sort() + .reduce((obj, key) => { + obj[key] = dependencies[key]; + return obj; + }, {}); +} + module.exports = { getLatestVoltoVersion, getLatestCanaryVoltoVersion, getVoltoYarnLock, + getVoltoPackageJSON, + getPloneTypesVersion, + orderedDependencies, }; diff --git a/packages/generator-volto/package.json b/packages/generator-volto/package.json index 3526b759d3..171f7a9b71 100644 --- a/packages/generator-volto/package.json +++ b/packages/generator-volto/package.json @@ -10,7 +10,7 @@ } ], "license": "MIT", - "version": "9.0.0-alpha.11", + "version": "9.0.0-alpha.13", "repository": { "type": "git", "url": "git+https://github.com/plone/generator-volto.git" diff --git a/packages/registry/CHANGELOG.md b/packages/registry/CHANGELOG.md index 5d523daeb3..a9328a363e 100644 --- a/packages/registry/CHANGELOG.md +++ b/packages/registry/CHANGELOG.md @@ -8,6 +8,12 @@ +## 1.5.3 (2024-03-19) + +### Bugfix + +- Cross-package manager Volto path resolver in `webpack-relative-resolver` @sneridagh [#5893](https://github.com/plone/volto/issues/5893) + ## 1.5.2 (2024-03-05) ### Bugfix diff --git a/packages/registry/package.json b/packages/registry/package.json index 184d25a6b1..051cf5d9fd 100644 --- a/packages/registry/package.json +++ b/packages/registry/package.json @@ -9,7 +9,7 @@ ], "funding": "https://github.com/sponsors/plone", "license": "MIT", - "version": "1.5.2", + "version": "1.5.3", "repository": { "type": "git", "url": "https://github.com/plone/volto.git" diff --git a/packages/registry/src/addon-registry.js b/packages/registry/src/addon-registry.js index 659ed612e5..29de18b88c 100644 --- a/packages/registry/src/addon-registry.js +++ b/packages/registry/src/addon-registry.js @@ -114,6 +114,7 @@ class AddonConfigurationRegistry { } this.projectRootPath = projectRootPath; + this.isVoltoProject = packageJson.name !== '@plone/volto'; this.voltoPath = packageJson.name === '@plone/volto' ? `${projectRootPath}` diff --git a/packages/scripts/CHANGELOG.md b/packages/scripts/CHANGELOG.md index 7c8924e118..d6b4fdca86 100644 --- a/packages/scripts/CHANGELOG.md +++ b/packages/scripts/CHANGELOG.md @@ -8,6 +8,18 @@ +## 3.6.1 (2024-03-18) + +### Bugfix + +- Fix volto-update-deps script, remove `@plone` packages from the sync @sneridagh [#5889](https://github.com/plone/volto/issues/5889) + +## 3.6.0 (2024-03-18) + +### Feature + +- Added project dependencies sync utility `volto-update-deps`. @sneridagh [#5879](https://github.com/plone/volto/issues/5879) + ## 3.5.0 (2024-03-05) ### Feature diff --git a/packages/scripts/README.md b/packages/scripts/README.md index 7f5d96f47a..e7560313fb 100644 --- a/packages/scripts/README.md +++ b/packages/scripts/README.md @@ -10,7 +10,29 @@ See https://6.docs.plone.org/volto/development/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. -## changelogupdater +## `volto-update-deps` + +Given an existing project path, `volto-update-deps` updates the Volto `dependencies` and `devDependencies` for the existing Volto (`@plone/volto`) version in the `package.json` file. + +If you are in the process of upgrading your project to a given Volto version, you should update the `package.json` `@plone/volto` dependencies key to use the updated version, then run the script. +The script is included in the `@plone/scripts` package. +You can run it from inside your project's directory root. + +```shell +pnpm exec volto-update-deps . +``` + +Or run it directly from the `.bin` folder. + +```shell +./node_modules/.bin/volto-update-deps.js path/to/my/project +``` + +## Deprecated utilites + +The following utilities are no longer used by core or in projects. + +### changelogupdater It updates the change log according the current defaults in the Volto project. @@ -18,7 +40,7 @@ See how Volto core uses it, along with `release-it`, to automate the release pro https://github.com/plone/volto/blob/4f52bf61062d1e34e3391ed0a36781b8df98a316/package.json#L173-L192 -### Bump +#### Bump Given the version, you can update the first `unreleased` literal. `release-it` provides it as a `version` variable. @@ -26,7 +48,7 @@ Given the version, you can update the first `unreleased` literal. `release-it` p yarn changelogupdater bump ${version} ``` -### Excerpt +#### Excerpt It generates the change log of the version to be released. This is useful when creating the Release information and sending it to GitHub. @@ -34,7 +56,7 @@ It generates the change log of the version to be released. This is useful when c yarn changelogupdater.js excerpt ``` -### Back +#### Back It creates the blank placeholder for the next release. Given the (next) version, it will be added to the placeholder. @@ -42,7 +64,7 @@ It creates the blank placeholder for the next release. Given the (next) version, yarn changelogupdater.js back ${version} ``` -## addon +### addon This script creates and configures a vanilla project using the Volto generator. The project is configured to have the current add-on installed and ready to work with. @@ -63,7 +85,7 @@ The name of the created project is parameterizable. After that you can use the full fledged project, and run any standard Volto command for linting, acceptance test or unit tests. -### clone (git) +#### clone (git) Given the add-on remote git repository, it pulls and configures it into the vanilla project generated by the script. @@ -99,7 +121,7 @@ The idea is to issue commands inside the generated `addon-testing-project` proje Take special care on how to pass down to the `npx` command the current pull request branch. Depending on your CI system, this might be different. -### clone local +#### clone local You can also clone the local add-on using: @@ -109,7 +131,7 @@ npx -p @plone/scripts addon clone . This only works if you execute the command from the root of your add-on directory. -### consolidate +#### consolidate While developing, you might have done changes inside the generated project, and you most probably want to consolidate them, back into the root of the repository. By running this script, it copies over from `addon-testing-project/src/addons/` to the root of your repository. diff --git a/packages/scripts/package.json b/packages/scripts/package.json index a3f9c86e92..a52c30c938 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "3.5.0", + "version": "3.6.1", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" @@ -36,7 +36,8 @@ "bin": { "addon": "./addon/index.js", "changelogupdater": "./changelogupdater.cjs", - "i18n": "./i18n.cjs" + "i18n": "./i18n.cjs", + "volto-update-deps": "./volto-update-deps.js" }, "publishConfig": { "access": "public" diff --git a/packages/scripts/volto-update-deps.js b/packages/scripts/volto-update-deps.js new file mode 100755 index 0000000000..ae6b0f695d --- /dev/null +++ b/packages/scripts/volto-update-deps.js @@ -0,0 +1,120 @@ +#!/usr/bin/env node +/* eslint no-console: 0 */ +import fs from 'fs'; +import https from 'https'; + +function loadPackageJSON(path = '.') { + return JSON.parse(fs.readFileSync(`${path}/package.json`, 'utf8')); +} + +async function getVoltoPackageJSON(tag) { + const url = `https://raw.githubusercontent.com/plone/volto/${tag}/packages/volto/package.json`; + const requestContent = await new Promise((resolve, reject) => { + https + .get(url, {}, (resp) => { + let data = ''; + resp.on('data', (chunk) => { + data += chunk; + }); + resp.on('end', () => { + resolve(data); + }); + }) + .on('error', (err) => { + reject(err); + }); + }); + return JSON.parse(requestContent); +} + +async function getPloneTypesVersion(tag) { + const url = `https://raw.githubusercontent.com/plone/volto/${tag}/packages/types/package.json`; + const requestContent = await new Promise((resolve, reject) => { + https + .get(url, {}, (resp) => { + let data = ''; + resp.on('data', (chunk) => { + data += chunk; + }); + resp.on('end', () => { + resolve(data); + }); + }) + .on('error', (err) => { + reject(err); + }); + }); + return JSON.parse(requestContent).version; +} + +function orderedDependencies(dependencies) { + return Object.keys(dependencies) + .sort() + .reduce((obj, key) => { + obj[key] = dependencies[key]; + return obj; + }, {}); +} + +function updatePackageJSON(path = '.', packageJSON) { + // Replace the dependencies with the ordered version + packageJSON.dependencies = orderedDependencies(packageJSON.dependencies); + // Replace the devDependencies with the ordered version + packageJSON.devDependencies = orderedDependencies( + packageJSON.devDependencies, + ); + + fs.writeFileSync( + `${path}/package.json`, + `${JSON.stringify(packageJSON, null, 2)}`, + ); +} + +async function main() { + const path = process.argv[2]; + const packageJSON = loadPackageJSON(path); + const currentVoltoVersion = packageJSON.dependencies['@plone/volto']; + let voltoPackageJSON; + let ploneTypesVersion; + if (currentVoltoVersion === 'workspace:*') { + voltoPackageJSON = loadPackageJSON('packages/volto'); + ploneTypesVersion = await getPloneTypesVersion('main'); + } else { + voltoPackageJSON = await getVoltoPackageJSON(currentVoltoVersion); + ploneTypesVersion = await getPloneTypesVersion(currentVoltoVersion); + } + + const VoltoDependencies = voltoPackageJSON.dependencies; + const VoltoDevDependencies = voltoPackageJSON.devDependencies; + + // Manually add devDependency on @plone/types + packageJSON.devDependencies['@plone/types'] = ploneTypesVersion; + + Object.entries(VoltoDevDependencies).forEach(([pkg, version]) => { + if (!pkg.startsWith('@plone')) { + if (packageJSON.devDependencies[pkg]) { + packageJSON.devDependencies[pkg] = version; + console.log(`Updated devDependency on ${pkg} to version ${version}`); + } else { + packageJSON.devDependencies[pkg] = version; + console.log(`Added devDependency on ${pkg} to version ${version}`); + } + } + }); + + Object.entries(VoltoDependencies).forEach(([pkg, version]) => { + if (!pkg.startsWith('@plone')) { + if (packageJSON.dependencies[pkg]) { + packageJSON.dependencies[pkg] = version; + console.log(`Updated dependency on ${pkg} to version ${version}`); + } else { + packageJSON.dependencies[pkg] = version; + console.log(`Added dependency on ${pkg} to version ${version}`); + } + } + }); + + updatePackageJSON(path, packageJSON); +} + +main(); diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index 31633e115b..b47f065f4e 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -8,6 +8,12 @@ +## 1.0.0-alpha.7 (2024-03-18) + +### Feature + +- Improve @plone/types - Block*Props and Widgets @sneridagh [#5876](https://github.com/plone/volto/issues/5876) + ## 1.0.0-alpha.6 (2024-03-14) ### Internal diff --git a/packages/types/package.json b/packages/types/package.json index d80c6e474b..6798557a2c 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -9,7 +9,7 @@ ], "funding": "https://github.com/sponsors/plone", "license": "MIT", - "version": "1.0.0-alpha.6", + "version": "1.0.0-alpha.7", "repository": { "type": "git", "url": "https://github.com/plone/volto.git" diff --git a/packages/types/src/blocks/index.d.ts b/packages/types/src/blocks/index.d.ts index fb8893908d..4a367f730c 100644 --- a/packages/types/src/blocks/index.d.ts +++ b/packages/types/src/blocks/index.d.ts @@ -111,4 +111,8 @@ export interface BlockEditProps { path: string; className: string; style: Record<`--${string}`, string>; + content: Content; + history: History; + location: Location; + token: string; } diff --git a/packages/types/src/config/Blocks.d.ts b/packages/types/src/config/Blocks.d.ts index 8df89840e7..b509a274e8 100644 --- a/packages/types/src/config/Blocks.d.ts +++ b/packages/types/src/config/Blocks.d.ts @@ -20,7 +20,6 @@ export interface BlocksConfigData { listing: BlockConfigBase; video: BlockConfigBase; toc: BlockConfigBase; - hero: BlockConfigBase; maps: BlockConfigBase; html: BlockConfigBase; table: BlockConfigBase; @@ -116,6 +115,7 @@ export interface BlockConfigBase { */ // TODO: Improve extensions shape extensions?: Record; + blocksConfig?: Partial; } export type BlockExtension = ( diff --git a/packages/types/src/config/Widgets.d.ts b/packages/types/src/config/Widgets.d.ts index 7be30c7f46..62bd0f1293 100644 --- a/packages/types/src/config/Widgets.d.ts +++ b/packages/types/src/config/Widgets.d.ts @@ -1,7 +1,95 @@ -export type WidgetsConfig = - | { - [key: string]: { - [key: string]: React.ComponentType; - }; - } - | { defaultWidget: React.ComponentType }; +export interface WidgetsConfig { + default: React.ComponentType; + id: { + schema: React.ComponentType; + subjects: React.ComponentType; + query: React.ComponentType; + recurrence: React.ComponentType; + remoteUrl: React.ComponentType; + id: React.ComponentType; + site_logo: React.ComponentType; + }; + widget: { + textarea: React.ComponentType; + datetime: React.ComponentType; + date: React.ComponentType; + password: React.ComponentType; + file: React.ComponentType; + align: React.ComponentType; + buttons: React.ComponentType; + url: React.ComponentType; + internal_url: React.ComponentType; + email: React.ComponentType; + array: React.ComponentType; + token: React.ComponentType; + query: React.ComponentType; + query_sort_on: React.ComponentType; + querystring: React.ComponentType; + object_browser: React.ComponentType; + object: React.ComponentType; + object_list: React.ComponentType; + vocabularyterms: React.ComponentType; + image_size: React.ComponentType; + select_querystring_field: React.ComponentType; + autocomplete: React.ComponentType; + color_picker: React.ComponentType; + select: React.ComponentType; + }; + vocabulary: { + 'plone.app.vocabularies.Catalog': React.ComponentType; + }; + factory: { + 'Relation List': React.ComponentType; + 'Relation Choice': React.ComponentType; + }; + choices: React.ComponentType; + type: { + boolean: React.ComponentType; + array: React.ComponentType; + object: React.ComponentType; + datetime: React.ComponentType; + date: React.ComponentType; + password: React.ComponentType; + number: React.ComponentType; + integer: React.ComponentType; + id: React.ComponentType; + }; + views: { + getWidget: React.ComponentType; + default: React.ComponentType; + id: { + file: React.ComponentType; + image: React.ComponentType; + relatedItems: React.ComponentType; + subjects: React.ComponentType; + }; + widget: { + array: React.ComponentType; + boolean: React.ComponentType; + choices: React.ComponentType; + date: React.ComponentType; + datetime: React.ComponentType; + description: React.ComponentType; + email: React.ComponentType; + file: React.ComponentType; + image: React.ComponentType; + password: React.ComponentType; + relation: React.ComponentType; + relations: React.ComponentType; + richtext: React.ComponentType; + string: React.ComponentType; + tags: React.ComponentType; + textarea: React.ComponentType; + title: React.ComponentType; + url: React.ComponentType; + internal_url: React.ComponentType; + object: React.ComponentType; + }; + vocabulary: {}; + choices: React.ComponentType; + type: { + array: React.ComponentType; + boolean: React.ComponentType; + }; + }; +} diff --git a/packages/volto/CHANGELOG.md b/packages/volto/CHANGELOG.md index e3e05ba00a..b55351be71 100644 --- a/packages/volto/CHANGELOG.md +++ b/packages/volto/CHANGELOG.md @@ -17,6 +17,37 @@ myst: +## 18.0.0-alpha.22 (2024-03-19) + +### Bugfix + +- Correctly sort facet values if they are numbers @erral [#5864](https://github.com/plone/volto/issues/5864) +- Cross-package manager Volto path resolver in `webpack-relative-resolver` @sneridagh [#5893](https://github.com/plone/volto/issues/5893) + +### Documentation + +- `Volto 18.0.0-alpha.21` and `volto-update-deps` documentation @sneridagh [#5892](https://github.com/plone/volto/issues/5892) + +## 18.0.0-alpha.21 (2024-03-18) + +### Breaking + +- Moved `devDependencies` and `dependencies` to where they belong. @sneridagh [#5879](https://github.com/plone/volto/issues/5879) + +### Feature + +- Match props passed to the BlockView if reused from the BlockEdit @sneridagh [#5876](https://github.com/plone/volto/issues/5876) +- Added download link to filename in file widget @sabrina-bongiovanni [#5880](https://github.com/plone/volto/issues/5880) + +### Internal + +- Bump all the versions in GitHub workflows. @stevepiercy [#5873](https://github.com/plone/volto/issues/5873) + +### Documentation + +- Update `volto-slate` configuration documentation to indicate it is now part of Volto core. @MostafaMagdyy [#5342](https://github.com/plone/volto/issues/5342) +- Modified `slate.useLinkedHeadings` documentation to mention feature is disabled for authenticated users after #5225 changes. @ichim-david [#5885](https://github.com/plone/volto/issues/5885) + ## 18.0.0-alpha.20 (2024-03-14) ### Bugfix diff --git a/packages/volto/__tests__/webpack-relative-resolver.test.js b/packages/volto/__tests__/webpack-relative-resolver.test.js index 729b197f55..429946a216 100644 --- a/packages/volto/__tests__/webpack-relative-resolver.test.js +++ b/packages/volto/__tests__/webpack-relative-resolver.test.js @@ -79,8 +79,10 @@ describe('WebpackRelativeResolver', () => { it('handles "installed Volto" resolve requests', () => { const registry = makeRegistry(); - registry.voltoPath = '/myvoltoproject/node_modules/@plone/volto'; + registry.isVoltoProject = true; const resolver = new WebpackRelativeResolver(registry); + resolver.voltoPaths['@plone/volto/'] = + '/myvoltoproject/node_modules/@plone/volto/src'; const req = makeInstalledVoltoRequest(); const resolvePath = resolver.getResolvePath(req); diff --git a/packages/volto/package.json b/packages/volto/package.json index 7b9a7e8df3..45c7c8b12c 100644 --- a/packages/volto/package.json +++ b/packages/volto/package.json @@ -9,7 +9,7 @@ } ], "license": "MIT", - "version": "18.0.0-alpha.20", + "version": "18.0.0-alpha.22", "repository": { "type": "git", "url": "git@github.com:plone/volto.git" @@ -87,6 +87,7 @@ "@plone/volto-slate/(.*)$": "/../volto-slate/src/$1", "@plone/registry": "/../registry/src", "@plone/registry/(.*)$": "/../registry/src/$1", + "@plone/volto": "/src/index.js", "~/config": "/src/config", "~/../locales/${lang}.json": "/locales/en.json", "(.*)/locales/(.*)": "/locales/$2", @@ -175,102 +176,44 @@ "node": "^16 || ^18 || ^20" }, "dependencies": { - "@babel/core": "^7.0.0", - "@babel/eslint-parser": "7.22.15", - "@babel/plugin-proposal-export-default-from": "7.18.10", - "@babel/plugin-proposal-export-namespace-from": "7.18.9", - "@babel/plugin-proposal-json-strings": "7.18.6", - "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", - "@babel/plugin-proposal-throw-expressions": "7.18.6", - "@babel/plugin-syntax-export-namespace-from": "7.8.3", - "@babel/runtime": "7.20.6", - "@babel/types": "7.20.5", - "@loadable/babel-plugin": "5.13.2", "@loadable/component": "5.14.1", "@loadable/server": "5.14.0", - "@loadable/webpack-plugin": "5.15.2", "@plone/registry": "workspace:*", "@plone/scripts": "workspace:*", "@plone/volto-slate": "workspace:*", "@redux-devtools/extension": "^3.3.0", - "@types/react": "^18.2.57", - "@types/react-dom": "^18.2.19", - "autoprefixer": "10.4.8", - "axe-core": "4.4.2", - "babel-plugin-add-module-exports": "0.2.1", - "babel-plugin-lodash": "3.3.4", - "babel-plugin-react-intl": "5.1.17", - "babel-plugin-root-import": "6.1.0", - "babel-preset-razzle": "4.2.18", - "circular-dependency-plugin": "5.2.2", "classnames": "2.2.6", - "commander": "8.2.0", "connected-react-router": "6.8.0", - "crypto-random-string": "3.2.0", - "css-loader": "5.2.7", "debug": "4.3.2", "decorate-component-with-props": "1.2.1", - "deep-freeze": "0.0.1", "dependency-graph": "0.10.0", "detect-browser": "5.1.0", "diff": "3.5.0", - "eslint": "8.49.0", - "eslint-config-prettier": "9.1.0", - "eslint-config-react-app": "7.0.1", - "eslint-import-resolver-alias": "1.1.2", - "eslint-import-resolver-babel-plugin-root-import": "1.1.1", - "eslint-plugin-import": "2.29.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-prettier": "5.1.3", - "eslint-plugin-react": "7.33.2", - "eslint-plugin-react-hooks": "4.6.0", "express": "4.17.3", "filesize": "6", "github-slugger": "1.4.0", - "glob": "7.1.6", "history": "4.10.1", "hoist-non-react-statics": "3.3.2", - "html-webpack-plugin": "5.5.0", "http-proxy-middleware": "2.0.1", - "identity-obj-proxy": "3.0.0", "image-extensions": "1.1.0", "immutable": "3", "is-hotkey": "0.2.0", "is-url": "1.2.4", - "jest-file": "1.0.0", "jotai": "2.0.3", "jwt-decode": "2.2.0", - "less": "3.11.1", - "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.6", - "mini-css-extract-plugin": "2.7.2", "moment": "2.29.4", - "moment-locales-webpack-plugin": "1.2.0", "object-assign": "4.1.1", - "pofile": "1.0.10", - "postcss": "8.4.31", - "postcss-flexbugs-fixes": "5.0.2", - "postcss-less": "6.0.0", - "postcss-load-config": "3.1.4", - "postcss-loader": "7.0.2", - "postcss-overrides": "3.1.4", - "postcss-scss": "4.0.6", "prepend-http": "2", - "prettier": "3.2.5", "pretty-bytes": "5.3.0", "prismjs": "1.27.0", "process": "^0.11.10", "promise-file-reader": "1.0.2", "prop-types": "15.7.2", "query-string": "7.1.0", - "razzle": "4.2.18", - "razzle-dev-utils": "4.2.18", - "razzle-plugin-scss": "4.2.18", "rc-time-picker": "3.7.3", "react": "18.2.0", "react-anchor-link-smooth-scroll": "1.0.12", @@ -318,28 +261,28 @@ "slate": "0.100.0", "slate-hyperscript": "0.100.0", "slate-react": "0.98.4", - "start-server-and-test": "1.14.0", - "style-loader": "3.3.1", - "stylelint": "16.2.1", - "stylelint-config-idiomatic-order": "10.0.0", - "stylelint-prettier": "5.0.0", "superagent": "3.8.2", - "svg-loader": "0.0.2", - "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", "url": "^0.11.3", "use-deep-compare-effect": "1.8.1", - "uuid": "^8.3.2", - "webpack": "5.76.1", - "webpack-bundle-analyzer": "4.10.1", - "webpack-dev-server": "4.11.1", - "webpack-node-externals": "3.0.0" + "uuid": "^8.3.2" }, "devDependencies": { + "@babel/core": "^7.0.0", + "@babel/eslint-parser": "7.22.15", + "@babel/plugin-proposal-export-default-from": "7.18.10", + "@babel/plugin-proposal-export-namespace-from": "7.18.9", + "@babel/plugin-proposal-json-strings": "7.18.6", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6", + "@babel/plugin-proposal-throw-expressions": "7.18.6", + "@babel/plugin-syntax-export-namespace-from": "7.8.3", + "@babel/runtime": "7.20.6", + "@babel/types": "7.20.5", + "@loadable/babel-plugin": "5.13.2", + "@loadable/webpack-plugin": "5.15.2", "@jest/globals": "^29.7.0", "@plone/types": "workspace:*", "@plone/volto-coresandbox": "workspace:*", @@ -365,28 +308,78 @@ "@types/uuid": "^9.0.2", "@typescript-eslint/eslint-plugin": "7.1.1", "@typescript-eslint/parser": "7.1.1", + "autoprefixer": "10.4.8", + "axe-core": "4.4.2", "babel-loader": "9.1.0", + "babel-plugin-add-module-exports": "0.2.1", + "babel-plugin-lodash": "3.3.4", + "babel-plugin-react-intl": "5.1.17", + "babel-plugin-root-import": "6.1.0", + "babel-preset-razzle": "4.2.18", "bundlewatch": "0.3.3", + "circular-dependency-plugin": "5.2.2", + "css-loader": "5.2.7", "cypress": "13.6.6", "cypress-axe": "1.5.0", "cypress-file-upload": "5.0.8", + "deep-freeze": "0.0.1", + "eslint": "8.49.0", + "eslint-config-prettier": "9.1.0", + "eslint-config-react-app": "7.0.1", + "eslint-import-resolver-alias": "1.1.2", + "eslint-import-resolver-babel-plugin-root-import": "1.1.1", + "eslint-plugin-import": "2.29.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-prettier": "5.1.3", + "eslint-plugin-react": "7.33.2", + "eslint-plugin-react-hooks": "4.6.0", "full-icu": "1.4.0", + "html-webpack-plugin": "5.5.0", "identity-obj-proxy": "3.0.0", "jest": "26.6.3", "jest-environment-jsdom": "^26", "jsdom": "^16.7.0", + "jest-file": "1.0.0", "jsonwebtoken": "9.0.0", + "less": "3.11.1", + "less-loader": "11.1.0", + "lodash-webpack-plugin": "0.11.6", + "mini-css-extract-plugin": "2.7.2", + "moment-locales-webpack-plugin": "1.2.0", + "postcss": "8.4.31", + "postcss-flexbugs-fixes": "5.0.2", + "postcss-less": "6.0.0", + "postcss-load-config": "3.1.4", + "postcss-loader": "7.0.2", + "postcss-overrides": "3.1.4", + "postcss-scss": "4.0.6", + "prettier": "3.2.5", + "razzle": "4.2.18", + "razzle-dev-utils": "4.2.18", + "razzle-plugin-scss": "4.2.18", "react-docgen-typescript-plugin": "^1.0.5", "react-error-overlay": "6.0.9", "react-is": "^18.2.0", "release-it": "^17.1.1", "semver": "^7.5.4", + "start-server-and-test": "1.14.0", + "style-loader": "3.3.1", + "stylelint": "16.2.1", + "stylelint-config-idiomatic-order": "10.0.0", + "stylelint-prettier": "5.0.0", + "svg-loader": "0.0.2", + "svgo-loader": "3.0.3", + "terser-webpack-plugin": "5.3.6", "tmp": "0.2.1", "ts-jest": "^26.4.2", "ts-loader": "9.4.4", - "typescript": "5.2.2", + "typescript": "^5.4.2", "use-trace-update": "1.3.2", "wait-on": "6.0.0", + "webpack": "5.76.1", + "webpack-bundle-analyzer": "4.10.1", + "webpack-dev-server": "4.11.1", + "webpack-node-externals": "3.0.0", "why": "0.6.2" }, "volta": { diff --git a/packages/volto/src/components/manage/Add/Add.jsx b/packages/volto/src/components/manage/Add/Add.jsx index 536981c360..cf5057267b 100644 --- a/packages/volto/src/components/manage/Add/Add.jsx +++ b/packages/volto/src/components/manage/Add/Add.jsx @@ -394,6 +394,10 @@ class Add extends Component { this.setState({ formSelected: 'addForm' }); }} global + // Properties to pass to the BlocksForm to match the View ones + history={this.props.history} + location={this.props.location} + token={this.props.token} /> {this.state.isClient && createPortal( diff --git a/packages/volto/src/components/manage/Blocks/Block/BlocksForm.jsx b/packages/volto/src/components/manage/Blocks/Block/BlocksForm.jsx index 22fb0b176f..0424a307bc 100644 --- a/packages/volto/src/components/manage/Blocks/Block/BlocksForm.jsx +++ b/packages/volto/src/components/manage/Blocks/Block/BlocksForm.jsx @@ -48,6 +48,9 @@ const BlocksForm = (props) => { blocksConfig = config.blocks.blocksConfig, editable = true, direction = 'vertical', + history, + location, + token, } = props; const blockList = getBlocks(properties); @@ -271,6 +274,11 @@ const BlocksForm = (props) => { editable, showBlockChooser: selectedBlock === childId, detached: isContainer, + // Properties to pass to the BlocksForm to match the View ones + content: properties, + history, + location, + token, }; return editBlockWrapper( dragProps, diff --git a/packages/volto/src/components/manage/Blocks/Search/components/Facets.jsx b/packages/volto/src/components/manage/Blocks/Search/components/Facets.jsx index 28ecc0c636..2995896a10 100644 --- a/packages/volto/src/components/manage/Blocks/Search/components/Facets.jsx +++ b/packages/volto/src/components/manage/Blocks/Search/components/Facets.jsx @@ -22,6 +22,18 @@ const defaultShowFacet = (index) => { : values && Object.keys(values).length > 0; }; +export const sortFacetChoices = (choices) => { + const sorted_choices = choices.sort((a, b) => + typeof a.label === 'string' && typeof b.label === 'string' + ? a.label.localeCompare(b.label, 'en', { sensitivity: 'base' }) + : typeof a.label === 'number' && typeof b.label == 'number' + ? a.label - b.label + : 0, + ); + + return sorted_choices; +}; + const Facets = (props) => { const [hidden, setHidden] = useState(true); const { @@ -81,9 +93,7 @@ const Facets = (props) => { : true, ); - choices = choices.sort((a, b) => - a.label.localeCompare(b.label, 'en', { sensitivity: 'base' }), - ); + choices = sortFacetChoices(choices); const isMulti = facetSettings.multiple; const selectedValue = facets[facetSettings?.field?.value]; diff --git a/packages/volto/src/components/manage/Blocks/Search/components/Facets.test.jsx b/packages/volto/src/components/manage/Blocks/Search/components/Facets.test.jsx new file mode 100644 index 0000000000..7ff7067300 --- /dev/null +++ b/packages/volto/src/components/manage/Blocks/Search/components/Facets.test.jsx @@ -0,0 +1,76 @@ +import { sortFacetChoices } from './Facets'; + +describe('sortFacetChoices', () => { + it('sort choices with string labels', () => { + const choices = [ + { label: 'b' }, + { label: 'd' }, + { label: 'a' }, + { label: 'c' }, + ]; + const sortedChoices = sortFacetChoices(choices); + expect(sortedChoices).toStrictEqual([ + { label: 'a' }, + { label: 'b' }, + { label: 'c' }, + { label: 'd' }, + ]); + }); + it('sort choices with string labels with accents (1)', () => { + const choices = [ + { label: 'éventa' }, + { label: 'portal' }, + { label: 'newsitem' }, + { label: 'eventb' }, + ]; + const sortedChoices = sortFacetChoices(choices); + expect(sortedChoices).toStrictEqual([ + { label: 'éventa' }, + { label: 'eventb' }, + { label: 'newsitem' }, + { label: 'portal' }, + ]); + }); + + it('sort choices with string labels with accents (2)', () => { + const choices = [ + { label: 'eventa' }, + { label: 'portal' }, + { label: 'newsitem' }, + { label: 'éventb' }, + ]; + const sortedChoices = sortFacetChoices(choices); + expect(sortedChoices).toStrictEqual([ + { label: 'eventa' }, + { label: 'éventb' }, + { label: 'newsitem' }, + { label: 'portal' }, + ]); + }); + + it('sort choices with int labels', () => { + const choices = [{ label: 7 }, { label: 3 }, { label: 1 }, { label: 4 }]; + const sortedChoices = sortFacetChoices(choices); + expect(sortedChoices).toStrictEqual([ + { label: 1 }, + { label: 3 }, + { label: 4 }, + { label: 7 }, + ]); + }); + it('sort choices with labels of any kind', () => { + const choices = [ + { label: 7 }, + { label: '1' }, + { label: 'b' }, + { label: 5 }, + ]; + const sortedChoices = sortFacetChoices(choices); + expect(sortedChoices).toStrictEqual([ + { label: 7 }, + { label: '1' }, + { label: 'b' }, + { label: 5 }, + ]); + }); +}); diff --git a/packages/volto/src/components/manage/Edit/Edit.jsx b/packages/volto/src/components/manage/Edit/Edit.jsx index bf27da632d..38e2c6474a 100644 --- a/packages/volto/src/components/manage/Edit/Edit.jsx +++ b/packages/volto/src/components/manage/Edit/Edit.jsx @@ -333,6 +333,10 @@ class Edit extends Component { this.setState({ formSelected: 'editForm' }); }} global + // Properties to pass to the BlocksForm to match the View ones + history={this.props.history} + location={this.props.location} + token={this.props.token} /> ); diff --git a/packages/volto/src/components/manage/Form/Form.jsx b/packages/volto/src/components/manage/Form/Form.jsx index 2eff094e47..cdf7209408 100644 --- a/packages/volto/src/components/manage/Form/Form.jsx +++ b/packages/volto/src/components/manage/Form/Form.jsx @@ -719,6 +719,10 @@ class Form extends Component { showRestricted={this.props.showRestricted} editable={this.props.editable} isMainForm={this.props.editable} + // Properties to pass to the BlocksForm to match the View ones + history={this.props.history} + location={this.props.location} + token={this.props.token} /> {this.state.isClient && this.state.sidebarMetadataIsAvailable && diff --git a/packages/volto/src/components/manage/Widgets/FileWidget.jsx b/packages/volto/src/components/manage/Widgets/FileWidget.jsx index 4a717b97de..e35b015cad 100644 --- a/packages/volto/src/components/manage/Widgets/FileWidget.jsx +++ b/packages/volto/src/components/manage/Widgets/FileWidget.jsx @@ -9,7 +9,7 @@ import { Button, Image, Dimmer } from 'semantic-ui-react'; import { readAsDataURL } from 'promise-file-reader'; import { injectIntl } from 'react-intl'; import deleteSVG from '@plone/volto/icons/delete.svg'; -import { Icon, FormFieldWrapper } from '@plone/volto/components'; +import { Icon, FormFieldWrapper, UniversalLink } from '@plone/volto/components'; import loadable from '@loadable/component'; import { flattenToAppURL, validateFileUploadSize } from '@plone/volto/helpers'; import { defineMessages, useIntl } from 'react-intl'; @@ -170,7 +170,11 @@ const FileWidget = (props) => { )}
- {value && value.filename} + {value && ( + + {value.filename} + + )} {value && (