From cf3e82dd4e470b8ea404eeb8effd7f99cbbe46ba Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 23 Mar 2024 18:09:24 +0100
Subject: [PATCH 001/125] File: fix not creating PDF as different format
Fixes #6268
---
src/Cms/FileActions.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Cms/FileActions.php b/src/Cms/FileActions.php
index 890610fe82..fb3b943ece 100644
--- a/src/Cms/FileActions.php
+++ b/src/Cms/FileActions.php
@@ -139,8 +139,8 @@ public function changeTemplate(string|null $template): static
// rename and/or resize the file if configured by new blueprint
$create = $file->blueprint()->create();
+ $file = $file->manipulate($create);
$file = $file->changeExtension($file, $create['format'] ?? null);
- $file->manipulate($create);
return $file;
});
@@ -266,7 +266,6 @@ public static function create(array $props, bool $move = false): File
// we need to already rename it so that the correct file rules
// are applied
$create = $file->blueprint()->create();
- $file = $file->changeExtension($file, $create['format'] ?? null);
// run the hook
$arguments = compact('file', 'upload');
@@ -284,6 +283,7 @@ public static function create(array $props, bool $move = false): File
// resize the file on upload if configured
$file = $file->manipulate($create);
+ $file = $file->changeExtension($file, $create['format'] ?? null);
// store the content if necessary
// (always create files in the default language)
@@ -384,8 +384,8 @@ public function replace(string $source, bool $move = false): static
// apply the resizing/crop options from the blueprint
$create = $file->blueprint()->create();
- $file = $file->changeExtension($file, $create['format'] ?? null);
$file = $file->manipulate($create);
+ $file = $file->changeExtension($file, $create['format'] ?? null);
// return a fresh clone
return $file->clone();
From 47bd0b99eeaca10655ee9cc483dabaf77e932b97 Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Mon, 25 Mar 2024 15:08:18 +0100
Subject: [PATCH 002/125] Fix deprecation warning in router
---
router.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/router.php b/router.php
index 10386c7cc7..c89b72509e 100644
--- a/router.php
+++ b/router.php
@@ -1,7 +1,7 @@
Date: Wed, 27 Mar 2024 11:38:03 +0100
Subject: [PATCH 003/125] Another try
---
router.php | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/router.php b/router.php
index c89b72509e..59d26d211d 100644
--- a/router.php
+++ b/router.php
@@ -1,11 +1,10 @@
Date: Wed, 27 Mar 2024 20:51:27 +0100
Subject: [PATCH 004/125] Add comment
---
router.php | 2 ++
1 file changed, 2 insertions(+)
diff --git a/router.php b/router.php
index 59d26d211d..ea8cc864ca 100644
--- a/router.php
+++ b/router.php
@@ -1,5 +1,7 @@
Date: Sat, 30 Mar 2024 15:33:17 +0100
Subject: [PATCH 005/125] New text vertical align icons
---
panel/public/img/icons.svg | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/panel/public/img/icons.svg b/panel/public/img/icons.svg
index 950867ee6e..0da75ac7f1 100644
--- a/panel/public/img/icons.svg
+++ b/panel/public/img/icons.svg
@@ -406,24 +406,16 @@
-
-
-
+
-
-
-
+
-
-
-
+
-
-
-
+
@@ -578,6 +570,15 @@
+
+
+
+
+
+
+
+
+
From cc395c0af2dc25e64c4584fdef6a32fbc0e8955f Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 6 Apr 2024 15:00:52 +0200
Subject: [PATCH 006/125] Editor: add `insertNode` util
---
panel/src/components/Forms/Writer/Nodes/HardBreak.js | 5 +----
.../src/components/Forms/Writer/Nodes/HorizontalRule.js | 5 ++---
panel/src/components/Forms/Writer/Utils/index.js | 2 ++
panel/src/components/Forms/Writer/Utils/insertNode.js | 9 +++++++++
4 files changed, 14 insertions(+), 7 deletions(-)
create mode 100644 panel/src/components/Forms/Writer/Utils/insertNode.js
diff --git a/panel/src/components/Forms/Writer/Nodes/HardBreak.js b/panel/src/components/Forms/Writer/Nodes/HardBreak.js
index dab4d5e5f5..9b146c06d3 100644
--- a/panel/src/components/Forms/Writer/Nodes/HardBreak.js
+++ b/panel/src/components/Forms/Writer/Nodes/HardBreak.js
@@ -6,10 +6,7 @@ export default class HardBreak extends Node {
}
createHardBreak(utils, type) {
- return utils.chainCommands(utils.exitCode, (state, dispatch) => {
- dispatch(state.tr.replaceSelectionWith(type.create()).scrollIntoView());
- return true;
- });
+ return utils.chainCommands(utils.exitCode, utils.insertNode(type));
}
get defaults() {
diff --git a/panel/src/components/Forms/Writer/Nodes/HorizontalRule.js b/panel/src/components/Forms/Writer/Nodes/HorizontalRule.js
index 298e0940d7..13a594a1d4 100644
--- a/panel/src/components/Forms/Writer/Nodes/HorizontalRule.js
+++ b/panel/src/components/Forms/Writer/Nodes/HorizontalRule.js
@@ -1,9 +1,8 @@
import Node from "../Node";
export default class HorizontalRule extends Node {
- commands({ type }) {
- return () => (state, dispatch) =>
- dispatch(state.tr.replaceSelectionWith(type.create()));
+ commands({ type, utils }) {
+ return () => utils.insertNode(type);
}
inputRules({ type, utils }) {
diff --git a/panel/src/components/Forms/Writer/Utils/index.js b/panel/src/components/Forms/Writer/Utils/index.js
index e3c7f2bb77..e4f09ea93a 100644
--- a/panel/src/components/Forms/Writer/Utils/index.js
+++ b/panel/src/components/Forms/Writer/Utils/index.js
@@ -25,6 +25,7 @@ import {
// custom
import getMarkAttrs from "./getMarkAttrs";
import getNodeAttrs from "./getNodeAttrs";
+import insertNode from "./insertNode";
import markInputRule from "./markInputRule";
import markIsActive from "./markIsActive";
import markPasteRule from "./markPasteRule";
@@ -61,6 +62,7 @@ export default {
// custom
getMarkAttrs,
getNodeAttrs,
+ insertNode,
markInputRule,
markIsActive,
markPasteRule,
diff --git a/panel/src/components/Forms/Writer/Utils/insertNode.js b/panel/src/components/Forms/Writer/Utils/insertNode.js
new file mode 100644
index 0000000000..01eeb53a66
--- /dev/null
+++ b/panel/src/components/Forms/Writer/Utils/insertNode.js
@@ -0,0 +1,9 @@
+export default function insertNode(type, attrs, content, marks) {
+ return (state, dispatch) => {
+ dispatch(
+ state.tr
+ .replaceSelectionWith(type.create(attrs, content, marks))
+ .scrollIntoView()
+ );
+ };
+}
From 44f606439c379ec295cd81803e6544ba3f8e47e7 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 6 Apr 2024 19:11:18 +0200
Subject: [PATCH 007/125] Fix `nodeInputRule`
---
.../components/Forms/Writer/Nodes/HorizontalRule.js | 10 +++++++++-
.../src/components/Forms/Writer/Utils/nodeInputRule.js | 2 +-
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/panel/src/components/Forms/Writer/Nodes/HorizontalRule.js b/panel/src/components/Forms/Writer/Nodes/HorizontalRule.js
index 298e0940d7..a60b5505f3 100644
--- a/panel/src/components/Forms/Writer/Nodes/HorizontalRule.js
+++ b/panel/src/components/Forms/Writer/Nodes/HorizontalRule.js
@@ -7,7 +7,15 @@ export default class HorizontalRule extends Node {
}
inputRules({ type, utils }) {
- return [utils.nodeInputRule(/^(?:---|___\s|\*\*\*\s)$/, type)];
+ // create regular input rule for horizontal rule
+ const rule = utils.nodeInputRule(/^(?:---|___\s|\*\*\*\s)$/, type);
+
+ // extend handler to remove the leftover empty line
+ const handler = rule.handler;
+ rule.handler = (state, match, start, end) =>
+ handler(state, match, start, end).replaceWith(start - 1, start, "");
+
+ return [rule];
}
get name() {
diff --git a/panel/src/components/Forms/Writer/Utils/nodeInputRule.js b/panel/src/components/Forms/Writer/Utils/nodeInputRule.js
index 067d903cde..2352238e6a 100644
--- a/panel/src/components/Forms/Writer/Utils/nodeInputRule.js
+++ b/panel/src/components/Forms/Writer/Utils/nodeInputRule.js
@@ -6,7 +6,7 @@ export default function (regexp, type, getAttrs) {
const { tr } = state;
if (match[0]) {
- tr.replaceWith(start - 1, end, type.create(attrs));
+ tr.replaceWith(start, end, type.create(attrs));
}
return tr;
From 8fd14c847f9faa1558aca16fa650e80c50a9d49a Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 6 Apr 2024 21:59:27 +0200
Subject: [PATCH 008/125] Writer: fix nodes for `inline: true`
---
panel/src/components/Forms/Writer/Writer.vue | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/panel/src/components/Forms/Writer/Writer.vue b/panel/src/components/Forms/Writer/Writer.vue
index 4063da1402..fe529bf28e 100644
--- a/panel/src/components/Forms/Writer/Writer.vue
+++ b/panel/src/components/Forms/Writer/Writer.vue
@@ -285,11 +285,6 @@ export default {
enter: this.inline
});
- // inline fields only get the hard break
- if (this.inline === true) {
- return [hardBreak];
- }
-
return this.filterExtensions(
{
bulletList: new BulletList(),
@@ -310,6 +305,11 @@ export default {
installed.push(new ListItem());
}
+ // inline fields should not have non-inline nodes
+ if (this.inline === true) {
+ installed = installed.filter((node) => node.schema.inline === true);
+ }
+
// always install the hard break
installed.push(hardBreak);
From f8000c299fac20a66abe1d8d7ab35ccec7516ffc Mon Sep 17 00:00:00 2001
From: Tobias Leugger
Date: Fri, 12 Apr 2024 11:23:19 +0200
Subject: [PATCH 009/125] Update searches.php: Fixing panel search when uuids
are disabled
---
config/areas/site/searches.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/areas/site/searches.php b/config/areas/site/searches.php
index 3791ad2f68..4cefefe5ff 100644
--- a/config/areas/site/searches.php
+++ b/config/areas/site/searches.php
@@ -22,7 +22,7 @@
'text' => Escape::html($page->title()->value()),
'link' => $page->panel()->url(true),
'info' => Escape::html($page->id()),
- 'uuid' => $page->uuid()->toString(),
+ 'uuid' => $page->uuid()?->toString(),
]),
'pagination' => $pages->pagination()->toArray()
];
From 578724d016bfe9586a0a9145a398b0d5f38c7b12 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Fri, 12 Apr 2024 16:06:27 +0200
Subject: [PATCH 010/125] Upgrade to eslint 9
---
panel/.eslintrc.js | 20 -
panel/eslint.config.mjs | 28 +
panel/package-lock.json | 481 +++++++++---------
panel/package.json | 20 +-
.../src/components/Dialogs/LicenseDialog.vue | 1 -
panel/src/components/Dialogs/SearchDialog.vue | 2 +-
.../components/Forms/Field/ObjectField.vue | 2 -
panel/src/components/Forms/FormButtons.vue | 2 +-
.../components/Forms/Input/ColornameInput.vue | 2 +-
.../Forms/Writer/Utils/markPasteRule.js | 1 -
.../src/components/Navigation/Pagination.vue | 2 +-
panel/src/components/Views/SearchView.vue | 2 +-
panel/src/helpers/embed.js | 4 +-
panel/src/helpers/link.js | 4 +-
panel/src/helpers/upload.js | 2 +-
panel/src/helpers/url.js | 2 +-
panel/src/store/modules/content.js | 2 +-
17 files changed, 293 insertions(+), 284 deletions(-)
delete mode 100644 panel/.eslintrc.js
create mode 100644 panel/eslint.config.mjs
diff --git a/panel/.eslintrc.js b/panel/.eslintrc.js
deleted file mode 100644
index 4953eb51aa..0000000000
--- a/panel/.eslintrc.js
+++ /dev/null
@@ -1,20 +0,0 @@
-module.exports = {
- extends: ["eslint:recommended", "plugin:vue/recommended", "prettier"],
- rules: {
- "vue/attributes-order": "error",
- "vue/component-definition-name-casing": "off",
- "vue/html-closing-bracket-newline": [
- "error",
- {
- singleline: "never",
- multiline: "always"
- }
- ],
- "vue/multi-word-component-names": "off",
- "vue/require-default-prop": "off",
- "vue/require-prop-types": "error"
- },
- parserOptions: {
- ecmaVersion: 2022
- }
-};
diff --git a/panel/eslint.config.mjs b/panel/eslint.config.mjs
new file mode 100644
index 0000000000..cfe049eadc
--- /dev/null
+++ b/panel/eslint.config.mjs
@@ -0,0 +1,28 @@
+import js from "@eslint/js";
+import prettier from "eslint-config-prettier";
+import vue from "eslint-plugin-vue";
+
+export default [
+ js.configs.recommended,
+ ...vue.configs["flat/vue2-recommended"],
+ prettier,
+ {
+ rules: {
+ "vue/attributes-order": "error",
+ "vue/component-definition-name-casing": "off",
+ "vue/html-closing-bracket-newline": [
+ "error",
+ {
+ singleline: "never",
+ multiline: "always"
+ }
+ ],
+ "vue/multi-word-component-names": "off",
+ "vue/require-default-prop": "off",
+ "vue/require-prop-types": "error"
+ },
+ languageOptions: {
+ ecmaVersion: 2022
+ }
+ }
+];
diff --git a/panel/package-lock.json b/panel/package-lock.json
index 5965e1156e..b85aa61cc7 100644
--- a/panel/package-lock.json
+++ b/panel/package-lock.json
@@ -15,9 +15,9 @@
"prosemirror-history": "^1.4.0",
"prosemirror-inputrules": "^1.4.0",
"prosemirror-keymap": "^1.2.2",
- "prosemirror-model": "^1.19.4",
+ "prosemirror-model": "^1.20.0",
"prosemirror-schema-list": "^1.3.0",
- "prosemirror-view": "^1.33.3",
+ "prosemirror-view": "^1.33.4",
"vue": "^2.7.16",
"vuedraggable": "^2.24.3",
"vuelidate": "^0.7.7",
@@ -25,17 +25,17 @@
},
"devDependencies": {
"@vitejs/plugin-vue2": "^2.3.1",
- "eslint": "^8.57.0",
+ "eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
- "eslint-plugin-vue": "^9.23.0",
- "glob": "^10.3.10",
+ "eslint-plugin-vue": "^9.24.1",
+ "glob": "^10.3.12",
"jsdom": "^24.0.0",
"prettier": "^3.2.5",
- "rollup-plugin-external-globals": "^0.9.2",
- "terser": "^5.29.2",
- "vite": "^5.2.4",
- "vite-plugin-static-copy": "^1.0.1",
- "vitest": "^1.4.0",
+ "rollup-plugin-external-globals": "^0.10.0",
+ "terser": "^5.30.3",
+ "vite": "^5.2.8",
+ "vite-plugin-static-copy": "^1.0.2",
+ "vitest": "^1.5.0",
"vue-docgen-api": "^4.78.0",
"vue-template-compiler": "^2.7.16"
}
@@ -485,15 +485,15 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
- "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.0.2.tgz",
+ "integrity": "sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.6.0",
- "globals": "^13.19.0",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
@@ -501,28 +501,57 @@
"strip-json-comments": "^3.1.1"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
+ "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/espree": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz",
+ "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.11.3",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@eslint/js": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
- "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.0.0.tgz",
+ "integrity": "sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==",
"dev": true,
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@humanwhocodes/config-array": {
- "version": "0.11.14",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
- "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "version": "0.12.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.12.3.tgz",
+ "integrity": "sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==",
"dev": true,
"dependencies": {
- "@humanwhocodes/object-schema": "^2.0.2",
+ "@humanwhocodes/object-schema": "^2.0.3",
"debug": "^4.3.1",
"minimatch": "^3.0.5"
},
@@ -544,9 +573,9 @@
}
},
"node_modules/@humanwhocodes/object-schema": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
- "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
"dev": true
},
"node_modules/@isaacs/cliui": {
@@ -922,12 +951,6 @@
"undici-types": "~5.26.4"
}
},
- "node_modules/@ungap/structured-clone": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
- "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
- "dev": true
- },
"node_modules/@vitejs/plugin-vue2": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue2/-/plugin-vue2-2.3.1.tgz",
@@ -942,13 +965,13 @@
}
},
"node_modules/@vitest/expect": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.4.0.tgz",
- "integrity": "sha512-Jths0sWCJZ8BxjKe+p+eKsoqev1/T8lYcrjavEaz8auEJ4jAVY0GwW3JKmdVU4mmNPLPHixh4GNXP7GFtAiDHA==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.0.tgz",
+ "integrity": "sha512-0pzuCI6KYi2SIC3LQezmxujU9RK/vwC1U9R0rLuGlNGcOuDWxqWKu6nUdFsX9tH1WU0SXtAxToOsEjeUn1s3hA==",
"dev": true,
"dependencies": {
- "@vitest/spy": "1.4.0",
- "@vitest/utils": "1.4.0",
+ "@vitest/spy": "1.5.0",
+ "@vitest/utils": "1.5.0",
"chai": "^4.3.10"
},
"funding": {
@@ -956,12 +979,12 @@
}
},
"node_modules/@vitest/runner": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.4.0.tgz",
- "integrity": "sha512-EDYVSmesqlQ4RD2VvWo3hQgTJ7ZrFQ2VSJdfiJiArkCerDAGeyF1i6dHkmySqk573jLp6d/cfqCN+7wUB5tLgg==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.0.tgz",
+ "integrity": "sha512-7HWwdxXP5yDoe7DTpbif9l6ZmDwCzcSIK38kTSIt6CFEpMjX4EpCgT6wUmS0xTXqMI6E/ONmfgRKmaujpabjZQ==",
"dev": true,
"dependencies": {
- "@vitest/utils": "1.4.0",
+ "@vitest/utils": "1.5.0",
"p-limit": "^5.0.0",
"pathe": "^1.1.1"
},
@@ -997,9 +1020,9 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.4.0.tgz",
- "integrity": "sha512-saAFnt5pPIA5qDGxOHxJ/XxhMFKkUSBJmVt5VgDsAqPTX6JP326r5C/c9UuCMPoXNzuudTPsYDZCoJ5ilpqG2A==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.0.tgz",
+ "integrity": "sha512-qpv3fSEuNrhAO3FpH6YYRdaECnnRjg9VxbhdtPwPRnzSfHVXnNzzrpX4cJxqiwgRMo7uRMWDFBlsBq4Cr+rO3A==",
"dev": true,
"dependencies": {
"magic-string": "^0.30.5",
@@ -1017,9 +1040,9 @@
"dev": true
},
"node_modules/@vitest/snapshot/node_modules/magic-string": {
- "version": "0.30.8",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
- "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
+ "version": "0.30.9",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.9.tgz",
+ "integrity": "sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@@ -1029,9 +1052,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.4.0.tgz",
- "integrity": "sha512-Ywau/Qs1DzM/8Uc+yA77CwSegizMlcgTJuYGAi0jujOteJOUf1ujunHThYo243KG9nAyWT3L9ifPYZ5+As/+6Q==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.0.tgz",
+ "integrity": "sha512-vu6vi6ew5N5MMHJjD5PoakMRKYdmIrNJmyfkhRpQt5d9Ewhw9nZ5Aqynbi3N61bvk9UvZ5UysMT6ayIrZ8GA9w==",
"dev": true,
"dependencies": {
"tinyspy": "^2.2.0"
@@ -1041,9 +1064,9 @@
}
},
"node_modules/@vitest/utils": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.4.0.tgz",
- "integrity": "sha512-mx3Yd1/6e2Vt/PUC98DcqTirtfxUyAZ32uK82r8rZzbtBeBo+nqgnjx/LvqQdWsrvNtm14VmurNgcf4nqY5gJg==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.0.tgz",
+ "integrity": "sha512-BDU0GNL8MWkRkSRdNFvCUCAVOeHaUlVJ9Tx0TYBZyXaaOTmGtUFObzchCivIBrIwKzvZA7A9sCejVhXM2aY98A==",
"dev": true,
"dependencies": {
"diff-sequences": "^29.6.3",
@@ -1144,9 +1167,9 @@
"dev": true
},
"node_modules/acorn": {
- "version": "8.10.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
- "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@@ -1717,18 +1740,6 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/doctypes": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
@@ -1816,41 +1827,37 @@
}
},
"node_modules/eslint": {
- "version": "8.57.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
- "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.0.0.tgz",
+ "integrity": "sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
- "@eslint/eslintrc": "^2.1.4",
- "@eslint/js": "8.57.0",
- "@humanwhocodes/config-array": "^0.11.14",
+ "@eslint/eslintrc": "^3.0.2",
+ "@eslint/js": "9.0.0",
+ "@humanwhocodes/config-array": "^0.12.3",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
- "@ungap/structured-clone": "^1.2.0",
"ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
"debug": "^4.3.2",
- "doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.2",
- "eslint-visitor-keys": "^3.4.3",
- "espree": "^9.6.1",
+ "eslint-scope": "^8.0.1",
+ "eslint-visitor-keys": "^4.0.0",
+ "espree": "^10.0.1",
"esquery": "^1.4.2",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
+ "file-entry-cache": "^8.0.0",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
- "globals": "^13.19.0",
"graphemer": "^1.4.0",
"ignore": "^5.2.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
"is-path-inside": "^3.0.3",
- "js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
"lodash.merge": "^4.6.2",
@@ -1864,7 +1871,7 @@
"eslint": "bin/eslint.js"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
@@ -1883,12 +1890,13 @@
}
},
"node_modules/eslint-plugin-vue": {
- "version": "9.23.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.23.0.tgz",
- "integrity": "sha512-Bqd/b7hGYGrlV+wP/g77tjyFmp81lh5TMw0be9093X02SyelxRRfCI6/IsGq/J7Um0YwB9s0Ry0wlFyjPdmtUw==",
+ "version": "9.24.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.24.1.tgz",
+ "integrity": "sha512-wk3SuwmS1pZdcuJlokGYEi/buDOwD6KltvhIZyOnpJ/378dcQ4zchu9PAMbbLAaydCz1iYc5AozszcOOgZIIOg==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
+ "globals": "^13.24.0",
"natural-compare": "^1.4.0",
"nth-check": "^2.1.1",
"postcss-selector-parser": "^6.0.15",
@@ -1900,7 +1908,22 @@
"node": "^14.17.0 || >=16.0.0"
},
"peerDependencies": {
- "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0"
+ "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-vue/node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint-scope": {
@@ -1931,6 +1954,51 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz",
+ "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
+ "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/espree": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz",
+ "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.11.3",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.0.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/esm-resolve": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/esm-resolve/-/esm-resolve-1.0.8.tgz",
@@ -2094,15 +2162,15 @@
}
},
"node_modules/file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
"dependencies": {
- "flat-cache": "^3.0.4"
+ "flat-cache": "^4.0.0"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": ">=16.0.0"
}
},
"node_modules/fill-range": {
@@ -2134,22 +2202,22 @@
}
},
"node_modules/flat-cache": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
- "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
"dependencies": {
- "flatted": "^3.1.0",
- "rimraf": "^3.0.2"
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": ">=16"
}
},
"node_modules/flatted": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
- "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
"dev": true
},
"node_modules/for-each": {
@@ -2177,12 +2245,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -2239,16 +2301,16 @@
}
},
"node_modules/glob": {
- "version": "10.3.10",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
- "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
+ "version": "10.3.12",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
+ "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
"dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
- "jackspeak": "^2.3.5",
+ "jackspeak": "^2.3.6",
"minimatch": "^9.0.1",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
- "path-scurry": "^1.10.1"
+ "minipass": "^7.0.4",
+ "path-scurry": "^1.10.2"
},
"bin": {
"glob": "dist/esm/bin.mjs"
@@ -2297,15 +2359,12 @@
}
},
"node_modules/globals": {
- "version": "13.23.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
- "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
- "dependencies": {
- "type-fest": "^0.20.2"
- },
"engines": {
- "node": ">=8"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -2470,9 +2529,9 @@
}
},
"node_modules/ignore": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
- "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
"dev": true,
"engines": {
"node": ">= 4"
@@ -2503,16 +2562,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
@@ -2851,6 +2900,12 @@
"node": ">=18"
}
},
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -2891,6 +2946,15 @@
"promise": "^7.0.1"
}
},
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -3175,9 +3239,9 @@
}
},
"node_modules/lru-cache": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
- "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
+ "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
"dev": true,
"engines": {
"node": "14 || >=16.14"
@@ -3408,15 +3472,6 @@
"node": ">= 0.4"
}
},
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
"node_modules/onetime": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
@@ -3517,15 +3572,6 @@
"node": ">=8"
}
},
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -3542,12 +3588,12 @@
"dev": true
},
"node_modules/path-scurry": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
- "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
+ "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
"dev": true,
"dependencies": {
- "lru-cache": "^9.1.1 || ^10.0.0",
+ "lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
@@ -3747,9 +3793,9 @@
}
},
"node_modules/prosemirror-model": {
- "version": "1.19.4",
- "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.19.4.tgz",
- "integrity": "sha512-RPmVXxUfOhyFdayHawjuZCxiROsm9L4FCUA6pWI+l7n2yCBsWy9VpdE1hpDHUS8Vad661YLY9AzqfjLhAKQ4iQ==",
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.20.0.tgz",
+ "integrity": "sha512-q7AY7vMjKYqDCeoedgUiAgrLabliXxndJuuFmcmc2+YU1SblvnOiG2WEACF2lwAZsMlfLpiAilA3L+TWlDqIsQ==",
"dependencies": {
"orderedmap": "^2.0.0"
}
@@ -3783,11 +3829,11 @@
}
},
"node_modules/prosemirror-view": {
- "version": "1.33.3",
- "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.3.tgz",
- "integrity": "sha512-P4Ao/bc4OrU/2yLIf8dL4lJaEtjLR3QjIvQHgJYp2jUS7kYM4bSR6okbBjkqzOs/FwUon6UGjTLdKMnPL1MZqw==",
+ "version": "1.33.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.4.tgz",
+ "integrity": "sha512-xQqAhH8/HGleVpKDhQsrd+oqdyeKMxFtdCWDxWMmP+n0k27fBpyUqa8pA+RB5cFY8rqDDc1hll69aRZQa7UaAw==",
"dependencies": {
- "prosemirror-model": "^1.16.0",
+ "prosemirror-model": "^1.20.0",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0"
}
@@ -4033,41 +4079,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/rimraf/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/rollup": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz",
@@ -4101,9 +4112,9 @@
}
},
"node_modules/rollup-plugin-external-globals": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/rollup-plugin-external-globals/-/rollup-plugin-external-globals-0.9.2.tgz",
- "integrity": "sha512-BUzbNhcN20irgWFNOL9XYSAN8pVRL7BfyZJce7oJMxjgPuxMOlQo3oTp3LRH1ehddXQEnp0/XxglMisl/GhnJQ==",
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/rollup-plugin-external-globals/-/rollup-plugin-external-globals-0.10.0.tgz",
+ "integrity": "sha512-RXlupZrmn97AaaS5dWnktkjM+Iy+od0E+8L0mUkMIs3iuoUXNJebueQocQKV7Ircd54fSGGmkBaXwNzY05J1yQ==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.1.0",
@@ -4455,9 +4466,9 @@
"dev": true
},
"node_modules/terser": {
- "version": "5.29.2",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz",
- "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==",
+ "version": "5.30.3",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.30.3.tgz",
+ "integrity": "sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
@@ -4491,9 +4502,9 @@
"dev": true
},
"node_modules/tinypool": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.2.tgz",
- "integrity": "sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ==",
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.3.tgz",
+ "integrity": "sha512-Ud7uepAklqRH1bvwy22ynrliC7Dljz7Tm8M/0RBUW+YRa4YHhZ6e4PpgE+fu1zr/WqB1kbeuVrdfeuyIBpy4tw==",
"dev": true,
"engines": {
"node": ">=14.0.0"
@@ -4678,13 +4689,13 @@
"dev": true
},
"node_modules/vite": {
- "version": "5.2.4",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.4.tgz",
- "integrity": "sha512-vjFghvHWidBTinu5TCymJk/lRHlR5ljqB83yugr0HA1xspUPdOZHqbqDLnZ8f9/jINrtFHTCYYyIUi+o+Q5iyg==",
+ "version": "5.2.8",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz",
+ "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==",
"dev": true,
"dependencies": {
"esbuild": "^0.20.1",
- "postcss": "^8.4.36",
+ "postcss": "^8.4.38",
"rollup": "^4.13.0"
},
"bin": {
@@ -4733,9 +4744,9 @@
}
},
"node_modules/vite-node": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.4.0.tgz",
- "integrity": "sha512-VZDAseqjrHgNd4Kh8icYHWzTKSCZMhia7GyHfhtzLW33fZlG9SwsB6CEhgyVOWkJfJ2pFLrp/Gj1FSfAiqH9Lw==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.0.tgz",
+ "integrity": "sha512-tV8h6gMj6vPzVCa7l+VGq9lwoJjW8Y79vst8QZZGiuRAfijU+EEWuc0kFpmndQrWhMMhet1jdSF+40KSZUqIIw==",
"dev": true,
"dependencies": {
"cac": "^6.7.14",
@@ -4755,9 +4766,9 @@
}
},
"node_modules/vite-plugin-static-copy": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-1.0.1.tgz",
- "integrity": "sha512-3eGL4mdZoPJMDBT68pv/XKIHR4MgVolStIxxv1gIBP4R8TpHn9C9EnaU0hesqlseJ4ycLGUxckFTu/jpuJXQlA==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-1.0.2.tgz",
+ "integrity": "sha512-AfmEF+a/mfjsUsrgjbCkhzUCeIUF4EKQXXt3Ie1cour9MBpy6f6GphbdW2td28oYfOrwCyRzFCksgLkpk58q6Q==",
"dev": true,
"dependencies": {
"chokidar": "^3.5.3",
@@ -4787,16 +4798,16 @@
}
},
"node_modules/vitest": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.4.0.tgz",
- "integrity": "sha512-gujzn0g7fmwf83/WzrDTnncZt2UiXP41mHuFYFrdwaLRVQ6JYQEiME2IfEjU3vcFL3VKa75XhI3lFgn+hfVsQw==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.0.tgz",
+ "integrity": "sha512-d8UKgR0m2kjdxDWX6911uwxout6GHS0XaGH1cksSIVVG8kRlE7G7aBw7myKQCvDI5dT4j7ZMa+l706BIORMDLw==",
"dev": true,
"dependencies": {
- "@vitest/expect": "1.4.0",
- "@vitest/runner": "1.4.0",
- "@vitest/snapshot": "1.4.0",
- "@vitest/spy": "1.4.0",
- "@vitest/utils": "1.4.0",
+ "@vitest/expect": "1.5.0",
+ "@vitest/runner": "1.5.0",
+ "@vitest/snapshot": "1.5.0",
+ "@vitest/spy": "1.5.0",
+ "@vitest/utils": "1.5.0",
"acorn-walk": "^8.3.2",
"chai": "^4.3.10",
"debug": "^4.3.4",
@@ -4808,9 +4819,9 @@
"std-env": "^3.5.0",
"strip-literal": "^2.0.0",
"tinybench": "^2.5.1",
- "tinypool": "^0.8.2",
+ "tinypool": "^0.8.3",
"vite": "^5.0.0",
- "vite-node": "1.4.0",
+ "vite-node": "1.5.0",
"why-is-node-running": "^2.2.2"
},
"bin": {
@@ -4825,8 +4836,8 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "1.4.0",
- "@vitest/ui": "1.4.0",
+ "@vitest/browser": "1.5.0",
+ "@vitest/ui": "1.5.0",
"happy-dom": "*",
"jsdom": "*"
},
@@ -5234,12 +5245,6 @@
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
"node_modules/ws": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
diff --git a/panel/package.json b/panel/package.json
index 1ae9821d24..a9e2b9e3f1 100644
--- a/panel/package.json
+++ b/panel/package.json
@@ -20,9 +20,9 @@
"prosemirror-history": "^1.4.0",
"prosemirror-inputrules": "^1.4.0",
"prosemirror-keymap": "^1.2.2",
- "prosemirror-model": "^1.19.4",
+ "prosemirror-model": "^1.20.0",
"prosemirror-schema-list": "^1.3.0",
- "prosemirror-view": "^1.33.3",
+ "prosemirror-view": "^1.33.4",
"vue": "^2.7.16",
"vuedraggable": "^2.24.3",
"vuelidate": "^0.7.7",
@@ -30,17 +30,17 @@
},
"devDependencies": {
"@vitejs/plugin-vue2": "^2.3.1",
- "eslint": "^8.57.0",
+ "eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
- "eslint-plugin-vue": "^9.23.0",
- "glob": "^10.3.10",
+ "eslint-plugin-vue": "^9.24.1",
+ "glob": "^10.3.12",
"jsdom": "^24.0.0",
"prettier": "^3.2.5",
- "rollup-plugin-external-globals": "^0.9.2",
- "terser": "^5.29.2",
- "vite": "^5.2.4",
- "vite-plugin-static-copy": "^1.0.1",
- "vitest": "^1.4.0",
+ "rollup-plugin-external-globals": "^0.10.0",
+ "terser": "^5.30.3",
+ "vite": "^5.2.8",
+ "vite-plugin-static-copy": "^1.0.2",
+ "vitest": "^1.5.0",
"vue-docgen-api": "^4.78.0",
"vue-template-compiler": "^2.7.16"
},
diff --git a/panel/src/components/Dialogs/LicenseDialog.vue b/panel/src/components/Dialogs/LicenseDialog.vue
index d3493af29b..3e936d6b42 100644
--- a/panel/src/components/Dialogs/LicenseDialog.vue
+++ b/panel/src/components/Dialogs/LicenseDialog.vue
@@ -47,7 +47,6 @@ export const props = {
mixins: [Dialog],
props: {
license: Object,
- // eslint-disable-next-line vue/require-prop-types
size: {
default: "large"
}
diff --git a/panel/src/components/Dialogs/SearchDialog.vue b/panel/src/components/Dialogs/SearchDialog.vue
index 25080ba6e9..686f7ae98e 100644
--- a/panel/src/components/Dialogs/SearchDialog.vue
+++ b/panel/src/components/Dialogs/SearchDialog.vue
@@ -155,7 +155,7 @@ export default {
const response = await this.$search(this.current, this.query);
this.items = response.results;
this.pagination = response.pagination;
- } catch (error) {
+ } catch {
this.items = [];
this.pagination = {};
} finally {
diff --git a/panel/src/components/Forms/Field/ObjectField.vue b/panel/src/components/Forms/Field/ObjectField.vue
index f85b2cbbd0..82a70ab847 100644
--- a/panel/src/components/Forms/Field/ObjectField.vue
+++ b/panel/src/components/Forms/Field/ObjectField.vue
@@ -123,8 +123,6 @@ export default {
this.object = {};
this.save();
},
- // TODO: field is not yet used to pre-focus correct field
- // eslint-disable-next-line no-unused-vars
open(field) {
if (this.disabled) {
return false;
diff --git a/panel/src/components/Forms/FormButtons.vue b/panel/src/components/Forms/FormButtons.vue
index 869b20b6fa..ae97c175e6 100644
--- a/panel/src/components/Forms/FormButtons.vue
+++ b/panel/src/components/Forms/FormButtons.vue
@@ -230,7 +230,7 @@ export default {
if (lock === true) {
try {
await this.$api.patch(...this.api);
- } catch (error) {
+ } catch {
// If setting lock failed, a competing lock has been set between
// API calls. In that case, discard changes, stop setting lock
clearInterval(this.isLocking);
diff --git a/panel/src/components/Forms/Input/ColornameInput.vue b/panel/src/components/Forms/Input/ColornameInput.vue
index aabaee7eec..eb49af01a9 100644
--- a/panel/src/components/Forms/Input/ColornameInput.vue
+++ b/panel/src/components/Forms/Input/ColornameInput.vue
@@ -68,7 +68,7 @@ export default {
try {
// first try to parse the color via the library
return this.$library.colors.toString(value, this.format, this.alpha);
- } catch (e) {
+ } catch {
// if that fails,
// create a new secret tester
const test = document.createElement("div");
diff --git a/panel/src/components/Forms/Writer/Utils/markPasteRule.js b/panel/src/components/Forms/Writer/Utils/markPasteRule.js
index b2df111409..a281986156 100644
--- a/panel/src/components/Forms/Writer/Utils/markPasteRule.js
+++ b/panel/src/components/Forms/Writer/Utils/markPasteRule.js
@@ -13,7 +13,6 @@ export default function (regexp, type, getAttrs) {
const isLink = !!marks.filter((x) => x.type.name === "link")[0];
- // eslint-disable-next-line
while (!isLink && (match = regexp.exec(text)) !== null) {
if (parent?.type?.allowsMarkType(type) && match[1]) {
const start = match.index;
diff --git a/panel/src/components/Navigation/Pagination.vue b/panel/src/components/Navigation/Pagination.vue
index fee41577e3..a981f60fb3 100644
--- a/panel/src/components/Navigation/Pagination.vue
+++ b/panel/src/components/Navigation/Pagination.vue
@@ -157,7 +157,7 @@ export default {
offset: start - 1,
total: this.total
});
- } catch (e) {
+ } catch {
// pagination stopped
}
},
diff --git a/panel/src/components/Views/SearchView.vue b/panel/src/components/Views/SearchView.vue
index f4a001dd83..1e9a4e215b 100644
--- a/panel/src/components/Views/SearchView.vue
+++ b/panel/src/components/Views/SearchView.vue
@@ -125,7 +125,7 @@ export default {
});
this.items = response.results;
this.pagination = response.pagination;
- } catch (error) {
+ } catch {
this.items = [];
this.pagination = {};
} finally {
diff --git a/panel/src/helpers/embed.js b/panel/src/helpers/embed.js
index d2999dfd6e..c378c83d39 100644
--- a/panel/src/helpers/embed.js
+++ b/panel/src/helpers/embed.js
@@ -14,7 +14,7 @@ export function youtube(url, doNotTrack = false) {
try {
uri = new URL(url);
- } catch (e) {
+ } catch {
return false;
}
@@ -103,7 +103,7 @@ export function vimeo(url, doNotTrack = false) {
try {
uri = new URL(url);
- } catch (e) {
+ } catch {
return false;
}
diff --git a/panel/src/helpers/link.js b/panel/src/helpers/link.js
index db7d97d22b..554b601c5b 100644
--- a/panel/src/helpers/link.js
+++ b/panel/src/helpers/link.js
@@ -102,7 +102,7 @@ async function previewForFile(id, fields = ["filename", "panelImage"]) {
label: file.filename,
image: file.panelImage
};
- } catch (e) {
+ } catch {
return null;
}
}
@@ -123,7 +123,7 @@ async function previewForPage(id, fields = ["title", "panelImage"]) {
label: page.title,
image: page.panelImage
};
- } catch (e) {
+ } catch {
return null;
}
}
diff --git a/panel/src/helpers/upload.js b/panel/src/helpers/upload.js
index a5d01343bc..515d21ed30 100644
--- a/panel/src/helpers/upload.js
+++ b/panel/src/helpers/upload.js
@@ -62,7 +62,7 @@ export default async (file, params) => {
try {
response = JSON.parse(event.target.response);
- } catch (error) {
+ } catch {
response = {
status: "error",
message: "The file could not be uploaded"
diff --git a/panel/src/helpers/url.js b/panel/src/helpers/url.js
index 378a68f39c..67acf99984 100644
--- a/panel/src/helpers/url.js
+++ b/panel/src/helpers/url.js
@@ -97,7 +97,7 @@ export function isUrl(url, strict) {
// validate it
try {
new URL(url, window.location);
- } catch (error) {
+ } catch {
return false;
}
diff --git a/panel/src/store/modules/content.js b/panel/src/store/modules/content.js
index 69729d3a4f..a3db508722 100644
--- a/panel/src/store/modules/content.js
+++ b/panel/src/store/modules/content.js
@@ -214,7 +214,7 @@ export default {
try {
data = JSON.parse(json);
- } catch (e) {
+ } catch {
// fail silently
}
From 24acf16e4c5660fc8141335072b4b717f1ec537f Mon Sep 17 00:00:00 2001
From: Lukas Bestle
Date: Sun, 21 Apr 2024 18:03:58 +0200
Subject: [PATCH 011/125] Update check: Support for new license model
Closes #5974
---
src/Cms/System/UpdateStatus.php | 55 ++++-
tests/Cms/System/UpdateStatusTest.php | 192 ++++++++++++------
.../getkirby.com/security.json | 6 +-
.../UpdateStatusTest/logic/basic.json | 14 +-
4 files changed, 201 insertions(+), 66 deletions(-)
diff --git a/src/Cms/System/UpdateStatus.php b/src/Cms/System/UpdateStatus.php
index b9e80e3d84..8adf65df0b 100644
--- a/src/Cms/System/UpdateStatus.php
+++ b/src/Cms/System/UpdateStatus.php
@@ -392,6 +392,46 @@ protected function filterArrayByVersion(array $array, array $filters, string $re
});
}
+ /**
+ * Finds the maximum possible major update
+ * that is included with the current license
+ *
+ * @return string|null Version number of the update or
+ * `null` if no free update is possible
+ */
+ protected function findMaximumFreeUpdate(): string|null
+ {
+ // get the timestamp of included updates
+ $renewal = $this->app->system()->license()->renewal();
+
+ if ($renewal === null || $this->data === null) {
+ return null;
+ }
+
+ foreach ($this->data['versions'] ?? [] as $entry) {
+ $initialRelease = $entry['initialRelease'] ?? null;
+ $latest = $entry['latest'] ?? '';
+
+ // skip entries of irrelevant releases
+ if (
+ is_string($initialRelease) !== true ||
+ version_compare($latest, $this->currentVersion, '<=') === true
+ ) {
+ continue;
+ }
+
+ $timestamp = strtotime($initialRelease);
+
+ // update is free if the initial release was before the
+ // license renewal date
+ if (is_int($timestamp) === true && $timestamp < $renewal) {
+ return $latest;
+ }
+ }
+
+ return null;
+ }
+
/**
* Finds the minimum possible security update
* to fix all known vulnerabilities
@@ -655,7 +695,7 @@ protected function targetData(): array
];
}
- // check if free updates are possible from the current version
+ // check if updates within the same major version are possible
$latest = $versionEntry['latest'] ?? null;
if (is_string($latest) === true && $latest !== $this->currentVersion) {
return $this->targetData = [
@@ -665,6 +705,19 @@ protected function targetData(): array
];
}
+ // check if the license includes updates to a newer major version
+ if ($version = $this->findMaximumFreeUpdate()) {
+ // extract the part before the first dot
+ // to find the major release page URL
+ preg_match('/^(\w+)\./', $version, $matches);
+
+ return $this->targetData = [
+ 'status' => 'update',
+ 'url' => $this->urlFor($matches[1] . '.0', 'changes'),
+ 'version' => $version
+ ];
+ }
+
// no free update is possible, but we are not on the latest version,
// so the overall latest version must be an upgrade
return $this->targetData = [
diff --git a/tests/Cms/System/UpdateStatusTest.php b/tests/Cms/System/UpdateStatusTest.php
index 70f4b1d7b4..8e9c895e05 100644
--- a/tests/Cms/System/UpdateStatusTest.php
+++ b/tests/Cms/System/UpdateStatusTest.php
@@ -2,10 +2,12 @@
namespace Kirby\Cms\System;
+use Kirby\Cms\License;
use Kirby\Cms\Plugin;
use Kirby\Data\Json;
use Kirby\Filesystem\Dir;
use Kirby\TestCase;
+use ReflectionProperty;
/**
* @coversDefaultClass \Kirby\Cms\System\UpdateStatus
@@ -55,7 +57,8 @@ public function testLoadData()
'*' => [
'description' => 'Actively supported',
'latest' => '88888.8.8',
- 'status' => 'active-support'
+ 'status' => 'active-support',
+ 'initialRelease' => '2023-11-28'
]
],
'urls' => [
@@ -68,7 +71,8 @@ public function testLoadData()
'php' => [
'8.0' => '2023-11-26',
'8.1' => '2024-11-25',
- '8.2' => '2025-12-08'
+ '8.2' => '2025-12-08',
+ '8.3' => '2026-11-23'
],
'incidents' => [],
'messages' => [],
@@ -87,13 +91,15 @@ public function testLoadDataCacheKirby()
'versions' => [
'*' => [
'latest' => '88888.8.6',
- 'status' => 'active-support'
+ 'status' => 'active-support',
+ 'initialRelease' => '2023-11-28'
]
],
'php' => [
'8.0' => '2023-11-26',
'8.1' => '2024-11-25',
- '8.2' => '2025-12-08'
+ '8.2' => '2025-12-08',
+ '8.3' => '2026-11-23'
],
'urls' => [
'*' => [
@@ -123,7 +129,8 @@ public function testLoadDataCacheKirby()
'*' => [
'description' => 'Actively supported',
'latest' => '88888.8.8',
- 'status' => 'active-support'
+ 'status' => 'active-support',
+ 'initialRelease' => '2023-11-28'
]
],
'urls' => [
@@ -136,7 +143,8 @@ public function testLoadDataCacheKirby()
'php' => [
'8.0' => '2023-11-26',
'8.1' => '2024-11-25',
- '8.2' => '2025-12-08'
+ '8.2' => '2025-12-08',
+ '8.3' => '2026-11-23'
],
'incidents' => [],
'messages' => [],
@@ -241,7 +249,8 @@ public function testLoadDataCacheInvalid()
'*' => [
'description' => 'Actively supported',
'latest' => '88888.8.8',
- 'status' => 'active-support'
+ 'status' => 'active-support',
+ 'initialRelease' => '2023-11-28'
]
],
'urls' => [
@@ -254,7 +263,8 @@ public function testLoadDataCacheInvalid()
'php' => [
'8.0' => '2023-11-26',
'8.1' => '2024-11-25',
- '8.2' => '2025-12-08'
+ '8.2' => '2025-12-08',
+ '8.3' => '2026-11-23'
],
'incidents' => [],
'messages' => [],
@@ -353,12 +363,12 @@ public function testLoadDataNotJson()
*/
public function testLogic(
string $packageType,
- string|null $version,
+ array $packageData,
bool $securityOnly,
array|null $data,
array $expected
) {
- $package = $this->$packageType($version);
+ $package = $this->$packageType(...$packageData);
$updateStatus = new UpdateStatus($package, $securityOnly, $data);
foreach ($expected as $method => $value) {
@@ -372,7 +382,7 @@ public static function logicProvider(): array
// update check (Kirby)
'Kirby up-to-date' => [
'app',
- '88888.8.8',
+ ['88888.8.8'],
false,
static::data('basic'),
[
@@ -391,7 +401,7 @@ public static function logicProvider(): array
],
'Kirby unreleased' => [
'app',
- '88888.8.9-rc.1',
+ ['88888.8.9-rc.1'],
false,
static::data('basic'),
[
@@ -410,7 +420,7 @@ public static function logicProvider(): array
],
'Kirby security-update' => [
'app',
- '77777.1.2',
+ ['77777.1.2'],
false,
static::data('basic'),
[
@@ -443,7 +453,7 @@ public static function logicProvider(): array
],
'Kirby security-upgrade' => [
'app',
- '55555.1.2',
+ ['55555.1.2'],
false,
static::data('basic'),
[
@@ -476,7 +486,7 @@ public static function logicProvider(): array
],
'Kirby not-vulnerable (update "no-vulnerabilities")' => [
'app',
- '77777.7.6',
+ ['77777.7.6'],
true,
static::data('basic'),
[
@@ -495,7 +505,7 @@ public static function logicProvider(): array
],
'Kirby not-vulnerable (update)' => [
'app',
- '66666.6.5',
+ ['66666.6.5'],
true,
static::data('basic'),
[
@@ -512,9 +522,28 @@ public static function logicProvider(): array
'exceptionMessages' => []
]
],
+ 'Kirby not-vulnerable (free major update)' => [
+ 'app',
+ ['66666.6.6', '2023-11-28'],
+ true,
+ static::data('basic'),
+ [
+ 'currentVersion' => '66666.6.6',
+ 'icon' => 'check',
+ 'label' => 'No known vulnerabilities',
+ 'latestVersion' => '88888.8.8',
+ 'messages' => [],
+ 'status' => 'not-vulnerable',
+ 'targetVersion' => null,
+ 'theme' => 'positive',
+ 'url' => 'https://getkirby.com/old-releases/66666.6.6',
+ 'vulnerabilities' => [],
+ 'exceptionMessages' => []
+ ]
+ ],
'Kirby not-vulnerable (upgrade)' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
true,
static::data('basic'),
[
@@ -533,7 +562,7 @@ public static function logicProvider(): array
],
'Kirby update' => [
'app',
- '77777.7.6',
+ ['77777.7.6'],
false,
static::data('basic'),
[
@@ -550,9 +579,47 @@ public static function logicProvider(): array
'exceptionMessages' => []
]
],
- 'Kirby upgrade' => [
+ 'Kirby free major update' => [
+ 'app',
+ ['66666.6.6', '2023-11-28'],
+ false,
+ static::data('basic'),
+ [
+ 'currentVersion' => '66666.6.6',
+ 'icon' => 'info',
+ 'label' => 'Free update 77777.7.7 available',
+ 'latestVersion' => '88888.8.8',
+ 'messages' => [],
+ 'status' => 'update',
+ 'targetVersion' => '77777.7.7',
+ 'theme' => 'info',
+ 'url' => 'https://getkirby.com/old-releases/77777.0',
+ 'vulnerabilities' => [],
+ 'exceptionMessages' => []
+ ]
+ ],
+ 'Kirby upgrade (without license)' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
+ false,
+ static::data('basic'),
+ [
+ 'currentVersion' => '77777.7.7',
+ 'icon' => 'info',
+ 'label' => 'Upgrade 88888.8.8 available',
+ 'latestVersion' => '88888.8.8',
+ 'messages' => [],
+ 'status' => 'upgrade',
+ 'targetVersion' => '88888.8.8',
+ 'theme' => 'info',
+ 'url' => 'https://getkirby.com/releases/88888',
+ 'vulnerabilities' => [],
+ 'exceptionMessages' => []
+ ]
+ ],
+ 'Kirby upgrade (with inactive license)' => [
+ 'app',
+ ['77777.7.7', '2023-11-28'],
false,
static::data('basic'),
[
@@ -573,7 +640,7 @@ public static function logicProvider(): array
// update check (plugin)
'Plugin up-to-date' => [
'plugin',
- '88888.8.8',
+ ['88888.8.8'],
false,
static::data('basic'),
[
@@ -595,7 +662,7 @@ public static function logicProvider(): array
],
'Plugin unreleased' => [
'plugin',
- '88888.8.9-rc.1',
+ ['88888.8.9-rc.1'],
false,
static::data('basic'),
[
@@ -617,7 +684,7 @@ public static function logicProvider(): array
],
'Plugin security-update' => [
'plugin',
- '77777.1.2',
+ ['77777.1.2'],
false,
static::data('basic'),
[
@@ -656,7 +723,7 @@ public static function logicProvider(): array
],
'Plugin security-upgrade' => [
'plugin',
- '55555.1.2',
+ ['55555.1.2'],
false,
static::data('basic'),
[
@@ -695,7 +762,7 @@ public static function logicProvider(): array
],
'Plugin update' => [
'plugin',
- '77777.7.6',
+ ['77777.7.6'],
false,
static::data('basic'),
[
@@ -717,7 +784,7 @@ public static function logicProvider(): array
],
'Plugin upgrade' => [
'plugin',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('basic'),
[
@@ -739,7 +806,7 @@ public static function logicProvider(): array
],
'Plugin with prefix' => [
'plugin',
- 'v77777.7.7',
+ ['v77777.7.7'],
false,
static::data('basic'),
[
@@ -761,7 +828,7 @@ public static function logicProvider(): array
],
'Plugin with invalid version' => [
'plugin',
- 'not a version',
+ ['not a version'],
false,
static::data('basic'),
[
@@ -783,7 +850,7 @@ public static function logicProvider(): array
],
'Plugin without version' => [
'plugin',
- null,
+ [null],
false,
static::data('basic'),
[
@@ -807,7 +874,7 @@ public static function logicProvider(): array
// vulnerabilities
'Vulnerability sorting' => [
'app',
- '77777.1.2',
+ ['77777.1.2'],
false,
static::data('incidents-severity'),
[
@@ -888,7 +955,7 @@ public static function logicProvider(): array
],
'Unstable release' => [
'app',
- '77777.0.0-rc.1',
+ ['77777.0.0-rc.1'],
false,
static::data('basic'),
[
@@ -921,7 +988,7 @@ public static function logicProvider(): array
],
'Minimum security update' => [
'app',
- '77777.1.2',
+ ['77777.1.2'],
false,
static::data('incidents-cascade'),
[
@@ -954,7 +1021,7 @@ public static function logicProvider(): array
],
'Incidents with infinite loop' => [
'app',
- '77777.1.2',
+ ['77777.1.2'],
false,
static::data('incidents-loop'),
[
@@ -989,7 +1056,7 @@ public static function logicProvider(): array
// messages
'Messages' => [
'app',
- '77777.6.0',
+ ['77777.6.0'],
false,
static::data('basic'),
[
@@ -1014,7 +1081,7 @@ public static function logicProvider(): array
],
'EOL warning (Kirby)' => [
'app',
- '44444.1.2',
+ ['44444.1.2'],
false,
static::data('basic'),
[
@@ -1052,7 +1119,7 @@ public static function logicProvider(): array
],
'EOL warning (plugin)' => [
'plugin',
- '44444.1.2',
+ ['44444.1.2'],
false,
static::data('basic'),
[
@@ -1090,7 +1157,7 @@ public static function logicProvider(): array
],
'EOL warning (PHP)' => [
'app',
- '88888.8.8',
+ ['88888.8.8'],
false,
static::data('php'),
[
@@ -1117,7 +1184,7 @@ public static function logicProvider(): array
],
'EOL warning with custom link' => [
'app',
- '44444.1.2',
+ ['44444.1.2'],
false,
static::data('eol-link'),
[
@@ -1157,7 +1224,7 @@ public static function logicProvider(): array
// invalid/incomplete data array
'No data' => [
'plugin',
- '77777.7.7',
+ ['77777.7.7'],
false,
null,
[
@@ -1179,7 +1246,7 @@ public static function logicProvider(): array
],
'Empty data' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
[],
[
@@ -1201,7 +1268,7 @@ public static function logicProvider(): array
],
'No latest version (update)' => [
'app',
- '77777.7.5',
+ ['77777.7.5'],
false,
static::data('no-latest'),
[
@@ -1220,7 +1287,7 @@ public static function logicProvider(): array
],
'No latest version (upgrade)' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('no-latest'),
[
@@ -1239,7 +1306,7 @@ public static function logicProvider(): array
],
'No versions' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('no-versions'),
[
@@ -1260,7 +1327,7 @@ public static function logicProvider(): array
],
'No URLs' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('no-urls'),
[
@@ -1281,7 +1348,7 @@ public static function logicProvider(): array
],
'No PHP' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('no-php'),
[
@@ -1300,7 +1367,7 @@ public static function logicProvider(): array
],
'No incidents' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('no-incidents'),
[
@@ -1319,7 +1386,7 @@ public static function logicProvider(): array
],
'No messages' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('no-messages'),
[
@@ -1338,7 +1405,7 @@ public static function logicProvider(): array
],
'Missing URL entry' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('no-url-entry'),
[
@@ -1359,7 +1426,7 @@ public static function logicProvider(): array
],
'URL entry without `changes` key' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('url-entry-without-changes'),
[
@@ -1380,7 +1447,7 @@ public static function logicProvider(): array
],
'Missing version entry' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('no-version-entry'),
[
@@ -1401,7 +1468,7 @@ public static function logicProvider(): array
],
'Missing version entry (with vulnerability)' => [
'app',
- '77777.4.3',
+ ['77777.4.3'],
false,
static::data('no-version-entry'),
[
@@ -1436,7 +1503,7 @@ public static function logicProvider(): array
],
'Version entry without `latest` key' => [
'app',
- '77777.7.5',
+ ['77777.7.5'],
false,
static::data('version-entry-without-latest'),
[
@@ -1455,7 +1522,7 @@ public static function logicProvider(): array
],
'Invalid constraint (message)' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('invalid-constraint-message'),
[
@@ -1479,7 +1546,7 @@ public static function logicProvider(): array
],
'Invalid constraint (incident)' => [
'app',
- '77777.3.2',
+ ['77777.3.2'],
false,
static::data('invalid-constraint-incident'),
[
@@ -1501,7 +1568,7 @@ public static function logicProvider(): array
],
'Invalid constraint (URL entry)' => [
'app',
- '77777.7.5',
+ ['77777.7.5'],
false,
static::data('invalid-constraint-url'),
[
@@ -1523,7 +1590,7 @@ public static function logicProvider(): array
],
'Invalid constraint (version entry)' => [
'app',
- '77777.7.5',
+ ['77777.7.5'],
false,
static::data('invalid-constraint-version'),
[
@@ -1545,7 +1612,7 @@ public static function logicProvider(): array
],
'Missing constraint (message)' => [
'app',
- '77777.7.7',
+ ['77777.7.7'],
false,
static::data('missing-constraint-message'),
[
@@ -1567,7 +1634,7 @@ public static function logicProvider(): array
],
'Missing constraint (incident)' => [
'app',
- '77777.3.2',
+ ['77777.3.2'],
false,
static::data('missing-constraint-incident'),
[
@@ -1610,14 +1677,19 @@ public function testMessagesCache()
$this->assertSame($expected, $updateStatus->messages());
}
- protected function app(string $version): MockApp
+ protected function app(string $version, string|null $activation = null): MockApp
{
MockApp::$version = $version;
- return new MockApp([
+ $app = new MockApp([
'roots' => [
'index' => static::TMP
]
]);
+
+ $property = new ReflectionProperty($app->system(), 'license');
+ $property->setValue($app->system(), new License(activation: $activation));
+
+ return $app;
}
protected static function data(string $name): array
diff --git a/tests/Cms/System/fixtures/UpdateStatusTest/getkirby.com/security.json b/tests/Cms/System/fixtures/UpdateStatusTest/getkirby.com/security.json
index 868f081be8..ae35bd070c 100644
--- a/tests/Cms/System/fixtures/UpdateStatusTest/getkirby.com/security.json
+++ b/tests/Cms/System/fixtures/UpdateStatusTest/getkirby.com/security.json
@@ -8,7 +8,8 @@
"*": {
"description": "Actively supported",
"latest": "88888.8.8",
- "status": "active-support"
+ "status": "active-support",
+ "initialRelease": "2023-11-28"
}
},
"urls": {
@@ -21,7 +22,8 @@
"php": {
"8.0": "2023-11-26",
"8.1": "2024-11-25",
- "8.2": "2025-12-08"
+ "8.2": "2025-12-08",
+ "8.3": "2026-11-23"
},
"incidents": [],
"messages": []
diff --git a/tests/Cms/System/fixtures/UpdateStatusTest/logic/basic.json b/tests/Cms/System/fixtures/UpdateStatusTest/logic/basic.json
index 87387e462d..e613bc99ea 100644
--- a/tests/Cms/System/fixtures/UpdateStatusTest/logic/basic.json
+++ b/tests/Cms/System/fixtures/UpdateStatusTest/logic/basic.json
@@ -7,17 +7,25 @@
">=77777.5.5": {
"status": "no-vulnerabilities"
},
+ "88888.*": {
+ "latest": "88888.8.8",
+ "status": "active-support",
+ "initialRelease": "2027-10-05"
+ },
"77777.*": {
"latest": "77777.7.7",
- "status": "active-support"
+ "status": "active-support",
+ "initialRelease": "2026-10-05"
},
"66666.*": {
"latest": "66666.6.6",
- "status": "security-support"
+ "status": "security-support",
+ "initialRelease": "2025-10-05"
},
"55555.*": {
"latest": "55555.5.5",
- "status": "security-support"
+ "status": "security-support",
+ "initialRelease": "2024-10-05"
},
"<55555.0.0": {
"latest": "44444.4.4",
From 251d8cd910cfa9943c2ace37fd5076a802540f81 Mon Sep 17 00:00:00 2001
From: Ahmet Bora
Date: Tue, 23 Apr 2024 13:23:11 +0300
Subject: [PATCH 012/125] Fix email dialog title prop translation #6402
---
panel/src/components/Dialogs/EmailDialog.vue | 2 +-
.../components/Forms/Toolbar/EmailDialog.vue | 17 +++++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/panel/src/components/Dialogs/EmailDialog.vue b/panel/src/components/Dialogs/EmailDialog.vue
index 0ac36037d6..6e01554d33 100644
--- a/panel/src/components/Dialogs/EmailDialog.vue
+++ b/panel/src/components/Dialogs/EmailDialog.vue
@@ -24,7 +24,7 @@ export default {
icon: "email"
},
title: {
- label: window.panel.$t("link.text"),
+ label: window.panel.$t("title"),
type: "text",
icon: "title"
}
diff --git a/panel/src/components/Forms/Toolbar/EmailDialog.vue b/panel/src/components/Forms/Toolbar/EmailDialog.vue
index f12b3cc920..3c1c225615 100644
--- a/panel/src/components/Forms/Toolbar/EmailDialog.vue
+++ b/panel/src/components/Forms/Toolbar/EmailDialog.vue
@@ -3,6 +3,23 @@ import EmailDialog from "@/components/Dialogs/EmailDialog.vue";
export default {
extends: EmailDialog,
+ props: {
+ // eslint-disable-next-line vue/require-prop-types
+ fields: {
+ default: () => ({
+ href: {
+ label: window.panel.$t("email"),
+ type: "email",
+ icon: "email"
+ },
+ title: {
+ label: window.panel.$t("link.text"),
+ type: "text",
+ icon: "title"
+ }
+ })
+ },
+ },
methods: {
submit() {
const email = this.values.href ?? "";
From 592618109490eaee5537c15f653c56e1b72f87a2 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Tue, 23 Apr 2024 21:48:44 +0200
Subject: [PATCH 013/125] CSS `data-theme` with color names
---
panel/src/styles/utilities/theme.css | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/panel/src/styles/utilities/theme.css b/panel/src/styles/utilities/theme.css
index b6a882ef46..4298247060 100644
--- a/panel/src/styles/utilities/theme.css
+++ b/panel/src/styles/utilities/theme.css
@@ -32,6 +32,7 @@
}
/* Color themes */
+[data-theme="red"],
[data-theme="error"],
[data-theme="negative"] {
--theme-color-h: var(--color-red-h);
@@ -39,36 +40,53 @@
--theme-color-boost: var(--color-red-boost);
}
+[data-theme="orange"],
[data-theme="notice"] {
--theme-color-h: var(--color-orange-h);
--theme-color-s: var(--color-orange-s);
--theme-color-boost: var(--color-orange-boost);
}
+[data-theme="yellow"],
[data-theme="warning"] {
--theme-color-h: var(--color-yellow-h);
--theme-color-s: var(--color-yellow-s);
--theme-color-boost: var(--color-yellow-boost);
}
+[data-theme="blue"],
[data-theme="info"] {
--theme-color-h: var(--color-blue-h);
--theme-color-s: var(--color-blue-s);
--theme-color-boost: var(--color-blue-boost);
}
+[data-theme="pink"],
[data-theme="love"] {
--theme-color-h: var(--color-pink-h);
--theme-color-s: var(--color-pink-s);
--theme-color-boost: var(--color-pink-boost);
}
+[data-theme="green"],
[data-theme="positive"] {
--theme-color-h: var(--color-green-h);
--theme-color-s: var(--color-green-s);
--theme-color-boost: var(--color-green-boost);
}
+[data-theme="aqua"] {
+ --theme-color-h: var(--color-aqua-h);
+ --theme-color-s: var(--color-aqua-s);
+ --theme-color-boost: var(--color-aqua-boost);
+}
+
+[data-theme="purple"] {
+ --theme-color-h: var(--color-purple-h);
+ --theme-color-s: var(--color-purple-s);
+ --theme-color-boost: var(--color-purple-boost);
+}
+
[data-theme="passive"] {
--theme-color-h: var(--color-gray-h);
--theme-color-s: var(--color-gray-s);
From d570140d86f1e0996f202485ad1583ffe133c86e Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Wed, 24 Apr 2024 15:33:27 +0200
Subject: [PATCH 014/125] Theme lab examples
---
panel/lab/basics/utilities/theme/index.vue | 144 +++++++++++++++++++++
panel/src/styles/utilities/theme.css | 1 +
2 files changed, 145 insertions(+)
create mode 100644 panel/lab/basics/utilities/theme/index.vue
diff --git a/panel/lab/basics/utilities/theme/index.vue b/panel/lab/basics/utilities/theme/index.vue
new file mode 100644
index 0000000000..8e6df65d8d
--- /dev/null
+++ b/panel/lab/basics/utilities/theme/index.vue
@@ -0,0 +1,144 @@
+
+
+
+
+
+ The data-theme
attribute can be slapped on any element to
+ apply pre-defined theme colors via CSS. The element receives the
+ following CSS variables that you can then use for your styles:
+
+ {{ variables }}
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
Example Text
+
Example Text Dimmed
+
+
+
+
+
+
+
+
+
diff --git a/panel/src/styles/utilities/theme.css b/panel/src/styles/utilities/theme.css
index 4298247060..81587655fe 100644
--- a/panel/src/styles/utilities/theme.css
+++ b/panel/src/styles/utilities/theme.css
@@ -87,6 +87,7 @@
--theme-color-boost: var(--color-purple-boost);
}
+[data-theme="gray"],
[data-theme="passive"] {
--theme-color-h: var(--color-gray-h);
--theme-color-s: var(--color-gray-s);
From 9fd6ec96761d999045cae730b625dfde60a83512 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 11 Apr 2024 20:44:22 +0200
Subject: [PATCH 015/125] `k-button`: New `variant` for only colored icon
---
panel/src/components/Navigation/Button.vue | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/panel/src/components/Navigation/Button.vue b/panel/src/components/Navigation/Button.vue
index 9a5de5b66b..fb276f830f 100644
--- a/panel/src/components/Navigation/Button.vue
+++ b/panel/src/components/Navigation/Button.vue
@@ -307,13 +307,12 @@ export default {
--button-color-text: var(--button-color-dimmed-off);
}
.k-button:where([data-theme][data-variant="dimmed"]) {
- --button-color-icon: var(--theme-color-icon);
--button-color-dimmed-on: var(--theme-color-text-dimmed);
--button-color-dimmed-off: var(--theme-color-text);
}
/** Filled Buttons **/
-.k-button:where([data-variant="filled"]) {
+.k-button:where([data-variant="filled"], [data-variant="filled-icon"]) {
--button-color-back: var(--color-gray-300);
}
.k-button:where([data-variant="filled"]):not([aria-disabled]):hover {
@@ -325,6 +324,11 @@ export default {
--button-color-text: var(--theme-color-text);
}
+.k-button:where([data-theme][data-variant="filled-icon"]) {
+ --button-color-back: var(--color-gray-300);
+ --button-color-icon: var(--theme-color-600);
+}
+
/** Icon Buttons **/
/** TODO: .k-button:not(:has(.k-button-text)) */
.k-button:not([data-has-text="true"]) {
From 3b8ce345c60e4d59281881cd24d0019d180edeac Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 11 Apr 2024 21:01:53 +0200
Subject: [PATCH 016/125] `k-button`: `theme="positive-icon"`
---
panel/src/components/Navigation/Button.vue | 14 ++++----
panel/src/components/Views/Pages/PageView.vue | 7 ----
panel/src/helpers/page.js | 6 ++--
panel/src/styles/utilities/theme.css | 36 +++++++++----------
4 files changed, 28 insertions(+), 35 deletions(-)
diff --git a/panel/src/components/Navigation/Button.vue b/panel/src/components/Navigation/Button.vue
index fb276f830f..4a572786b7 100644
--- a/panel/src/components/Navigation/Button.vue
+++ b/panel/src/components/Navigation/Button.vue
@@ -312,23 +312,23 @@ export default {
}
/** Filled Buttons **/
-.k-button:where([data-variant="filled"], [data-variant="filled-icon"]) {
+.k-button:where([data-variant="filled"]) {
--button-color-back: var(--color-gray-300);
}
.k-button:where([data-variant="filled"]):not([aria-disabled]):hover {
filter: brightness(97%);
}
-.k-button:where([data-theme][data-variant="filled"]) {
+.k-button:where([data-theme$="-icon"][data-variant="filled"]) {
+ --button-color-icon: var(--theme-color-600);
+}
+.k-button:where([data-theme][data-variant="filled"]):not(
+ [data-theme$="-icon"]
+ ) {
--button-color-icon: var(--theme-color-700);
--button-color-back: var(--theme-color-back);
--button-color-text: var(--theme-color-text);
}
-.k-button:where([data-theme][data-variant="filled-icon"]) {
- --button-color-back: var(--color-gray-300);
- --button-color-icon: var(--theme-color-600);
-}
-
/** Icon Buttons **/
/** TODO: .k-button:not(:has(.k-button-text)) */
.k-button:not([data-has-text="true"]) {
diff --git a/panel/src/components/Views/Pages/PageView.vue b/panel/src/components/Views/Pages/PageView.vue
index 114be29bd7..8fc70db8c0 100644
--- a/panel/src/components/Views/Pages/PageView.vue
+++ b/panel/src/components/Views/Pages/PageView.vue
@@ -51,7 +51,6 @@
v-if="status"
v-bind="statusBtn"
class="k-page-view-status"
- variant="filled"
@click="$dialog(id + '/changeStatus')"
/>
@@ -106,10 +105,4 @@ export default {
.k-page-view[data-has-tabs="true"] .k-page-view-header {
margin-bottom: 0;
}
-
-.k-page-view-status {
- --button-color-back: var(--color-gray-300);
- --button-color-icon: var(--theme-color-600);
- --button-color-text: initial;
-}
diff --git a/panel/src/helpers/page.js b/panel/src/helpers/page.js
index 8913549b51..af2a6bc0ad 100644
--- a/panel/src/helpers/page.js
+++ b/panel/src/helpers/page.js
@@ -24,11 +24,11 @@ export function status(status, disabled = false) {
}
if (status === "draft") {
- button.theme = "negative";
+ button.theme = "negative-icon";
} else if (status === "unlisted") {
- button.theme = "info";
+ button.theme = "info-icon";
} else {
- button.theme = "positive";
+ button.theme = "positive-icon";
}
return button;
diff --git a/panel/src/styles/utilities/theme.css b/panel/src/styles/utilities/theme.css
index 81587655fe..3b04cf241b 100644
--- a/panel/src/styles/utilities/theme.css
+++ b/panel/src/styles/utilities/theme.css
@@ -32,63 +32,63 @@
}
/* Color themes */
-[data-theme="red"],
-[data-theme="error"],
-[data-theme="negative"] {
+[data-theme^="red"],
+[data-theme^="error"],
+[data-theme^="negative"] {
--theme-color-h: var(--color-red-h);
--theme-color-s: var(--color-red-s);
--theme-color-boost: var(--color-red-boost);
}
-[data-theme="orange"],
-[data-theme="notice"] {
+[data-theme^="orange"],
+[data-theme^="notice"] {
--theme-color-h: var(--color-orange-h);
--theme-color-s: var(--color-orange-s);
--theme-color-boost: var(--color-orange-boost);
}
-[data-theme="yellow"],
-[data-theme="warning"] {
+[data-theme^="yellow"],
+[data-theme^="warning"] {
--theme-color-h: var(--color-yellow-h);
--theme-color-s: var(--color-yellow-s);
--theme-color-boost: var(--color-yellow-boost);
}
-[data-theme="blue"],
-[data-theme="info"] {
+[data-theme^="blue"],
+[data-theme^="info"] {
--theme-color-h: var(--color-blue-h);
--theme-color-s: var(--color-blue-s);
--theme-color-boost: var(--color-blue-boost);
}
-[data-theme="pink"],
-[data-theme="love"] {
+[data-theme^="pink"],
+[data-theme^="love"] {
--theme-color-h: var(--color-pink-h);
--theme-color-s: var(--color-pink-s);
--theme-color-boost: var(--color-pink-boost);
}
-[data-theme="green"],
-[data-theme="positive"] {
+[data-theme^="green"],
+[data-theme^="positive"] {
--theme-color-h: var(--color-green-h);
--theme-color-s: var(--color-green-s);
--theme-color-boost: var(--color-green-boost);
}
-[data-theme="aqua"] {
+[data-theme^="aqua"] {
--theme-color-h: var(--color-aqua-h);
--theme-color-s: var(--color-aqua-s);
--theme-color-boost: var(--color-aqua-boost);
}
-[data-theme="purple"] {
+[data-theme^="purple"] {
--theme-color-h: var(--color-purple-h);
--theme-color-s: var(--color-purple-s);
--theme-color-boost: var(--color-purple-boost);
}
-[data-theme="gray"],
-[data-theme="passive"] {
+[data-theme^="gray"],
+[data-theme^="passive"] {
--theme-color-h: var(--color-gray-h);
--theme-color-s: var(--color-gray-s);
--theme-color-boost: 10%;
@@ -103,7 +103,7 @@
}
/* Special Themes */
-[data-theme="dark"] {
+[data-theme^="dark"] {
--theme-color-h: var(--color-gray-h);
--theme-color-s: var(--color-gray-s);
--theme-color-boost: var(--color-gray-boost);
From b1b3a758d5e2984be7476224dc126369192adf5b Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 11 Apr 2024 21:06:38 +0200
Subject: [PATCH 017/125] Simplify CSS
---
panel/src/components/Navigation/Button.vue | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/panel/src/components/Navigation/Button.vue b/panel/src/components/Navigation/Button.vue
index 4a572786b7..8b7afd7b34 100644
--- a/panel/src/components/Navigation/Button.vue
+++ b/panel/src/components/Navigation/Button.vue
@@ -318,11 +318,9 @@ export default {
.k-button:where([data-variant="filled"]):not([aria-disabled]):hover {
filter: brightness(97%);
}
-.k-button:where([data-theme$="-icon"][data-variant="filled"]) {
- --button-color-icon: var(--theme-color-600);
-}
-.k-button:where([data-theme][data-variant="filled"]):not(
- [data-theme$="-icon"]
+
+.k-button:where([data-theme]):not([data-theme$="-icon"]):where(
+ [data-variant="filled"]
) {
--button-color-icon: var(--theme-color-700);
--button-color-back: var(--theme-color-back);
From 31d96d400a84e0adaa8a68323016aa2334b50e4c Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Tue, 23 Apr 2024 21:46:08 +0200
Subject: [PATCH 018/125] Fix regression
---
panel/src/components/Navigation/Button.vue | 1 +
1 file changed, 1 insertion(+)
diff --git a/panel/src/components/Navigation/Button.vue b/panel/src/components/Navigation/Button.vue
index 8b7afd7b34..5806bc0542 100644
--- a/panel/src/components/Navigation/Button.vue
+++ b/panel/src/components/Navigation/Button.vue
@@ -307,6 +307,7 @@ export default {
--button-color-text: var(--button-color-dimmed-off);
}
.k-button:where([data-theme][data-variant="dimmed"]) {
+ --button-color-icon: var(--theme-color-icon);
--button-color-dimmed-on: var(--theme-color-text-dimmed);
--button-color-dimmed-off: var(--theme-color-text);
}
From 2c99ade92965e473028104e45fb79c81cd34dbd6 Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Wed, 24 Apr 2024 15:47:29 +0200
Subject: [PATCH 019/125] Extend lab examples
---
panel/lab/components/buttons/2_themes/index.php | 1 +
panel/lab/components/buttons/2_themes/index.vue | 15 +++++++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/panel/lab/components/buttons/2_themes/index.php b/panel/lab/components/buttons/2_themes/index.php
index 9e3a1d31cf..3de529a8e3 100644
--- a/panel/lab/components/buttons/2_themes/index.php
+++ b/panel/lab/components/buttons/2_themes/index.php
@@ -7,6 +7,7 @@
'warning',
'positive',
'info',
+ 'love',
null,
'empty',
]
diff --git a/panel/lab/components/buttons/2_themes/index.vue b/panel/lab/components/buttons/2_themes/index.vue
index 2b6733e376..aee2f88d21 100644
--- a/panel/lab/components/buttons/2_themes/index.vue
+++ b/panel/lab/components/buttons/2_themes/index.vue
@@ -27,13 +27,24 @@
Button
+
+
+ Button
+
+
From 435a3ce35ffda3f7ae8ff237166fa03b56c505d0 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 25 Apr 2024 10:54:13 +0200
Subject: [PATCH 020/125] Fix text color of only-icon themed filled btn
---
panel/src/components/Navigation/Button.vue | 3 +++
1 file changed, 3 insertions(+)
diff --git a/panel/src/components/Navigation/Button.vue b/panel/src/components/Navigation/Button.vue
index 5806bc0542..12a8b46314 100644
--- a/panel/src/components/Navigation/Button.vue
+++ b/panel/src/components/Navigation/Button.vue
@@ -292,6 +292,9 @@ export default {
--button-color-icon: var(--theme-color-icon);
--button-color-text: var(--theme-color-text);
}
+.k-button[data-theme$="-icon"] {
+ --button-color-text: currentColor;
+}
/** Dimmed Buttons **/
.k-button:where([data-variant="dimmed"]) {
From 7db0c588076006fb40e1589e166d3ead5cc4d92b Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Thu, 25 Apr 2024 12:17:35 +0200
Subject: [PATCH 021/125] Improve theme and button styles
---
.../lab/components/buttons/2_themes/index.php | 15 +++++----
.../lab/components/buttons/2_themes/index.vue | 24 +++++++++++---
panel/src/components/Navigation/Button.vue | 32 +++++++++++--------
panel/src/styles/utilities/theme.css | 10 ++++--
4 files changed, 52 insertions(+), 29 deletions(-)
diff --git a/panel/lab/components/buttons/2_themes/index.php b/panel/lab/components/buttons/2_themes/index.php
index 3de529a8e3..7745db2cf1 100644
--- a/panel/lab/components/buttons/2_themes/index.php
+++ b/panel/lab/components/buttons/2_themes/index.php
@@ -2,13 +2,14 @@
return [
'themes' => [
- 'negative',
- 'notice',
- 'warning',
- 'positive',
- 'info',
- 'love',
null,
- 'empty',
+ 'red',
+ 'orange',
+ 'yellow',
+ 'green',
+ 'aqua',
+ 'blue',
+ 'purple',
+ 'pink',
]
];
diff --git a/panel/lab/components/buttons/2_themes/index.vue b/panel/lab/components/buttons/2_themes/index.vue
index aee2f88d21..b360bab703 100644
--- a/panel/lab/components/buttons/2_themes/index.vue
+++ b/panel/lab/components/buttons/2_themes/index.vue
@@ -1,11 +1,11 @@
-
+
Button
-
+
-
+
+
+ Button
+
+
+
-
+
Button
+
+ Button
+
diff --git a/panel/src/components/Navigation/Button.vue b/panel/src/components/Navigation/Button.vue
index 12a8b46314..e023dbff13 100644
--- a/panel/src/components/Navigation/Button.vue
+++ b/panel/src/components/Navigation/Button.vue
@@ -292,27 +292,28 @@ export default {
--button-color-icon: var(--theme-color-icon);
--button-color-text: var(--theme-color-text);
}
-.k-button[data-theme$="-icon"] {
+.k-button:where([data-theme$="-icon"]) {
--button-color-text: currentColor;
}
/** Dimmed Buttons **/
.k-button:where([data-variant="dimmed"]) {
--button-color-icon: var(--color-text);
- --button-color-dimmed-on: var(--color-text-dimmed);
- --button-color-dimmed-off: var(--color-text);
- --button-color-text: var(--button-color-dimmed-on);
+ --button-color-text: var(--color-text-dimmed);
}
.k-button:where([data-variant="dimmed"]):not([aria-disabled]):is(
:hover,
[aria-current]
- ) {
- --button-color-text: var(--button-color-dimmed-off);
+ )
+ .k-button-text {
+ filter: brightness(75%);
}
-.k-button:where([data-theme][data-variant="dimmed"]) {
+.k-button:where([data-variant="dimmed"][data-theme]) {
--button-color-icon: var(--theme-color-icon);
- --button-color-dimmed-on: var(--theme-color-text-dimmed);
- --button-color-dimmed-off: var(--theme-color-text);
+ --button-color-text: var(--theme-color-text-dimmed);
+}
+.k-button:where([data-variant="dimmed"][data-theme$="-icon"]) {
+ --button-color-text: var(--color-text-dimmed);
}
/** Filled Buttons **/
@@ -322,13 +323,16 @@ export default {
.k-button:where([data-variant="filled"]):not([aria-disabled]):hover {
filter: brightness(97%);
}
-
-.k-button:where([data-theme]):not([data-theme$="-icon"]):where(
- [data-variant="filled"]
- ) {
+.k-button:where([data-variant="filled"][data-theme]) {
--button-color-icon: var(--theme-color-700);
--button-color-back: var(--theme-color-back);
- --button-color-text: var(--theme-color-text);
+}
+.k-button:where([data-theme$="-icon"][data-variant="filled"]) {
+ --button-color-icon: hsl(
+ var(--theme-color-hs),
+ 57%
+ ); /* slightly improve the contrast */
+ --button-color-back: var(--color-gray-300);
}
/** Icon Buttons **/
diff --git a/panel/src/styles/utilities/theme.css b/panel/src/styles/utilities/theme.css
index 3b04cf241b..fcd4a8f1bf 100644
--- a/panel/src/styles/utilities/theme.css
+++ b/panel/src/styles/utilities/theme.css
@@ -25,7 +25,11 @@
--theme-color-900: hsl(var(--theme-color-hs), var(--theme-color-l-900));
--theme-color-text: var(--theme-color-900);
- --theme-color-text-dimmed: var(--theme-color-700);
+ --theme-color-text-dimmed: hsl(
+ var(--theme-color-h),
+ calc(var(--theme-color-s) - 60%),
+ 50%
+ );
--theme-color-back: var(--theme-color-400);
--theme-color-hover: var(--theme-color-500);
--theme-color-icon: var(--theme-color-600);
@@ -94,8 +98,8 @@
--theme-color-boost: 10%;
}
-[data-theme="white"],
-[data-theme="text"] {
+[data-theme^="white"],
+[data-theme^="text"] {
--theme-color-back: var(--color-white);
--theme-color-icon: var(--color-gray-800);
--theme-color-text: var(--color-text);
From abdc5baead92a0db6664973aecdbd2da24b1446c Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 25 Apr 2024 15:26:55 +0200
Subject: [PATCH 022/125] Language view: fix slot assignment
---
.../Views/Languages/LanguageView.vue | 53 ++++++++++---------
1 file changed, 28 insertions(+), 25 deletions(-)
diff --git a/panel/src/components/Views/Languages/LanguageView.vue b/panel/src/components/Views/Languages/LanguageView.vue
index f17d82a664..d2fe42e239 100644
--- a/panel/src/components/Views/Languages/LanguageView.vue
+++ b/panel/src/components/Views/Languages/LanguageView.vue
@@ -6,31 +6,34 @@
{{ name }}
-
-
-
-
-
+
+
+
+
+
+
+
+
From 5a7fdc57d43f6ace58a0d2d66e6e404d857d0cf4 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 25 Apr 2024 19:03:02 +0200
Subject: [PATCH 023/125] Clean up Panel js dev assets loading
---
src/Panel/Assets.php | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)
diff --git a/src/Panel/Assets.php b/src/Panel/Assets.php
index 808026b430..70dccfe081 100644
--- a/src/Panel/Assets.php
+++ b/src/Panel/Assets.php
@@ -201,8 +201,8 @@ public function favicons(): array
*/
public function icons(): string
{
- $dir = $this->kirby->root('panel') . '/';
- $dir .= $this->dev ? 'public' : 'dist';
+ $dir = $this->kirby->root('panel') . '/';
+ $dir .= $this->dev ? 'public' : 'dist';
$icons = F::read($dir . '/img/icons.svg');
$icons = preg_replace('//', '', $icons);
return $icons;
@@ -254,23 +254,18 @@ public function js(): array
// path to `index.js` - vendor does not need
// to be loaded in dev mode
if ($this->dev === true) {
+ // load the non-minified index.js, remove vendor script and
+ // development version of Vue
+ $js['vendor']['src'] = null;
+ $js['index']['src'] = $this->url . '/src/index.js';
+ $js['vue']['src'] = $this->url . '/node_modules/vue/dist/vue.js';
+
+ // add vite dev client
$js['vite'] = [
'nonce' => $this->nonce,
'src' => $this->url . '/@vite/client',
'type' => 'module'
];
-
- $js['index'] = [
- 'nonce' => $this->nonce,
- 'src' => $this->url . '/src/index.js',
- 'type' => 'module'
- ];
-
- // load the development version of Vue
- $js['vue']['src'] = $this->url . '/node_modules/vue/dist/vue.js';
-
- // remove the vendor script
- $js['vendor']['src'] = null;
}
return array_filter($js, fn ($js) => empty($js['src']) === false);
From 7b284fefeefd0757a0ad056a46f3d5fd943507dd Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 25 Apr 2024 20:07:05 +0200
Subject: [PATCH 024/125] Panel Assets: simplify code
---
src/Panel/Assets.php | 68 ++++++++++++++++++++------------------------
1 file changed, 31 insertions(+), 37 deletions(-)
diff --git a/src/Panel/Assets.php b/src/Panel/Assets.php
index 70dccfe081..1bf45a8669 100644
--- a/src/Panel/Assets.php
+++ b/src/Panel/Assets.php
@@ -56,13 +56,11 @@ public function __construct()
*/
public function css(): array
{
- $css = A::merge(
- [
- 'index' => $this->url . '/css/style.min.css',
- 'plugins' => $this->plugins->url('css')
- ],
- $this->custom('panel.css')
- );
+ $css = [
+ 'index' => $this->url . '/css/style.min.css',
+ 'plugins' => $this->plugins->url('css'),
+ ...$this->custom('panel.css')
+ ];
// during dev mode we do not need to load
// the general stylesheet (as styling will be inlined)
@@ -213,41 +211,37 @@ public function icons(): string
*/
public function js(): array
{
- $js = A::merge(
- [
- 'vue' => [
- 'nonce' => $this->nonce,
- 'src' => $this->url . '/js/vue.min.js'
- ],
- 'vendor' => [
- 'nonce' => $this->nonce,
- 'src' => $this->url . '/js/vendor.min.js',
- 'type' => 'module'
- ],
- 'pluginloader' => [
- 'nonce' => $this->nonce,
- 'src' => $this->url . '/js/plugins.js',
- 'type' => 'module'
- ],
- 'plugins' => [
- 'nonce' => $this->nonce,
- 'src' => $this->plugins->url('js'),
- 'defer' => true
- ]
+ $js = [
+ 'vue' => [
+ 'nonce' => $this->nonce,
+ 'src' => $this->url . '/js/vue.min.js'
+ ],
+ 'vendor' => [
+ 'nonce' => $this->nonce,
+ 'src' => $this->url . '/js/vendor.min.js',
+ 'type' => 'module'
+ ],
+ 'pluginloader' => [
+ 'nonce' => $this->nonce,
+ 'src' => $this->url . '/js/plugins.js',
+ 'type' => 'module'
],
- A::map($this->custom('panel.js'), fn ($src) => [
+ 'plugins' => [
+ 'nonce' => $this->nonce,
+ 'src' => $this->plugins->url('js'),
+ 'defer' => true
+ ],
+ ...A::map($this->custom('panel.js'), fn ($src) => [
'nonce' => $this->nonce,
'src' => $src,
'type' => 'module'
]),
- [
- 'index' => [
- 'nonce' => $this->nonce,
- 'src' => $this->url . '/js/index.min.js',
- 'type' => 'module'
- ],
- ]
- );
+ 'index' => [
+ 'nonce' => $this->nonce,
+ 'src' => $this->url . '/js/index.min.js',
+ 'type' => 'module'
+ ],
+ ];
// during dev mode, add vite client and adapt
From 69c77124509b1f00c348334ccb834a6574504d02 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 25 Apr 2024 20:07:17 +0200
Subject: [PATCH 025/125] Vite config: segment config code
---
panel/vite.config.mjs | 103 ++++++++++++++++++++++++++++--------------
1 file changed, 70 insertions(+), 33 deletions(-)
diff --git a/panel/vite.config.mjs b/panel/vite.config.mjs
index f7270d3894..a00619efee 100644
--- a/panel/vite.config.mjs
+++ b/panel/vite.config.mjs
@@ -4,21 +4,61 @@ import path from "path";
import { defineConfig, splitVendorChunkPlugin } from "vite";
import vue from "@vitejs/plugin-vue2";
import { viteStaticCopy } from "vite-plugin-static-copy";
-import externalGlobals from "rollup-plugin-external-globals";
+import externalize from "rollup-plugin-external-globals";
import kirby from "./scripts/vite-kirby.mjs";
-let customServer;
-try {
- customServer = require("./vite.config.custom.js");
-} catch (err) {
- customServer = {};
+/**
+ * Returns all aliases used in the project
+ */
+function createAliases() {
+ return {
+ "@": path.resolve(__dirname, "src")
+ };
}
-export default defineConfig(({ command }) => {
- // gather plugins depending on environment
+/**
+ * Returns the server configuration
+ */
+function createServer() {
+ const proxy = {
+ target: process.env.VUE_APP_DEV_SERVER ?? "http://sandbox.test",
+ changeOrigin: true,
+ secure: false
+ };
+
+ return {
+ proxy: {
+ "/api": proxy,
+ "/env": proxy,
+ "/media": proxy
+ },
+ open: proxy.target + "/panel",
+ port: 3000,
+ ...createCustomServer()
+ };
+}
+
+/**
+ * Returns custom server configuration, if it exists
+ */
+function createCustomServer() {
+ try {
+ return require("./vite.config.custom.js");
+ } catch {
+ return {};
+ }
+}
+
+/**
+ * Returns an array of plugins used,
+ * depending on the mode (development or build)
+ */
+function createPlugins(mode) {
const plugins = [vue(), splitVendorChunkPlugin(), kirby()];
- if (command === "build") {
+ // when building…
+ if (mode === "build") {
+ //copy Vue to the dist directory
plugins.push(
viteStaticCopy({
targets: [
@@ -36,20 +76,32 @@ export default defineConfig(({ command }) => {
// Externalize Vue so it's not loaded from node_modules
// but accessed via window.Vue
{
- ...externalGlobals({ vue: "Vue" }),
+ ...externalize({ vue: "Vue" }),
enforce: "post"
}
);
}
- const proxy = {
- target: process.env.VUE_APP_DEV_SERVER ?? "http://sandbox.test",
- changeOrigin: true,
- secure: false
+ return plugins;
+}
+
+/**
+ * Returns vitest configuration
+ */
+function createTest() {
+ return {
+ environment: "node",
+ include: ["**/*.test.js"],
+ setupFiles: ["vitest.setup.js"]
};
+}
+/**
+ * Returns the Vite configuration
+ */
+export default defineConfig(({ command }) => {
return {
- plugins,
+ plugins: createPlugins(command),
define: {
// Fix vuelidate error
"process.env.BUILD": JSON.stringify("production")
@@ -73,24 +125,9 @@ export default defineConfig(({ command }) => {
holdUntilCrawlEnd: false
},
resolve: {
- alias: {
- "@": path.resolve(__dirname, "src")
- }
- },
- server: {
- proxy: {
- "/api": proxy,
- "/env": proxy,
- "/media": proxy
- },
- open: proxy.target + "/panel",
- port: 3000,
- ...customServer
+ alias: createAliases()
},
- test: {
- environment: "node",
- include: ["**/*.test.js"],
- setupFiles: ["vitest.setup.js"]
- }
+ server: createServer(),
+ test: createTest()
};
});
From 134343c05d4e30998b4fff90506f99edaa13c8c1 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 25 Apr 2024 21:05:51 +0200
Subject: [PATCH 026/125] Improve button themes lab example
---
.../lab/components/buttons/2_themes/index.php | 15 -------
.../lab/components/buttons/2_themes/index.vue | 44 ++++++++++++++++---
2 files changed, 37 insertions(+), 22 deletions(-)
delete mode 100644 panel/lab/components/buttons/2_themes/index.php
diff --git a/panel/lab/components/buttons/2_themes/index.php b/panel/lab/components/buttons/2_themes/index.php
deleted file mode 100644
index 7745db2cf1..0000000000
--- a/panel/lab/components/buttons/2_themes/index.php
+++ /dev/null
@@ -1,15 +0,0 @@
- [
- null,
- 'red',
- 'orange',
- 'yellow',
- 'green',
- 'aqua',
- 'blue',
- 'purple',
- 'pink',
- ]
-];
diff --git a/panel/lab/components/buttons/2_themes/index.vue b/panel/lab/components/buttons/2_themes/index.vue
index b360bab703..5be3144971 100644
--- a/panel/lab/components/buttons/2_themes/index.vue
+++ b/panel/lab/components/buttons/2_themes/index.vue
@@ -1,11 +1,15 @@
-
+
Button
-
+
-
+
-
+
From 16482eb201c79fc57aab1de46f8f06977f65788f Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 25 Apr 2024 21:06:31 +0200
Subject: [PATCH 027/125] Fix button themes lab example once more
---
panel/lab/components/buttons/2_themes/index.vue | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/panel/lab/components/buttons/2_themes/index.vue b/panel/lab/components/buttons/2_themes/index.vue
index 5be3144971..5495e53baa 100644
--- a/panel/lab/components/buttons/2_themes/index.vue
+++ b/panel/lab/components/buttons/2_themes/index.vue
@@ -35,7 +35,11 @@
Button
-
+
Date: Fri, 26 Apr 2024 20:14:33 +0200
Subject: [PATCH 028/125] DropdownContent: support global events for `click`
---
.../components/Dropdowns/DropdownContent.vue | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/panel/src/components/Dropdowns/DropdownContent.vue b/panel/src/components/Dropdowns/DropdownContent.vue
index fafca3f62f..e5950994f3 100644
--- a/panel/src/components/Dropdowns/DropdownContent.vue
+++ b/panel/src/components/Dropdowns/DropdownContent.vue
@@ -187,10 +187,24 @@ export default {
onOptionClick(option) {
this.close();
+ // click handler is a callback function
+ // which is executed
if (typeof option.click === "function") {
- option.click.call(this);
- } else if (option.click) {
+ return option.click.call(this);
+ }
+
+ // click handler is an action string
+ // which is emitted to the parent as well as globally
+ if (typeof option.click === "string") {
this.$emit("action", option.click);
+ this.$events.emit("dropdown:" + option.click);
+ return;
+ }
+
+ // click handler is an object with a name and payload
+ // which is emitted globally
+ if (option.click) {
+ this.$events.emit(option.click.name, option.click.payload);
}
},
/**
From 9383b4eb9afe4d71909226870487ab8873e0385d Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 27 Apr 2024 11:42:38 +0200
Subject: [PATCH 029/125] Video KirbyTag: support `disablepictureinpicture`
---
config/tags.php | 2 ++
tests/Text/VideoKirbyTagTest.php | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/config/tags.php b/config/tags.php
index e90c1eb7ac..0c5ac780f0 100644
--- a/config/tags.php
+++ b/config/tags.php
@@ -252,6 +252,7 @@
'caption',
'controls',
'class',
+ 'disablepictureinpicture',
'height',
'loop',
'muted',
@@ -300,6 +301,7 @@
// for ex : `autoplay` will not work if `false` is a `string` instead of a `boolean`
$attrs['autoplay'] = $autoplay = Str::toType($tag->autoplay, 'bool');
$attrs['controls'] = Str::toType($tag->controls ?? true, 'bool');
+ $attrs['disablepictureinpicture'] = Str::toType($tag->disablepictureinpicture ?? false, 'bool');
$attrs['loop'] = Str::toType($tag->loop, 'bool');
$attrs['muted'] = Str::toType($tag->muted ?? $autoplay, 'bool');
$attrs['playsinline'] = Str::toType($tag->playsinline ?? $autoplay, 'bool');
diff --git a/tests/Text/VideoKirbyTagTest.php b/tests/Text/VideoKirbyTagTest.php
index 62eb5f2809..b757ea3959 100644
--- a/tests/Text/VideoKirbyTagTest.php
+++ b/tests/Text/VideoKirbyTagTest.php
@@ -67,6 +67,7 @@ public function testInlineAttrs()
caption: Lorem ipsum
controls: false
class: video-class
+ disablepictureinpicture: true
height: 350
loop: true
muted: true
@@ -90,7 +91,7 @@ class: video-class
$image = $page->file('sample.jpg');
$video = $page->file('sample.mp4');
- $expected = 'Lorem ipsum ';
+ $expected = 'Lorem ipsum ';
$this->assertSame($expected, $page->text()->kt()->value());
}
From f5440d765bbdb2db2753635b63eb0348be6e5846 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 27 Apr 2024 12:20:30 +0200
Subject: [PATCH 030/125] Page section: show Add based on `create` status
---
config/sections/pages.php | 57 +++++++++++++++++++++++++++------------
1 file changed, 40 insertions(+), 17 deletions(-)
diff --git a/config/sections/pages.php b/config/sections/pages.php
index 79424b44bc..fbb022edb6 100644
--- a/config/sections/pages.php
+++ b/config/sections/pages.php
@@ -232,11 +232,30 @@
return false;
}
- if (in_array($this->status, ['draft', 'all']) === false) {
+ if ($this->isFull() === true) {
return false;
}
- if ($this->isFull() === true) {
+ // ensure that the add button is only shown when
+ // the section is displaying pages with the same status
+ // as the status that is used for page creation
+ $statuses = [];
+
+ foreach ($this->blueprintNames() as $blueprint) {
+ try {
+ $props = Blueprint::load('pages/' . $blueprint);
+ $statuses[] = $props['create']['status'] ?? 'draft';
+ } catch (Throwable) {
+ }
+ }
+
+ $statuses = array_unique($statuses);
+
+ if (count($statuses) > 1 && $this->status !== 'all') {
+ return false;
+ }
+
+ if (in_array($this->status, [...$statuses, 'all']) === false) {
return false;
}
@@ -249,22 +268,12 @@
'methods' => [
'blueprints' => function () {
$blueprints = [];
- $templates = empty($this->create) === false ? A::wrap($this->create) : $this->templates;
-
- if (empty($templates) === true) {
- $templates = $this->kirby()->blueprints();
- }
-
- // excludes ignored templates
- if ($templatesIgnore = $this->templatesIgnore) {
- $templates = array_diff($templates, $templatesIgnore);
- }
// convert every template to a usable option array
// for the template select box
- foreach ($templates as $template) {
+ foreach ($this->blueprintNames() as $blueprint) {
try {
- $props = Blueprint::load('pages/' . $template);
+ $props = Blueprint::load('pages/' . $blueprint);
$blueprints[] = [
'name' => basename($props['name']),
@@ -272,14 +281,28 @@
];
} catch (Throwable) {
$blueprints[] = [
- 'name' => basename($template),
- 'title' => ucfirst($template),
+ 'name' => basename($blueprint),
+ 'title' => ucfirst($blueprint),
];
}
}
return $blueprints;
- }
+ },
+ 'blueprintNames' => function () {
+ $blueprints = empty($this->create) === false ? A::wrap($this->create) : $this->templates;
+
+ if (empty($blueprints) === true) {
+ $blueprints = $this->kirby()->blueprints();
+ }
+
+ // excludes ignored templates
+ if ($templatesIgnore = $this->templatesIgnore) {
+ $blueprints = array_diff($blueprints, $templatesIgnore);
+ }
+
+ return $blueprints;
+ },
],
'toArray' => function () {
return [
From 50208fd9e52eb282faf7ef75385bc98b1965c8ae Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 27 Apr 2024 12:47:05 +0200
Subject: [PATCH 031/125] Remove server allowlist
---
i18n/translations/en.json | 1 -
src/Cms/System.php | 39 ++++----------
tests/Cms/Api/routes/SystemRoutesTest.php | 15 ------
tests/Cms/System/SystemTest.php | 62 ++++-------------------
tests/Panel/Areas/InstallationTest.php | 13 ++---
5 files changed, 23 insertions(+), 107 deletions(-)
diff --git a/i18n/translations/en.json b/i18n/translations/en.json
index 5fa13376d9..045ff8b8c5 100644
--- a/i18n/translations/en.json
+++ b/i18n/translations/en.json
@@ -386,7 +386,6 @@
"installation.issues.mbstring": "The MB String
extension is required",
"installation.issues.media": "The /media
folder does not exist or is not writable",
"installation.issues.php": "Make sure to use PHP 8+
",
- "installation.issues.server": "Kirby requires Apache
, Nginx
or Caddy
",
"installation.issues.sessions": "The /site/sessions
folder does not exist or is not writable",
"language": "Language",
diff --git a/src/Cms/System.php b/src/Cms/System.php
index 472c7568c5..9998e12068 100644
--- a/src/Cms/System.php
+++ b/src/Cms/System.php
@@ -379,32 +379,12 @@ public function register(string $license = null, string $email = null): bool
return true;
}
- /**
- * Check for a valid server environment
- */
- public function server(): bool
- {
- return $this->serverSoftware() !== null;
- }
-
/**
* Returns the detected server software
*/
- public function serverSoftware(): string|null
+ public function serverSoftware(): string
{
- $servers = $this->app->option('servers', [
- 'apache',
- 'caddy',
- 'litespeed',
- 'nginx',
- 'php'
- ]);
-
- $software = $this->app->environment()->get('SERVER_SOFTWARE', '');
-
- preg_match('!(' . implode('|', A::wrap($servers)) . ')!i', $software, $matches);
-
- return $matches[0] ?? null;
+ return $this->app->environment()->get('SERVER_SOFTWARE', '–');
}
/**
@@ -421,14 +401,13 @@ public function sessions(): bool
public function status(): array
{
return [
- 'accounts' => $this->accounts(),
- 'content' => $this->content(),
- 'curl' => $this->curl(),
- 'sessions' => $this->sessions(),
- 'mbstring' => $this->mbstring(),
- 'media' => $this->media(),
- 'php' => $this->php(),
- 'server' => $this->server(),
+ 'accounts' => $this->accounts(),
+ 'content' => $this->content(),
+ 'curl' => $this->curl(),
+ 'sessions' => $this->sessions(),
+ 'mbstring' => $this->mbstring(),
+ 'media' => $this->media(),
+ 'php' => $this->php()
];
}
diff --git a/tests/Cms/Api/routes/SystemRoutesTest.php b/tests/Cms/Api/routes/SystemRoutesTest.php
index f182c8047e..0ff085355c 100644
--- a/tests/Cms/Api/routes/SystemRoutesTest.php
+++ b/tests/Cms/Api/routes/SystemRoutesTest.php
@@ -19,21 +19,6 @@ public function setUp(): void
]);
}
- public function testGetWithInvalidServerSoftware()
- {
- // set invalid server software
- $app = $this->app->clone([
- 'server' => [
- 'SERVER_SOFTWARE' => 'invalid'
- ]
- ]);
-
- $response = $app->api()->call('system', 'GET');
-
- $this->assertFalse($response['data']['isOk']);
- $this->assertFalse($response['data']['requirements']['server']);
- }
-
public function testGetWithValidServerSoftware()
{
$app = $this->app->clone([
diff --git a/tests/Cms/System/SystemTest.php b/tests/Cms/System/SystemTest.php
index d0107d59d4..de49b869f9 100644
--- a/tests/Cms/System/SystemTest.php
+++ b/tests/Cms/System/SystemTest.php
@@ -135,8 +135,9 @@ public static function providerForServerSoftware(): array
['Nginx', true],
['caddy', true],
['Caddy', true],
- ['iis', false],
- ['something', false],
+ ['iis', true],
+ ['something', true],
+ [null, false]
];
}
@@ -619,11 +620,10 @@ public function testPlugins()
}
/**
- * @covers ::server
* @covers ::serverSoftware
* @dataProvider providerForServerSoftware
*/
- public function testServer($software, $expected)
+ public function testServerSoftware($software, $expected)
{
$app = $this->app->clone([
'server' => [
@@ -632,56 +632,14 @@ public function testServer($software, $expected)
]);
$system = new System($app);
- $server = $system->server();
-
- $this->assertSame($expected, $server);
if ($expected === true) {
$this->assertSame($software, $system->serverSoftware());
} else {
- $this->assertNull($system->serverSoftware());
+ $this->assertSame('–', $system->serverSoftware());
}
}
- /**
- * @covers ::server
- * @covers ::serverSoftware
- */
- public function testServerOverwrite()
- {
- // single server
- $app = $this->app->clone([
- 'options' => [
- 'servers' => 'symfony'
- ],
- 'server' => [
- 'SERVER_SOFTWARE' => 'symfony'
- ]
- ]);
-
- $system = new System($app);
- $server = $system->server();
-
- $this->assertSame('symfony', $system->serverSoftware());
- $this->assertTrue($server);
-
- // array of servers
- $app = $this->app->clone([
- 'options' => [
- 'servers' => ['symfony', 'apache']
- ],
- 'server' => [
- 'SERVER_SOFTWARE' => 'symfony'
- ]
- ]);
-
- $system = new System($app);
- $server = $system->server();
-
- $this->assertSame('symfony', $system->serverSoftware());
- $this->assertTrue($server);
- }
-
/**
* @covers ::accounts
* @covers ::content
@@ -690,7 +648,6 @@ public function testServerOverwrite()
* @covers ::mbstring
* @covers ::media
* @covers ::php
- * @covers ::server
* @covers ::status
* @covers ::toArray
* @covers ::__debugInfo
@@ -701,13 +658,12 @@ public function testStatus()
$expected = [
'accounts' => true,
- 'content' => true,
- 'curl' => true,
+ 'content' => true,
+ 'curl' => true,
'sessions' => true,
'mbstring' => true,
- 'media' => true,
- 'php' => true,
- 'server' => false,
+ 'media' => true,
+ 'php' => true
];
$this->assertSame($expected, $system->status());
$this->assertSame($expected, $system->toArray());
diff --git a/tests/Panel/Areas/InstallationTest.php b/tests/Panel/Areas/InstallationTest.php
index b469d12793..89d25fee51 100644
--- a/tests/Panel/Areas/InstallationTest.php
+++ b/tests/Panel/Areas/InstallationTest.php
@@ -21,20 +21,18 @@ public function testInstallation()
$this->assertSame('Installation', $view['title']);
$this->assertSame('k-installation-view', $view['component']);
- // cli is not a valid server, therefor installation fails
$this->assertFalse($view['props']['isInstallable']);
$this->assertFalse($view['props']['isInstalled']);
- $this->assertFalse($view['props']['isOk']);
+ $this->assertTrue($view['props']['isOk']);
$requirements = [
'accounts' => true,
- 'content' => true,
- 'curl' => true,
+ 'content' => true,
+ 'curl' => true,
'sessions' => true,
'mbstring' => true,
- 'media' => true,
- 'php' => true,
- 'server' => false
+ 'media' => true,
+ 'php' => true,
];
$this->assertSame($requirements, $view['props']['requirements']);
@@ -53,7 +51,6 @@ public function testInstallationWhenReady()
$this->assertTrue($view['props']['isInstallable']);
$this->assertFalse($view['props']['isInstalled']);
$this->assertTrue($view['props']['isOk']);
- $this->assertTrue($view['props']['requirements']['server']);
}
public function testInstallationWhenInstalled()
From fd14c381f46f710af15a612aa9cf7603a9af8ee8 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 27 Apr 2024 13:01:21 +0200
Subject: [PATCH 032/125] System view: copy info
---
i18n/translations/en.json | 2 ++
.../components/Views/System/SystemView.vue | 36 ++++++++++++++++++-
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/i18n/translations/en.json b/i18n/translations/en.json
index 5fa13376d9..4fcaf4906d 100644
--- a/i18n/translations/en.json
+++ b/i18n/translations/en.json
@@ -618,6 +618,8 @@
"stats.empty": "No reports",
"status": "Status",
+ "system.info.copy": "Copy info",
+ "system.info.copied": "System info copied",
"system.issues.content": "The content folder seems to be exposed",
"system.issues.eol.kirby": "Your installed Kirby version has reached end-of-life and will not receive further security updates",
"system.issues.eol.plugin": "Your installed version of the { plugin } plugin is has reached end-of-life and will not receive further security updates",
diff --git a/panel/src/components/Views/System/SystemView.vue b/panel/src/components/Views/System/SystemView.vue
index 67e96d37a9..aa2d8f0e5f 100644
--- a/panel/src/components/Views/System/SystemView.vue
+++ b/panel/src/components/Views/System/SystemView.vue
@@ -4,7 +4,17 @@
{{ $t("view.system") }}
-
+
@@ -42,6 +52,30 @@ export default {
this.exceptions.map((exception) => console.warn(exception));
console.info("End of errors from the update check.");
}
+ },
+ methods: {
+ copy() {
+ const info = JSON.stringify(
+ {
+ version: this.environment[1].value,
+ license: this.environment[0].value,
+ php: this.environment[2].value,
+ server: this.environment[3].value,
+ security: this.security.map((issue) => issue.text),
+ plugins: this.plugins.map((plugin) => ({
+ name: plugin.name.text,
+ version: plugin.version.currentVersion
+ }))
+ },
+ null,
+ 2
+ );
+
+ this.$helper.clipboard.write(info);
+ this.$panel.notification.success({
+ message: this.$t("system.info.copied")
+ });
+ }
}
};
From 22d7a2aa540fe3c5c493d73253973d98ff935e5f Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 27 Apr 2024 13:41:01 +0200
Subject: [PATCH 033/125] Remove dead code
---
panel/src/components/Views/Files/FileView.vue | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/panel/src/components/Views/Files/FileView.vue b/panel/src/components/Views/Files/FileView.vue
index 55b84040fe..04414c8246 100644
--- a/panel/src/components/Views/Files/FileView.vue
+++ b/panel/src/components/Views/Files/FileView.vue
@@ -86,16 +86,6 @@ export default {
const [x, y] = focus.replaceAll("%", "").split(" ");
return { x: parseFloat(x), y: parseFloat(y) };
- },
- isFocusable() {
- return (
- !this.isLocked &&
- this.preview.image.src &&
- this.permissions.update &&
- (!window.panel.multilang ||
- window.panel.languages.length === 0 ||
- window.panel.language.default)
- );
}
},
methods: {
From 0e9a9009e15c6834ba85534cce571bb45cbf2b9d Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sat, 27 Apr 2024 18:39:25 +0200
Subject: [PATCH 034/125] DRY button props
---
.../src/components/Dropdowns/DropdownItem.vue | 13 ++---
panel/src/components/Navigation/Button.vue | 52 +++++++------------
panel/src/components/Navigation/Link.vue | 42 ++++++++++++---
3 files changed, 55 insertions(+), 52 deletions(-)
diff --git a/panel/src/components/Dropdowns/DropdownItem.vue b/panel/src/components/Dropdowns/DropdownItem.vue
index e161800a9a..ca860eee82 100644
--- a/panel/src/components/Dropdowns/DropdownItem.vue
+++ b/panel/src/components/Dropdowns/DropdownItem.vue
@@ -11,23 +11,16 @@
From fd1ae628f1b4e47d6c95c4cdaf9af474010c996d Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Mon, 29 Apr 2024 14:48:25 +0200
Subject: [PATCH 043/125] Fix permissions
Co-authored-by: Lukas Bestle
---
tests/Cms/System/SystemTest.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/Cms/System/SystemTest.php b/tests/Cms/System/SystemTest.php
index 922ff73477..8c8ec73351 100644
--- a/tests/Cms/System/SystemTest.php
+++ b/tests/Cms/System/SystemTest.php
@@ -511,7 +511,7 @@ public function testIsOkContentMissingPermissions()
$system = new System($app);
$before = fileperms($app->root('content'));
- chmod($app->root('content'), 0000);
+ chmod($app->root('content'), 0o000);
$this->assertFalse($system->isOk());
From 98332ba60c416c6ed552579c1eb5061897ba5aa6 Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Mon, 29 Apr 2024 16:04:31 +0200
Subject: [PATCH 044/125] Use fields from parent dialog
---
.../components/Forms/Toolbar/EmailDialog.vue | 22 ++++++++-----------
1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/panel/src/components/Forms/Toolbar/EmailDialog.vue b/panel/src/components/Forms/Toolbar/EmailDialog.vue
index 3c1c225615..4caa63b36d 100644
--- a/panel/src/components/Forms/Toolbar/EmailDialog.vue
+++ b/panel/src/components/Forms/Toolbar/EmailDialog.vue
@@ -6,19 +6,15 @@ export default {
props: {
// eslint-disable-next-line vue/require-prop-types
fields: {
- default: () => ({
- href: {
- label: window.panel.$t("email"),
- type: "email",
- icon: "email"
- },
- title: {
- label: window.panel.$t("link.text"),
- type: "text",
- icon: "title"
- }
- })
- },
+ default: () => {
+ const fields = EmailDialog.props.fields.default();
+
+ // change the label to "Link Text"
+ fields.title.label = window.panel.$t("link.text");
+
+ return fields;
+ }
+ }
},
methods: {
submit() {
From 0167ed733370ff26acb6c4c48d3bf026e82374ac Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Mon, 29 Apr 2024 19:47:35 +0200
Subject: [PATCH 045/125] Adaptations after code review
---
.../src/components/Dropdowns/DropdownContent.vue | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/panel/src/components/Dropdowns/DropdownContent.vue b/panel/src/components/Dropdowns/DropdownContent.vue
index e5950994f3..6bf446ec3c 100644
--- a/panel/src/components/Dropdowns/DropdownContent.vue
+++ b/panel/src/components/Dropdowns/DropdownContent.vue
@@ -194,17 +194,21 @@ export default {
}
// click handler is an action string
- // which is emitted to the parent as well as globally
+ // which is emitted to the parent
if (typeof option.click === "string") {
- this.$emit("action", option.click);
- this.$events.emit("dropdown:" + option.click);
- return;
+ return this.$emit("action", option.click);
}
// click handler is an object with a name and payload
- // which is emitted globally
+ // and optional flag to also emit globally
if (option.click) {
- this.$events.emit(option.click.name, option.click.payload);
+ if (option.click.name) {
+ this.$emit(option.click.name, option.click.payload);
+ }
+
+ if (option.click.global) {
+ this.$events.emit(option.click.global, option.click.payload);
+ }
}
},
/**
From e2c2632be88fd0b8ed6afb85eb8887b065eead98 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Tue, 30 Apr 2024 11:50:05 +0200
Subject: [PATCH 046/125] Panel notifcations: support themes
---
.../internals/panel/notification/index.vue | 45 +++++++++++++------
panel/src/panel/notification.js | 26 ++++-------
panel/src/panel/notification.test.js | 1 +
3 files changed, 41 insertions(+), 31 deletions(-)
diff --git a/panel/lab/internals/panel/notification/index.vue b/panel/lab/internals/panel/notification/index.vue
index 2e46b6f1c1..931725e871 100644
--- a/panel/lab/internals/panel/notification/index.vue
+++ b/panel/lab/internals/panel/notification/index.vue
@@ -9,7 +9,7 @@
{{ $panel.notification.context || " " }}
@@ -24,7 +24,7 @@
{{ $panel.notification.details || " " }}
{{ $panel.notification.icon || " " }}
{{ $panel.notification.message || " " }}
{{ $panel.notification.timeout || " " }}
{{ $panel.notification.type || " " }}
window.panel.notification.close();
Closes the current notification
@@ -136,7 +136,7 @@
>
Used to show a deprecation warning in the console.
@@ -149,7 +149,7 @@
>
Displays an error notification.
@@ -162,7 +162,7 @@
>
Displays a fatal error in an iframe overlay for better isolation
@@ -174,11 +174,18 @@
>window.panel.notification.open(notification);
Open a custom notification
+
+
+
@@ -190,7 +197,7 @@
>
Displays a success notification
@@ -198,3 +205,15 @@
+
+
diff --git a/panel/src/panel/notification.js b/panel/src/panel/notification.js
index 27639f93ef..e487929b81 100644
--- a/panel/src/panel/notification.js
+++ b/panel/src/panel/notification.js
@@ -11,6 +11,7 @@ export const defaults = () => {
icon: null,
isOpen: false,
message: null,
+ theme: null,
timeout: null,
type: null
};
@@ -89,8 +90,7 @@ export default (panel = {}) => {
// convert strings to full error objects
if (typeof error === "string") {
error = {
- message: error,
- type: "error"
+ message: error
};
}
@@ -105,16 +105,16 @@ export default (panel = {}) => {
if (panel.context === "view") {
panel.dialog.open({
component: "k-error-dialog",
- props: error,
- type: "error"
+ props: error
});
}
// show the error notification bar
return this.open({
message: error.message,
- type: "error",
- icon: "alert"
+ icon: "alert",
+ theme: "negative",
+ type: "error"
});
},
@@ -209,23 +209,13 @@ export default (panel = {}) => {
}
return this.open({
- timeout: 4000,
- type: "success",
icon: "check",
+ theme: "positive",
+ timeout: 4000,
...success
});
},
- /**
- * Getter that converts the notification type
- * into the matching notification component theme
- *
- * @returns {String}
- */
- get theme() {
- return this.type === "error" ? "negative" : "positive";
- },
-
/**
* Holds the timer object
*/
diff --git a/panel/src/panel/notification.test.js b/panel/src/panel/notification.test.js
index 44c3814e74..d286073d20 100644
--- a/panel/src/panel/notification.test.js
+++ b/panel/src/panel/notification.test.js
@@ -19,6 +19,7 @@ describe("panel.notification", () => {
icon: null,
isOpen: false,
message: null,
+ theme: null,
timeout: null,
type: null
};
From ca7966d5e927fee1c103883a7a8cbb92f30bea86 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Tue, 30 Apr 2024 12:02:59 +0200
Subject: [PATCH 047/125] Panel notification: improve timeout handling
---
panel/src/panel/notification.js | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/panel/src/panel/notification.js b/panel/src/panel/notification.js
index e487929b81..a118491a4f 100644
--- a/panel/src/panel/notification.js
+++ b/panel/src/panel/notification.js
@@ -174,6 +174,11 @@ export default (panel = {}) => {
return this.success(notification);
}
+ // add timeout if not error or fatal notification
+ if (notification.type !== "error" && notification.type !== "fatal") {
+ notification.timeout ??= 4000;
+ }
+
// set the new state
this.set({
// add the current editing context
@@ -211,7 +216,6 @@ export default (panel = {}) => {
return this.open({
icon: "check",
theme: "positive",
- timeout: 4000,
...success
});
},
From 154a573ed76992ec36b8bfb9d78987e9f4051865 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Tue, 30 Apr 2024 12:06:37 +0200
Subject: [PATCH 048/125] `panel.notification.info(message)`
---
.../internals/panel/notification/index.vue | 13 ++++++++++
panel/src/panel/modal.test.js | 2 +-
panel/src/panel/notification.js | 26 +++++++++++++++----
panel/src/panel/notification.test.js | 8 ++++--
4 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/panel/lab/internals/panel/notification/index.vue b/panel/lab/internals/panel/notification/index.vue
index 931725e871..4e109f7630 100644
--- a/panel/lab/internals/panel/notification/index.vue
+++ b/panel/lab/internals/panel/notification/index.vue
@@ -55,6 +55,19 @@
/>
+
+
+ window.panel.notification.info(notification);
+ Displays an info notification
+
+
+
diff --git a/panel/src/panel/modal.test.js b/panel/src/panel/modal.test.js
index 7a8a50e5e5..f2eb71a252 100644
--- a/panel/src/panel/modal.test.js
+++ b/panel/src/panel/modal.test.js
@@ -147,8 +147,8 @@ describe.concurrent("panel/modal.js", () => {
message: "Test"
});
- expect(panel.notification.type).toStrictEqual("success");
expect(panel.notification.message).toStrictEqual("Test");
+ expect(panel.notification.theme).toStrictEqual("positive");
});
it("should emit panel events after submit", async () => {
diff --git a/panel/src/panel/notification.js b/panel/src/panel/notification.js
index a118491a4f..b99811626b 100644
--- a/panel/src/panel/notification.js
+++ b/panel/src/panel/notification.js
@@ -118,6 +118,26 @@ export default (panel = {}) => {
});
},
+ /**
+ * Shortcut to create an info
+ * notification. You can pass a simple
+ * string or a state object.
+ *
+ * @param {Object|String} info
+ * @returns {Object} The notification state
+ */
+ info(info = {}) {
+ if (typeof info === "string") {
+ info = { message: info };
+ }
+
+ return this.open({
+ icon: "info",
+ theme: "info",
+ ...info
+ });
+ },
+
/**
* Checks if the notification is a fatal
* error. Those are displayed in the
@@ -204,11 +224,7 @@ export default (panel = {}) => {
* @param {Object|String} success
* @returns {Object} The notification state
*/
- success(success) {
- if (!success) {
- success = {};
- }
-
+ success(success = {}) {
if (typeof success === "string") {
success = { message: success };
}
diff --git a/panel/src/panel/notification.test.js b/panel/src/panel/notification.test.js
index d286073d20..d53d91c1a1 100644
--- a/panel/src/panel/notification.test.js
+++ b/panel/src/panel/notification.test.js
@@ -100,12 +100,16 @@ describe("panel.notification", () => {
const notification = Notification(panel);
notification.success("Test");
-
expect(notification.theme).toStrictEqual("positive");
- notification.error("Test");
+ notification.info("Test");
+ expect(notification.theme).toStrictEqual("info");
+ notification.error("Test");
expect(notification.theme).toStrictEqual("negative");
+
+ notification.open({ theme: "love" });
+ expect(notification.theme).toStrictEqual("love");
});
it("should set a timer for success notifications", async () => {
From 324859318c7243b919f302a28b9b5211fcfe498c Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Tue, 30 Apr 2024 19:33:51 +0200
Subject: [PATCH 049/125] Fix DropdownItem
---
.../src/components/Dropdowns/DropdownItem.vue | 26 ++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/panel/src/components/Dropdowns/DropdownItem.vue b/panel/src/components/Dropdowns/DropdownItem.vue
index ca860eee82..4793a6db18 100644
--- a/panel/src/components/Dropdowns/DropdownItem.vue
+++ b/panel/src/components/Dropdowns/DropdownItem.vue
@@ -1,7 +1,16 @@
@@ -10,6 +19,8 @@
+current: [Boolean, String],
+
diff --git a/panel/src/components/Dialogs/Elements/index.js b/panel/src/components/Dialogs/Elements/index.js
index 31b12f8f4f..68420b4066 100644
--- a/panel/src/components/Dialogs/Elements/index.js
+++ b/panel/src/components/Dialogs/Elements/index.js
@@ -6,6 +6,8 @@ import Notification from "./Notification.vue";
import Search from "./Search.vue";
import Text from "./Text.vue";
+import UploadPreview from "./UploadPreview.vue";
+
export default {
install(app) {
app.component("k-dialog-body", Body);
@@ -15,5 +17,7 @@ export default {
app.component("k-dialog-notification", Notification);
app.component("k-dialog-search", Search);
app.component("k-dialog-text", Text);
+
+ app.component("k-upload-dialog-preview", UploadPreview);
}
};
diff --git a/panel/src/components/Dialogs/UploadDialog.vue b/panel/src/components/Dialogs/UploadDialog.vue
index 966cc61ea6..5f7e70a3b3 100644
--- a/panel/src/components/Dialogs/UploadDialog.vue
+++ b/panel/src/components/Dialogs/UploadDialog.vue
@@ -8,81 +8,76 @@
@submit="$emit('submit')"
>
-
-
- {{ $t("files.empty") }}
-
-
-
-
-
-
-
-
-
-
+
+ {{ $t("files.empty") }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ file.niceSize }}
+ - {{ file.progress }}%
+
+
+ {{ file.error }}
+
+
-
-
- {{ file.niceSize }}
-
- - {{ file.progress }}%
-
-
-
- {{ file.error }}
-
-
-
-
-
+
-
-
-
+
+
+
@@ -105,34 +100,6 @@ export default {
};
}
}
- },
- methods: {
- isPreviewable(mime) {
- return [
- "image/jpeg",
- "image/jpg",
- "image/gif",
- "image/png",
- "image/webp",
- "image/avif",
- "image/svg+xml"
- ].includes(mime);
- },
- previewIcon(mime) {
- if (mime.startsWith("image/")) {
- return "file-image";
- }
-
- if (mime.startsWith("audio/")) {
- return "file-audio";
- }
-
- if (mime.startsWith("video/")) {
- return "file-video";
- }
-
- return "file";
- }
}
};
diff --git a/panel/src/components/Dialogs/UploadReplaceDialog.vue b/panel/src/components/Dialogs/UploadReplaceDialog.vue
index a47204c927..f7c20ebf70 100644
--- a/panel/src/components/Dialogs/UploadReplaceDialog.vue
+++ b/panel/src/components/Dialogs/UploadReplaceDialog.vue
@@ -8,18 +8,11 @@
>
-
-
@@ -31,21 +24,13 @@
:data-completed="file.completed"
class="k-upload-item"
>
-
-
-
-
+
+
+
{{ file.niceSize }}
@@ -60,12 +46,14 @@
{{ file.error }}
+
+
+
From 34927ce990a61b7d84ae5f69749034ce1b8544a3 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Tue, 30 Apr 2024 19:40:33 +0200
Subject: [PATCH 054/125] CSS fixes
---
panel/src/components/Dialogs/Elements/UploadPreview.vue | 2 +-
panel/src/components/Dialogs/UploadDialog.vue | 2 ++
panel/src/components/Dialogs/UploadReplaceDialog.vue | 5 +++++
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/panel/src/components/Dialogs/Elements/UploadPreview.vue b/panel/src/components/Dialogs/Elements/UploadPreview.vue
index 790ed3246c..7a5f4b94c3 100644
--- a/panel/src/components/Dialogs/Elements/UploadPreview.vue
+++ b/panel/src/components/Dialogs/Elements/UploadPreview.vue
@@ -1,5 +1,5 @@
-
+
Date: Wed, 1 May 2024 13:34:44 +0200
Subject: [PATCH 055/125] CalendarInput: fix when no value
---
panel/src/components/Forms/Input/CalendarInput.vue | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/panel/src/components/Forms/Input/CalendarInput.vue b/panel/src/components/Forms/Input/CalendarInput.vue
index 3acfdaa3cf..c6b102adff 100644
--- a/panel/src/components/Forms/Input/CalendarInput.vue
+++ b/panel/src/components/Forms/Input/CalendarInput.vue
@@ -99,13 +99,15 @@ import { IsoDateProps } from "./DateInput.vue";
export default {
mixins: [InputProps, IsoDateProps],
data() {
+ const today = this.$library.dayjs();
+
return {
maxdate: null,
mindate: null,
- month: null,
+ month: today.month(),
selected: null,
- today: this.$library.dayjs(),
- year: null
+ today: today,
+ year: today.year()
};
},
computed: {
@@ -309,8 +311,10 @@ export default {
* @param {number} day
* @param {number} month
*/
- toDate(day = 1, month = this.month) {
- return this.$library.dayjs(`${this.year}-${month + 1}-${day}`);
+ toDate(day = 1, month) {
+ return this.$library.dayjs(
+ `${this.year}-${(month ?? this.month) + 1}-${day}`
+ );
},
/**
* Generates select options between min and max
From d40c0fb579b84c8e209953be002950882d70d6ab Mon Sep 17 00:00:00 2001
From: Lukas Bestle
Date: Wed, 1 May 2024 13:38:40 +0200
Subject: [PATCH 056/125] Clean up permissions in `tearDown()`
---
tests/Cms/System/SystemTest.php | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/tests/Cms/System/SystemTest.php b/tests/Cms/System/SystemTest.php
index 8c8ec73351..564e28818b 100644
--- a/tests/Cms/System/SystemTest.php
+++ b/tests/Cms/System/SystemTest.php
@@ -507,15 +507,14 @@ public function testIsOk()
*/
public function testIsOkContentMissingPermissions()
{
- $app = $this->app->clone([]);
- $system = new System($app);
+ // reset permissions in `tearDown()`
+ $this->subTmp = static::TMP . '/content';
+
+ $system = new System($this->app);
- $before = fileperms($app->root('content'));
- chmod($app->root('content'), 0o000);
+ chmod($this->app->root('content'), 0o000);
$this->assertFalse($system->isOk());
-
- chmod($app->root('content'), $before);
}
/**
From 8b994b3b5f569223c60572510861f4b05d807123 Mon Sep 17 00:00:00 2001
From: Lukas Bestle
Date: Wed, 1 May 2024 13:39:01 +0200
Subject: [PATCH 057/125] New test for `status`
---
tests/Cms/System/SystemTest.php | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/tests/Cms/System/SystemTest.php b/tests/Cms/System/SystemTest.php
index 564e28818b..ae782c6d73 100644
--- a/tests/Cms/System/SystemTest.php
+++ b/tests/Cms/System/SystemTest.php
@@ -674,6 +674,33 @@ public function testStatus()
$this->assertSame($expected, $system->__debugInfo());
}
+ /**
+ * @covers ::content
+ * @covers ::status
+ */
+ public function testStatusContentMissingPermissions()
+ {
+ // reset permissions in `tearDown()`
+ $this->subTmp = static::TMP . '/content';
+
+ $system = new System($this->app);
+
+ chmod($this->app->root('content'), 0o000);
+
+ $expected = [
+ 'accounts' => true,
+ 'content' => false,
+ 'curl' => true,
+ 'sessions' => true,
+ 'mbstring' => true,
+ 'media' => true,
+ 'php' => true
+ ];
+ $this->assertSame($expected, $system->status());
+ $this->assertSame($expected, $system->toArray());
+ $this->assertSame($expected, $system->__debugInfo());
+ }
+
/**
* @covers ::title
*/
From b281b3617784b1d76d4ffcf5bec1b8b5d2f9808d Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Wed, 1 May 2024 14:01:40 +0200
Subject: [PATCH 058/125] DateInput: fix clearing
---
panel/src/components/Forms/Field/DateField.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/panel/src/components/Forms/Field/DateField.vue b/panel/src/components/Forms/Field/DateField.vue
index c4176a51a8..72cd514dfa 100644
--- a/panel/src/components/Forms/Field/DateField.vue
+++ b/panel/src/components/Forms/Field/DateField.vue
@@ -136,10 +136,10 @@ export default {
*/
isEmpty() {
if (this.time) {
- return this.iso.date === null && this.iso.time;
+ return !this.iso.date || !this.iso.time;
}
- return this.iso.date === null;
+ return !this.iso.date;
}
},
watch: {
From 35e44a8015d5654d4b0835f9fd3d1a493676abad Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Wed, 1 May 2024 14:20:02 +0200
Subject: [PATCH 059/125] Fix tab badges
Fixes #6427
---
panel/src/components/Layout/Tabs.vue | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/panel/src/components/Layout/Tabs.vue b/panel/src/components/Layout/Tabs.vue
index e8dfd22bdc..63f845c572 100644
--- a/panel/src/components/Layout/Tabs.vue
+++ b/panel/src/components/Layout/Tabs.vue
@@ -1,19 +1,18 @@
-
- {{ btn.text }}
-
+
+
+ {{ btn.text }}
+
{{ btn.badge }}
-
+
Date: Wed, 1 May 2024 14:40:10 +0200
Subject: [PATCH 060/125] File upload: fix sort number
---
panel/src/panel/upload.js | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/panel/src/panel/upload.js b/panel/src/panel/upload.js
index b7cf22efd4..c55b016b25 100644
--- a/panel/src/panel/upload.js
+++ b/panel/src/panel/upload.js
@@ -286,8 +286,14 @@ export default (panel) => {
file.error = null;
file.progress = 0;
+ // clone the attributes to ensure that
+ // each file has its own copy, e.g. of sort
+ // (otherwise all files would use the state
+ // of attributes from the last file in the loop)
+ const attributes = { ...this.attributes };
+
// add file to upload queue
- files.push(async () => await this.upload(file));
+ files.push(async () => await this.upload(file, attributes));
const sort = this.attributes?.sort;
@@ -304,10 +310,10 @@ export default (panel) => {
return this.done();
}
},
- async upload(file) {
+ async upload(file, attributes) {
try {
const response = await upload(file.src, {
- attributes: this.attributes,
+ attributes: attributes,
headers: { "x-csrf": panel.system.csrf },
filename: file.name + "." + file.extension,
url: this.url,
From 5d38eab93944fff9250e16ef7b6c4f78bb03f234 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 08:53:15 +0200
Subject: [PATCH 061/125] Add missing `void` return types
---
src/Cms/LanguageRules.php | 2 +-
src/Session/Sessions.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Cms/LanguageRules.php b/src/Cms/LanguageRules.php
index 6263b90481..a59a678a98 100644
--- a/src/Cms/LanguageRules.php
+++ b/src/Cms/LanguageRules.php
@@ -42,7 +42,7 @@ public static function create(Language $language): bool
/**
* Validates if the language can be updated
*/
- public static function update(Language $language)
+ public static function update(Language $language): void
{
static::validLanguageCode($language);
static::validLanguageName($language);
diff --git a/src/Session/Sessions.php b/src/Session/Sessions.php
index b4c618db13..581d144b78 100644
--- a/src/Session/Sessions.php
+++ b/src/Session/Sessions.php
@@ -218,7 +218,7 @@ public function collectGarbage(): void
* @internal
* @param \Kirby\Session\Session $session Session instance to push to the cache
*/
- public function updateCache(Session $session)
+ public function updateCache(Session $session): void
{
$this->cache[$session->token()] = $session;
}
From 471cd138176ba3912a19d945f1a4b56d58ef1bff Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:06:58 +0200
Subject: [PATCH 062/125] Use elvis operator
---
src/Text/KirbyTag.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Text/KirbyTag.php b/src/Text/KirbyTag.php
index bf62924bf6..c87411fad1 100644
--- a/src/Text/KirbyTag.php
+++ b/src/Text/KirbyTag.php
@@ -177,7 +177,7 @@ public static function parse(
}
$pos = strpos($tag, ':');
- $type = trim(substr($tag, 0, $pos ? $pos : null));
+ $type = trim(substr($tag, 0, $pos ?: null));
$type = strtolower($type);
$attr = static::$types[$type]['attr'] ?? [];
From b1a09cb485a03b5b33ba5b7e394142cbc2d90205 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:10:16 +0200
Subject: [PATCH 063/125] Fix static method calls
---
src/Cms/App.php | 2 +-
src/Cms/Blueprint.php | 12 ++++++------
src/Toolkit/Component.php | 2 +-
src/Uuid/FieldUuid.php | 2 +-
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index 01f380e9b7..f8ef594e34 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -170,7 +170,7 @@ public function __debugInfo(): array
'roots' => $this->roots(),
'site' => $this->site(),
'urls' => $this->urls(),
- 'version' => $this->version(),
+ 'version' => static::version(),
];
}
diff --git a/src/Cms/Blueprint.php b/src/Cms/Blueprint.php
index 7ef2e2c971..7895c851c6 100644
--- a/src/Cms/Blueprint.php
+++ b/src/Cms/Blueprint.php
@@ -65,7 +65,7 @@ public function __construct(array $props)
unset($props['model']);
// extend the blueprint in general
- $props = $this->extend($props);
+ $props = static::extend($props);
// apply any blueprint preset
$props = $this->preset($props);
@@ -652,7 +652,7 @@ protected function normalizeOptions(
}
// extend options if possible
- $options = $this->extend($options);
+ $options = static::extend($options);
foreach ($options as $key => $value) {
$alias = $aliases[$key] ?? null;
@@ -686,7 +686,7 @@ protected function normalizeSections(
}
// inject all section extensions
- $sectionProps = $this->extend($sectionProps);
+ $sectionProps = static::extend($sectionProps);
$sections[$sectionName] = $sectionProps = [
...$sectionProps,
@@ -699,14 +699,14 @@ protected function normalizeSections(
'name' => $sectionName,
'label' => 'Invalid section type for section "' . $sectionName . '"',
'type' => 'info',
- 'text' => 'The following section types are available: ' . $this->helpList(array_keys(Section::$types))
+ 'text' => 'The following section types are available: ' . static::helpList(array_keys(Section::$types))
];
} elseif (isset(Section::$types[$type]) === false) {
$sections[$sectionName] = [
'name' => $sectionName,
'label' => 'Invalid section type ("' . $type . '")',
'type' => 'info',
- 'text' => 'The following section types are available: ' . $this->helpList(array_keys(Section::$types))
+ 'text' => 'The following section types are available: ' . static::helpList(array_keys(Section::$types))
];
}
@@ -764,7 +764,7 @@ protected function normalizeTabs($tabs): array
}
// inject all tab extensions
- $tabProps = $this->extend($tabProps);
+ $tabProps = static::extend($tabProps);
// inject a preset if available
$tabProps = $this->preset($tabProps);
diff --git a/src/Toolkit/Component.php b/src/Toolkit/Component.php
index e1a8533a2c..cd81f104ce 100644
--- a/src/Toolkit/Component.php
+++ b/src/Toolkit/Component.php
@@ -76,7 +76,7 @@ public function __construct(string $type, array $attrs = [])
}
$this->attrs = $attrs;
- $this->options = $options = $this->setup($type);
+ $this->options = $options = static::setup($type);
$this->methods = $methods = $options['methods'] ?? [];
foreach ($attrs as $attrName => $attrValue) {
diff --git a/src/Uuid/FieldUuid.php b/src/Uuid/FieldUuid.php
index 626bd5c2cf..e63adeef99 100644
--- a/src/Uuid/FieldUuid.php
+++ b/src/Uuid/FieldUuid.php
@@ -47,7 +47,7 @@ protected function findByCache(): Identifiable|null
$parent = Uuid::for($value['parent'])->model();
if ($field = $parent?->content()->get($value['field'])) {
- return $this->fieldToCollection($field)->get($value['id']);
+ return static::fieldToCollection($field)->get($value['id']);
}
}
}
From 86744288601c5c1a89dc2be46c97aa55210b170d Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:10:51 +0200
Subject: [PATCH 064/125] Use `**` instead of `pow()`
---
src/Filesystem/F.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Filesystem/F.php b/src/Filesystem/F.php
index 226cd40ac6..0f4a98359c 100644
--- a/src/Filesystem/F.php
+++ b/src/Filesystem/F.php
@@ -580,7 +580,7 @@ public static function niceSize(
}
// the math magic
- $size = round($size / pow(1024, ($unit = floor(log($size, 1024)))), 2);
+ $size = round($size / 1024 ** ($unit = floor(log($size, 1024))), 2);
// format the number if requested
if ($locale !== false) {
From d4afccb26e4590299a71714f88e2a7c9ffcb7dbd Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:12:51 +0200
Subject: [PATCH 065/125] Use `random_int()` instead `rand()`
---
src/Toolkit/Str.php | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/Toolkit/Str.php b/src/Toolkit/Str.php
index 8635b51986..a8f450fe7b 100644
--- a/src/Toolkit/Str.php
+++ b/src/Toolkit/Str.php
@@ -386,10 +386,13 @@ public static function encode(string $string): string
$encoded = '';
for ($i = 0; $i < static::length($string); $i++) {
- $char = static::substr($string, $i, 1);
- $char = mb_convert_encoding($char, 'UCS-4BE', 'UTF-8');
- list(, $code) = unpack('N', $char);
- $encoded .= rand(1, 2) === 1 ? '' . $code . ';' : '' . dechex($code) . ';';
+ $char = static::substr($string, $i, 1);
+ $char = mb_convert_encoding($char, 'UCS-4BE', 'UTF-8');
+ [, $code] = unpack('N', $char);
+ $encoded .= match (random_int(1, 2)) {
+ 1 => '' . $code . ';',
+ 2 => '' . dechex($code) . ';'
+ };
}
return $encoded;
From 7211f6d77e0695674d8cc3e18aba0c7a175eb5ca Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:15:07 +0200
Subject: [PATCH 066/125] Use shrothand list destruct syntax
---
src/Cms/App.php | 2 +-
src/Database/Sql.php | 4 ++--
src/Toolkit/Dom.php | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index f8ef594e34..5f54e104ee 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -255,7 +255,7 @@ protected function bakeOptions(): static
foreach ($this->options as $key => $value) {
// detect option keys with the `vendor.plugin.option` format
if (preg_match('/^([a-z0-9-]+\.[a-z0-9-]+)\.(.*)$/i', $key, $matches) === 1) {
- list(, $plugin, $option) = $matches;
+ [, $plugin, $option] = $matches;
// verify that it's really a plugin option
if (isset(static::$plugins[str_replace('.', '/', $plugin)]) !== true) {
diff --git a/src/Database/Sql.php b/src/Database/Sql.php
index f5829e24d1..16349af1c5 100644
--- a/src/Database/Sql.php
+++ b/src/Database/Sql.php
@@ -112,7 +112,7 @@ public function columnDefault(string $name, array $column): array
public function columnName(string $table, string $column, bool $enforceQualified = false): string|null
{
// ensure we have clean $table and $column values without qualified identifiers
- list($table, $column) = $this->splitIdentifier($table, $column);
+ [$table, $column] = $this->splitIdentifier($table, $column);
// combine the identifiers again
if ($this->database->validateColumn($table, $column) === true) {
@@ -624,7 +624,7 @@ public function selected(string $table, array|string|null $columns = null): stri
$result = [];
foreach ($columns as $column) {
- list($table, $columnPart) = $this->splitIdentifier($table, $column);
+ [$table, $columnPart] = $this->splitIdentifier($table, $column);
if ($this->validateColumn($table, $columnPart) === true) {
$result[] = $this->combineIdentifier($table, $columnPart);
diff --git a/src/Toolkit/Dom.php b/src/Toolkit/Dom.php
index 4b42d7af77..4362d4185c 100644
--- a/src/Toolkit/Dom.php
+++ b/src/Toolkit/Dom.php
@@ -464,7 +464,7 @@ public static function listContainsName(
$namespaceUri = null;
$itemLocal = $item;
if (Str::contains($item, ':') === true) {
- list($namespaceName, $itemLocal) = explode(':', $item);
+ [$namespaceName, $itemLocal] = explode(':', $item);
$namespaceUri = $allowedNamespaces[$namespaceName] ?? null;
} else {
// list items without namespace are from the default namespace
From da9d2c7ba887cfeba2382d5e00dbd4f392777ce6 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:16:14 +0200
Subject: [PATCH 067/125] Remove superfluous parameter
---
src/Cms/FileVersion.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Cms/FileVersion.php b/src/Cms/FileVersion.php
index 669fdc9910..159da71ba7 100644
--- a/src/Cms/FileVersion.php
+++ b/src/Cms/FileVersion.php
@@ -50,7 +50,7 @@ public function __call(string $method, array $arguments = []): mixed
// content fields
if ($this->original() instanceof File) {
- return $this->original()->content()->get($method, $arguments);
+ return $this->original()->content()->get($method);
}
}
From 3c3295cf5f84f88311f37b2515806cf8dabc09bf Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:20:38 +0200
Subject: [PATCH 068/125] Fix passing null to `get_class()`
---
src/Api/Model.php | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/Api/Model.php b/src/Api/Model.php
index 0c78f93b91..24af00bbca 100644
--- a/src/Api/Model.php
+++ b/src/Api/Model.php
@@ -59,7 +59,11 @@ public function __construct(
isset($schema['type']) === true &&
$this->data instanceof $schema['type'] === false
) {
- throw new Exception(sprintf('Invalid model type "%s" expected: "%s"', get_class($this->data), $schema['type']));
+ $class = match ($this->data) {
+ null => 'null',
+ default => get_class($this->data),
+ };
+ throw new Exception(sprintf('Invalid model type "%s" expected: "%s"', $class, $schema['type']));
}
}
From 1f93d9646d06ef2cf23fa96906208bdcddcea1e3 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:30:38 +0200
Subject: [PATCH 069/125] Use more null coalescing operator
---
src/Cms/App.php | 4 ++--
src/Cms/AppPlugins.php | 2 +-
src/Cms/AppTranslations.php | 2 +-
src/Cms/Auth.php | 4 ++--
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index 5f54e104ee..e3016a860a 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -623,7 +623,7 @@ public function file(
return Uuid::for($path, $parent?->files())->model();
}
- $parent = $parent ?? $this->site();
+ $parent ??= $this->site();
$id = dirname($path);
$filename = basename($path);
@@ -1141,7 +1141,7 @@ public function page(
return null;
}
- $parent = $parent ?? $this->site();
+ $parent ??= $this->site();
if ($page = $parent->find($id)) {
/**
diff --git a/src/Cms/AppPlugins.php b/src/Cms/AppPlugins.php
index 5971f2148f..3a63fd37a1 100644
--- a/src/Cms/AppPlugins.php
+++ b/src/Cms/AppPlugins.php
@@ -720,7 +720,7 @@ public static function plugin(
}
// get the correct root for the plugin
- $extends['root'] = $extends['root'] ?? dirname(debug_backtrace()[0]['file']);
+ $extends['root'] ??= dirname(debug_backtrace()[0]['file']);
$plugin = new Plugin($name, $extends);
$name = $plugin->name();
diff --git a/src/Cms/AppTranslations.php b/src/Cms/AppTranslations.php
index 5efc39d754..f3d80b114f 100644
--- a/src/Cms/AppTranslations.php
+++ b/src/Cms/AppTranslations.php
@@ -148,7 +148,7 @@ public function setCurrentTranslation(string $translationCode = null): void
*/
public function translation(string|null $locale = null): Translation
{
- $locale = $locale ?? I18n::locale();
+ $locale ??= I18n::locale();
$locale = basename($locale);
// prefer loading them from the translations collection
diff --git a/src/Cms/Auth.php b/src/Cms/Auth.php
index 91f5d2bb16..d02b01e158 100644
--- a/src/Cms/Auth.php
+++ b/src/Cms/Auth.php
@@ -575,8 +575,8 @@ public function log(): array
}
// ensure that the category arrays are defined
- $log['by-ip'] = $log['by-ip'] ?? [];
- $log['by-email'] = $log['by-email'] ?? [];
+ $log['by-ip'] ??= [];
+ $log['by-email'] ??= [];
// remove all elements on the top level with different keys (old structure)
$log = array_intersect_key($log, array_flip(['by-ip', 'by-email']));
From 6c10445e07982430d045a5cdcd5a3b2a37f89324 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:31:58 +0200
Subject: [PATCH 070/125] Set nullable props default as null
---
src/Cms/ModelWithContent.php | 2 +-
src/Cms/PagePicker.php | 2 +-
src/Http/Request/Query.php | 2 +-
src/Toolkit/Escape.php | 2 +-
src/Toolkit/Html.php | 2 +-
src/Uuid/BlockUuid.php | 2 +-
src/Uuid/FileUuid.php | 2 +-
src/Uuid/ModelUuid.php | 2 +-
src/Uuid/PageUuid.php | 2 +-
src/Uuid/SiteUuid.php | 2 +-
src/Uuid/StructureUuid.php | 2 +-
src/Uuid/UserUuid.php | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/Cms/ModelWithContent.php b/src/Cms/ModelWithContent.php
index 5f5dae3e4a..1a7baf5011 100644
--- a/src/Cms/ModelWithContent.php
+++ b/src/Cms/ModelWithContent.php
@@ -46,7 +46,7 @@ abstract class ModelWithContent implements Identifiable
public static App $kirby;
protected Site|null $site;
protected ContentStorage $storage;
- public Collection|null $translations;
+ public Collection|null $translations = null;
/**
* Store values used to initilaize object
diff --git a/src/Cms/PagePicker.php b/src/Cms/PagePicker.php
index f84cc55443..f8dccf8002 100644
--- a/src/Cms/PagePicker.php
+++ b/src/Cms/PagePicker.php
@@ -22,7 +22,7 @@ class PagePicker extends Picker
// remove once our implementation is better
protected Pages|null $items = null;
protected Pages|null $itemsForQuery = null;
- protected Page|Site|null $parent;
+ protected Page|Site|null $parent = null;
/**
* Extends the basic defaults
diff --git a/src/Http/Request/Query.php b/src/Http/Request/Query.php
index b6c4ad1eb4..51b004aab4 100644
--- a/src/Http/Request/Query.php
+++ b/src/Http/Request/Query.php
@@ -20,7 +20,7 @@ class Query
/**
* The Query data array
*/
- protected array|null $data;
+ protected array|null $data = null;
/**
* Creates a new Query object.
diff --git a/src/Toolkit/Escape.php b/src/Toolkit/Escape.php
index 8b62259a5f..9f23c62e0a 100644
--- a/src/Toolkit/Escape.php
+++ b/src/Toolkit/Escape.php
@@ -26,7 +26,7 @@ class Escape
/**
* The internal singleton escaper instance
*/
- protected static Escaper|null $escaper;
+ protected static Escaper|null $escaper = null;
/**
* Escape common HTML attributes data
diff --git a/src/Toolkit/Html.php b/src/Toolkit/Html.php
index cacd86ce82..56c4ed845a 100644
--- a/src/Toolkit/Html.php
+++ b/src/Toolkit/Html.php
@@ -20,7 +20,7 @@ class Html extends Xml
/**
* An internal store for an HTML entities translation table
*/
- public static array|null $entities;
+ public static array|null $entities = null;
/**
* List of HTML tags that can be used inline
diff --git a/src/Uuid/BlockUuid.php b/src/Uuid/BlockUuid.php
index 14d1b4b777..1d4628a6c3 100644
--- a/src/Uuid/BlockUuid.php
+++ b/src/Uuid/BlockUuid.php
@@ -26,7 +26,7 @@ class BlockUuid extends FieldUuid
/**
* @var \Kirby\Cms\Block|null
*/
- public Identifiable|null $model;
+ public Identifiable|null $model = null;
/**
* Converts content field to a Blocks collection
diff --git a/src/Uuid/FileUuid.php b/src/Uuid/FileUuid.php
index c5bbfcd2eb..68dfe89f50 100644
--- a/src/Uuid/FileUuid.php
+++ b/src/Uuid/FileUuid.php
@@ -22,7 +22,7 @@ class FileUuid extends ModelUuid
/**
* @var \Kirby\Cms\File|null
*/
- public Identifiable|null $model;
+ public Identifiable|null $model = null;
/**
* Looks up UUID in cache and resolves to file object;
diff --git a/src/Uuid/ModelUuid.php b/src/Uuid/ModelUuid.php
index ab52dae200..43eb5f3830 100644
--- a/src/Uuid/ModelUuid.php
+++ b/src/Uuid/ModelUuid.php
@@ -20,7 +20,7 @@ abstract class ModelUuid extends Uuid
/**
* @var \Kirby\Cms\ModelWithContent|null
*/
- public Identifiable|null $model;
+ public Identifiable|null $model = null;
/**
* Looks up UUID in local and global index
diff --git a/src/Uuid/PageUuid.php b/src/Uuid/PageUuid.php
index 57f631d7cf..2ab8c29f7c 100644
--- a/src/Uuid/PageUuid.php
+++ b/src/Uuid/PageUuid.php
@@ -23,7 +23,7 @@ class PageUuid extends ModelUuid
/**
* @var \Kirby\Cms\Page|null
*/
- public Identifiable|null $model;
+ public Identifiable|null $model = null;
/**
* Looks up UUID in cache and resolves
diff --git a/src/Uuid/SiteUuid.php b/src/Uuid/SiteUuid.php
index 4203b3003f..f7fa0216fb 100644
--- a/src/Uuid/SiteUuid.php
+++ b/src/Uuid/SiteUuid.php
@@ -23,7 +23,7 @@ class SiteUuid extends Uuid
/**
* @var \Kirby\Cms\Site|null
*/
- public Identifiable|null $model;
+ public Identifiable|null $model = null;
/*
* Returns empty string since
diff --git a/src/Uuid/StructureUuid.php b/src/Uuid/StructureUuid.php
index 76f6bbc4ea..6d8f11f54c 100644
--- a/src/Uuid/StructureUuid.php
+++ b/src/Uuid/StructureUuid.php
@@ -26,7 +26,7 @@ class StructureUuid extends FieldUuid
/**
* @var \Kirby\Cms\StructureObject|null
*/
- public Identifiable|null $model;
+ public Identifiable|null $model = null;
/**
* Converts content field to a Structure collection
diff --git a/src/Uuid/UserUuid.php b/src/Uuid/UserUuid.php
index 7d175ed033..c42ee31016 100644
--- a/src/Uuid/UserUuid.php
+++ b/src/Uuid/UserUuid.php
@@ -23,7 +23,7 @@ class UserUuid extends Uuid
/**
* @var \Kirby\Cms\User|null
*/
- public Identifiable|null $model;
+ public Identifiable|null $model = null;
/*
* Returns the user ID
From 50db4a3aab4e991b6e8d564ef532385eb8a7fc16 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:35:44 +0200
Subject: [PATCH 071/125] Short arrow function
---
src/Panel/Lab/Example.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/Panel/Lab/Example.php b/src/Panel/Lab/Example.php
index a5ab2d6690..61e165fe0e 100644
--- a/src/Panel/Lab/Example.php
+++ b/src/Panel/Lab/Example.php
@@ -219,9 +219,11 @@ public function vueExamples(string|null $template, string|null $script): array
$tail = $matches[2][$key];
$code = $matches[3][$key];
- $scriptId = trim(preg_replace_callback('!script="(.*?)"!', function ($match) {
- return trim($match[1]);
- }, $tail));
+ $scriptId = trim(preg_replace_callback(
+ '!script="(.*?)"!',
+ fn($match) => trim($match[1]),
+ $tail
+ ));
$scriptBlock = $scripts[$scriptId] ?? null;
From 33137f9a7b92a29efa072ea377efcb4fc5e06dc0 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 09:47:24 +0200
Subject: [PATCH 072/125] Fix cs
---
src/Panel/Lab/Example.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Panel/Lab/Example.php b/src/Panel/Lab/Example.php
index 61e165fe0e..153bb12aa2 100644
--- a/src/Panel/Lab/Example.php
+++ b/src/Panel/Lab/Example.php
@@ -221,7 +221,7 @@ public function vueExamples(string|null $template, string|null $script): array
$scriptId = trim(preg_replace_callback(
'!script="(.*?)"!',
- fn($match) => trim($match[1]),
+ fn ($match) => trim($match[1]),
$tail
));
From 013a42ebb759cb804625eb30ee2cb2ee41acb520 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 10:37:27 +0200
Subject: [PATCH 073/125] More null coalescing operators
---
config/presets/page.php | 2 +-
config/presets/pages.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/config/presets/page.php b/config/presets/page.php
index e01bcf10e5..a2102efae5 100644
--- a/config/presets/page.php
+++ b/config/presets/page.php
@@ -44,7 +44,7 @@
}
if (empty($sidebar) === true) {
- $props['fields'] = $props['fields'] ?? [];
+ $props['fields'] ??= [];
unset(
$props['files'],
diff --git a/config/presets/pages.php b/config/presets/pages.php
index 32a45890fa..a2c77143f7 100644
--- a/config/presets/pages.php
+++ b/config/presets/pages.php
@@ -26,7 +26,7 @@
// inject the global templates definition
if (empty($templates) === false) {
- $props['templates'] = $props['templates'] ?? $templates;
+ $props['templates'] ??= $templates;
}
return array_replace_recursive($defaults, $props);
From c9b49f46bbd3797699bde723ac1bb53f91af0b68 Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Thu, 2 May 2024 12:49:33 +0200
Subject: [PATCH 074/125] Add lab example
---
.../components/dropdowns/3_options/index.vue | 64 ++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
diff --git a/panel/lab/components/dropdowns/3_options/index.vue b/panel/lab/components/dropdowns/3_options/index.vue
index df7ab5ce58..c6146d9446 100644
--- a/panel/lab/components/dropdowns/3_options/index.vue
+++ b/panel/lab/components/dropdowns/3_options/index.vue
@@ -21,6 +21,16 @@
@action="onAction"
/>
+
+
+
@@ -100,7 +110,59 @@ export const clickStringHandler = {
};
/** @script-end */
+/** @script: clickGlobalHandler */
+export const clickGlobalHandler = {
+ created() {
+ this.$panel.events.on("dropdown:action", this.onGlobalAction);
+ },
+ destroyed() {
+ this.$panel.events.off("dropdown:action", this.onGlobalAction);
+ },
+ computed: {
+ optionsWithGlobalHandler() {
+ return [
+ {
+ text: "Edit",
+ icon: "edit",
+ click: {
+ global: "dropdown:action",
+ payload: "edit"
+ }
+ },
+ {
+ text: "Duplicate",
+ icon: "copy",
+ click: {
+ global: "dropdown:action",
+ payload: "duplicate"
+ }
+ },
+ "-",
+ {
+ text: "Delete",
+ icon: "trash",
+ click: {
+ global: "dropdown:action",
+ payload: "delete"
+ }
+ }
+ ];
+ }
+ },
+ methods: {
+ onGlobalAction(payload) {
+ console.log(payload);
+ }
+ }
+};
+/** @script-end */
+
export default {
- mixins: [multipleOptions, singleOption, clickStringHandler]
+ mixins: [
+ multipleOptions,
+ singleOption,
+ clickStringHandler,
+ clickGlobalHandler
+ ]
};
From 0850e9cc4b36691c961414642718502f6faac708 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 14:20:36 +0200
Subject: [PATCH 075/125] Fix DropdownItem props, revert change
---
.../src/components/Dropdowns/DropdownItem.vue | 30 ++++---------------
1 file changed, 6 insertions(+), 24 deletions(-)
diff --git a/panel/src/components/Dropdowns/DropdownItem.vue b/panel/src/components/Dropdowns/DropdownItem.vue
index 7dd5e5837c..165632efb4 100644
--- a/panel/src/components/Dropdowns/DropdownItem.vue
+++ b/panel/src/components/Dropdowns/DropdownItem.vue
@@ -1,16 +1,7 @@
@@ -20,28 +11,19 @@
diff --git a/panel/src/components/Dialogs/Elements/index.js b/panel/src/components/Dialogs/Elements/index.js
index 68420b4066..31b12f8f4f 100644
--- a/panel/src/components/Dialogs/Elements/index.js
+++ b/panel/src/components/Dialogs/Elements/index.js
@@ -6,8 +6,6 @@ import Notification from "./Notification.vue";
import Search from "./Search.vue";
import Text from "./Text.vue";
-import UploadPreview from "./UploadPreview.vue";
-
export default {
install(app) {
app.component("k-dialog-body", Body);
@@ -17,7 +15,5 @@ export default {
app.component("k-dialog-notification", Notification);
app.component("k-dialog-search", Search);
app.component("k-dialog-text", Text);
-
- app.component("k-upload-dialog-preview", UploadPreview);
}
};
diff --git a/panel/src/components/Dialogs/UploadDialog.vue b/panel/src/components/Dialogs/UploadDialog.vue
index 362f211af0..857e26c135 100644
--- a/panel/src/components/Dialogs/UploadDialog.vue
+++ b/panel/src/components/Dialogs/UploadDialog.vue
@@ -19,66 +19,20 @@
-
-
-
-
-
-
-
-
- {{ file.niceSize }}
- - {{ file.progress }}%
-
-
- {{ file.error }}
-
-
-
-
-
-
-
+ {
+ $panel.upload.remove(file.id);
+ }
+ "
+ @rename="
+ (file, name) => {
+ file.name = name;
+ }
+ "
+ />
@@ -109,87 +63,4 @@ export default {
.k-upload-dialog.k-dialog {
--dialog-width: 40rem;
}
-
-.k-upload-items {
- display: grid;
- gap: 0.25rem;
-}
-.k-upload-item {
- accent-color: var(--color-focus);
- display: grid;
- grid-template-areas:
- "preview input input"
- "preview body toggle";
- grid-template-columns: 6rem 1fr auto;
- grid-template-rows: var(--input-height) 1fr;
- border-radius: var(--rounded);
- background: var(--color-white);
- box-shadow: var(--shadow);
- min-height: 6rem;
-}
-.k-upload-item-preview {
- --icon-size: 1.75rem;
-
- grid-area: preview;
- display: flex;
- width: 100%;
- height: 100%;
- overflow: hidden;
- border-start-start-radius: var(--rounded);
- border-end-start-radius: var(--rounded);
-}
-.k-upload-item-preview:focus {
- border-radius: var(--rounded);
- outline: 2px solid var(--color-focus);
- z-index: 1;
-}
-
-.k-upload-item-body {
- grid-area: body;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- padding: var(--spacing-2) var(--spacing-3);
- min-width: 0;
-}
-.k-upload-item-input.k-input {
- --input-color-border: transparent;
- --input-padding: var(--spacing-2) var(--spacing-3);
- --input-rounded: 0;
- grid-area: input;
- font-size: var(--text-sm);
- border-bottom: 1px solid var(--color-light);
- border-start-end-radius: var(--rounded);
-}
-.k-upload-item-input.k-input:focus-within {
- outline: 2px solid var(--color-focus);
- z-index: 1;
- border-radius: var(--rounded);
-}
-.k-upload-item-input .k-input-after {
- color: var(--color-gray-600);
-}
-.k-upload-item-meta {
- font-size: var(--text-xs);
- color: var(--color-gray-600);
-}
-.k-upload-item-error {
- font-size: var(--text-xs);
- margin-top: 0.25rem;
- color: var(--color-red-700);
-}
-.k-upload-item-progress {
- --progress-height: 0.25rem;
- --progress-color-back: var(--color-light);
-}
-.k-upload-item-toggle {
- grid-area: toggle;
- align-self: end;
-}
-.k-upload-item-toggle > * {
- padding: var(--spacing-3);
-}
-.k-upload-item[data-completed] .k-upload-item-progress {
- --progress-color-value: var(--color-green-400);
-}
diff --git a/panel/src/components/Uploads/UploadItem.vue b/panel/src/components/Uploads/UploadItem.vue
new file mode 100644
index 0000000000..9db75cb1d9
--- /dev/null
+++ b/panel/src/components/Uploads/UploadItem.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+ {{ niceSize }}
+ - {{ progress }}%
+
+
+ {{ error }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/panel/src/components/Uploads/UploadItemPreview.vue b/panel/src/components/Uploads/UploadItemPreview.vue
new file mode 100644
index 0000000000..cca548d9fe
--- /dev/null
+++ b/panel/src/components/Uploads/UploadItemPreview.vue
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/panel/src/components/Uploads/UploadItems.vue b/panel/src/components/Uploads/UploadItems.vue
new file mode 100644
index 0000000000..920e958e6b
--- /dev/null
+++ b/panel/src/components/Uploads/UploadItems.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/panel/src/components/Uploads/index.js b/panel/src/components/Uploads/index.js
new file mode 100644
index 0000000000..dadc4712a7
--- /dev/null
+++ b/panel/src/components/Uploads/index.js
@@ -0,0 +1,11 @@
+import UploadItem from "./UploadItem.vue";
+import UploadItemPreview from "./UploadItemPreview.vue";
+import UploadItems from "./UploadItems.vue";
+
+export default {
+ install(app) {
+ app.component("k-upload-item", UploadItem);
+ app.component("k-upload-item-preview", UploadItemPreview);
+ app.component("k-upload-items", UploadItems);
+ }
+};
diff --git a/panel/src/components/index.js b/panel/src/components/index.js
index 3b7af25dd9..4262c6cc65 100644
--- a/panel/src/components/index.js
+++ b/panel/src/components/index.js
@@ -9,6 +9,7 @@ import Misc from "@/components/Misc/index.js";
import Navigation from "@/components/Navigation/index.js";
import Sections from "@/components/Sections/index.js";
import Text from "@/components/Text/index.js";
+import Uploads from "@/components/Uploads/index.js";
import View from "@/components/View/index.js";
import Views from "@/components/Views/index.js";
@@ -28,6 +29,7 @@ export default {
app.use(Navigation);
app.use(Sections);
app.use(Text);
+ app.use(Uploads);
app.use(View);
app.use(Views);
From af58c7871e65effc06b3a4bfc14c71ab4ff1d79a Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Thu, 2 May 2024 21:25:25 +0200
Subject: [PATCH 077/125] New lab examples
---
panel/lab/components/uploaditem/index.vue | 64 +++++++++++++++++++
.../components/uploaditempreview/index.vue | 28 ++++++++
panel/lab/components/uploaditems/index.vue | 54 ++++++++++++++++
3 files changed, 146 insertions(+)
create mode 100644 panel/lab/components/uploaditem/index.vue
create mode 100644 panel/lab/components/uploaditempreview/index.vue
create mode 100644 panel/lab/components/uploaditems/index.vue
diff --git a/panel/lab/components/uploaditem/index.vue b/panel/lab/components/uploaditem/index.vue
new file mode 100644
index 0000000000..76c20db13a
--- /dev/null
+++ b/panel/lab/components/uploaditem/index.vue
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/panel/lab/components/uploaditempreview/index.vue b/panel/lab/components/uploaditempreview/index.vue
new file mode 100644
index 0000000000..5ecb623488
--- /dev/null
+++ b/panel/lab/components/uploaditempreview/index.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/panel/lab/components/uploaditems/index.vue b/panel/lab/components/uploaditems/index.vue
new file mode 100644
index 0000000000..eab0b53a0b
--- /dev/null
+++ b/panel/lab/components/uploaditems/index.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
From ad2936fbbb03b5c815e5d65fcca744aea9c567ad Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Thu, 2 May 2024 21:42:20 +0200
Subject: [PATCH 078/125] Fix replace dialog
---
panel/src/components/Dialogs/UploadReplaceDialog.vue | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/panel/src/components/Dialogs/UploadReplaceDialog.vue b/panel/src/components/Dialogs/UploadReplaceDialog.vue
index e153ffff67..2f9d15262b 100644
--- a/panel/src/components/Dialogs/UploadReplaceDialog.vue
+++ b/panel/src/components/Dialogs/UploadReplaceDialog.vue
@@ -8,11 +8,11 @@
>
-
@@ -24,12 +24,11 @@
:data-completed="file.completed"
class="k-upload-item"
>
-
Date: Thu, 2 May 2024 22:28:26 +0200
Subject: [PATCH 079/125] Merge upload components lab examples
---
panel/lab/components/uploads/1_upload-items/index.php | 5 +++++
.../{uploaditems => uploads/1_upload-items}/index.vue | 0
panel/lab/components/uploads/2_upload-item/index.php | 5 +++++
.../{uploaditem => uploads/2_upload-item}/index.vue | 0
panel/lab/components/uploads/3_upload-item-preview/index.php | 5 +++++
.../3_upload-item-preview}/index.vue | 0
6 files changed, 15 insertions(+)
create mode 100644 panel/lab/components/uploads/1_upload-items/index.php
rename panel/lab/components/{uploaditems => uploads/1_upload-items}/index.vue (100%)
create mode 100644 panel/lab/components/uploads/2_upload-item/index.php
rename panel/lab/components/{uploaditem => uploads/2_upload-item}/index.vue (100%)
create mode 100644 panel/lab/components/uploads/3_upload-item-preview/index.php
rename panel/lab/components/{uploaditempreview => uploads/3_upload-item-preview}/index.vue (100%)
diff --git a/panel/lab/components/uploads/1_upload-items/index.php b/panel/lab/components/uploads/1_upload-items/index.php
new file mode 100644
index 0000000000..dbc4bee102
--- /dev/null
+++ b/panel/lab/components/uploads/1_upload-items/index.php
@@ -0,0 +1,5 @@
+ 'k-upload-items',
+];
diff --git a/panel/lab/components/uploaditems/index.vue b/panel/lab/components/uploads/1_upload-items/index.vue
similarity index 100%
rename from panel/lab/components/uploaditems/index.vue
rename to panel/lab/components/uploads/1_upload-items/index.vue
diff --git a/panel/lab/components/uploads/2_upload-item/index.php b/panel/lab/components/uploads/2_upload-item/index.php
new file mode 100644
index 0000000000..312c6f3e6b
--- /dev/null
+++ b/panel/lab/components/uploads/2_upload-item/index.php
@@ -0,0 +1,5 @@
+ 'k-upload-item',
+];
diff --git a/panel/lab/components/uploaditem/index.vue b/panel/lab/components/uploads/2_upload-item/index.vue
similarity index 100%
rename from panel/lab/components/uploaditem/index.vue
rename to panel/lab/components/uploads/2_upload-item/index.vue
diff --git a/panel/lab/components/uploads/3_upload-item-preview/index.php b/panel/lab/components/uploads/3_upload-item-preview/index.php
new file mode 100644
index 0000000000..1f1fdef1d1
--- /dev/null
+++ b/panel/lab/components/uploads/3_upload-item-preview/index.php
@@ -0,0 +1,5 @@
+ 'k-upload-item-preview',
+];
diff --git a/panel/lab/components/uploaditempreview/index.vue b/panel/lab/components/uploads/3_upload-item-preview/index.vue
similarity index 100%
rename from panel/lab/components/uploaditempreview/index.vue
rename to panel/lab/components/uploads/3_upload-item-preview/index.vue
From ecaea19c826e160eb869c130d7a04d14fb55d709 Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 2 May 2024 23:09:36 +0200
Subject: [PATCH 080/125] Use `k-upload-item` for upload replace dialog
---
.../uploads/2_upload-item/index.vue | 10 +++
.../uploads/3_upload-item-preview/index.vue | 6 ++
.../Dialogs/UploadReplaceDialog.vue | 66 ++++-------------
panel/src/components/Uploads/UploadItem.vue | 73 +++++++++++++++++--
.../components/Uploads/UploadItemPreview.vue | 29 ++++++--
panel/src/components/Uploads/UploadItems.vue | 3 +
6 files changed, 121 insertions(+), 66 deletions(-)
diff --git a/panel/lab/components/uploads/2_upload-item/index.vue b/panel/lab/components/uploads/2_upload-item/index.vue
index 76c20db13a..9ffaf8bb42 100644
--- a/panel/lab/components/uploads/2_upload-item/index.vue
+++ b/panel/lab/components/uploads/2_upload-item/index.vue
@@ -35,6 +35,16 @@
@rename="rename"
/>
+
+
+
+
+
+
+
+
+
diff --git a/panel/src/components/Dialogs/UploadReplaceDialog.vue b/panel/src/components/Dialogs/UploadReplaceDialog.vue
index 2f9d15262b..3bf2204321 100644
--- a/panel/src/components/Dialogs/UploadReplaceDialog.vue
+++ b/panel/src/components/Dialogs/UploadReplaceDialog.vue
@@ -18,55 +18,14 @@
←
-
-
-
-
-
-
-
- {{ file.niceSize }}
- - {{ file.progress }}%
-
-
{{ file.error }}
-
-
-
-
-
-
-
-
+
@@ -90,6 +49,11 @@ export default {
};
}
}
+ },
+ computed: {
+ file() {
+ return this.$panel.upload.files[0];
+ }
}
};
@@ -108,10 +72,6 @@ export default {
overflow: hidden;
}
-.k-upload-item-input {
- --input-color-back: var(--color-white) !important;
-}
-
.k-upload-replace-dialog .k-upload-item {
flex-grow: 1;
}
diff --git a/panel/src/components/Uploads/UploadItem.vue b/panel/src/components/Uploads/UploadItem.vue
index 9db75cb1d9..09945becc2 100644
--- a/panel/src/components/Uploads/UploadItem.vue
+++ b/panel/src/components/Uploads/UploadItem.vue
@@ -1,9 +1,14 @@
-
+
-
-
+
+
@@ -92,6 +147,9 @@ export default {
z-index: 1;
border-radius: var(--rounded);
}
+.k-upload-item-input.k-input[data-disabled="true"] {
+ --input-color-back: var(--color-white);
+}
.k-upload-item-input .k-input-after {
color: var(--color-gray-600);
}
@@ -107,6 +165,7 @@ export default {
.k-upload-item-progress {
--progress-height: 0.25rem;
--progress-color-back: var(--color-light);
+ margin-bottom: 0.3125rem;
}
.k-upload-item-toggle {
grid-area: toggle;
diff --git a/panel/src/components/Uploads/UploadItemPreview.vue b/panel/src/components/Uploads/UploadItemPreview.vue
index cca548d9fe..2379873d2e 100644
--- a/panel/src/components/Uploads/UploadItemPreview.vue
+++ b/panel/src/components/Uploads/UploadItemPreview.vue
@@ -12,17 +12,34 @@
diff --git a/panel/src/components/Uploads/UploadItems.vue b/panel/src/components/Uploads/UploadItems.vue
index 0d087a39e9..07ddf9dfb8 100644
--- a/panel/src/components/Uploads/UploadItems.vue
+++ b/panel/src/components/Uploads/UploadItems.vue
@@ -12,12 +12,14 @@
From d31e27a85b1575bf369c0a2fa92be65f0dbcdad0 Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Fri, 3 May 2024 12:59:11 +0200
Subject: [PATCH 083/125] Refactor App::language and introduce
App::currentLanguage
---
src/Cms/App.php | 33 +++++++++++++++------------------
1 file changed, 15 insertions(+), 18 deletions(-)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index e3016a860a..43a14ac6b9 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -538,6 +538,14 @@ public function csrf(string|null $check = null): string|bool
return false;
}
+ /**
+ * Returns the current language, set by `static::setCurrentLanguage`
+ */
+ public function currentLanguage(): Language
+ {
+ return $this->language ??= $this->defaultLanguage();
+ }
+
/**
* Returns the default language object
*/
@@ -879,27 +887,16 @@ public function kirbytext(string $text = null, array $options = []): string
}
/**
- * Returns the current language
+ * Returns the language by code or shortcut (`default`, `current`).
+ * Passing `null` is an alias for passing `current`
*/
public function language(string $code = null): Language|null
{
- if ($this->multilang() === false) {
- return null;
- }
-
- if ($code === 'default') {
- return $this->defaultLanguage();
- }
-
- // if requesting a non-default language,
- // find it but don't cache it
- if ($code !== null) {
- return $this->languages()->find($code);
- }
-
- // otherwise return language set by `AppTranslation::setCurrentLanguage`
- // or default language
- return $this->language ??= $this->defaultLanguage();
+ return match($code ?? 'current') {
+ 'default' => $this->defaultLanguage(),
+ 'current' => $this->currentLanguage(),
+ default => $this->languages()->find($code)
+ };
}
/**
From be2cb3baa1d7998bb6bd008d2e1e62c8549d8073 Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Fri, 3 May 2024 13:03:52 +0200
Subject: [PATCH 084/125] Fix CS issue
---
src/Cms/App.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index 43a14ac6b9..92ecbf5706 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -892,7 +892,7 @@ public function kirbytext(string $text = null, array $options = []): string
*/
public function language(string $code = null): Language|null
{
- return match($code ?? 'current') {
+ return match ($code ?? 'current') {
'default' => $this->defaultLanguage(),
'current' => $this->currentLanguage(),
default => $this->languages()->find($code)
From 330406c959482dc01765b1596721180af288933c Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Fri, 3 May 2024 13:04:44 +0200
Subject: [PATCH 085/125] Fix return type
---
src/Cms/App.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index 92ecbf5706..c81d95f0a9 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -539,9 +539,9 @@ public function csrf(string|null $check = null): string|bool
}
/**
- * Returns the current language, set by `static::setCurrentLanguage`
+ * Returns the current language, if set by `static::setCurrentLanguage`
*/
- public function currentLanguage(): Language
+ public function currentLanguage(): Language|null
{
return $this->language ??= $this->defaultLanguage();
}
From e611cd83ad5044ca4ba0e5cfaaa2bf8b914cdd2a Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Fri, 3 May 2024 13:26:34 +0200
Subject: [PATCH 086/125] Better be safe
---
src/Cms/App.php | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index c81d95f0a9..1e37de1666 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -892,6 +892,10 @@ public function kirbytext(string $text = null, array $options = []): string
*/
public function language(string $code = null): Language|null
{
+ if ($this->multilang() === false) {
+ return null;
+ }
+
return match ($code ?? 'current') {
'default' => $this->defaultLanguage(),
'current' => $this->currentLanguage(),
From 7111bcde226fcb2307f692a2a8a92d6b1f4d02c0 Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Fri, 3 May 2024 13:37:52 +0200
Subject: [PATCH 087/125] Move App::setCurrentLanguage and fix type hinting
---
src/Cms/App.php | 27 ++++++++++++++++++++++++++-
src/Cms/AppTranslations.php | 28 ----------------------------
2 files changed, 26 insertions(+), 29 deletions(-)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index 1e37de1666..b91f192f23 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -31,6 +31,7 @@
use Kirby\Toolkit\Controller;
use Kirby\Toolkit\LazyValue;
use Kirby\Toolkit\Str;
+use Kirby\Toolkit\Locale;
use Kirby\Uuid\Uuid;
use Throwable;
@@ -1213,7 +1214,7 @@ public function request(): Request
* @internal
* @throws \Kirby\Exception\NotFoundException if the home page cannot be found
*/
- public function resolve(string $path = null, string $language = null): mixed
+ public function resolve(string|null $path = null, string|null $language = null): mixed
{
// set the current translation
$this->setCurrentTranslation($language);
@@ -1411,6 +1412,30 @@ public function sessionHandler(): AutoSession
);
}
+ /**
+ * Load and set the current language if it exists
+ * Otherwise fall back to the default language
+ *
+ * @internal
+ */
+ public function setCurrentLanguage(
+ string|null $languageCode = null
+ ): Language|null {
+ if ($this->multilang() === false) {
+ Locale::set($this->option('locale', 'en_US.utf-8'));
+ return $this->language = null;
+ }
+
+ $this->language = $this->language($languageCode) ?? $this->defaultLanguage();
+
+ Locale::set($this->language->locale());
+
+ // add language slug rules to Str class
+ Str::$language = $this->language->rules();
+
+ return $this->language;
+ }
+
/**
* Create your own set of languages
*
diff --git a/src/Cms/AppTranslations.php b/src/Cms/AppTranslations.php
index f3d80b114f..1efae287cb 100644
--- a/src/Cms/AppTranslations.php
+++ b/src/Cms/AppTranslations.php
@@ -3,7 +3,6 @@
namespace Kirby\Cms;
use Kirby\Toolkit\I18n;
-use Kirby\Toolkit\Locale;
use Kirby\Toolkit\Str;
/**
@@ -104,33 +103,6 @@ public function panelLanguage(): string
return $this->option('panel.language', $defaultCode);
}
- /**
- * Load and set the current language if it exists
- * Otherwise fall back to the default language
- *
- * @internal
- */
- public function setCurrentLanguage(
- string $languageCode = null
- ): Language|null {
- if ($this->multilang() === false) {
- Locale::set($this->option('locale', 'en_US.utf-8'));
- return $this->language = null;
- }
-
- $this->language = $this->language($languageCode);
- $this->language ??= $this->defaultLanguage();
-
- if ($this->language) {
- Locale::set($this->language->locale());
- }
-
- // add language slug rules to Str class
- Str::$language = $this->language->rules();
-
- return $this->language;
- }
-
/**
* Set the current translation
*
From 8b84c9681b783806364b5e544c7aecbc0acaa2a6 Mon Sep 17 00:00:00 2001
From: Bastian Allgeier
Date: Fri, 3 May 2024 13:44:33 +0200
Subject: [PATCH 088/125] Fix CS issue
---
src/Cms/App.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Cms/App.php b/src/Cms/App.php
index b91f192f23..a29aa14cdf 100644
--- a/src/Cms/App.php
+++ b/src/Cms/App.php
@@ -30,8 +30,8 @@
use Kirby\Toolkit\Config;
use Kirby\Toolkit\Controller;
use Kirby\Toolkit\LazyValue;
-use Kirby\Toolkit\Str;
use Kirby\Toolkit\Locale;
+use Kirby\Toolkit\Str;
use Kirby\Uuid\Uuid;
use Throwable;
From e4f85589456e5184de31ab0f4f826d0961ba683c Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Thu, 9 May 2024 10:43:29 +0200
Subject: [PATCH 089/125] QrCode: `border` argument
---
src/Image/QrCode.php | 28 +++++++++++++++--------
tests/Image/QrCodeTest.php | 9 ++++++++
tests/Image/fixtures/qr/image-border.png | Bin 0 -> 623 bytes
3 files changed, 27 insertions(+), 10 deletions(-)
create mode 100644 tests/Image/fixtures/qr/image-border.png
diff --git a/src/Image/QrCode.php b/src/Image/QrCode.php
index b6599fb6eb..d675f41d0a 100644
--- a/src/Image/QrCode.php
+++ b/src/Image/QrCode.php
@@ -59,13 +59,15 @@ public function __construct(public string $data)
* @param int|null $size Image width/height in pixels, defaults to a size per module of 4x4
* @param string $color Foreground color in hex format
* @param string $back Background color in hex format
+ * @param int $border Border size in number of modules
*/
public function toDataUri(
int|null $size = null,
string $color = '#000000',
- string $back = '#ffffff'
+ string $back = '#ffffff',
+ int $border = 4
): string {
- $image = $this->toImage($size, $color, $back);
+ $image = $this->toImage($size, $color, $back, $border);
ob_start();
imagepng($image);
@@ -82,14 +84,16 @@ public function toDataUri(
* @param int|null $size Image width/height in pixels, defaults to a size per module of 4x4
* @param string $color Foreground color in hex format
* @param string $back Background color in hex format
+ * @param int $border Border size in number of modules
*/
public function toImage(
int|null $size = null,
string $color = '#000000',
- string $back = '#ffffff'
+ string $back = '#ffffff',
+ int $border = 4
): GdImage {
// get code and size measurements
- $code = $this->encode();
+ $code = $this->encode($border);
[$width, $height] = $this->measure($code);
$size ??= ceil($width * 4);
$ws = $size / $width;
@@ -132,13 +136,15 @@ public function toImage(
* @param int|string|null $size Optional CSS width of the `` element
* @param string $color Foreground color in hex format
* @param string $back Background color in hex format
+ * @param int $border Border size in number of modules
*/
public function toSvg(
int|string|null $size = null,
string $color = '#000000',
- string $back = '#ffffff'
+ string $back = '#ffffff',
+ int $border = 4
): string {
- $code = $this->encode();
+ $code = $this->encode($border);
[$vbw, $vbh] = $this->measure($code);
$modules = $this->eachModuleGroup(
@@ -167,15 +173,17 @@ public function __toString(): string
* @param int|string|null $size Optional image width/height in pixels (defaults to a size per module of 4x4) or CSS width of the `` element
* @param string $color Foreground color in hex format
* @param string $back Background color in hex format
+ * @param int $border Border size in number of modules
*/
public function write(
string $file,
int|string|null $size = null,
string $color = '#000000',
- string $back = '#ffffff'
+ string $back = '#ffffff',
+ int $border = 4
): void {
$format = F::extension($file);
- $args = [$size, $color, $back];
+ $args = [$size, $color, $back, $border];
match ($format) {
'gif' => imagegif($this->toImage(...$args), $file),
@@ -395,7 +403,7 @@ protected function eachModuleGroup(array $code, Closure $action): array
return $result;
}
- protected function encode(): array
+ protected function encode(int $q = 4): array
{
[$data, $version, $ecl, $ec] = $this->encodeData();
$data = $this->encodeErrorCorrection($data, $ec, $version);
@@ -404,7 +412,7 @@ protected function encode(): array
$mtx = $this->finalizeMatrix($mtx, $size, $ecl, $mask, $version);
return [
- 'q' => [4, 4, 4, 4],
+ 'q' => [$q, $q, $q, $q],
'size' => [$size, $size],
'bits' => $mtx
];
diff --git a/tests/Image/QrCodeTest.php b/tests/Image/QrCodeTest.php
index 2b573af41a..69905a3395 100644
--- a/tests/Image/QrCodeTest.php
+++ b/tests/Image/QrCodeTest.php
@@ -72,6 +72,15 @@ public function testToImageColors()
$this->assertSame($expected, $data);
}
+ public function testToImageBorder()
+ {
+ $qr = new QrCode('https://getkirby.com');
+ $image = $qr->toImage(null, '#000000', '#ffffff', 0);
+ $data = $this->imageContent($image);
+ $expected = F::read(static::FIXTURES . '/image-border.png');
+ $this->assertSame($expected, $data);
+ }
+
public function testToSvg()
{
$qr = new QrCode('12345678');
diff --git a/tests/Image/fixtures/qr/image-border.png b/tests/Image/fixtures/qr/image-border.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb1227f792503bab8645eba85a4e994eb34003dc
GIT binary patch
literal 623
zcmeAS@N?(olHy`uVBq!ia0vp^DIm(=Sjx8|JD&b;3Pafr>+H78?oHr?MIdi+9Skab!LBiQk`PMOLIefPR@
zC;Y7h$kHjS8m}J+mp&1VPG09?JH7aD{34M4iUgy|u(WJh+mCnr)$dC}RA$)bTSylB
zJ}Zg--5Fg9b9Pkm;V$d>xn;Jm`xk<=E-nnK+OKc8&wArE#SW0?d(M@vSa)Bl-uK!q
z&AE0^TRW~FRDY!?lzy?qE*t8!*XM41|6;jFeQwONeTf24r)j?Y`u@mG(-Qv!CxD^2
zK<7a8oM5l(hhDti!Vh!6y?1jiO+K>u!gEuT<4~7YM4q$qyt1
Date: Sun, 12 May 2024 12:00:32 +0200
Subject: [PATCH 090/125] Upgrad npm dependencies
---
panel/package-lock.json | 214 ++++++++++++++++++++--------------------
panel/package.json | 20 ++--
2 files changed, 119 insertions(+), 115 deletions(-)
diff --git a/panel/package-lock.json b/panel/package-lock.json
index b85aa61cc7..6222f4806e 100644
--- a/panel/package-lock.json
+++ b/panel/package-lock.json
@@ -8,16 +8,16 @@
"dependencies": {
"autosize": "^6.0.1",
"container-query-polyfill": "^1.0.2",
- "dayjs": "^1.11.10",
+ "dayjs": "^1.11.11",
"mitt": "^3.0.1",
"portal-vue": "^2.1.7",
"prosemirror-commands": "^1.5.2",
"prosemirror-history": "^1.4.0",
"prosemirror-inputrules": "^1.4.0",
"prosemirror-keymap": "^1.2.2",
- "prosemirror-model": "^1.20.0",
+ "prosemirror-model": "^1.21.0",
"prosemirror-schema-list": "^1.3.0",
- "prosemirror-view": "^1.33.4",
+ "prosemirror-view": "^1.33.6",
"vue": "^2.7.16",
"vuedraggable": "^2.24.3",
"vuelidate": "^0.7.7",
@@ -25,17 +25,17 @@
},
"devDependencies": {
"@vitejs/plugin-vue2": "^2.3.1",
- "eslint": "^9.0.0",
+ "eslint": "^9.2.0",
"eslint-config-prettier": "^9.1.0",
- "eslint-plugin-vue": "^9.24.1",
- "glob": "^10.3.12",
+ "eslint-plugin-vue": "^9.26.0",
+ "glob": "^10.3.15",
"jsdom": "^24.0.0",
"prettier": "^3.2.5",
"rollup-plugin-external-globals": "^0.10.0",
- "terser": "^5.30.3",
- "vite": "^5.2.8",
- "vite-plugin-static-copy": "^1.0.2",
- "vitest": "^1.5.0",
+ "terser": "^5.31.0",
+ "vite": "^5.2.11",
+ "vite-plugin-static-copy": "^1.0.4",
+ "vitest": "^1.6.0",
"vue-docgen-api": "^4.78.0",
"vue-template-compiler": "^2.7.16"
}
@@ -537,18 +537,18 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.0.0.tgz",
- "integrity": "sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==",
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.2.0.tgz",
+ "integrity": "sha512-ESiIudvhoYni+MdsI8oD7skpprZ89qKocwRM2KEvhhBJ9nl5MRh7BXU5GTod7Mdygq+AUl+QzId6iWJKR/wABA==",
"dev": true,
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@humanwhocodes/config-array": {
- "version": "0.12.3",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.12.3.tgz",
- "integrity": "sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==",
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
"dev": true,
"dependencies": {
"@humanwhocodes/object-schema": "^2.0.3",
@@ -578,6 +578,19 @@
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
"dev": true
},
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.2.4.tgz",
+ "integrity": "sha512-Ttl/jHpxfS3st5sxwICYfk4pOH0WrLI1SpW283GgQL7sCWU7EHIOhX4b4fkIxr3tkfzwg8+FNojtzsIEE7Ecgg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -965,13 +978,13 @@
}
},
"node_modules/@vitest/expect": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.0.tgz",
- "integrity": "sha512-0pzuCI6KYi2SIC3LQezmxujU9RK/vwC1U9R0rLuGlNGcOuDWxqWKu6nUdFsX9tH1WU0SXtAxToOsEjeUn1s3hA==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz",
+ "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==",
"dev": true,
"dependencies": {
- "@vitest/spy": "1.5.0",
- "@vitest/utils": "1.5.0",
+ "@vitest/spy": "1.6.0",
+ "@vitest/utils": "1.6.0",
"chai": "^4.3.10"
},
"funding": {
@@ -979,12 +992,12 @@
}
},
"node_modules/@vitest/runner": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.0.tgz",
- "integrity": "sha512-7HWwdxXP5yDoe7DTpbif9l6ZmDwCzcSIK38kTSIt6CFEpMjX4EpCgT6wUmS0xTXqMI6E/ONmfgRKmaujpabjZQ==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz",
+ "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==",
"dev": true,
"dependencies": {
- "@vitest/utils": "1.5.0",
+ "@vitest/utils": "1.6.0",
"p-limit": "^5.0.0",
"pathe": "^1.1.1"
},
@@ -1020,9 +1033,9 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.0.tgz",
- "integrity": "sha512-qpv3fSEuNrhAO3FpH6YYRdaECnnRjg9VxbhdtPwPRnzSfHVXnNzzrpX4cJxqiwgRMo7uRMWDFBlsBq4Cr+rO3A==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz",
+ "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==",
"dev": true,
"dependencies": {
"magic-string": "^0.30.5",
@@ -1040,21 +1053,18 @@
"dev": true
},
"node_modules/@vitest/snapshot/node_modules/magic-string": {
- "version": "0.30.9",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.9.tgz",
- "integrity": "sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==",
+ "version": "0.30.10",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
+ "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
- },
- "engines": {
- "node": ">=12"
}
},
"node_modules/@vitest/spy": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.0.tgz",
- "integrity": "sha512-vu6vi6ew5N5MMHJjD5PoakMRKYdmIrNJmyfkhRpQt5d9Ewhw9nZ5Aqynbi3N61bvk9UvZ5UysMT6ayIrZ8GA9w==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz",
+ "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==",
"dev": true,
"dependencies": {
"tinyspy": "^2.2.0"
@@ -1064,9 +1074,9 @@
}
},
"node_modules/@vitest/utils": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.0.tgz",
- "integrity": "sha512-BDU0GNL8MWkRkSRdNFvCUCAVOeHaUlVJ9Tx0TYBZyXaaOTmGtUFObzchCivIBrIwKzvZA7A9sCejVhXM2aY98A==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz",
+ "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==",
"dev": true,
"dependencies": {
"diff-sequences": "^29.6.3",
@@ -1641,9 +1651,9 @@
}
},
"node_modules/dayjs": {
- "version": "1.11.10",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
- "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ=="
+ "version": "1.11.11",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz",
+ "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
},
"node_modules/de-indent": {
"version": "1.0.2",
@@ -1827,17 +1837,18 @@
}
},
"node_modules/eslint": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.0.0.tgz",
- "integrity": "sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==",
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.2.0.tgz",
+ "integrity": "sha512-0n/I88vZpCOzO+PQpt0lbsqmn9AsnsJAQseIqhZFI8ibQT0U1AkEKRxA3EVMos0BoHSXDQvCXY25TUjB5tr8Og==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^3.0.2",
- "@eslint/js": "9.0.0",
- "@humanwhocodes/config-array": "^0.12.3",
+ "@eslint/js": "9.2.0",
+ "@humanwhocodes/config-array": "^0.13.0",
"@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.2.3",
"@nodelib/fs.walk": "^1.2.8",
"ajv": "^6.12.4",
"chalk": "^4.0.0",
@@ -1853,7 +1864,6 @@
"file-entry-cache": "^8.0.0",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
- "graphemer": "^1.4.0",
"ignore": "^5.2.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
@@ -1890,9 +1900,9 @@
}
},
"node_modules/eslint-plugin-vue": {
- "version": "9.24.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.24.1.tgz",
- "integrity": "sha512-wk3SuwmS1pZdcuJlokGYEi/buDOwD6KltvhIZyOnpJ/378dcQ4zchu9PAMbbLAaydCz1iYc5AozszcOOgZIIOg==",
+ "version": "9.26.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.26.0.tgz",
+ "integrity": "sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
@@ -2301,22 +2311,22 @@
}
},
"node_modules/glob": {
- "version": "10.3.12",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
- "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
+ "version": "10.3.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz",
+ "integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==",
"dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^2.3.6",
"minimatch": "^9.0.1",
"minipass": "^7.0.4",
- "path-scurry": "^1.10.2"
+ "path-scurry": "^1.11.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -2388,12 +2398,6 @@
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
"dev": true
},
- "node_modules/graphemer": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
- "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
- "dev": true
- },
"node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@@ -3239,9 +3243,9 @@
}
},
"node_modules/lru-cache": {
- "version": "10.2.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
- "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
+ "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
"dev": true,
"engines": {
"node": "14 || >=16.14"
@@ -3330,9 +3334,9 @@
}
},
"node_modules/minipass": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
- "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz",
+ "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==",
"dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -3588,16 +3592,16 @@
"dev": true
},
"node_modules/path-scurry": {
- "version": "1.10.2",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
- "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dev": true,
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -3793,9 +3797,9 @@
}
},
"node_modules/prosemirror-model": {
- "version": "1.20.0",
- "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.20.0.tgz",
- "integrity": "sha512-q7AY7vMjKYqDCeoedgUiAgrLabliXxndJuuFmcmc2+YU1SblvnOiG2WEACF2lwAZsMlfLpiAilA3L+TWlDqIsQ==",
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.21.0.tgz",
+ "integrity": "sha512-zLpS1mVCZLA7VTp82P+BfMiYVPcX1/z0Mf3gsjKZtzMWubwn2pN7CceMV0DycjlgE5JeXPR7UF4hJPbBV98oWA==",
"dependencies": {
"orderedmap": "^2.0.0"
}
@@ -3829,9 +3833,9 @@
}
},
"node_modules/prosemirror-view": {
- "version": "1.33.4",
- "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.4.tgz",
- "integrity": "sha512-xQqAhH8/HGleVpKDhQsrd+oqdyeKMxFtdCWDxWMmP+n0k27fBpyUqa8pA+RB5cFY8rqDDc1hll69aRZQa7UaAw==",
+ "version": "1.33.6",
+ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.6.tgz",
+ "integrity": "sha512-zRLUNgLIQfd8IfGprsXxWTjdA8xEAFJe8cDNrOptj6Mop9sj+BMeVbJvceyAYCm5G2dOdT2prctH7K9dfnpIMw==",
"dependencies": {
"prosemirror-model": "^1.20.0",
"prosemirror-state": "^1.0.0",
@@ -4004,9 +4008,9 @@
]
},
"node_modules/react-is": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
- "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
"dev": true
},
"node_modules/readdirp": {
@@ -4466,9 +4470,9 @@
"dev": true
},
"node_modules/terser": {
- "version": "5.30.3",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.30.3.tgz",
- "integrity": "sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==",
+ "version": "5.31.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz",
+ "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
@@ -4689,9 +4693,9 @@
"dev": true
},
"node_modules/vite": {
- "version": "5.2.8",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz",
- "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==",
+ "version": "5.2.11",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
+ "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==",
"dev": true,
"dependencies": {
"esbuild": "^0.20.1",
@@ -4744,9 +4748,9 @@
}
},
"node_modules/vite-node": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.0.tgz",
- "integrity": "sha512-tV8h6gMj6vPzVCa7l+VGq9lwoJjW8Y79vst8QZZGiuRAfijU+EEWuc0kFpmndQrWhMMhet1jdSF+40KSZUqIIw==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz",
+ "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==",
"dev": true,
"dependencies": {
"cac": "^6.7.14",
@@ -4766,9 +4770,9 @@
}
},
"node_modules/vite-plugin-static-copy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-1.0.2.tgz",
- "integrity": "sha512-AfmEF+a/mfjsUsrgjbCkhzUCeIUF4EKQXXt3Ie1cour9MBpy6f6GphbdW2td28oYfOrwCyRzFCksgLkpk58q6Q==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-1.0.4.tgz",
+ "integrity": "sha512-UtyOttgoeotSCwmBugsEZCZJZcIpjE9NGO7jlZ9OeedYpBueBdspD8waRZrjE+yQLH6qGNU2CvYB2FILviCQjg==",
"dev": true,
"dependencies": {
"chokidar": "^3.5.3",
@@ -4798,16 +4802,16 @@
}
},
"node_modules/vitest": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.0.tgz",
- "integrity": "sha512-d8UKgR0m2kjdxDWX6911uwxout6GHS0XaGH1cksSIVVG8kRlE7G7aBw7myKQCvDI5dT4j7ZMa+l706BIORMDLw==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz",
+ "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==",
"dev": true,
"dependencies": {
- "@vitest/expect": "1.5.0",
- "@vitest/runner": "1.5.0",
- "@vitest/snapshot": "1.5.0",
- "@vitest/spy": "1.5.0",
- "@vitest/utils": "1.5.0",
+ "@vitest/expect": "1.6.0",
+ "@vitest/runner": "1.6.0",
+ "@vitest/snapshot": "1.6.0",
+ "@vitest/spy": "1.6.0",
+ "@vitest/utils": "1.6.0",
"acorn-walk": "^8.3.2",
"chai": "^4.3.10",
"debug": "^4.3.4",
@@ -4821,7 +4825,7 @@
"tinybench": "^2.5.1",
"tinypool": "^0.8.3",
"vite": "^5.0.0",
- "vite-node": "1.5.0",
+ "vite-node": "1.6.0",
"why-is-node-running": "^2.2.2"
},
"bin": {
@@ -4836,8 +4840,8 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/node": "^18.0.0 || >=20.0.0",
- "@vitest/browser": "1.5.0",
- "@vitest/ui": "1.5.0",
+ "@vitest/browser": "1.6.0",
+ "@vitest/ui": "1.6.0",
"happy-dom": "*",
"jsdom": "*"
},
diff --git a/panel/package.json b/panel/package.json
index a9e2b9e3f1..4446c4c83f 100644
--- a/panel/package.json
+++ b/panel/package.json
@@ -13,16 +13,16 @@
"dependencies": {
"autosize": "^6.0.1",
"container-query-polyfill": "^1.0.2",
- "dayjs": "^1.11.10",
+ "dayjs": "^1.11.11",
"mitt": "^3.0.1",
"portal-vue": "^2.1.7",
"prosemirror-commands": "^1.5.2",
"prosemirror-history": "^1.4.0",
"prosemirror-inputrules": "^1.4.0",
"prosemirror-keymap": "^1.2.2",
- "prosemirror-model": "^1.20.0",
+ "prosemirror-model": "^1.21.0",
"prosemirror-schema-list": "^1.3.0",
- "prosemirror-view": "^1.33.4",
+ "prosemirror-view": "^1.33.6",
"vue": "^2.7.16",
"vuedraggable": "^2.24.3",
"vuelidate": "^0.7.7",
@@ -30,17 +30,17 @@
},
"devDependencies": {
"@vitejs/plugin-vue2": "^2.3.1",
- "eslint": "^9.0.0",
+ "eslint": "^9.2.0",
"eslint-config-prettier": "^9.1.0",
- "eslint-plugin-vue": "^9.24.1",
- "glob": "^10.3.12",
+ "eslint-plugin-vue": "^9.26.0",
+ "glob": "^10.3.15",
"jsdom": "^24.0.0",
"prettier": "^3.2.5",
"rollup-plugin-external-globals": "^0.10.0",
- "terser": "^5.30.3",
- "vite": "^5.2.8",
- "vite-plugin-static-copy": "^1.0.2",
- "vitest": "^1.5.0",
+ "terser": "^5.31.0",
+ "vite": "^5.2.11",
+ "vite-plugin-static-copy": "^1.0.4",
+ "vitest": "^1.6.0",
"vue-docgen-api": "^4.78.0",
"vue-template-compiler": "^2.7.16"
},
From 94d5729e861ccfc0bbdd8b846d8b82bd8188cd1c Mon Sep 17 00:00:00 2001
From: Nico Hoffmann
Date: Sun, 24 Mar 2024 18:15:19 +0100
Subject: [PATCH 091/125] Login lab examples
---
.../lab/components/login/login-code/index.php | 5 +
.../lab/components/login/login-code/index.vue | 15 ++
panel/lab/components/login/login/index.php | 5 +
panel/lab/components/login/login/index.vue | 26 +++
panel/src/components/Forms/Login.vue | 155 +++++++++++-------
panel/src/components/Forms/LoginCode.vue | 41 +++--
.../src/components/Views/Login/LoginView.vue | 59 ++-----
7 files changed, 189 insertions(+), 117 deletions(-)
create mode 100644 panel/lab/components/login/login-code/index.php
create mode 100644 panel/lab/components/login/login-code/index.vue
create mode 100644 panel/lab/components/login/login/index.php
create mode 100644 panel/lab/components/login/login/index.vue
diff --git a/panel/lab/components/login/login-code/index.php b/panel/lab/components/login/login-code/index.php
new file mode 100644
index 0000000000..939f9c01da
--- /dev/null
+++ b/panel/lab/components/login/login-code/index.php
@@ -0,0 +1,5 @@
+ 'k-login-code'
+];
diff --git a/panel/lab/components/login/login-code/index.vue b/panel/lab/components/login/login-code/index.vue
new file mode 100644
index 0000000000..a9581334a8
--- /dev/null
+++ b/panel/lab/components/login/login-code/index.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/panel/lab/components/login/login/index.php b/panel/lab/components/login/login/index.php
new file mode 100644
index 0000000000..681fdf8c82
--- /dev/null
+++ b/panel/lab/components/login/login/index.php
@@ -0,0 +1,5 @@
+ 'k-login'
+];
diff --git a/panel/lab/components/login/login/index.vue b/panel/lab/components/login/login/index.vue
new file mode 100644
index 0000000000..7b201b4df2
--- /dev/null
+++ b/panel/lab/components/login/login/index.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/panel/src/components/Forms/Login.vue b/panel/src/components/Forms/Login.vue
index 27b2535048..d006baf3a3 100644
--- a/panel/src/components/Forms/Login.vue
+++ b/panel/src/components/Forms/Login.vue
@@ -1,32 +1,31 @@
@@ -48,12 +46,18 @@ export const props = {
/**
* List of available login method names
*/
- methods: Array,
+ methods: {
+ type: Array,
+ default: () => []
+ },
/**
* Values to prefill the inputs
- * @value { email: String, password: String }
+ * @value { email: String, password: String, remember: Boolean }
*/
- value: Object
+ value: {
+ type: Object,
+ default: () => ({})
+ }
}
};
@@ -62,22 +66,36 @@ export default {
emits: ["error"],
data() {
return {
- currentForm: null,
+ mode: null,
isLoading: false,
user: {
- email: this.value.email ?? "",
- password: this.value.password ?? "",
- remember: false
+ email: "",
+ password: "",
+ remember: false,
+ ...this.value
}
};
},
computed: {
+ alternateMode() {
+ if (this.form === "email-password") {
+ return "email";
+ }
+
+ return "email-password";
+ },
canToggle() {
+ if (this.codeMode === null) {
+ return false;
+ }
+
+ if (this.methods.includes("password") === false) {
+ return false;
+ }
+
return (
- this.codeMode !== null &&
- this.methods.includes("password") === true &&
- (this.methods.includes("password-reset") === true ||
- this.methods.includes("code") === true)
+ this.methods.includes("password-reset") === true ||
+ this.methods.includes("code") === true
);
},
codeMode() {
@@ -90,7 +108,7 @@ export default {
return null;
},
fields() {
- let fields = {
+ const fields = {
email: {
autofocus: true,
label: this.$t("email"),
@@ -114,8 +132,8 @@ export default {
return fields;
},
form() {
- if (this.currentForm) {
- return this.currentForm;
+ if (this.mode) {
+ return this.mode;
}
if (this.methods[0] === "password") {
@@ -127,28 +145,30 @@ export default {
isResetForm() {
return this.codeMode === "password-reset" && this.form === "email";
},
+ submitText() {
+ const suffix = this.isLoading ? " …" : "";
+
+ if (this.isResetForm) {
+ return this.$t("login.reset") + suffix;
+ }
+
+ return this.$t("login") + suffix;
+ },
toggleText() {
return this.$t(
- "login.toggleText." + this.codeMode + "." + this.formOpposite(this.form)
+ "login.toggleText." + this.codeMode + "." + this.alternateMode
);
}
},
methods: {
- formOpposite(input) {
- if (input === "email-password") {
- return "email";
- } else {
- return "email-password";
- }
- },
async login() {
this.$emit("error", null);
this.isLoading = true;
// clear field data that is not needed for login
- let user = Object.assign({}, this.user);
+ const user = Object.assign({}, this.user);
- if (this.currentForm === "email") {
+ if (this.mode === "email") {
user.password = null;
}
@@ -173,10 +193,35 @@ export default {
this.isLoading = false;
}
},
- toggleForm() {
- this.currentForm = this.formOpposite(this.form);
+ toggle() {
+ this.mode = this.alternateMode;
this.$refs.fieldset.focus("email");
}
}
};
+
+
diff --git a/panel/src/components/Forms/LoginCode.vue b/panel/src/components/Forms/LoginCode.vue
index 642dcf9b2d..dfe25125d3 100644
--- a/panel/src/components/Forms/LoginCode.vue
+++ b/panel/src/components/Forms/LoginCode.vue
@@ -1,6 +1,6 @@
@@ -49,12 +49,18 @@ export const props = {
/**
* List of available login method names
*/
- methods: Array,
+ methods: {
+ type: Array,
+ default: () => []
+ },
/**
* Pending login data (user email, challenge type)
* @value { email: String, challenge: String }
*/
- pending: Object,
+ pending: {
+ type: Object,
+ default: () => ({ challenge: "email" })
+ },
/**
* Code value to prefill the input
*/
@@ -68,27 +74,20 @@ export default {
data() {
return {
code: this.value ?? "",
- isLoadingBack: false,
- isLoadingLogin: false
+ isLoading: false
};
},
computed: {
mode() {
- if (this.methods.includes("password-reset") === true) {
- return "password-reset";
- }
-
- return "login";
+ return this.methods.includes("password-reset")
+ ? "password-reset"
+ : "login";
}
},
methods: {
- async back() {
- this.isLoadingBack = true;
- this.$go("/logout");
- },
async login() {
this.$emit("error", null);
- this.isLoadingLogin = true;
+ this.isLoading = true;
try {
await this.$api.auth.verifyCode(this.code);
@@ -106,7 +105,7 @@ export default {
} catch (error) {
this.$emit("error", error);
} finally {
- this.isLoadingLogin = false;
+ this.isLoading = false;
}
}
}
diff --git a/panel/src/components/Views/Login/LoginView.vue b/panel/src/components/Views/Login/LoginView.vue
index 4552b4d817..4118caa96b 100644
--- a/panel/src/components/Views/Login/LoginView.vue
+++ b/panel/src/components/Views/Login/LoginView.vue
@@ -1,7 +1,9 @@
-
+
-
+
{{ $t("login") }}
@@ -16,7 +18,12 @@
v-bind="{ methods, pending, value: value.code }"
@error="onError"
/>
-
+
@@ -24,14 +31,14 @@