menu and NavBar

pull/37/head
Niko PLP 4 months ago
parent 3f635248be
commit ff379ccf65
  1. 148
      ng-app/src/lib/FullLayout.svelte
  2. 17
      ng-app/src/lib/Home.svelte
  3. 16
      ng-app/src/lib/Login.svelte
  4. 2
      ng-app/src/lib/MobileBottomBar.svelte
  5. 2
      ng-app/src/lib/components/MenuItem.svelte
  6. 77
      ng-app/src/lib/components/NavBar.svelte
  7. 54
      ng-app/src/lib/components/NavIcon.svelte
  8. 3
      ng-app/src/locales/de.json
  9. 7
      ng-app/src/locales/en.json
  10. 24
      ng-app/src/routes/NURI.svelte
  11. 2
      ng-app/src/styles.css
  12. 40
      ng-app/src/tab.ts

@ -21,6 +21,7 @@
import { link, location } from "svelte-spa-router"; import { link, location } from "svelte-spa-router";
import MobileBottomBarItem from "./MobileBottomBarItem.svelte"; import MobileBottomBarItem from "./MobileBottomBarItem.svelte";
import MobileBottomBar from "./MobileBottomBar.svelte"; import MobileBottomBar from "./MobileBottomBar.svelte";
import NavIcon from "./components/NavIcon.svelte";
// @ts-ignore // @ts-ignore
import Logo from "./components/Logo.svelte"; import Logo from "./components/Logo.svelte";
import MenuItem from "./components/MenuItem.svelte"; import MenuItem from "./components/MenuItem.svelte";
@ -29,7 +30,7 @@
import { onMount, tick } from "svelte"; import { onMount, tick } from "svelte";
import { cur_branch_has_discrete, cur_tab, cur_viewer, cur_editor, toggle_graph_discrete, open_doc, import { cur_branch_has_discrete, cur_tab, cur_viewer, cur_editor, toggle_graph_discrete, open_doc,
available_editors, available_viewers, set_editor, set_viewer, set_view_or_edit, toggle_live_edit, available_editors, available_viewers, set_editor, set_viewer, set_view_or_edit, toggle_live_edit,
has_editor_chat } from "../tab"; has_editor_chat, all_files_count, all_comments_count, nav_bar, save, hideMenu } from "../tab";
import ZeraIcon from "./ZeraIcon.svelte"; import ZeraIcon from "./ZeraIcon.svelte";
import { import {
Home, Home,
@ -74,12 +75,15 @@
Beaker, Beaker,
WrenchScrewdriver, WrenchScrewdriver,
Sparkles, Sparkles,
PaperClip,
} from "svelte-heros-v2"; } from "svelte-heros-v2";
import NavBar from "./components/NavBar.svelte";
export let withoutNavBar = false;
let width: number; let width: number;
let breakPoint: number = 662; let breakPoint: number = 662;
let mobile = false; let mobile = false;
let show_menu = true;
let open_view_as = false; let open_view_as = false;
let open_edit_with = false; let open_edit_with = false;
let open_share = false; let open_share = false;
@ -92,14 +96,19 @@
} }
let top; let top;
let topMenu; let shareMenu;
let toolsMenu;
async function scrollToTop() { async function scrollToTop() {
await tick(); await tick();
top.scrollIntoView(); top.scrollIntoView();
} }
async function scrollToTopMenu() { async function scrollToMenuShare() {
await tick();
shareMenu.scrollIntoView();
}
async function scrollToMenuTools() {
await tick(); await tick();
topMenu.scrollIntoView(); toolsMenu.scrollIntoView();
} }
onMount(async () => {await open_doc(""); await scrollToTop()}); onMount(async () => {await open_doc(""); await scrollToTop()});
@ -107,37 +116,37 @@
const launchAppStore = (class_name:string) => { const launchAppStore = (class_name:string) => {
//TODO //TODO
show_menu = false; hideMenu();
}; };
const openAction = (action:string) => { const openAction = (action:string) => {
// TODO // TODO
show_menu = false; hideMenu();
} }
const openPane = (pane:string) => { const openPane = (pane:string) => {
// TODO // TODO
show_menu = false; hideMenu();
} }
const openShare = (share:string) => { const openShare = (share:string) => {
// TODO // TODO
show_menu = false; hideMenu();
} }
const find = (share:string) => { const find = (share:string) => {
// TODO // TODO
show_menu = false; hideMenu();
} }
const bookmark = (share:string) => { const bookmark = (share:string) => {
// TODO // TODO
show_menu = false; hideMenu();
} }
const annotate = (share:string) => { const annotate = (share:string) => {
// TODO // TODO
show_menu = false; hideMenu();
} }
const share_items = [ const share_items = [
@ -174,14 +183,14 @@
<Modal id="menu-modal" <Modal id="menu-modal"
outsideclose outsideclose
bind:open={show_menu} bind:open={$cur_tab.show_menu}
size = 'xs' size = 'xs'
placement = 'top-right' placement = 'top-right'
backdropClass="bg-gray-900 bg-opacity-50 dark:bg-opacity-80 menu-bg-modal" backdropClass="bg-gray-900 bg-opacity-50 dark:bg-opacity-80 menu-bg-modal"
> >
<aside style="width:295px;" class="bg-white" aria-label="Sidebar"> <aside style="width:295px;" class="bg-white" aria-label="Sidebar">
<div class="bg-gray-60 overflow-y-auto dark:bg-gray-800" bind:this={topMenu}> <div class="bg-gray-60 overflow-y-auto dark:bg-gray-800">
<ul class="space-y-1 space-x-0 mb-10"> <ul class="space-y-1 space-x-0 mb-10">
{#if $cur_branch_has_discrete} {#if $cur_branch_has_discrete}
<li> <li>
@ -196,7 +205,7 @@
</li> </li>
{/if} {/if}
{#if $cur_viewer} {#if $cur_viewer}
<MenuItem selected={$cur_tab.view_or_edit} title={$cur_viewer["ng:a"]} clickable={($available_viewers.length > 1 || !$cur_tab.view_or_edit) && function () { if ($available_viewers.length > 1) { open_view_as = !open_view_as; } else { set_view_or_edit(true); show_menu = false; } open_edit_with=false;} }> <MenuItem selected={$cur_tab.view_or_edit} title={$cur_viewer["ng:a"]} clickable={($available_viewers.length > 1 || !$cur_tab.view_or_edit) && function () { if ($available_viewers.length > 1) { open_view_as = !open_view_as; } else { set_view_or_edit(true); hideMenu(); } open_edit_with=false;} }>
<Eye <Eye
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white " class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white "
@ -205,7 +214,7 @@
</MenuItem> </MenuItem>
{#if open_view_as && $available_viewers.length > 1 } {#if open_view_as && $available_viewers.length > 1 }
{#each $available_viewers as viewer} {#each $available_viewers as viewer}
<MenuItem title={viewer["ng:a"]} extraClass="submenu" clickable={(viewer["ng:g"] !== $cur_viewer["ng:g"] || !$cur_tab.view_or_edit) && function () { set_view_or_edit(true); set_viewer(viewer["ng:g"]); show_menu = false; open_view_as = false} }> <MenuItem title={viewer["ng:a"]} extraClass="submenu" clickable={(viewer["ng:g"] !== $cur_viewer["ng:g"] || !$cur_tab.view_or_edit) && function () { set_view_or_edit(true); set_viewer(viewer["ng:g"]); hideMenu(); open_view_as = false} }>
<ZeraIcon <ZeraIcon
zera={viewer["ng:u"]} zera={viewer["ng:u"]}
config={{ config={{
@ -220,7 +229,7 @@
{/if} {/if}
{#if $cur_tab.doc.can_edit} {#if $cur_tab.doc.can_edit}
{#if $cur_editor} {#if $cur_editor}
<MenuItem title={$cur_editor["ng:a"]} selected={!$cur_tab.view_or_edit} clickable={ ($available_editors.length > 1 || $cur_tab.view_or_edit) && function () { if ($available_editors.length > 1) { open_edit_with = !open_edit_with; } else { set_view_or_edit(false); show_menu = false; } open_view_as=false;} }> <MenuItem title={$cur_editor["ng:a"]} selected={!$cur_tab.view_or_edit} clickable={ ($available_editors.length > 1 || $cur_tab.view_or_edit) && function () { if ($available_editors.length > 1) { open_edit_with = !open_edit_with; } else { set_view_or_edit(false); hideMenu(); } open_view_as=false;} }>
<PencilSquare <PencilSquare
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white " class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white "
@ -229,7 +238,7 @@
</MenuItem> </MenuItem>
{#if open_edit_with && $available_editors.length > 1 } {#if open_edit_with && $available_editors.length > 1 }
{#each $available_editors as editor} {#each $available_editors as editor}
<MenuItem title={editor["ng:a"]} extraClass="submenu" clickable={(editor["ng:g"] !== $cur_editor["ng:g"] || $cur_tab.view_or_edit) && function () { set_view_or_edit(false); set_editor(editor["ng:g"]); show_menu = false; open_edit_with = false} }> <MenuItem title={editor["ng:a"]} extraClass="submenu" clickable={(editor["ng:g"] !== $cur_editor["ng:g"] || $cur_tab.view_or_edit) && function () { set_view_or_edit(false); set_editor(editor["ng:g"]); hideMenu(); open_edit_with = false} }>
<ZeraIcon <ZeraIcon
zera={editor["ng:u"]} zera={editor["ng:u"]}
config={{ config={{
@ -262,6 +271,7 @@
</MenuItem> </MenuItem>
{/if} {/if}
{/if} {/if}
{#if $cur_tab.doc.can_edit} {#if $cur_tab.doc.can_edit}
<MenuItem title={$t("doc.menu.items.new_block.desc")} clickable={ ()=> openAction("new_block") }> <MenuItem title={$t("doc.menu.items.new_block.desc")} clickable={ ()=> openAction("new_block") }>
<PlusCircle <PlusCircle
@ -280,6 +290,15 @@
<span class="ml-3">{$t("doc.menu.items.editor_chat.label")}</span> <span class="ml-3">{$t("doc.menu.items.editor_chat.label")}</span>
</MenuItem> </MenuItem>
{/if} {/if}
<MenuItem title={$t("doc.menu.items.mc.desc")} clickable={ ()=> openPane("mc") }>
<Sparkles
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.mc.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.folders.desc")} clickable={ ()=> openPane("folders") }> <MenuItem title={$t("doc.menu.items.folders.desc")} clickable={ ()=> openPane("folders") }>
<FolderOpen <FolderOpen
tabindex="-1" tabindex="-1"
@ -294,15 +313,15 @@
/> />
<span class="ml-3">{$t("doc.menu.items.toc.label")}</span> <span class="ml-3">{$t("doc.menu.items.toc.label")}</span>
</MenuItem> </MenuItem>
<MenuItem title={$t("doc.menu.items.mc.desc")} clickable={ ()=> openPane("mc") }> <MenuItem title={$t("doc.menu.items.files.desc")} clickable={ ()=> openPane("files") }>
<Sparkles <PaperClip
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/> />
<span class="ml-3">{$t("doc.menu.items.mc.label")}</span> <span class="ml-3">{$t("doc.menu.items.files.label")} {$all_files_count}</span>
</MenuItem> </MenuItem>
<div style="padding:0;" bind:this={shareMenu}></div>
<MenuItem title={$t("doc.menu.items.share.desc")} clickable={ () => open_share = !open_share }> <MenuItem title={$t("doc.menu.items.share.desc")} clickable={ () => { open_share = !open_share; scrollToMenuShare(); } }>
<Share <Share
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
@ -323,7 +342,7 @@
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/> />
<span class="ml-3">{$t("doc.menu.items.comments.label")}</span> <span class="ml-3">{$t("doc.menu.items.comments.label")} {$all_comments_count}</span>
</MenuItem> </MenuItem>
<MenuItem title={$t("doc.menu.items.branches.desc")} clickable={ ()=> openPane("branches") }> <MenuItem title={$t("doc.menu.items.branches.desc")} clickable={ ()=> openPane("branches") }>
@ -405,8 +424,8 @@
/> />
<span class="ml-3">{$t("doc.menu.items.settings.label")}</span> <span class="ml-3">{$t("doc.menu.items.settings.label")}</span>
</MenuItem> </MenuItem>
<div style="padding:0;" bind:this={toolsMenu}></div>
<MenuItem title={$t("doc.menu.items.tools.desc")} clickable={ () => open_tools = !open_tools }> <MenuItem title={$t("doc.menu.items.tools.desc")} clickable={ () => {open_tools = !open_tools; scrollToMenuTools();} } >
<WrenchScrewdriver <WrenchScrewdriver
tabindex="-1" tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
@ -428,25 +447,32 @@
{#if mobile} {#if mobile}
<div class="full-layout"> <div class="full-layout">
<main class="pb-14" bind:this={top}> {#if !withoutNavBar}
<div class="fixed top-0 left-0 right-0">
<NavBar {scrollToTop}/>
</div>
{/if}
<div bind:this={top}></div>
<main class:mt-12={!withoutNavBar} class="pb-14 bg-white dark:bg-black">
<slot /> <slot />
</main> </main>
<MobileBottomBar {activeUrl}> <MobileBottomBar {activeUrl}>
<MobileBottomBarItem href="#/" icon={Home} on:click={scrollToTop}> <MobileBottomBarItem href="#/" icon={Home} on:click={scrollToTop} >
<span <span
class="inline-flex justify-center items-center p-3 mt-1 -ml-2 w-3 h-3 text-sm font-medium text-primary-600 bg-primary-200 rounded-full dark:bg-primary-900 dark:text-primary-200" class="inline-flex justify-center items-center p-3 mt-1 -ml-2 w-3 h-3 text-sm font-medium text-primary-600 bg-primary-200 rounded-full dark:bg-primary-900 dark:text-primary-200"
> >
13 13
</span> </span>
</MobileBottomBarItem> </MobileBottomBarItem>
<MobileBottomBarItem href="#/stream" icon={Bolt} on:click={scrollToTop} /> <MobileBottomBarItem href="#/stream" icon={Bolt} on:click={scrollToTop} />
<MobileBottomBarItem <MobileBottomBarItem
href="#/search" href="#/search"
icon={MagnifyingGlass} icon={MagnifyingGlass}
on:click={scrollToTop} on:click={scrollToTop}
/> />
<MobileBottomBarItem href="#/create" icon={PlusCircle} /> <MobileBottomBarItem href="#/create" icon={PlusCircle} />
<MobileBottomBarItem href="#/site" icon={User} on:click={scrollToTop} /> <MobileBottomBarItem href="#/site" icon={User} on:click={scrollToTop} />
</MobileBottomBar> </MobileBottomBar>
</div> </div>
{:else} {:else}
@ -464,7 +490,7 @@
<SidebarItem <SidebarItem
label={$t("pages.full_layout.home")} label={$t("pages.full_layout.home")}
href="#/" href="#/"
on:click={scrollToTop} on:click={scrollToTop} on:keypress={scrollToTop}
class="py-1 tall-xs:p-2" class="py-1 tall-xs:p-2"
> >
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
@ -538,6 +564,7 @@
label={$t("pages.full_layout.messages")} label={$t("pages.full_layout.messages")}
href="#/messages" href="#/messages"
class="py-1 tall-xs:p-2" class="py-1 tall-xs:p-2"
on:click={scrollToTop} on:keypress={scrollToTop}
> >
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<PaperAirplane <PaperAirplane
@ -555,6 +582,7 @@
label={$t("pages.full_layout.notifications")} label={$t("pages.full_layout.notifications")}
href="#/notifications" href="#/notifications"
class="mt-1 py-1 tall-xs:p-2" class="mt-1 py-1 tall-xs:p-2"
on:click={scrollToTop} on:keypress={scrollToTop}
> >
<svelte:fragment slot="icon"> <svelte:fragment slot="icon">
<Bell <Bell
@ -572,7 +600,61 @@
</SidebarWrapper> </SidebarWrapper>
</Sidebar> </Sidebar>
<main class="ml-48" bind:this={top}> <!-- $: nav_bar = {
icon: false,
title: "",
back: true,
newest: 0,
save: undefined,
};-->
<!-- <div style="background-color: #f6f6f6;" class="fixed top-0 left-48 right-0 h-10 flex text-center text-gray-900 dark:text-white">
{#if $nav_bar.back}
<div role="button" tabindex="0" on:click={back} on:keypress={back} class="flex-none w-10 flex justify-center items-center">
<ArrowLeft tabindex="-1" class="w-8 h-8 focus:outline-none"/>
</div>
{/if}
{#if $nav_bar.icon}
<div style="cursor:pointer;" class="flex-none w-8 m-1 " on:click={scrollToTop} on:keypress={scrollToTop}>
<NavIcon img={$nav_bar.icon} config={{
tabindex:"-1",
class:"w-8 h-8 focus:outline-none"
}}/>
</div>
{/if}
<div style="cursor:pointer;" class="grow w-10 items-center flex px-1"><span class="inline-block truncate" on:click={scrollToTop} on:keypress={scrollToTop}> {$nav_bar.title} </span></div>
{#if $nav_bar.newest}
<div role="button" tabindex="0" class="flex-none m-1 rounded-full bg-primary-700 text-white dark:bg-primary-700" on:click={scrollToTop}>
<div class="flex items-center grow pr-2">
<ChevronDoubleUp tabindex="-1" class="w-6 h-6 m-1 focus:outline-none"/>
<span class="inline-block">{@html $nav_bar.newest < 100 ? "+ "+$nav_bar.newest : "<span class=\"text-xl\">&infin;</span>"}</span>
</div>
</div>
{/if}
{#if $nav_bar.save !== undefined}
{#if $nav_bar.save }
<div class="flex-none w-10" role="button" on:click={save} on:keypress={save} title="Save">
<CheckCircle variation="solid" tabindex="-1" strokeWidth="3" class="w-10 h-10 text-primary-400 focus:outline-none"/>
</div>
{:else}
<div class="flex-none w-10" title="Saved!">
<CheckBadge tabindex="-1" class="w-8 h-8 m-1 text-green-500 focus:outline-none"/>
</div>
{/if}
{/if}
<div class="flex-none w-10 " role="button" title="Open Menu" on:click={()=>show_menu = true} on:keypress={()=>show_menu = true}>
<EllipsisVertical tabindex="-1" class="w-8 h-8 my-1 mr-2"/>
</div>
</div> -->
<div class="fixed top-0 left-48 right-0">
<NavBar {scrollToTop}/>
</div>
<div bind:this={top}></div>
<main class="ml-48 mt-12 bg-white dark:bg-black" >
<slot /> <slot />
</main> </main>
</div> </div>
@ -585,7 +667,7 @@
overflow: auto; overflow: auto;
} }
main { main {
overflow: hidden; overflow-x: clip;
overflow-wrap: break-word; overflow-wrap: break-word;
} }
.graph-discrete-toggle button { .graph-discrete-toggle button {

@ -19,7 +19,9 @@
Users, Users,
} from "svelte-heros-v2"; } from "svelte-heros-v2";
import Logo from "./components/Logo.svelte"; import Logo from "./components/Logo.svelte";
import NavBar from "./components/NavBar.svelte";
let top;
let width: number; let width: number;
let breakPoint: number = 662; let breakPoint: number = 662;
let mobile = false; let mobile = false;
@ -28,12 +30,16 @@
} else { } else {
mobile = true; mobile = true;
} }
function scrollToTop() {
top.scrollIntoView();
}
</script> </script>
<FullLayout> <FullLayout withoutNavBar={true}>
{#if mobile} {#if mobile}
<nav <nav bind:this={top}
class="border-t border-solid border-gray-200 bg-white dark:bg-gray-900 text-gray-700 dark:text-gray-200 dark:border-gray-700 divide-gray-100 dark:divide-gray-700 px-2 sm:px-4 py-2.5 w-full" style="background-color: #f6f6f6;" class="border-t border-solid border-gray-200 text-gray-700 dark:text-gray-200 dark:border-gray-700 divide-gray-100 dark:divide-gray-700 px-2 sm:px-4 py-2.5 w-full"
> >
<div <div
class="mx-auto flex flex-wrap justify-between items-center w-full xxs:px-8 xs:px-10" class="mx-auto flex flex-wrap justify-between items-center w-full xxs:px-8 xs:px-10"
@ -78,6 +84,11 @@
</div> </div>
</div> </div>
</nav> </nav>
<div class="sticky top-0 w-full">
<NavBar {scrollToTop}/>
</div>
{/if} {/if}
<Test /> <Test />

@ -343,8 +343,8 @@
<div <div
class="flex-col justify-center md:max-w-2xl py-4 sm:px-8" class="flex-col justify-center md:max-w-2xl py-4 sm:px-8"
class:h-screen={step !== "load" && height > 660} class:h-screen={step !== "load" && height > 640}
class:flex={height > 660} class:flex={height > 640}
bind:this={top} bind:this={top}
> >
{#if step == "load"} {#if step == "load"}
@ -460,8 +460,8 @@
{:else if step == "pazzle" || step == "order" || step == "pin" || step == "mnemonic"} {:else if step == "pazzle" || step == "order" || step == "pin" || step == "mnemonic"}
<div <div
class="flex-col justify-center h-screen" class="flex-col justify-center h-screen"
class:flex={height > 660} class:flex={height > 640}
class:min-w-[310px]={mobile} class:min-w-[300px]={mobile}
class:min-w-[500px]={!mobile} class:min-w-[500px]={!mobile}
class:max-w-[370px]={mobile} class:max-w-[370px]={mobile}
class:max-w-[600px]={!mobile} class:max-w-[600px]={!mobile}
@ -585,7 +585,7 @@
tabindex="0" tabindex="0"
class="pindigit m-1 disabled:opacity-15 disabled:text-gray-200 select-none align-bottom text-7xl p-0 w-full aspect-square border-0" class="pindigit m-1 disabled:opacity-15 disabled:text-gray-200 select-none align-bottom text-7xl p-0 w-full aspect-square border-0"
class:h-[160px]={!mobile} class:h-[160px]={!mobile}
class:h-[100px]={mobile} class:h-[93px]={mobile}
class:text-8xl={!mobile} class:text-8xl={!mobile}
on:click={async () => await on_pin_key(num)} on:click={async () => await on_pin_key(num)}
disabled={pin_code.length >= 4} disabled={pin_code.length >= 4}
@ -601,7 +601,7 @@
tabindex="0" tabindex="0"
class="pindigit disabled:opacity-15 m-1 disabled:text-gray-200 select-none align-bottom text-7xl p-0 w-full aspect-square border-0" class="pindigit disabled:opacity-15 m-1 disabled:text-gray-200 select-none align-bottom text-7xl p-0 w-full aspect-square border-0"
class:h-[160px]={!mobile} class:h-[160px]={!mobile}
class:h-[100px]={mobile} class:h-[93px]={mobile}
class:text-8xl={!mobile} class:text-8xl={!mobile}
on:click={async () => await on_pin_key(shuffle_pin[9])} on:click={async () => await on_pin_key(shuffle_pin[9])}
disabled={pin_code.length >= 4} disabled={pin_code.length >= 4}
@ -620,7 +620,7 @@
/> />
</Button> </Button>
</div> </div>
<span class="mt-3 text-9xl min-h-[8rem] text-center" <span class="select-none text-9xl h-[4rem] text-center"
>{#each pin_code as pin_key}*{/each}</span >{#each pin_code as pin_key}*{/each}</span
> >
{/if} {/if}
@ -727,7 +727,7 @@
<style> <style>
.pindigit { .pindigit {
min-height: 99px; min-height: 93px;
} }
/* .pazzleline { /* .pazzleline {

@ -24,7 +24,7 @@
</script> </script>
<nav <nav
class="border-t border-solid border-gray-200 bg-white dark:bg-gray-900 text-gray-700 dark:text-gray-200 dark:border-gray-700 divide-gray-100 dark:divide-gray-700 px-2 sm:px-4 py-2.5 w-full fixed bottom-0 left-0 z-20" style="background-color: #f6f6f6;" class="border-t border-solid border-gray-200 text-gray-700 dark:text-gray-200 dark:border-gray-700 divide-gray-100 dark:divide-gray-700 px-2 sm:px-4 py-2.5 w-full fixed bottom-0 left-0 z-20"
> >
<div <div
class="mx-auto flex flex-wrap justify-between items-center w-full px-2 xxs:px-8 xs:px-10" class="mx-auto flex flex-wrap justify-between items-center w-full px-2 xxs:px-8 xs:px-10"

@ -22,7 +22,7 @@
{#if clickable} {#if clickable}
<li {title} role="menuitem" tabindex="0" class:text-primary-600={selected} class:text-gray-800={!selected} class:dark:text-white={!selected} class:dark:text-primary-300={selected} <li {title} role="menuitem" tabindex="0" class:text-primary-600={selected} class:text-gray-800={!selected} class:dark:text-white={!selected} class:dark:text-primary-300={selected}
class="{extraClass} select-none clickable focus:outline-2 focus:outline flex items-center px-2 py-1 text-base font-normal rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 mt-1" class="{extraClass} select-none clickable focus:outline-2 focus:outline flex items-center px-2 py-1 text-base font-normal rounded-lg hover:bg-gray-200 dark:hover:bg-gray-700 mt-1"
on:click={clickable} on:keypress={clickable} on:keydown={(e) => {if (e.code=='Space') { e.preventDefault(); clickable();} }}> on:click={(e) => { e.currentTarget.blur(); clickable();}} on:keypress={clickable} on:keydown={(e) => {if (e.code=='Space') { e.preventDefault(); clickable();} }}>
<slot /> <slot />
</li> </li>
{:else} {:else}

@ -0,0 +1,77 @@
<!--
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
-->
<!--
@component DeviceIcon
Display an icon for a device class provided by the `device` attribute.
Pass `config` for custom attributes.
-->
<script lang="ts">
import {
ArrowLeft,
ChevronDoubleUp,
CheckCircle,
CheckBadge,
EllipsisVertical,
} from "svelte-heros-v2";
import NavIcon from "./NavIcon.svelte";
import {save, nav_bar, showMenu} from "../../tab";
export let scrollToTop = () => {};
const back = () => {
// going back
window.history.go(-1);
}
</script>
<div style="background-color: #f6f6f6;" class="h-12 pb-2 flex text-center text-gray-900 dark:text-white">
{#if $nav_bar.back}
<div role="button" tabindex="0" on:click={back} on:keypress={back} class="flex-none w-10 flex justify-center items-center">
<ArrowLeft tabindex="-1" class="w-8 h-8 focus:outline-none"/>
</div>
{/if}
{#if $nav_bar.icon}
<div style="cursor:pointer;" class:w-10={!$nav_bar.back} class:ml-3={!$nav_bar.back} class="flex-none w-8 m-1 " on:click={scrollToTop} on:keypress={scrollToTop}>
<NavIcon img={$nav_bar.icon} config={{
tabindex:"-1",
class:"w-8 h-8 focus:outline-none"
}}/>
</div>
{/if}
<div style="cursor:pointer;" class:pl-3={!$nav_bar.back && !$nav_bar.icon} class="grow w-10 items-center flex px-1"><span class="inline-block truncate" on:click={scrollToTop} on:keypress={scrollToTop}> {$nav_bar.title} </span></div>
{#if $nav_bar.newest}
<div role="button" tabindex="0" class="flex-none m-1 rounded-full bg-primary-700 text-white dark:bg-primary-700" on:click={scrollToTop} on:keypress={scrollToTop}>
<div class="flex items-center grow pr-2">
<ChevronDoubleUp tabindex="-1" class="w-6 h-6 m-1 focus:outline-none"/>
<span class="inline-block">{@html $nav_bar.newest < 100 ? "+ "+$nav_bar.newest : "<span class=\"text-xl\">&infin;</span>"}</span>
</div>
</div>
{/if}
{#if $nav_bar.save !== undefined}
{#if $nav_bar.save }
<div tabindex="0" class="flex-none w-10" role="button" on:click={save} on:keypress={save} title="Save">
<CheckCircle variation="solid" tabindex="-1" strokeWidth="3" class="w-10 h-10 text-primary-400 focus:outline-none"/>
</div>
{:else}
<div class="flex-none w-10" title="Saved!">
<CheckBadge tabindex="-1" class="w-8 h-8 m-1 text-green-500 focus:outline-none"/>
</div>
{/if}
{/if}
<div tabindex="0" class="flex-none w-10 " role="button" title="Open Menu" on:click={showMenu} on:keypress={showMenu}>
<EllipsisVertical tabindex="-1" class="w-8 h-8 my-1 mr-2"/>
</div>
</div>

@ -0,0 +1,54 @@
<!--
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
// All rights reserved.
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
-->
<!--
@component DeviceIcon
Display an icon for a device class provided by the `device` attribute.
Pass `config` for custom attributes.
-->
<script lang="ts">
import {
Icon,
Bolt,
Megaphone,
QuestionMarkCircle,
Key,
} from "svelte-heros-v2";
import DataClassIcon from "../DataClassIcon.svelte";
export let config = {};
export let img: string;
const mapping = {
stream: Bolt,
channel: Megaphone,
private: Key,
};
const find = (dataClass: string) => {
return mapping[dataClass] || QuestionMarkCircle;
};
</script>
{#if img.startsWith("blob:")}
<img style="aspect-ratio:1;" class="rounded-full" src={img} alt="profile"/>
{:else if img.startsWith("class:")}
<DataClassIcon {config} dataClass={img.slice(6)} />
{:else if img.startsWith("nav:")}
<Icon {...config} variation="outline" color="currentColor" icon={find(img.slice(4))} />
{:else}
<QuestionMarkCircle {...config}/>
{/if}

@ -4,9 +4,6 @@
"title": "Seite nicht gefunden", "title": "Seite nicht gefunden",
"message": "Die gesuchte Seite existiert nicht." "message": "Die gesuchte Seite existiert nicht."
}, },
"nextgraph_uri": {
"message": "Nextgraph Link {uri}"
},
"user_panel": { "user_panel": {
"title": "Nutzerbereich", "title": "Nutzerbereich",
"personal": "Privat" "personal": "Privat"

@ -25,6 +25,10 @@
"label": "Table of Content", "label": "Table of Content",
"desc": "Table of Content for Graph and Document" "desc": "Table of Content for Graph and Document"
}, },
"files": {
"label": "Attachments and Files",
"desc": "List all attached files and resources files, and download them if needed"
},
"share": { "share": {
"label": "Share", "label": "Share",
"desc": "Share with others, or react" "desc": "Share with others, or react"
@ -157,9 +161,6 @@
"title": "Page Not Found", "title": "Page Not Found",
"message": "The page you are looking for does not exist." "message": "The page you are looking for does not exist."
}, },
"nextgraph_uri": {
"message": "Nextgraph URI {uri}"
},
"user_panel": { "user_panel": {
"title": "User Panel", "title": "User Panel",
"personal": "Personal" "personal": "Personal"

@ -9,17 +9,27 @@
// according to those terms. // according to those terms.
--> -->
<script> <script>
import { onMount } from "svelte";
import { push } from "svelte-spa-router";
import FullLayout from "../lib/FullLayout.svelte";
import { t } from "svelte-i18n"; import { t } from "svelte-i18n";
// The params prop contains values matched from the URL // The params prop contains values matched from the URL
export let params = {}; export let params = {};
import {
active_session,
} from "../store";
console.log(params); console.log(params);
onMount(async () => {
if (!$active_session) {
push("#/");
} else {
//await scrollToTop();
}
});
</script> </script>
<div class="fix"> <FullLayout>
<div { params[1] }
class="h-screen aspect-[3/5] pazzleline max-w-[720px] bg-yellow-300 inner" </FullLayout>
>
<p>{$t("pages.nextgraph_uri.message", { values: { uri: params[1] } })}</p>
</div>
</div>

@ -34,6 +34,8 @@
} }
#menu-modal li { #menu-modal li {
margin: 0; margin: 0;
margin-top: 5px;
margin-bottom: 5px;
} }
#menu-modal li.submenu { #menu-modal li.submenu {
padding-left: 30px; padding-left: 30px;

@ -230,6 +230,46 @@ export const cur_tab = writable({
right_pane: false, // "folders", "toc", "branches", "files", "history", "comments", "info", "chat", "mc" right_pane: false, // "folders", "toc", "branches", "files", "history", "comments", "info", "chat", "mc"
action: false, // "repost", "dm", "react", "author", "copy", "forward", "links", "qr", "download", "embed", "new_block", "notifs", "schema", "signature", "permissions", "settings", "print", "console", "source", "services", "dev", action: false, // "repost", "dm", "react", "author", "copy", "forward", "links", "qr", "download", "embed", "new_block", "notifs", "schema", "signature", "permissions", "settings", "print", "console", "source", "services", "dev",
show_menu: false,
});
export const showMenu = () => {
cur_tab.update(ct => {
ct.show_menu = true;
return ct;
});
}
export const hideMenu = () => {
cur_tab.update(ct => {
ct.show_menu = false;
return ct;
});
}
export const nav_bar = writable({
//icon: "class:post/rich",
icon: "nav:private",
//icon: "blob:http://localhost:1421/be6f968f-ff51-4e8f-bd32-36c60b7af49a",
title: "Private Store",
back: false,
newest: 0,
save: true,
});
export const save = async () => {
// saving the doc
}
export const all_files_count = derived(cur_tab, ($cur_tab) => {
let total = $cur_tab.cur_branch.attachments + $cur_tab.cur_branch.files;
return total ? `(${total})` : "";
});
export const all_comments_count = derived(cur_tab, ($cur_tab) => {
let total = $cur_tab.cur_branch.comments;
return total ? `(${total})` : "";
}); });
export const has_editor_chat = derived(cur_tab, ($cur_tab) => { export const has_editor_chat = derived(cur_tab, ($cur_tab) => {

Loading…
Cancel
Save