From b5ba850122297e251fe6b1e58627556b2ea93074 Mon Sep 17 00:00:00 2001 From: Nico Hoffmann Date: Mon, 25 Mar 2024 15:10:05 +0100 Subject: [PATCH 1/2] Page tree: pagination --- config/areas/site/requests.php | 44 +++++++++++++------- panel/lab/components/trees/index.vue | 14 +++++-- panel/src/components/Navigation/PageTree.vue | 41 ++++++++++++++++-- panel/src/components/Navigation/Tree.vue | 19 +++++++++ 4 files changed, 96 insertions(+), 22 deletions(-) diff --git a/config/areas/site/requests.php b/config/areas/site/requests.php index 352334a400..3a86af5c0c 100644 --- a/config/areas/site/requests.php +++ b/config/areas/site/requests.php @@ -3,6 +3,7 @@ use Kirby\Cms\App; use Kirby\Cms\Find; use Kirby\Toolkit\I18n; +use Kirby\Toolkit\Str; return [ 'tree' => [ @@ -22,25 +23,35 @@ $value = $uuid ?? '/'; return [ - [ - 'children' => $panel->url(true), - 'disabled' => $move?->isMovableTo($site) === false, - 'hasChildren' => true, - 'icon' => 'home', - 'id' => '/', - 'label' => I18n::translate('view.site'), - 'open' => false, - 'url' => $url, - 'uuid' => $uuid, - 'value' => $value + 'items' => [ + [ + 'children' => $panel->url(true), + 'disabled' => $move?->isMovableTo($site) === false, + 'hasChildren' => true, + 'icon' => 'home', + 'id' => '/', + 'label' => I18n::translate('view.site'), + 'open' => false, + 'url' => $url, + 'uuid' => $uuid, + 'value' => $value + ] ] ]; } - $parent = Find::parent($parent); - $pages = []; + $pages = []; + $parent = Find::parent($parent); + $page = $request->get('page', 1); + $limit = $request->get('limit', 50); + $children = $parent->childrenAndDrafts(); + $children = $children->filterBy('isListable', true); + $children = $children->paginate([ + 'limit' => $limit, + 'page' => $page + ]); - foreach ($parent->childrenAndDrafts()->filterBy('isListable', true) as $child) { + foreach ($children as $child) { $panel = $child->panel(); $uuid = $child->uuid()?->toString(); $url = $child->url(); @@ -60,7 +71,10 @@ ]; } - return $pages; + return [ + 'items' => $pages, + 'pagination' => $children->pagination()->toArray() + ]; } ] ]; diff --git a/panel/lab/components/trees/index.vue b/panel/lab/components/trees/index.vue index 0a97737ee7..cab57c8a7e 100644 --- a/panel/lab/components/trees/index.vue +++ b/panel/lab/components/trees/index.vue @@ -1,8 +1,16 @@ @@ -10,8 +18,8 @@ export default { data() { return { - selected: null, + selected: null }; - }, + } }; diff --git a/panel/src/components/Navigation/PageTree.vue b/panel/src/components/Navigation/PageTree.vue index 749d5122c1..64470f2994 100644 --- a/panel/src/components/Navigation/PageTree.vue +++ b/panel/src/components/Navigation/PageTree.vue @@ -17,6 +17,12 @@ export default { current: { type: String }, + /** + * Items per folder to load at once + */ + limit: { + type: Number + }, move: { type: String } @@ -31,7 +37,7 @@ export default { this.state = this.items; } else { // load top-level items (e.g. only site) - const items = await this.load(null); + const { items } = await this.load(null); await this.open(items[0]); // if root is disabled, show the first level of children @@ -39,11 +45,22 @@ export default { } }, methods: { - async load(path) { + hasPaginate(item) { + if (!item.pagination) { + return false; + } + + return ( + item.pagination.page * item.pagination.limit < item.pagination.total + ); + }, + async load(path, page) { return await this.$panel.get("site/tree", { query: { move: this.move ?? null, - parent: path + parent: path, + page: page ?? 1, + limit: this.limit ?? null } }); }, @@ -56,10 +73,26 @@ export default { // children have not been loaded yet if (typeof item.children === "string") { - item.children = await this.load(item.children); + const { items, pagination } = await this.load(item.children); + item.endpoint = item.children; + item.children = items; + item.pagination = pagination; } this.$set(item, "open", true); + this.$set(item, "loading", false); + }, + async paginate(item) { + this.$set(item, "loading", true); + + // children have not been loaded yet + const { items, pagination } = await this.load( + item.endpoint, + item.pagination.page + 1 + ); + this.$set(item, "children", [...item.children, ...items]); + this.$set(item, "pagination", pagination); + this.$set(item, "loading", false); } } diff --git a/panel/src/components/Navigation/Tree.vue b/panel/src/components/Navigation/Tree.vue index 5310f63e18..ff5e5aaeb2 100644 --- a/panel/src/components/Navigation/Tree.vue +++ b/panel/src/components/Navigation/Tree.vue @@ -40,6 +40,13 @@ @select="$emit('select', $event)" @toggle="$emit('toggle', $event)" /> + + +
  • + +
  • @@ -75,6 +82,11 @@ export default { state: this.items }; }, + watch: { + items() { + this.state = this.items; + } + }, methods: { arrow(item) { if (item.loading === true) { @@ -87,6 +99,9 @@ export default { this.$set(item, "open", false); this.$emit("close", item); }, + hasPaginate(item) { + return false; + }, open(item) { this.$set(item, "open", true); this.$emit("open", item); @@ -193,4 +208,8 @@ li[aria-current] > .k-tree-branch { .k-tree-folder[disabled] { opacity: var(--opacity-disabled); } + +.k-tree-paginate { + color: var(--color-gray-500); +} From ef2879cdefcaddd05f426957f33722634d805b70 Mon Sep 17 00:00:00 2001 From: Nico Hoffmann Date: Mon, 25 Mar 2024 15:13:10 +0100 Subject: [PATCH 2/2] Fix cs --- config/areas/site/requests.php | 1 - panel/src/components/Navigation/Tree.vue | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/config/areas/site/requests.php b/config/areas/site/requests.php index 3a86af5c0c..ad1e7e992b 100644 --- a/config/areas/site/requests.php +++ b/config/areas/site/requests.php @@ -3,7 +3,6 @@ use Kirby\Cms\App; use Kirby\Cms\Find; use Kirby\Toolkit\I18n; -use Kirby\Toolkit\Str; return [ 'tree' => [ diff --git a/panel/src/components/Navigation/Tree.vue b/panel/src/components/Navigation/Tree.vue index ff5e5aaeb2..6d9cd0d5d6 100644 --- a/panel/src/components/Navigation/Tree.vue +++ b/panel/src/components/Navigation/Tree.vue @@ -99,7 +99,7 @@ export default { this.$set(item, "open", false); this.$emit("close", item); }, - hasPaginate(item) { + hasPaginate() { return false; }, open(item) {