From 9e02bee33e5bb47c503a69316c145429192fa85e Mon Sep 17 00:00:00 2001 From: Tobias Klika Date: Mon, 6 Apr 2020 18:45:23 +0200 Subject: [PATCH] nested tree with async loading --- zero.Core/Api/PageTreeApi.cs | 7 +- zero.Web/App/Components/tree.vue | 211 +++++++++++++++++- zero.Web/App/Pages/page.vue | 19 +- zero.Web/Controllers/PageTreeController.cs | 5 +- .../Resources/Localization/zero.en-us.json | 5 + zero.Web/Resources/tree.debug.json | 4 +- zero.Web/Sass/Canvas/_navigation.scss | 2 +- zero.Web/Sass/Core/_settings.scss | 5 +- zero.Web/Sass/Modules/Buttons/_button.scss | 1 + 9 files changed, 242 insertions(+), 17 deletions(-) diff --git a/zero.Core/Api/PageTreeApi.cs b/zero.Core/Api/PageTreeApi.cs index 4c8b4344..f286d829 100644 --- a/zero.Core/Api/PageTreeApi.cs +++ b/zero.Core/Api/PageTreeApi.cs @@ -3,6 +3,7 @@ using Raven.Client.Documents; using System; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; using zero.Core.Entities; namespace zero.Core.Api @@ -19,8 +20,10 @@ namespace zero.Core.Api /// - public IList GetChildren(string contentPath, string parent = null) // TODO remove content path as it's only needed to load test data + public async Task> GetChildren(string contentPath, string parent = null) // TODO remove content path as it's only needed to load test data { + await Task.Delay(parent != null ? 1200 : 0); + string path = System.IO.Path.Combine(contentPath, "Resources/tree" + (parent != null ? "-" + parent.ToString() : String.Empty) + ".debug.json"); string text = System.IO.File.ReadAllText(path, Encoding.UTF8); @@ -34,6 +37,6 @@ namespace zero.Core.Api /// /// Get all children for the current parent page (or root if empty) /// - IList GetChildren(string contentPath, string parent = null); + Task> GetChildren(string contentPath, string parent = null); } } diff --git a/zero.Web/App/Components/tree.vue b/zero.Web/App/Components/tree.vue index 1a6d8585..9198057c 100644 --- a/zero.Web/App/Components/tree.vue +++ b/zero.Web/App/Components/tree.vue @@ -1,6 +1,19 @@  @@ -10,15 +23,32 @@ name: 'uiTree', props: { + depth: { + type: Number, + default: 0 + }, + parent: { + type: String, + default: null + }, get: { type: Function, required: true + }, + onChange: { + type: Function, + default: () => { } } }, + data: () => ({ + items: [], + status: 'none' + }), + created () { - this.load(); + this.load(this.parent); }, methods: { @@ -26,20 +56,187 @@ // loads children of the given parent id or on root if empty load(parent) { - let promise = this.get(parent); + this.setStatus('loading', this.items); - //if (typeof promise !== 'object' || !promise['then'] || typeof promise.then !== 'function') + let promise = this.get(parent); promise.then(response => { - console.info(response); + this.items = response; + this.setStatus('loaded', this.items); }) .catch(error => { + this.setStatus('error', this.items, error); // TODO handle errors }); + }, + + + // updates the status for the current tree + setStatus(status) + { + this.status = status; + this.onChange(status, this.items); + }, + + + // sets the current status for child tree + setChildTreeStatus(status, items, x) + { + console.info(status, items, x, this); + }, + + + // toggles children of an item + toggle(item) + { + item.isOpen = !item.isOpen; + + //if (item.isOpen && !item.items) + //{ + // item.children = this.load(item.id, items => + // { + // item.items = items; + // }); + //} + }, + + + // get all classes for a tree item + getClasses(item) + { + return { + 'has-children': item.hasChildren, + 'is-open': item.isOpen + }; } } } - \ No newline at end of file + + + + \ No newline at end of file diff --git a/zero.Web/App/Pages/page.vue b/zero.Web/App/Pages/page.vue index 44cd3db4..a819a95a 100644 --- a/zero.Web/App/Pages/page.vue +++ b/zero.Web/App/Pages/page.vue @@ -14,11 +14,26 @@ export default { name: 'app-page', + data: () => ({ + cache: {} + }), + methods: { getItems(parent) { - return PageTreeApi.getChildren(parent); + const key = !parent ? '__root' : parent; + + if (this.cache[key]) + { + return Promise.resolve(this.cache[key]); + } + + return PageTreeApi.getChildren(parent).then(response => + { + this.cache[key] = response; + return response; + }); } } @@ -39,6 +54,6 @@ { width: 340px; background: var(--color-bg-light); - padding: var(--padding); + padding: var(--padding) 0; } \ No newline at end of file diff --git a/zero.Web/Controllers/PageTreeController.cs b/zero.Web/Controllers/PageTreeController.cs index 1f0a49fa..5784c0ae 100644 --- a/zero.Web/Controllers/PageTreeController.cs +++ b/zero.Web/Controllers/PageTreeController.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; using zero.Core; using zero.Core.Api; @@ -20,9 +21,9 @@ namespace zero.Web.Controllers } - public IActionResult GetChildren(string parent = null) + public async Task GetChildren(string parent = null) { - return Json(Api.GetChildren(Env.ContentRootPath, parent)); + return Json(await Api.GetChildren(Env.ContentRootPath, parent)); } } } diff --git a/zero.Web/Resources/Localization/zero.en-us.json b/zero.Web/Resources/Localization/zero.en-us.json index a873ef3c..a83a9779 100644 --- a/zero.Web/Resources/Localization/zero.en-us.json +++ b/zero.Web/Resources/Localization/zero.en-us.json @@ -11,5 +11,10 @@ "pages": "Pages", "settings": "Settings" } + }, + + "recyclebin": { + "name": "Recycle bin", + "description": "View recently deleted entities" } } \ No newline at end of file diff --git a/zero.Web/Resources/tree.debug.json b/zero.Web/Resources/tree.debug.json index b3676e1b..0b14e6dd 100644 --- a/zero.Web/Resources/tree.debug.json +++ b/zero.Web/Resources/tree.debug.json @@ -12,8 +12,8 @@ "id": "-99", "parentId": null, "sort": 1000, - "name": "@generic.recyclebin.name", - "description": "@generic.recyclebin.description", + "name": "@recyclebin.name", + "description": "@recyclebin.description", "icon": "fth-trash", "hasChildren": false } diff --git a/zero.Web/Sass/Canvas/_navigation.scss b/zero.Web/Sass/Canvas/_navigation.scss index 071c6b9c..75567ecd 100644 --- a/zero.Web/Sass/Canvas/_navigation.scss +++ b/zero.Web/Sass/Canvas/_navigation.scss @@ -60,7 +60,6 @@ a.app-nav-item &:hover, &.is-active { - background: rgba(black, 0.1); color: var(--color-fg-reverse); .app-nav-item-icon @@ -71,6 +70,7 @@ a.app-nav-item &.is-active { + background: rgba(black, 0.1); font-weight: 700; } diff --git a/zero.Web/Sass/Core/_settings.scss b/zero.Web/Sass/Core/_settings.scss index cf3c05d0..d5c9e81e 100644 --- a/zero.Web/Sass/Core/_settings.scss +++ b/zero.Web/Sass/Core/_settings.scss @@ -20,7 +20,7 @@ --color-bg-light: #242526; // line colors - --color-line: #eaebec; + --color-line: #2f3233; --color-line-mid: #d7d8d9; @@ -28,6 +28,9 @@ --padding: 32px; --height-top: 74px; + + --font-size: 14px; + --font-size-s: 12px; } diff --git a/zero.Web/Sass/Modules/Buttons/_button.scss b/zero.Web/Sass/Modules/Buttons/_button.scss index ca98099b..56a9f0ce 100644 --- a/zero.Web/Sass/Modules/Buttons/_button.scss +++ b/zero.Web/Sass/Modules/Buttons/_button.scss @@ -3,6 +3,7 @@ button { @extend %font; + color: var(--color-fg); &:focus {