diff --git a/config/areas/site/requests.php b/config/areas/site/requests.php
index 352334a400..ad1e7e992b 100644
--- a/config/areas/site/requests.php
+++ b/config/areas/site/requests.php
@@ -22,25 +22,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 +70,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..6d9cd0d5d6 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() {
+ 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);
+}