Skip to content

Commit

Permalink
feat: added categories to menu component
Browse files Browse the repository at this point in the history
  • Loading branch information
lucsoft committed Apr 16, 2023
1 parent 6076a26 commit 3811d4f
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 43 deletions.
10 changes: 2 additions & 8 deletions pages/admin/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { loadPayouts, loadReviews, loadUsers } from "./helper.ts";
import { UserPanel } from "./users.ts";
import { PayoutPanel } from "./payouts.ts";
import { OverviewPanel } from "./overview.ts";
import { getListCount } from "../shared/listCount.ts";
Redirect();
await RegisterAuthRefresh();

Expand Down Expand Up @@ -75,11 +76,4 @@ renewAccessTokenIfNeeded().then(() => {
loadReviews(view);
loadUsers(view);
loadPayouts(view);
});


// deno-lint-ignore no-explicit-any
function getListCount(list?: any[]) {
if (typeof list?.length == "number") return `(${list.length})`;
return "";
}
});
4 changes: 1 addition & 3 deletions pages/hosting/create.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Box, Card, Custom, DropDownInput, Grid, Horizontal, InputForm, MaterialIcons, Page, PlainText, Reactive, Spacer, State, TextInput, Vertical, View, WebGen, Wizard, createElement, css } from "webgen/mod.ts";
import { Box, Color, ButtonStyle, Custom, DropDownInput, Grid, Horizontal, InputForm, MaterialIcons, Page, PlainText, Reactive, Spacer, State, TextInput, Vertical, View, WebGen, Wizard, createElement } from "webgen/mod.ts";
import { Redirect, RegisterAuthRefresh } from "../manager/helper.ts";
import { DynaNavigation } from "../../components/nav.ts";
import '../../assets/css/main.css';
import '../../assets/css/hosting.css';
import { delay } from "https://deno.land/std@0.182.0/async/delay.ts";
import { Menu } from "../shared/Menu.ts";
import { Color } from "https://raw.githubusercontent.com/lucsoft/WebGen/3f922fc/src/lib/Color.ts";
import { ButtonStyle } from "https://raw.githubusercontent.com/lucsoft/WebGen/3f922fc/src/types.ts";
import { data } from "./data.ts";
import { format } from "https://deno.land/std@0.182.0/fmt/bytes.ts";

Expand Down
112 changes: 80 additions & 32 deletions pages/shared/Menu.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
/**
* Menu will be put into WebGen.
*
* Blocker:
* ActionBar should be put in WebGen first (requires rewrite)
* Entry should be put in WebGen first (requires rewrite)
* Add URL Router
*/

import { Component, Reactive, State, Vertical } from "webgen/mod.ts";
import { Box, ButtonComponent, Component, PlainText, Reactive, State, Vertical } from "webgen/mod.ts";
import { ActionBar, Link } from "../manager/misc/actionbar.ts";
import { Entry } from "../manager/misc/Entry.ts";

Expand All @@ -16,14 +7,36 @@ interface MenuItem {
id: `${string}/`;
subtitle?: string;

items?: MenuItem[] | { [ group in string ]: MenuItem[] };
items?: MenuItem[];
action?: (clickPath: string, item: MenuItem) => Promise<void> | void;
custom?: (clickPath: string) => Component;
/**
* @default true
*/
visible?: () => boolean;
button?: ButtonComponent;
}

interface RootMenuItem extends MenuItem {
categories?: { [ group in `${string}/` ]: Omit<MenuItem, "id"> };
}

const FilterLastItem = (_: MenuItem, index: number, list: MenuItem[]): boolean => index != list.length - 1;

export const Menu = (rootMenu: MenuItem) => new class extends Component {
/**
* # Declarative Tree Navigation
*
* Menu will be put into WebGen.
*
* Blocker till release:
*
* - ActionBar should be put in WebGen first (requires rewrite)
*
* - Entry should be put in WebGen first (requires rewrite)
*
* - Add URL Router
*/
export const Menu = (rootMenu: RootMenuItem) => new class extends Component {
nav = State({
active: <string>rootMenu.id
});
Expand All @@ -32,17 +45,30 @@ export const Menu = (rootMenu: MenuItem) => new class extends Component {
this.wrapper.append(Reactive(this.nav, "active", () => this.walkMenu()).draw());
}

setActivePath(clickPath: string) {
this.nav.active = clickPath;
return this;
}

getActivePath() {
const list = [ rootMenu ];
const list: (MenuItem | RootMenuItem)[] = [ rootMenu ];
for (const iterator of this.nav.active.match(/(\w+\/)/g) ?? []) {
const last = list.at(-1)!;
if (Array.isArray(last.items))
list.push(last.items.find(x => x.id == iterator)!);
if (isCategoryMenu(last) && last.id != iterator) {
// deno-lint-ignore no-explicit-any
const item = last.categories?.[ iterator as any ];
if (!item) continue;
list.push({ ...item, id: "+" + iterator } as MenuItem);
}
if (Array.isArray(last.items)) {
const item = last.items.find(x => x.id == iterator);
if (item) list.push(item);
}
}
return list;
}

isRootNav() {
private isRootNav() {
return this.nav.active == rootMenu.id;
}

Expand All @@ -56,28 +82,46 @@ export const Menu = (rootMenu: MenuItem) => new class extends Component {
this.nav.active = activeEntries.filter((_, index) => index <= i).map(x => x.id).join("");
}
}));
if (Array.isArray(active.items) || !active.items)

const parentIsCategoryMenu = activeEntries.at(-2) && isCategoryMenu(activeEntries.at(-2)!);

if (isCategoryMenu(active) || parentIsCategoryMenu)
return Vertical(
ActionBar(active.title, undefined, undefined, list),
Vertical(
active.items?.map(menu => Entry(
menu.title,
menu.subtitle,
this.menuClickHandler(menu)
)) ?? []
).setGap("var(--gap)"),
Box(this.renderCategoryBar(parentIsCategoryMenu ? rootMenu : active)).setMargin("0 0 1.5rem"),
this.renderList(active.items),
active.custom?.(activeEntries.map(x => x.id).join("") + active.id) ?? null
);
// TODO: Implement Categories

return Vertical(
ActionBar(active.title, Object.keys(active.items).map(group => ({
title: group,
selected: false,
onclick: () => { },
})))
ActionBar(active.title, undefined, undefined, list),
this.renderList(active.items),
active.custom?.(activeEntries.map(x => x.id).join("") + active.id) ?? null
);
}

private renderCategoryBar(rootMenu: RootMenuItem) {
return ActionBar(rootMenu.title, Object.entries(rootMenu.categories!).map(([ key, value ]) => {
return {
title: value.title,
selected: key == this.getActivePath().at(-1)!.id.replace("+", ""),
onclick: () => this.nav.active = rootMenu.id + key
};
}));
}

private renderList(active?: MenuItem[]): Component | null {
if (!active) return null;

return Vertical(
active?.map(menu => Entry(
menu.title,
menu.subtitle,
this.menuClickHandler(menu)
)) ?? []
)
.setGap("var(--gap)");
}

private menuClickHandler(menu: MenuItem) {
if (menu.items) return () => {
this.nav.active = this.nav.active + menu.id;
Expand All @@ -91,4 +135,8 @@ export const Menu = (rootMenu: MenuItem) => new class extends Component {
};
return undefined;
}
};
};

function isCategoryMenu(type: RootMenuItem | MenuItem): type is RootMenuItem {
return !!(<RootMenuItem>type).categories;
}
5 changes: 5 additions & 0 deletions pages/shared/listCount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// deno-lint-ignore no-explicit-any
export function getListCount(list?: any[]) {
if (typeof list?.length == "number") return `(${list.length})`;
return "";
}

0 comments on commit 3811d4f

Please sign in to comment.