From 15a6b3c845be567fb918ecda7d80b54821ab78c6 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Wed, 9 Oct 2024 16:32:07 +0200 Subject: [PATCH 01/34] First draft for a new comparison view --- config/areas/site/views.php | 17 +++ panel/public/img/icons.svg | 9 ++ panel/src/components/Forms/FormControls.vue | 2 +- .../Views/Pages/PageComparisonView.vue | 136 ++++++++++++++++++ panel/src/components/Views/Pages/index.js | 2 + src/Panel/Page.php | 2 +- 6 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 panel/src/components/Views/Pages/PageComparisonView.vue diff --git a/config/areas/site/views.php b/config/areas/site/views.php index 7465d2e324..36bd2868bb 100644 --- a/config/areas/site/views.php +++ b/config/areas/site/views.php @@ -8,6 +8,23 @@ 'pattern' => 'pages/(:any)', 'action' => fn (string $path) => Find::page($path)->panel()->view() ], + 'page.changes.compare' => [ + 'pattern' => 'pages/(:any)/changes/compare', + 'action' => function (string $path) { + $page = Find::page($path); + + return [ + 'component' => 'k-page-comparison-view', + 'props' => [ + 'changes' => $page->previewUrl() . '?_version=changes', + 'backlink' => $page->panel()->url(true), + 'lock' => $page->lock()->toArray(), + 'published' => $page->previewUrl(), + ], + 'title' => $page->title()->value(), + ]; + } + ], 'page.file' => [ 'pattern' => 'pages/(:any)/files/(:any)', 'action' => function (string $id, string $filename) { diff --git a/panel/public/img/icons.svg b/panel/public/img/icons.svg index 4ac88fe8b5..ce4efe04ea 100644 --- a/panel/public/img/icons.svg +++ b/panel/public/img/icons.svg @@ -359,6 +359,15 @@ + + + + + + + + + diff --git a/panel/src/components/Forms/FormControls.vue b/panel/src/components/Forms/FormControls.vue index 7c287d4ef1..d7fd9d7cd3 100644 --- a/panel/src/components/Forms/FormControls.vue +++ b/panel/src/components/Forms/FormControls.vue @@ -41,7 +41,7 @@ diff --git a/panel/src/components/Views/Pages/PageComparisonView.vue b/panel/src/components/Views/Pages/PageComparisonView.vue new file mode 100644 index 0000000000..3855e8e45d --- /dev/null +++ b/panel/src/components/Views/Pages/PageComparisonView.vue @@ -0,0 +1,136 @@ + + + + + diff --git a/panel/src/components/Views/Pages/index.js b/panel/src/components/Views/Pages/index.js index 98ac2a67bf..7b1238c742 100644 --- a/panel/src/components/Views/Pages/index.js +++ b/panel/src/components/Views/Pages/index.js @@ -1,9 +1,11 @@ import PageView from "./PageView.vue"; +import PageComparisonView from "./PageComparisonView.vue"; import SiteView from "./SiteView.vue"; export default { install(app) { app.component("k-page-view", PageView); + app.component("k-page-comparison-view", PageComparisonView); app.component("k-site-view", SiteView); } }; diff --git a/src/Panel/Page.php b/src/Panel/Page.php index f9b157caca..5b6afc2399 100644 --- a/src/Panel/Page.php +++ b/src/Panel/Page.php @@ -365,7 +365,7 @@ public function props(): array ...$props, ...$this->prevNext(), 'blueprint' => $this->model->intendedTemplate()->name(), - 'changesUrl' => $this->model->previewUrl() . '?_version=changes', + 'changesUrl' => $this->url(true) . '/changes/compare', 'model' => $model, 'title' => $model['title'], ]; From 97568ca443506b114849c796709e93c509bc1bb7 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Wed, 9 Oct 2024 16:52:08 +0200 Subject: [PATCH 02/34] Open in new window buttons --- .../Views/Pages/PageComparisonView.vue | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/panel/src/components/Views/Pages/PageComparisonView.vue b/panel/src/components/Views/Pages/PageComparisonView.vue index 3855e8e45d..8f97ab22bb 100644 --- a/panel/src/components/Views/Pages/PageComparisonView.vue +++ b/panel/src/components/Views/Pages/PageComparisonView.vue @@ -51,11 +51,29 @@
- Published version + + Published version + +
- Changed version + + Changed version + +
@@ -125,6 +143,9 @@ export default { border-right: 1px solid var(--color-border); } .k-page-comparison-grid > section .k-headline { + display: flex; + align-items: center; + justify-content: space-between; margin-bottom: var(--spacing-3); } .k-page-comparison-grid iframe { From 3a79ce4f2e341849532e97916aa75eb8453f0a08 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 12:31:19 +0200 Subject: [PATCH 03/34] Rename view to k-page-changes-view --- config/areas/site/views.php | 18 +- .../Views/Pages/PageChangesView.vue | 165 ++++++++++++++++++ .../Views/Pages/PageComparisonView.vue | 157 ----------------- panel/src/components/Views/Pages/index.js | 4 +- src/Panel/Page.php | 2 +- 5 files changed, 178 insertions(+), 168 deletions(-) create mode 100644 panel/src/components/Views/Pages/PageChangesView.vue delete mode 100644 panel/src/components/Views/Pages/PageComparisonView.vue diff --git a/config/areas/site/views.php b/config/areas/site/views.php index 36bd2868bb..5a5ae1a00a 100644 --- a/config/areas/site/views.php +++ b/config/areas/site/views.php @@ -8,20 +8,22 @@ 'pattern' => 'pages/(:any)', 'action' => fn (string $path) => Find::page($path)->panel()->view() ], - 'page.changes.compare' => [ - 'pattern' => 'pages/(:any)/changes/compare', + 'page.changes' => [ + 'pattern' => 'pages/(:any)/changes', 'action' => function (string $path) { $page = Find::page($path); + $view = Find::page($path)->panel()->view(); return [ - 'component' => 'k-page-comparison-view', + 'component' => 'k-page-changes-view', 'props' => [ - 'changes' => $page->previewUrl() . '?_version=changes', - 'backlink' => $page->panel()->url(true), - 'lock' => $page->lock()->toArray(), - 'published' => $page->previewUrl(), + ...$view['props'], + 'src' => [ + 'changes' => $page->previewUrl() . '?_version=changes', + 'latest' => $page->previewUrl(), + ] ], - 'title' => $page->title()->value(), + 'title' => $view['title'], ]; } ], diff --git a/panel/src/components/Views/Pages/PageChangesView.vue b/panel/src/components/Views/Pages/PageChangesView.vue new file mode 100644 index 0000000000..c2252248ce --- /dev/null +++ b/panel/src/components/Views/Pages/PageChangesView.vue @@ -0,0 +1,165 @@ + + + + + diff --git a/panel/src/components/Views/Pages/PageComparisonView.vue b/panel/src/components/Views/Pages/PageComparisonView.vue deleted file mode 100644 index 8f97ab22bb..0000000000 --- a/panel/src/components/Views/Pages/PageComparisonView.vue +++ /dev/null @@ -1,157 +0,0 @@ - - - - - diff --git a/panel/src/components/Views/Pages/index.js b/panel/src/components/Views/Pages/index.js index 7b1238c742..3df6769f36 100644 --- a/panel/src/components/Views/Pages/index.js +++ b/panel/src/components/Views/Pages/index.js @@ -1,11 +1,11 @@ import PageView from "./PageView.vue"; -import PageComparisonView from "./PageComparisonView.vue"; +import PageChangesView from "./PageChangesView.vue"; import SiteView from "./SiteView.vue"; export default { install(app) { app.component("k-page-view", PageView); - app.component("k-page-comparison-view", PageComparisonView); + app.component("k-page-changes-view", PageChangesView); app.component("k-site-view", SiteView); } }; diff --git a/src/Panel/Page.php b/src/Panel/Page.php index 5b6afc2399..ff380550fb 100644 --- a/src/Panel/Page.php +++ b/src/Panel/Page.php @@ -365,7 +365,7 @@ public function props(): array ...$props, ...$this->prevNext(), 'blueprint' => $this->model->intendedTemplate()->name(), - 'changesUrl' => $this->url(true) . '/changes/compare', + 'changesUrl' => $this->url(true) . '/changes', 'model' => $model, 'title' => $model['title'], ]; From 08ae8ecd7aa2248f4a450e768c92ffe445f2a91f Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 12:31:38 +0200 Subject: [PATCH 04/34] Move view logic to ModelView component instead of the content module --- panel/src/components/Views/ModelView.vue | 6 ++++-- panel/src/panel/content.js | 7 ++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/panel/src/components/Views/ModelView.vue b/panel/src/components/Views/ModelView.vue index 33314fbf7b..db9845f6e1 100644 --- a/panel/src/components/Views/ModelView.vue +++ b/panel/src/components/Views/ModelView.vue @@ -92,6 +92,7 @@ export default { } await this.$panel.content.discard(); + this.$panel.view.reload(); }, onInput(values) { if (this.isLocked === true) { @@ -105,13 +106,14 @@ export default { e?.preventDefault?.(); this.onSubmit(); }, - onSubmit(values = {}) { + async onSubmit(values = {}) { if (this.isLocked === true) { return false; } this.$panel.content.update(values); - this.$panel.content.publish(); + await this.$panel.content.publish(); + await this.$panel.view.refresh(); }, toPrev(e) { if (this.prev && e.target.localName === "body") { diff --git a/panel/src/panel/content.js b/panel/src/panel/content.js index 3165fb40e6..df943ae661 100644 --- a/panel/src/panel/content.js +++ b/panel/src/panel/content.js @@ -47,7 +47,6 @@ export default (panel) => { try { await panel.api.post(this.api + "/changes/discard"); panel.view.props.content = panel.view.props.originals; - panel.view.reload(); } finally { this.isProcessing = false; } @@ -102,13 +101,11 @@ export default (panel) => { panel.view.props.originals = panel.view.props.content; - await panel.view.refresh(); + panel.events.emit("model.update"); + panel.notification.success(); } finally { this.isProcessing = false; } - - panel.events.emit("model.update"); - panel.notification.success(); }, /** From fd5d4a825cc8e7a6a0eec9d01111f387d47fa011 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 12:33:43 +0200 Subject: [PATCH 05/34] Make iframes responsive --- panel/src/components/Views/Pages/PageChangesView.vue | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/panel/src/components/Views/Pages/PageChangesView.vue b/panel/src/components/Views/Pages/PageChangesView.vue index c2252248ce..4ef87d7010 100644 --- a/panel/src/components/Views/Pages/PageChangesView.vue +++ b/panel/src/components/Views/Pages/PageChangesView.vue @@ -134,8 +134,11 @@ export default { display: grid; grid-template-columns: 100%; } -.k-page-changes-grid[data-mode="compare"] { - grid-template-columns: 50% 50%; + +@media screen and (min-width: 50rem) { + .k-page-changes-grid[data-mode="compare"] { + grid-template-columns: 50% 50%; + } } .k-page-changes-grid > section { From 99a781c93bc34897d8be53107d03bd008ab27bf3 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 12:36:34 +0200 Subject: [PATCH 06/34] Set a default background for the iframes --- panel/src/components/Views/Pages/PageChangesView.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/panel/src/components/Views/Pages/PageChangesView.vue b/panel/src/components/Views/Pages/PageChangesView.vue index 4ef87d7010..1d56aae768 100644 --- a/panel/src/components/Views/Pages/PageChangesView.vue +++ b/panel/src/components/Views/Pages/PageChangesView.vue @@ -160,6 +160,7 @@ export default { flex-grow: 1; border-radius: var(--rounded-lg); box-shadow: var(--shadow-xl); + background: var(--color-white); } .k-page-changes-grid .k-empty { flex-grow: 1; From 5484c1af10fc323f70b2c2edf75d1b755d95bae1 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 12:44:22 +0200 Subject: [PATCH 07/34] Fix CS issues --- config/areas/site/views.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/areas/site/views.php b/config/areas/site/views.php index 5a5ae1a00a..03158542cd 100644 --- a/config/areas/site/views.php +++ b/config/areas/site/views.php @@ -19,7 +19,7 @@ 'props' => [ ...$view['props'], 'src' => [ - 'changes' => $page->previewUrl() . '?_version=changes', + 'changes' => $page->previewUrl() . '?_version=changes', 'latest' => $page->previewUrl(), ] ], From a5c57994e0d1706ad0f537bf7496e90ca8115d18 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 12:56:50 +0200 Subject: [PATCH 08/34] Add a unit test for the changes route --- tests/Panel/Areas/SiteTest.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/Panel/Areas/SiteTest.php b/tests/Panel/Areas/SiteTest.php index 3cd44563e5..dd36143690 100644 --- a/tests/Panel/Areas/SiteTest.php +++ b/tests/Panel/Areas/SiteTest.php @@ -58,6 +58,27 @@ public function testPage(): void $this->assertNull($props['prev']); } + public function testPageChanges(): void + { + $this->login(); + + $this->app->site()->createChild([ + 'slug' => 'test', + 'isDraft' => false, + 'content' => [ + 'title' => 'Test' + ] + ]); + + $view = $this->view('pages/test/changes'); + $props = $view['props']; + + $this->assertSame('k-page-changes-view', $view['component']); + $this->assertSame('Test', $view['title']); + $this->assertSame('/test?_version=changes', $props['src']['changes']); + $this->assertSame('/test', $props['src']['latest']); + } + public function testPageFileWithoutModel(): void { $this->login(); From 076003662d7e397f78c39074877247a81e8cc2f3 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 14:23:06 +0200 Subject: [PATCH 09/34] Translated labels --- i18n/translations/en.json | 3 +++ .../components/Views/Pages/PageChangesView.vue | 18 +++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/i18n/translations/en.json b/i18n/translations/en.json index e97387a5df..e500f11d69 100644 --- a/i18n/translations/en.json +++ b/i18n/translations/en.json @@ -748,10 +748,13 @@ "users": "Users", "version": "Version", + "version.changes": "Changed version", + "version.compare": "Compare versions", "version.current": "Current version", "version.latest": "Latest version", "versionInformation": "Version information", + "view": "View", "view.account": "Your account", "view.installation": "Installation", "view.languages": "Languages", diff --git a/panel/src/components/Views/Pages/PageChangesView.vue b/panel/src/components/Views/Pages/PageChangesView.vue index 1d56aae768..a2ceb64889 100644 --- a/panel/src/components/Views/Pages/PageChangesView.vue +++ b/panel/src/components/Views/Pages/PageChangesView.vue @@ -2,9 +2,17 @@
- + - There are no unsaved changes + {{ $t("lock.unsaved.empty") }} @@ -71,19 +79,19 @@ export default { modes() { return { latest: { - label: "Latest version", + label: this.$t("version.latest"), icon: "layout-right", current: this.mode === "latest", click: () => (this.mode = "latest") }, changes: { - label: "Changed version", + label: this.$t("version.changes"), icon: "layout-left", current: this.mode === "changes", click: () => (this.mode = "changes") }, compare: { - label: "Side by side", + label: this.$t("version.compare"), icon: "layout-columns", current: this.mode === "compare", click: () => (this.mode = "compare") From 57927a8d3f0721dec1eba2a53c3854324aecc000 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 14:25:02 +0200 Subject: [PATCH 10/34] Responsive header buttons --- panel/src/components/Views/Pages/PageChangesView.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/panel/src/components/Views/Pages/PageChangesView.vue b/panel/src/components/Views/Pages/PageChangesView.vue index a2ceb64889..0b410ae849 100644 --- a/panel/src/components/Views/Pages/PageChangesView.vue +++ b/panel/src/components/Views/Pages/PageChangesView.vue @@ -4,6 +4,7 @@ Date: Tue, 22 Oct 2024 14:25:07 +0200 Subject: [PATCH 11/34] Responsive form controls --- panel/src/components/Forms/FormControls.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/panel/src/components/Forms/FormControls.vue b/panel/src/components/Forms/FormControls.vue index d7fd9d7cd3..0ff9ef615e 100644 --- a/panel/src/components/Forms/FormControls.vue +++ b/panel/src/components/Forms/FormControls.vue @@ -4,6 +4,7 @@ Date: Tue, 22 Oct 2024 16:04:12 +0200 Subject: [PATCH 12/34] Better wording MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nico Hoffmann เทด. --- i18n/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/translations/en.json b/i18n/translations/en.json index e500f11d69..3b947c7211 100644 --- a/i18n/translations/en.json +++ b/i18n/translations/en.json @@ -749,7 +749,7 @@ "version": "Version", "version.changes": "Changed version", - "version.compare": "Compare versions", + "version.compare": "Comparing versions", "version.current": "Current version", "version.latest": "Latest version", "versionInformation": "Version information", From 4378bce9fca6ff7ff5bbb1fc6072f9be1983ac71 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 16:06:37 +0200 Subject: [PATCH 13/34] Remove repeating code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nico Hoffmann เทด. --- config/areas/site/views.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/areas/site/views.php b/config/areas/site/views.php index 03158542cd..d6f976fa96 100644 --- a/config/areas/site/views.php +++ b/config/areas/site/views.php @@ -12,7 +12,7 @@ 'pattern' => 'pages/(:any)/changes', 'action' => function (string $path) { $page = Find::page($path); - $view = Find::page($path)->panel()->view(); + $view = $page->panel()->view(); return [ 'component' => 'k-page-changes-view', From d3eefd0755a89e126077ef1a21f92abb43e8e806 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 22 Oct 2024 16:10:14 +0200 Subject: [PATCH 14/34] Flip the menu order --- panel/src/components/Views/Pages/PageChangesView.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panel/src/components/Views/Pages/PageChangesView.vue b/panel/src/components/Views/Pages/PageChangesView.vue index 0b410ae849..e3e50e7c08 100644 --- a/panel/src/components/Views/Pages/PageChangesView.vue +++ b/panel/src/components/Views/Pages/PageChangesView.vue @@ -101,7 +101,7 @@ export default { }; }, dropdown() { - return [this.modes.latest, this.modes.changes, "-", this.modes.compare]; + return [this.modes.compare, "-", this.modes.latest, this.modes.changes]; } }, methods: { From 5e8513d11f8fab52c7e34346837b272c42cfe12a Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Mon, 4 Nov 2024 16:45:03 +0100 Subject: [PATCH 15/34] New expand and collapse icons --- panel/public/img/icons.svg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/panel/public/img/icons.svg b/panel/public/img/icons.svg index ce4efe04ea..7852a28e71 100644 --- a/panel/public/img/icons.svg +++ b/panel/public/img/icons.svg @@ -131,6 +131,9 @@ + + + @@ -179,6 +182,9 @@ + + + From 99662e30e2c8b72b9eec4ae22521835d06f625d3 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Mon, 4 Nov 2024 16:52:46 +0100 Subject: [PATCH 16/34] Various UX changes --- .../Views/Pages/PageChangesView.vue | 181 ++++++++++++------ 1 file changed, 119 insertions(+), 62 deletions(-) diff --git a/panel/src/components/Views/Pages/PageChangesView.vue b/panel/src/components/Views/Pages/PageChangesView.vue index e3e50e7c08..dda3cad5e7 100644 --- a/panel/src/components/Views/Pages/PageChangesView.vue +++ b/panel/src/components/Views/Pages/PageChangesView.vue @@ -5,59 +5,92 @@ + @click="$refs.tree.toggle()" + > + + + {{ title }} + + + - + - -
-
- - {{ modes.latest.label }} - - - +
+
+ {{ modes.latest.label }} + + + + +
+
-
- - {{ modes.changes.label }} - - - + +
+
+ {{ modes.changes.label }} + + + + + +
+ {{ $t("lock.unsaved.empty") }}
@@ -80,23 +113,23 @@ export default { computed: { modes() { return { - latest: { - label: this.$t("version.latest"), - icon: "layout-right", - current: this.mode === "latest", - click: () => (this.mode = "latest") - }, changes: { label: this.$t("version.changes"), icon: "layout-left", current: this.mode === "changes", - click: () => (this.mode = "changes") + click: () => this.changeMode("changes") }, compare: { label: this.$t("version.compare"), icon: "layout-columns", current: this.mode === "compare", - click: () => (this.mode = "compare") + click: () => this.changeMode("compare") + }, + latest: { + label: this.$t("version.latest"), + icon: "layout-right", + current: this.mode === "latest", + click: () => this.changeMode("latest") } }; }, @@ -104,14 +137,30 @@ export default { return [this.modes.compare, "-", this.modes.latest, this.modes.changes]; } }, + watch: { + id: { + handler() { + this.changeMode(localStorage.getItem("kirby$preview$mode")); + }, + immediate: true + } + }, methods: { + changeMode(mode) { + if (!mode || !this.modes[mode]) { + return; + } + + this.mode = mode; + localStorage.setItem("kirby$preview$mode", mode); + }, async onDiscard() { if (this.isLocked === true) { return false; } await this.$panel.content.discard(); - await this.$panel.view.open(this.link); + await this.$panel.view.reload(); }, async onSubmit() { if (this.isLocked === true) { @@ -119,7 +168,7 @@ export default { } await this.$panel.content.publish(); - await this.$panel.view.open(this.link); + await this.$panel.reload(); } } }; @@ -136,31 +185,39 @@ export default { .k-page-changes-header { container-type: inline-size; display: flex; - align-items: center; + gap: var(--spacing-2); justify-content: space-between; + align-items: center; padding: var(--spacing-2); border-bottom: 1px solid var(--color-border); } -.k-page-changes-grid { - display: grid; - grid-template-columns: 100%; -} -@media screen and (min-width: 50rem) { - .k-page-changes-grid[data-mode="compare"] { - grid-template-columns: 50% 50%; +@media screen and (max-width: 40rem) { + .k-page-changes-header-controls > .k-button { + --button-text-display: none; } } -.k-page-changes-grid > section { +.k-page-changes-grid { + display: flex; +} +@media screen and (max-width: 60rem) { + .k-page-changes-grid { + flex-direction: column; + } +} +.k-page-changes-grid .k-page-changes-panel + .k-page-changes-panel { + border-left: 1px solid var(--color-border); +} +.k-page-changes-panel { + flex-grow: 1; display: flex; flex-direction: column; padding: var(--spacing-6); + background: var(--color-gray-200); } -.k-page-changes-grid > section:first-child { - border-right: 1px solid var(--color-border); -} -.k-page-changes-grid > section .k-headline { +.k-page-changes-panel header { + container-type: inline-size; display: flex; align-items: center; justify-content: space-between; From b76419d8d344f33674ad83940551f6508f2ef111 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Tue, 5 Nov 2024 12:24:35 +0100 Subject: [PATCH 17/34] Improve the wording in the discard dialog --- i18n/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/translations/en.json b/i18n/translations/en.json index 3b947c7211..e140c0a97c 100644 --- a/i18n/translations/en.json +++ b/i18n/translations/en.json @@ -378,7 +378,7 @@ "filter": "Filter", "form.discard": "Discard changes", - "form.discard.confirm": "Do you really want to delete all unpublished changes?", + "form.discard.confirm": "Do you really want to discard all your changes?", "form.locked": "This content is disabled for you as it is currently edited by another user", "form.unsaved": "The current changes have not yet been saved", "form.preview": "Preview changes", From 16b93c7c4baf75171f9597500067a6da1f8b0abf Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Wed, 6 Nov 2024 11:47:52 +0100 Subject: [PATCH 18/34] New asterisk and window icons --- panel/public/img/icons.svg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/panel/public/img/icons.svg b/panel/public/img/icons.svg index 7852a28e71..8ea8e714b4 100644 --- a/panel/public/img/icons.svg +++ b/panel/public/img/icons.svg @@ -36,6 +36,9 @@ + + + @@ -658,6 +661,9 @@ + + + From 541aed2340e372296ba34be2018be7fa4bdf47ce Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Wed, 6 Nov 2024 11:48:03 +0100 Subject: [PATCH 19/34] Slightly better wording --- i18n/translations/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/translations/en.json b/i18n/translations/en.json index e140c0a97c..0e03083c4a 100644 --- a/i18n/translations/en.json +++ b/i18n/translations/en.json @@ -749,7 +749,7 @@ "version": "Version", "version.changes": "Changed version", - "version.compare": "Comparing versions", + "version.compare": "Compare versions", "version.current": "Current version", "version.latest": "Latest version", "versionInformation": "Version information", From b407d6b55427bf46704ac9a7904b1a7cce2ba0b3 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Wed, 6 Nov 2024 11:52:55 +0100 Subject: [PATCH 20/34] Rename View and implement for the site --- config/areas/site/views.php | 57 +++++++++---- panel/src/components/Views/Pages/PageView.vue | 2 +- panel/src/components/Views/Pages/SiteView.vue | 2 +- panel/src/components/Views/Pages/index.js | 2 - .../PageChangesView.vue => PreviewView.vue} | 81 +++++++++---------- panel/src/components/Views/index.js | 2 + src/Panel/Page.php | 32 +++++--- src/Panel/Site.php | 1 - 8 files changed, 102 insertions(+), 77 deletions(-) rename panel/src/components/Views/{Pages/PageChangesView.vue => PreviewView.vue} (76%) diff --git a/config/areas/site/views.php b/config/areas/site/views.php index d6f976fa96..8c8d6e8e77 100644 --- a/config/areas/site/views.php +++ b/config/areas/site/views.php @@ -8,31 +8,34 @@ 'pattern' => 'pages/(:any)', 'action' => fn (string $path) => Find::page($path)->panel()->view() ], - 'page.changes' => [ - 'pattern' => 'pages/(:any)/changes', - 'action' => function (string $path) { - $page = Find::page($path); - $view = $page->panel()->view(); + 'page.file' => [ + 'pattern' => 'pages/(:any)/files/(:any)', + 'action' => function (string $id, string $filename) { + return Find::file('pages/' . $id, $filename)->panel()->view(); + } + ], + 'page.preview' => [ + 'pattern' => 'pages/(:any)/preview/(changes|latest|compare)', + 'action' => function (string $path, string $mode) { + $page = Find::page($path); + $view = $page->panel()->view(); + $preview = $page->previewUrl(); return [ - 'component' => 'k-page-changes-view', + 'component' => 'k-preview-view', 'props' => [ ...$view['props'], - 'src' => [ - 'changes' => $page->previewUrl() . '?_version=changes', - 'latest' => $page->previewUrl(), + 'back' => $view['props']['link'], + 'mode' => $mode, + 'src' => [ + 'changes' => $preview . '?_version=changes', + 'latest' => $preview, ] ], - 'title' => $view['title'], + 'title' => $view['props']['title'] . ' | ' . I18n::translate('changes'), ]; } ], - 'page.file' => [ - 'pattern' => 'pages/(:any)/files/(:any)', - 'action' => function (string $id, string $filename) { - return Find::file('pages/' . $id, $filename)->panel()->view(); - } - ], 'site' => [ 'pattern' => 'site', 'action' => fn () => App::instance()->site()->panel()->view() @@ -43,4 +46,26 @@ return Find::file('site', $filename)->panel()->view(); } ], + 'site.preview' => [ + 'pattern' => 'site/preview/(changes|latest|compare)', + 'action' => function (string $mode) { + $site = App::instance()->site(); + $view = $site->panel()->view(); + $preview = $site->previewUrl(); + + return [ + 'component' => 'k-preview-view', + 'props' => [ + ...$view['props'], + 'back' => $view['props']['link'], + 'mode' => $mode, + 'src' => [ + 'changes' => $preview . '?_version=changes', + 'latest' => $preview, + ] + ], + 'title' => I18n::translate('view.site') . ' | ' . I18n::translate('changes'), + ]; + } + ], ]; diff --git a/panel/src/components/Views/Pages/PageView.vue b/panel/src/components/Views/Pages/PageView.vue index 221df81afa..f66c3c62a9 100644 --- a/panel/src/components/Views/Pages/PageView.vue +++ b/panel/src/components/Views/Pages/PageView.vue @@ -24,7 +24,7 @@ :is-locked="isLocked" :is-unsaved="isUnsaved" :modified="modified" - :preview="changesUrl" + :preview="api + '/preview/compare'" @discard="onDiscard" @submit="onSubmit" /> diff --git a/panel/src/components/Views/Pages/SiteView.vue b/panel/src/components/Views/Pages/SiteView.vue index c20786de5e..235d16771e 100644 --- a/panel/src/components/Views/Pages/SiteView.vue +++ b/panel/src/components/Views/Pages/SiteView.vue @@ -20,7 +20,7 @@ :is-locked="isLocked" :is-unsaved="isUnsaved" :modified="modified" - :preview="changesUrl" + :preview="api + '/preview/compare'" @discard="onDiscard" @submit="onSubmit" /> diff --git a/panel/src/components/Views/Pages/index.js b/panel/src/components/Views/Pages/index.js index 3df6769f36..98ac2a67bf 100644 --- a/panel/src/components/Views/Pages/index.js +++ b/panel/src/components/Views/Pages/index.js @@ -1,11 +1,9 @@ import PageView from "./PageView.vue"; -import PageChangesView from "./PageChangesView.vue"; import SiteView from "./SiteView.vue"; export default { install(app) { app.component("k-page-view", PageView); - app.component("k-page-changes-view", PageChangesView); app.component("k-site-view", SiteView); } }; diff --git a/panel/src/components/Views/Pages/PageChangesView.vue b/panel/src/components/Views/PreviewView.vue similarity index 76% rename from panel/src/components/Views/Pages/PageChangesView.vue rename to panel/src/components/Views/PreviewView.vue index dda3cad5e7..a86df4a8da 100644 --- a/panel/src/components/Views/Pages/PageChangesView.vue +++ b/panel/src/components/Views/PreviewView.vue @@ -1,9 +1,9 @@ diff --git a/panel/src/components/Views/index.js b/panel/src/components/Views/index.js index e19f91a66c..86922c17b5 100644 --- a/panel/src/components/Views/index.js +++ b/panel/src/components/Views/index.js @@ -1,4 +1,5 @@ import ErrorView from "./ErrorView.vue"; +import PreviewView from "./PreviewView.vue"; import SearchView from "./SearchView.vue"; import Files from "./Files/index.js"; @@ -12,6 +13,7 @@ import System from "./System/index.js"; export default { install(app) { app.component("k-error-view", ErrorView); + app.component("k-preview-view", PreviewView); app.component("k-search-view", SearchView); app.use(Files); diff --git a/src/Panel/Page.php b/src/Panel/Page.php index ff380550fb..75cfd5ff97 100644 --- a/src/Panel/Page.php +++ b/src/Panel/Page.php @@ -103,16 +103,27 @@ public function dropdown(array $options = []): array $result = []; if ($view === 'list') { - $result['preview'] = [ - 'link' => $page->previewUrl(), - 'target' => '_blank', - 'icon' => 'open', - 'text' => I18n::translate('open'), - 'disabled' => $this->isDisabledDropdownOption('preview', $options, $permissions) - ]; - $result[] = '-'; + } + $result['preview'] = [ + 'link' => $page->previewUrl(), + 'target' => '_blank', + 'icon' => 'open', + 'text' => I18n::translate('open'), + 'disabled' => $this->isDisabledDropdownOption('preview', $options, $permissions) + ]; + + $result[] = '-'; + + $result['changes'] = [ + 'icon' => 'window', + 'link' => $page->panel()->url(true) . '/preview/compare', + 'text' => I18n::translate('preview'), + ]; + + $result[] = '-'; + $result['changeTitle'] = [ 'dialog' => [ 'url' => $url . '/changeTitle', @@ -365,7 +376,6 @@ public function props(): array ...$props, ...$this->prevNext(), 'blueprint' => $this->model->intendedTemplate()->name(), - 'changesUrl' => $this->url(true) . '/changes', 'model' => $model, 'title' => $model['title'], ]; @@ -382,8 +392,8 @@ public function view(): array return [ 'breadcrumb' => $this->model->panel()->breadcrumb(), 'component' => 'k-page-view', - 'props' => $this->props(), - 'title' => $this->model->title()->toString(), + 'props' => $props = $this->props(), + 'title' => $props['title'], ]; } } diff --git a/src/Panel/Site.php b/src/Panel/Site.php index fc87be3c10..95aff7b854 100644 --- a/src/Panel/Site.php +++ b/src/Panel/Site.php @@ -95,7 +95,6 @@ public function props(): array return [ ...$props, 'blueprint' => 'site', - 'changesUrl' => $this->model->previewUrl() . '?_version=changes', 'id' => '/', 'model' => $model, 'title' => $model['title'], From 9677b7a63f93530562e3e6cbe67256ccf8cd5829 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Wed, 6 Nov 2024 11:54:53 +0100 Subject: [PATCH 21/34] Fix the options in the page dropdown --- src/Panel/Page.php | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/Panel/Page.php b/src/Panel/Page.php index 75cfd5ff97..2c0e5bdc6f 100644 --- a/src/Panel/Page.php +++ b/src/Panel/Page.php @@ -103,27 +103,24 @@ public function dropdown(array $options = []): array $result = []; if ($view === 'list') { + $result['open'] = [ + 'link' => $page->previewUrl(), + 'target' => '_blank', + 'icon' => 'open', + 'text' => I18n::translate('open'), + 'disabled' => $this->isDisabledDropdownOption('preview', $options, $permissions) + ]; + + $result['preview'] = [ + 'icon' => 'window', + 'link' => $page->panel()->url(true) . '/preview/compare', + 'text' => I18n::translate('preview'), + ]; + + $result[] = '-'; } - $result['preview'] = [ - 'link' => $page->previewUrl(), - 'target' => '_blank', - 'icon' => 'open', - 'text' => I18n::translate('open'), - 'disabled' => $this->isDisabledDropdownOption('preview', $options, $permissions) - ]; - - $result[] = '-'; - - $result['changes'] = [ - 'icon' => 'window', - 'link' => $page->panel()->url(true) . '/preview/compare', - 'text' => I18n::translate('preview'), - ]; - - $result[] = '-'; - $result['changeTitle'] = [ 'dialog' => [ 'url' => $url . '/changeTitle', From 029a8b5a1e8ed1a0b26954649d2a118c25399068 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Wed, 6 Nov 2024 11:58:39 +0100 Subject: [PATCH 22/34] Fix / add unit tests --- src/Panel/Page.php | 1 - tests/Panel/Areas/SiteTest.php | 57 +++++++++++++++++++++------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/Panel/Page.php b/src/Panel/Page.php index 2c0e5bdc6f..37ec0c73a8 100644 --- a/src/Panel/Page.php +++ b/src/Panel/Page.php @@ -118,7 +118,6 @@ public function dropdown(array $options = []): array ]; $result[] = '-'; - } $result['changeTitle'] = [ diff --git a/tests/Panel/Areas/SiteTest.php b/tests/Panel/Areas/SiteTest.php index dd36143690..05957c5989 100644 --- a/tests/Panel/Areas/SiteTest.php +++ b/tests/Panel/Areas/SiteTest.php @@ -58,27 +58,6 @@ public function testPage(): void $this->assertNull($props['prev']); } - public function testPageChanges(): void - { - $this->login(); - - $this->app->site()->createChild([ - 'slug' => 'test', - 'isDraft' => false, - 'content' => [ - 'title' => 'Test' - ] - ]); - - $view = $this->view('pages/test/changes'); - $props = $view['props']; - - $this->assertSame('k-page-changes-view', $view['component']); - $this->assertSame('Test', $view['title']); - $this->assertSame('/test?_version=changes', $props['src']['changes']); - $this->assertSame('/test', $props['src']['latest']); - } - public function testPageFileWithoutModel(): void { $this->login(); @@ -140,6 +119,27 @@ public function testPageFile(): void $this->assertNull($props['prev']); } + public function testPagePreview(): void + { + $this->login(); + + $this->app->site()->createChild([ + 'slug' => 'test', + 'isDraft' => false, + 'content' => [ + 'title' => 'Test' + ] + ]); + + $view = $this->view('pages/test/preview/changes'); + $props = $view['props']; + + $this->assertSame('k-preview-view', $view['component']); + $this->assertSame('Test | Changes', $view['title']); + $this->assertSame('/test?_version=changes', $props['src']['changes']); + $this->assertSame('/test', $props['src']['latest']); + } + public function testSiteWithoutAuthentication(): void { $this->assertRedirect('site', 'login'); @@ -214,6 +214,21 @@ public function testSiteFile(): void $this->assertNull($props['prev']); } + public function testSitePreview(): void + { + $this->login(); + + $this->app->site(); + + $view = $this->view('site/preview/changes'); + $props = $view['props']; + + $this->assertSame('k-preview-view', $view['component']); + $this->assertSame('Site | Changes', $view['title']); + $this->assertSame('/?_version=changes', $props['src']['changes']); + $this->assertSame('/', $props['src']['latest']); + } + public function testSiteTitle(): void { $this->app([ From 3914f1bb5f48abc0e7518f95ef4949e51f5df10c Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Wed, 6 Nov 2024 13:20:14 +0100 Subject: [PATCH 23/34] New PreviewDropdownButton to handle the open/preview/copy dropdowns --- config/areas/site/buttons.php | 14 ++++- i18n/translations/en.json | 2 + panel/src/components/Forms/FormControls.vue | 2 +- panel/src/panel/events.js | 9 +++ src/Panel/Page.php | 9 ++- .../Ui/Buttons/PreviewDropdownButton.php | 58 +++++++++++++++++++ 6 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 src/Panel/Ui/Buttons/PreviewDropdownButton.php diff --git a/config/areas/site/buttons.php b/config/areas/site/buttons.php index 6daea92d60..575148af5c 100644 --- a/config/areas/site/buttons.php +++ b/config/areas/site/buttons.php @@ -5,16 +5,24 @@ use Kirby\Cms\Site; use Kirby\Panel\Ui\Buttons\LanguagesDropdown; use Kirby\Panel\Ui\Buttons\PageStatusButton; -use Kirby\Panel\Ui\Buttons\PreviewButton; +use Kirby\Panel\Ui\Buttons\PreviewDropdownButton; use Kirby\Panel\Ui\Buttons\SettingsButton; return [ 'site.preview' => function (Site $site) { - return new PreviewButton(link: $site->url()); + return new PreviewDropdownButton( + open: $site->url(), + preview: $site->panel()->url(true) . '/preview/compare', + copy: $site->url(), + ); }, 'page.preview' => function (Page $page) { if ($page->permissions()->can('preview') === true) { - return new PreviewButton(link: $page->previewUrl()); + return new PreviewDropdownButton( + open: $page->previewUrl(), + preview: $page->panel()->url(true) . '/preview/compare', + copy: $page->previewUrl(), + ); } }, 'page.settings' => function (Page $page) { diff --git a/i18n/translations/en.json b/i18n/translations/en.json index 0e03083c4a..c5b9ba62ce 100644 --- a/i18n/translations/en.json +++ b/i18n/translations/en.json @@ -18,9 +18,11 @@ "collapse.all": "Collapse All", "color": "Color", "coordinates": "Coordinates", + "copied": "Copied", "copy": "Copy", "copy.all": "Copy all", "copy.success": "{count} copied!", + "copy.url": "Copy URL", "create": "Create", "custom": "Custom", diff --git a/panel/src/components/Forms/FormControls.vue b/panel/src/components/Forms/FormControls.vue index 0ff9ef615e..d64a5c6eb1 100644 --- a/panel/src/components/Forms/FormControls.vue +++ b/panel/src/components/Forms/FormControls.vue @@ -42,7 +42,7 @@ diff --git a/panel/src/panel/events.js b/panel/src/panel/events.js index 6cd16ba7d8..fa2852a37f 100644 --- a/panel/src/panel/events.js +++ b/panel/src/panel/events.js @@ -33,6 +33,15 @@ export default (panel) => { emitter.on("keydown.cmd.shift.f", () => panel.search()); emitter.on("keydown.cmd./", () => panel.search()); + /** + * Custom copy to clipboard event + * @since 5.0.0 + */ + emitter.on("copyToClipboard", async (e) => { + navigator.clipboard.writeText(e); + panel.notification.success(panel.t("copied") + "!"); + }); + /** * Config for globally delegated events. * Some events need to be fired on the document diff --git a/src/Panel/Page.php b/src/Panel/Page.php index 37ec0c73a8..4b63eee132 100644 --- a/src/Panel/Page.php +++ b/src/Panel/Page.php @@ -92,11 +92,10 @@ public function dragText(string|null $type = null): string */ public function dropdown(array $options = []): array { - $page = $this->model; - $request = $page->kirby()->request(); - $defaults = $request->get(['view', 'sort', 'delete']); - $options = [...$defaults, $options]; - + $page = $this->model; + $request = $page->kirby()->request(); + $defaults = $request->get(['view', 'sort', 'delete']); + $options = [...$defaults, ...$options]; $permissions = $this->options(['preview']); $view = $options['view'] ?? 'view'; $url = $this->url(true); diff --git a/src/Panel/Ui/Buttons/PreviewDropdownButton.php b/src/Panel/Ui/Buttons/PreviewDropdownButton.php new file mode 100644 index 0000000000..61eb5ac7fc --- /dev/null +++ b/src/Panel/Ui/Buttons/PreviewDropdownButton.php @@ -0,0 +1,58 @@ + + * @link https://getkirby.com + * @copyright Bastian Allgeier + * @license https://getkirby.com/license + * @since 5.0.0 + * @internal + */ +class PreviewDropdownButton extends ViewButton +{ + public function __construct( + public string $open, + public string|null $preview, + public string|null $copy + ) { + parent::__construct( + class: 'k-preview-dropdown-view-button', + icon: 'open', + options: $this->options(), + title: I18n::translate('open') + ); + } + + public function options(): array + { + return [ + [ + 'text' => I18n::translate('open'), + 'icon' => 'open', + 'link' => $this->open, + 'target' => '_blank' + ], + [ + 'text' => I18n::translate('preview'), + 'icon' => 'window', + 'link' => $this->preview, + ], + '-', + [ + 'text' => I18n::translate('copy.url'), + 'icon' => 'copy', + 'click' => [ + 'global' => 'copyToClipboard', + 'payload' => $this->copy + ] + ] + ]; + } +} From 9f00a640d5edc181b431278c06341a27fcee9c39 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Sat, 9 Nov 2024 11:21:18 +0100 Subject: [PATCH 24/34] Fix outdated toggle method --- panel/src/components/Views/PreviewView.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/panel/src/components/Views/PreviewView.vue b/panel/src/components/Views/PreviewView.vue index a86df4a8da..6b3d41e1fc 100644 --- a/panel/src/components/Views/PreviewView.vue +++ b/panel/src/components/Views/PreviewView.vue @@ -9,7 +9,6 @@ icon="angle-left" size="sm" variant="filled" - @click="$refs.tree.toggle()" > From 78ccaf7dded3a9393432387bf551355a9476cf08 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Sat, 9 Nov 2024 13:14:26 +0100 Subject: [PATCH 25/34] Improve copy language strings --- i18n/translations/en.json | 4 ++-- panel/src/components/Forms/Blocks/Blocks.vue | 2 +- panel/src/components/Forms/Layouts/Layouts.vue | 2 +- panel/src/panel/events.js | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/i18n/translations/en.json b/i18n/translations/en.json index c5b9ba62ce..71c9747425 100644 --- a/i18n/translations/en.json +++ b/i18n/translations/en.json @@ -18,10 +18,10 @@ "collapse.all": "Collapse All", "color": "Color", "coordinates": "Coordinates", - "copied": "Copied", "copy": "Copy", "copy.all": "Copy all", - "copy.success": "{count} copied!", + "copy.success": "Copied", + "copy.success.multiple": "{count} copied!", "copy.url": "Copy URL", "create": "Create", "custom": "Custom", diff --git a/panel/src/components/Forms/Blocks/Blocks.vue b/panel/src/components/Forms/Blocks/Blocks.vue index 1ef942077f..cccdf8c123 100644 --- a/panel/src/components/Forms/Blocks/Blocks.vue +++ b/panel/src/components/Forms/Blocks/Blocks.vue @@ -263,7 +263,7 @@ export default { // a sign that it has been copied this.$panel.notification.success({ - message: this.$t("copy.success", { count: blocks.length }), + message: this.$t("copy.success.multiple", { count: blocks.length }), icon: "template" }); }, diff --git a/panel/src/components/Forms/Layouts/Layouts.vue b/panel/src/components/Forms/Layouts/Layouts.vue index 8268ec2b46..12cb3c8b7d 100644 --- a/panel/src/components/Forms/Layouts/Layouts.vue +++ b/panel/src/components/Forms/Layouts/Layouts.vue @@ -103,7 +103,7 @@ export default { // a sign that it has been pasted this.$panel.notification.success({ - message: this.$t("copy.success", { count: copy.length ?? 1 }), + message: this.$t("copy.success.multiple", { count: copy.length ?? 1 }), icon: "template" }); }, diff --git a/panel/src/panel/events.js b/panel/src/panel/events.js index fa2852a37f..35cf2491c7 100644 --- a/panel/src/panel/events.js +++ b/panel/src/panel/events.js @@ -39,7 +39,7 @@ export default (panel) => { */ emitter.on("copyToClipboard", async (e) => { navigator.clipboard.writeText(e); - panel.notification.success(panel.t("copied") + "!"); + panel.notification.success(panel.t("copy.success") + "!"); }); /** From 1b98a11e41185ef8f899db13f2b863d298517ab9 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Sat, 9 Nov 2024 13:20:49 +0100 Subject: [PATCH 26/34] Use existing clipboard helper --- panel/src/panel/events.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/panel/src/panel/events.js b/panel/src/panel/events.js index 35cf2491c7..7f22804bc2 100644 --- a/panel/src/panel/events.js +++ b/panel/src/panel/events.js @@ -1,4 +1,5 @@ import { lcfirst } from "@/helpers/string"; +import clipboard from "@/helpers/clipboard"; import mitt from "mitt"; /** @@ -38,7 +39,7 @@ export default (panel) => { * @since 5.0.0 */ emitter.on("copyToClipboard", async (e) => { - navigator.clipboard.writeText(e); + clipboard.write(e); panel.notification.success(panel.t("copy.success") + "!"); }); From 1b3a5a5701012f2f5e9fa27d233314d932f9857b Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Sat, 9 Nov 2024 13:41:37 +0100 Subject: [PATCH 27/34] New VersionId option for preview URLs --- config/areas/site/views.php | 18 ++++++++---------- src/Cms/Page.php | 24 +++++++++++++++--------- src/Cms/Site.php | 26 +++++++++++++++++++++----- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/config/areas/site/views.php b/config/areas/site/views.php index 8c8d6e8e77..4b294448b8 100644 --- a/config/areas/site/views.php +++ b/config/areas/site/views.php @@ -17,9 +17,8 @@ 'page.preview' => [ 'pattern' => 'pages/(:any)/preview/(changes|latest|compare)', 'action' => function (string $path, string $mode) { - $page = Find::page($path); - $view = $page->panel()->view(); - $preview = $page->previewUrl(); + $page = Find::page($path); + $view = $page->panel()->view(); return [ 'component' => 'k-preview-view', @@ -28,8 +27,8 @@ 'back' => $view['props']['link'], 'mode' => $mode, 'src' => [ - 'changes' => $preview . '?_version=changes', - 'latest' => $preview, + 'changes' => $page->previewUrl('changes'), + 'latest' => $page->previewUrl('latest'), ] ], 'title' => $view['props']['title'] . ' | ' . I18n::translate('changes'), @@ -49,9 +48,8 @@ 'site.preview' => [ 'pattern' => 'site/preview/(changes|latest|compare)', 'action' => function (string $mode) { - $site = App::instance()->site(); - $view = $site->panel()->view(); - $preview = $site->previewUrl(); + $site = App::instance()->site(); + $view = $site->panel()->view(); return [ 'component' => 'k-preview-view', @@ -60,8 +58,8 @@ 'back' => $view['props']['link'], 'mode' => $mode, 'src' => [ - 'changes' => $preview . '?_version=changes', - 'latest' => $preview, + 'changes' => $site->previewUrl('changes'), + 'latest' => $site->previewUrl('latest'), ] ], 'title' => I18n::translate('view.site') . ' | ' . I18n::translate('changes'), diff --git a/src/Cms/Page.php b/src/Cms/Page.php index 81477884a7..1a1131e518 100644 --- a/src/Cms/Page.php +++ b/src/Cms/Page.php @@ -4,6 +4,7 @@ use Closure; use Kirby\Content\Field; +use Kirby\Content\VersionId; use Kirby\Exception\Exception; use Kirby\Exception\InvalidArgumentException; use Kirby\Exception\NotFoundException; @@ -929,26 +930,31 @@ public function permissions(): PagePermissions * Draft preview Url * @internal */ - public function previewUrl(): string|null + public function previewUrl(VersionId|string $version = 'latest'): string|null { - $preview = $this->blueprint()->preview(); + $versionId = VersionId::from($version); + $url = $this->blueprint()->preview(); - if ($preview === false) { + if ($url === false) { return null; } - $url = match ($preview) { - true => $this->url(), - default => $preview + $url = match ($url) { + true, null => $this->url(), + default => $url }; + $uri = new Uri($url ?? $this->url()); + if ($this->isDraft() === true) { - $uri = new Uri($url); $uri->query->token = $this->token(); - $url = $uri->toString(); } - return $url; + if ($versionId->is('changes') === true) { + $uri->query->_version = 'changes'; + } + + return $uri->toString(); } /** diff --git a/src/Cms/Site.php b/src/Cms/Site.php index e9c3142c32..bb681c01e1 100644 --- a/src/Cms/Site.php +++ b/src/Cms/Site.php @@ -2,9 +2,11 @@ namespace Kirby\Cms; +use Kirby\Content\VersionId; use Kirby\Exception\InvalidArgumentException; use Kirby\Exception\LogicException; use Kirby\Filesystem\Dir; +use Kirby\Http\Uri; use Kirby\Panel\Site as Panel; use Kirby\Toolkit\A; @@ -351,13 +353,27 @@ public function permissions(): SitePermissions * Preview Url * @internal */ - public function previewUrl(): string|null + public function previewUrl(VersionId|string $versionId = 'latest'): string|null { - return match ($preview = $this->blueprint()->preview()) { - true => $this->url(), - false => null, - default => $preview + $versionId = VersionId::from($versionId); + $url = $this->blueprint()->preview(); + + if ($url === false) { + return null; + } + + $url = match ($url) { + true, null => $this->url(), + default => $url }; + + $uri = new Uri($url); + + if ($versionId->is('changes') === true) { + $uri->query->_version = 'changes'; + } + + return $uri->toString(); } /** From 23aba266ce55dfe8fae2d0bcb998d90d9e0217b3 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Sat, 9 Nov 2024 13:43:13 +0100 Subject: [PATCH 28/34] Add use statement --- config/areas/site/views.php | 1 + 1 file changed, 1 insertion(+) diff --git a/config/areas/site/views.php b/config/areas/site/views.php index 4b294448b8..99bc955043 100644 --- a/config/areas/site/views.php +++ b/config/areas/site/views.php @@ -2,6 +2,7 @@ use Kirby\Cms\App; use Kirby\Cms\Find; +use Kirby\Toolkit\I18n; return [ 'page' => [ From 05d31fa3502d71c7a265a841638505017edb6d92 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Mon, 11 Nov 2024 11:42:47 +0100 Subject: [PATCH 29/34] Remove unnecessary fallback --- src/Cms/Page.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Cms/Page.php b/src/Cms/Page.php index 1a1131e518..aa3c31bb72 100644 --- a/src/Cms/Page.php +++ b/src/Cms/Page.php @@ -944,7 +944,7 @@ public function previewUrl(VersionId|string $version = 'latest'): string|null default => $url }; - $uri = new Uri($url ?? $this->url()); + $uri = new Uri($url); if ($this->isDraft() === true) { $uri->query->token = $this->token(); From 4c268d76f28212ad9ff5499e469ebf5668003bf5 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Mon, 11 Nov 2024 11:58:46 +0100 Subject: [PATCH 30/34] Throw a permission exception if the preview view cannot be visited --- config/areas/site/views.php | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/config/areas/site/views.php b/config/areas/site/views.php index 99bc955043..1fd682e463 100644 --- a/config/areas/site/views.php +++ b/config/areas/site/views.php @@ -2,6 +2,7 @@ use Kirby\Cms\App; use Kirby\Cms\Find; +use Kirby\Exception\PermissionException; use Kirby\Toolkit\I18n; return [ @@ -21,6 +22,13 @@ $page = Find::page($path); $view = $page->panel()->view(); + $changesUrl = $page->previewUrl('changes'); + $latestUrl = $page->previewUrl('latest'); + + if ($latestUrl === null) { + throw new PermissionException('The preview is not available'); + } + return [ 'component' => 'k-preview-view', 'props' => [ @@ -28,8 +36,8 @@ 'back' => $view['props']['link'], 'mode' => $mode, 'src' => [ - 'changes' => $page->previewUrl('changes'), - 'latest' => $page->previewUrl('latest'), + 'changes' => $changesUrl, + 'latest' => $latestUrl, ] ], 'title' => $view['props']['title'] . ' | ' . I18n::translate('changes'), @@ -52,6 +60,13 @@ $site = App::instance()->site(); $view = $site->panel()->view(); + $changesUrl = $site->previewUrl('changes'); + $latestUrl = $site->previewUrl('latest'); + + if ($latestUrl === null) { + throw new PermissionException('The preview is not available'); + } + return [ 'component' => 'k-preview-view', 'props' => [ @@ -59,8 +74,8 @@ 'back' => $view['props']['link'], 'mode' => $mode, 'src' => [ - 'changes' => $site->previewUrl('changes'), - 'latest' => $site->previewUrl('latest'), + 'changes' => $changesUrl, + 'latest' => $latestUrl, ] ], 'title' => I18n::translate('view.site') . ' | ' . I18n::translate('changes'), From 43b0070d2e7d97ef72cd0ad19844ab34015e83da Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Mon, 11 Nov 2024 11:58:53 +0100 Subject: [PATCH 31/34] Remove outdated prop --- panel/src/components/Views/ModelView.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/panel/src/components/Views/ModelView.vue b/panel/src/components/Views/ModelView.vue index db9845f6e1..5b131565bc 100644 --- a/panel/src/components/Views/ModelView.vue +++ b/panel/src/components/Views/ModelView.vue @@ -9,7 +9,6 @@ export default { api: String, blueprint: String, buttons: Array, - changesUrl: String, content: Object, id: String, link: String, From b6a041a1d00f7d2f3e8268cd9bfbb6f912c47b63 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Mon, 11 Nov 2024 11:59:10 +0100 Subject: [PATCH 32/34] Check for permissions for the preview button in the dropdown --- panel/src/components/Views/Pages/PageView.vue | 2 +- panel/src/components/Views/Pages/SiteView.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/panel/src/components/Views/Pages/PageView.vue b/panel/src/components/Views/Pages/PageView.vue index f66c3c62a9..2bfb8c778c 100644 --- a/panel/src/components/Views/Pages/PageView.vue +++ b/panel/src/components/Views/Pages/PageView.vue @@ -24,7 +24,7 @@ :is-locked="isLocked" :is-unsaved="isUnsaved" :modified="modified" - :preview="api + '/preview/compare'" + :preview="permissions.preview ? api + '/preview/compare' : false" @discard="onDiscard" @submit="onSubmit" /> diff --git a/panel/src/components/Views/Pages/SiteView.vue b/panel/src/components/Views/Pages/SiteView.vue index 235d16771e..8527594275 100644 --- a/panel/src/components/Views/Pages/SiteView.vue +++ b/panel/src/components/Views/Pages/SiteView.vue @@ -20,7 +20,7 @@ :is-locked="isLocked" :is-unsaved="isUnsaved" :modified="modified" - :preview="api + '/preview/compare'" + :preview="permissions.preview ? api + '/preview/compare' : false" @discard="onDiscard" @submit="onSubmit" /> From bb96335bf2c2a9df609931af9d8ed43de67c78cc Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Mon, 11 Nov 2024 12:04:41 +0100 Subject: [PATCH 33/34] Leave the preview view on esc --- panel/src/components/Views/PreviewView.vue | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/panel/src/components/Views/PreviewView.vue b/panel/src/components/Views/PreviewView.vue index 6b3d41e1fc..b1416f5efd 100644 --- a/panel/src/components/Views/PreviewView.vue +++ b/panel/src/components/Views/PreviewView.vue @@ -139,6 +139,12 @@ export default { return [this.modes.compare, "-", this.modes.latest, this.modes.changes]; } }, + mounted() { + this.$events.on("keydown.esc", this.onExit); + }, + destroyed() { + this.$events.off("keydown.esc", this.onExit); + }, methods: { changeMode(mode) { if (!mode || !this.modes[mode]) { @@ -155,6 +161,13 @@ export default { await this.$panel.content.discard(); await this.$panel.view.reload(); }, + onExit() { + if (this.$panel.overlays().length > 0) { + return; + } + + this.$panel.view.open(this.link); + }, async onSubmit() { if (this.isLocked === true) { return false; From f9ce581b634c76b9793aeba4bbac9bbd1c597df4 Mon Sep 17 00:00:00 2001 From: Bastian Allgeier Date: Mon, 11 Nov 2024 12:09:16 +0100 Subject: [PATCH 34/34] Rename clipboard event --- panel/src/panel/events.js | 2 +- src/Panel/Ui/Buttons/PreviewDropdownButton.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/panel/src/panel/events.js b/panel/src/panel/events.js index 7f22804bc2..a99104e3ec 100644 --- a/panel/src/panel/events.js +++ b/panel/src/panel/events.js @@ -38,7 +38,7 @@ export default (panel) => { * Custom copy to clipboard event * @since 5.0.0 */ - emitter.on("copyToClipboard", async (e) => { + emitter.on("clipboard.write", async (e) => { clipboard.write(e); panel.notification.success(panel.t("copy.success") + "!"); }); diff --git a/src/Panel/Ui/Buttons/PreviewDropdownButton.php b/src/Panel/Ui/Buttons/PreviewDropdownButton.php index 61eb5ac7fc..0d6ed526b9 100644 --- a/src/Panel/Ui/Buttons/PreviewDropdownButton.php +++ b/src/Panel/Ui/Buttons/PreviewDropdownButton.php @@ -49,7 +49,7 @@ public function options(): array 'text' => I18n::translate('copy.url'), 'icon' => 'copy', 'click' => [ - 'global' => 'copyToClipboard', + 'global' => 'clipboard.write', 'payload' => $this->copy ] ]