document side menu pane

pull/37/head
Niko PLP 5 months ago
parent 1bc2d46ba8
commit 3f635248be
  1. 43
      ng-app/src/classes.ts
  2. 4
      ng-app/src/lib/CenteredLayout.svelte
  3. 4
      ng-app/src/lib/DataClassIcon.svelte
  4. 408
      ng-app/src/lib/FullLayout.svelte
  5. 5
      ng-app/src/lib/Home.svelte
  6. 4
      ng-app/src/lib/ZeraIcon.svelte
  7. 32
      ng-app/src/lib/components/MenuItem.svelte
  8. 153
      ng-app/src/locales/en.json
  9. 4
      ng-app/src/routes/AccountInfo.svelte
  10. 4
      ng-app/src/routes/User.svelte
  11. 4
      ng-app/src/routes/WalletInfo.svelte
  12. 91
      ng-app/src/store.ts
  13. 30
      ng-app/src/styles.css
  14. 317
      ng-app/src/tab.ts
  15. 179
      ng-app/src/zeras.ts
  16. 1
      ng-app/tailwind.config.cjs
  17. 6
      ng-app/vite.config.ts
  18. 1
      ng-net/src/app_protocol.rs

@ -26,6 +26,11 @@
// epub, dejavu,
// animation: snap, lottie, smil editor: https://github.com/HaikuTeam/animator/
export const has_toc = (class_name) => {
return class_name === "post/rich" || class_name === "post/md" || class_name === "post/html" || class_name === "post/asciidoc" || class_name === "app/z" || class_name === "class"
|| class_name.startsWith("schema") || class_name === "doc/pdf" || class_name === "doc/odf" || class_name === "doc/latex" || class_name === "doc/ps" || class_name === "prod/project" || class_name === "prod/slides"
};
export const official_classes = {
"post/rich": {
"ng:crdt": "YXml",
@ -119,7 +124,7 @@ export const official_classes = {
"ng:crdt": "Graph",
"ng:n": "Schema - RDFS",
"ng:a": "Define the Schema, Ontology or Vocabulary for your data and the relations between them, with RDFS",
"ng:o": "n:g:z:json_ld_editor", // default viewer
"ng:o": "n:g:z:json_ld_viewer", // default viewer
"ng:w": "n:g:z:ontology_editor", // default editor
"ng:x": {
"rdfs":true,
@ -143,7 +148,7 @@ export const official_classes = {
"ng:crdt": "Graph",
"ng:n": "Schema - SHACL",
"ng:a": "Define the Schema, Ontology or Vocabulary for your data and the relations between them, with SHACL",
"ng:o": "n:g:z:json_ld_editor", // default viewer
"ng:o": "n:g:z:json_ld_viewer", // default viewer
"ng:w": "n:g:z:ontology_editor", // default editor
"ng:x": {
"sh":true,
@ -155,7 +160,7 @@ export const official_classes = {
"ng:crdt": "Graph",
"ng:n": "Schema - SHEX",
"ng:a": "Define the Schema, Ontology or Vocabulary for your data and the relations between them, with SHEX",
"ng:o": "n:g:z:json_ld_editor", // default viewer
"ng:o": "n:g:z:json_ld_viewer", // default viewer
"ng:w": "n:g:z:ontology_editor", // default editor
"ng:x": {
"shex":true,
@ -230,7 +235,7 @@ export const official_classes = {
"ng:crdt": "Graph", // https://github.com/highlightjs/highlightjs-turtle/tree/master
"ng:n": "Graph",
"ng:a": "Define the Graph of your data with Semantic Web / Linked Data",
"ng:o": "n:g:z:json_ld_editor", // default viewer
"ng:o": "n:g:z:json_ld_viewer", // default viewer
"ng:w": "n:g:z:json_ld_editor", // default editor
"ng:x": {
"rdf":true,
@ -243,7 +248,7 @@ export const official_classes = {
"ng:crdt": "Automerge",
"ng:n": "JSON",
"ng:a": "JSON Data CRDT",
"ng:o": "n:g:z:json_editor", // default viewer
"ng:o": "n:g:z:json_viewer", // default viewer
"ng:w": "n:g:z:json_editor", // default editor
"ng:compat": ["file/iana/application/json", "code:json"],
},
@ -251,7 +256,7 @@ export const official_classes = {
"ng:crdt": "YArray",
"ng:n": "JSON Array",
"ng:a": "JSON Array CRDT",
"ng:o": "n:g:z:json_editor", // default viewer
"ng:o": "n:g:z:json_viewer", // default viewer
"ng:w": "n:g:z:json_editor", // default editor
"ng:compat": ["file/iana/application/json", "code:json"],
},
@ -259,7 +264,7 @@ export const official_classes = {
"ng:crdt": "YMap",
"ng:n": "JSON Map",
"ng:a": "JSON Map CRDT",
"ng:o": "n:g:z:json_editor", // default viewer
"ng:o": "n:g:z:json_viewer", // default viewer
"ng:w": "n:g:z:json_editor", // default editor
"ng:compat": ["file/iana/application/json", "code:json"],
},
@ -299,6 +304,13 @@ export const official_classes = {
},
"ng:compat": ["rdfs:member","ldp:contains","rdf:Bag","rdf:Alt"],
},
"data/plato": {
"ng:crdt": "Graph",
"ng:n": "Plato",
"ng:a": "A tree of files and folders",
"ng:o": "n:g:z:tree",
"ng:compat": ["ng:plato","ng:has_plato"],
},
"data/board": {
"ng:crdt": "Graph",
"ng:n": "Board",
@ -370,6 +382,12 @@ export const official_classes = {
"ng:a": "Pad representation of a document",
"ng:o": "n:g:z:pad",
},
"doc/compose" : {
"ng:crdt": "YArray",
"ng:n": "Composition",
"ng:a": "Compose several blocks into a single document",
"ng:o": "n:g:z:compose",
},
"doc/diagram/mermaid" : {
"ng:crdt": "YText",
"ng:n": "Diagram - Mermaid",
@ -639,6 +657,15 @@ export const official_classes = {
"ng:o": "n:g:z:media",
"ng:compat": []
},
"social/activity": {
"ng:crdt": "Graph",
"ng:n": "Activity",
"ng:a": "Activity sent in a Stream",
"ng:x": {
"as":true,
},
"ng:compat": ["as:Activity"]
},
"social/channel": {
"ng:crdt": "Graph",
"ng:n": "Channel",
@ -841,7 +868,6 @@ export const official_classes = {
"ng:n": "File",
"ng:a": "Binary file",
"ng:o": "n:g:z:file_viewer",
"ng:w": "n:g:z:file_viewer",
"ng:compat": []
},
"file/ng/wallet" : {
@ -864,7 +890,6 @@ export const official_classes = {
"ng:n": "File",
"ng:a": "Text file",
"ng:o": "n:g:z:file_viewer",
"ng:w": "n:g:z:file_viewer",
"ng:compat": ["file/iana/text/*", "file/iana/image/svg+xml", "file/iana/application/n-quads", "file/iana/application/trig", "file/iana/application/n-triples", "file/iana/application/rdf+xml", "file/iana/application/ld+json",
"file/iana/application/xml", "file/iana/application/yaml", "file/iana/application/xhtml+xml", "file/iana/application/node","file/iana/application/sparql-results+json","file/iana/application/sparql-results+xml",
"file/iana/message/rfc822","file/iana/multipart/related", "file/iana/text/vnd.graphviz", "file/iana/application/vnd.excalidraw+json", "file/iana/application/x-tex","file/iana/text/x-tex",

@ -106,7 +106,5 @@
text-align: center;
width: fit-content;
}
li.clickable {
cursor: pointer;
}
</style>

@ -64,6 +64,8 @@
StopCircle,
Bolt,
Heart,
Cog,
Square3Stack3d
} from "svelte-heros-v2";
export let config = {};
@ -71,6 +73,7 @@
const exact_mapping = {
page: Window,
"app": Cog,
"app/z": SquaresPlus,
class: ViewfinderCircle,
contract: Briefcase,
@ -79,6 +82,7 @@
"data/graph": Sun,
"data/table": TableCells,
"data/collection": ListBullet,
"data/container": Square3Stack3d,
"data/board": RectangleGroup,
"data/grid": Squares2x2,
"data/geomap": MapPin,

@ -15,16 +15,22 @@
SidebarGroup,
SidebarItem,
SidebarWrapper,
Modal,
Toggle,
} from "flowbite-svelte";
import { link, location } from "svelte-spa-router";
import MobileBottomBarItem from "./MobileBottomBarItem.svelte";
import MobileBottomBar from "./MobileBottomBar.svelte";
// @ts-ignore
import Logo from "./components/Logo.svelte";
import MenuItem from "./components/MenuItem.svelte";
// @ts-ignore
import { t } from "svelte-i18n";
import { onMount, tick } from "svelte";
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,
has_editor_chat } from "../tab";
import ZeraIcon from "./ZeraIcon.svelte";
import {
Home,
Bolt,
@ -34,11 +40,50 @@
Bell,
User,
Users,
Sun,
Cloud,
Eye,
PencilSquare,
ChatBubbleLeftEllipsis,
FolderOpen,
BookOpen,
Share,
Envelope,
Heart,
AtSymbol,
Forward,
Link,
QrCode,
DocumentArrowDown,
ChatBubbleOvalLeft,
Clock,
InformationCircle,
Bookmark,
Icon,
ChatBubbleLeftRight,
LockOpen,
Cog6Tooth,
DocumentDuplicate,
CodeBracketSquare,
ArrowsPointingOut,
ShieldCheck,
Cube,
Printer,
CommandLine,
CodeBracket,
Beaker,
WrenchScrewdriver,
Sparkles,
} from "svelte-heros-v2";
let width: number;
let breakPoint: number = 662;
let mobile = false;
let show_menu = true;
let open_view_as = false;
let open_edit_with = false;
let open_share = false;
let open_tools = false;
$: if (width >= breakPoint) {
mobile = false;
@ -47,14 +92,78 @@
}
let top;
let topMenu;
async function scrollToTop() {
await tick();
top.scrollIntoView();
}
onMount(async () => await scrollToTop());
async function scrollToTopMenu() {
await tick();
topMenu.scrollIntoView();
}
onMount(async () => {await open_doc(""); await scrollToTop()});
$: activeUrl = "#" + $location;
const launchAppStore = (class_name:string) => {
//TODO
show_menu = false;
};
const openAction = (action:string) => {
// TODO
show_menu = false;
}
const openPane = (pane:string) => {
// TODO
show_menu = false;
}
const openShare = (share:string) => {
// TODO
show_menu = false;
}
const find = (share:string) => {
// TODO
show_menu = false;
}
const bookmark = (share:string) => {
// TODO
show_menu = false;
}
const annotate = (share:string) => {
// TODO
show_menu = false;
}
const share_items = [
{n:"repost",i:Bolt},
{n:"dm",i:PaperAirplane},
{n:"react",i:Heart},
{n:"author",i:Envelope},
{n:"quote",i:AtSymbol},
{n:"forward",i:Forward},
{n:"link",i:Link},
{n:"qr",i:QrCode},
{n:"download",i:DocumentArrowDown},
];
const tools_items = [
{n:"copy",i:DocumentDuplicate},
{n:"embed",i:CodeBracketSquare},
{n:"schema",i:ArrowsPointingOut},
{n:"signature",i:ShieldCheck},
{n:"services",i:Cube},
{n:"print",i:Printer},
{n:"console",i:CommandLine},
{n:"source",i:CodeBracket},
{n:"dev",i:Beaker},
];
let asideClass = "w-48";
let spanClass = "flex-1 ml-3 whitespace-nowrap";
let nonActiveClass =
@ -62,6 +171,261 @@
</script>
<svelte:window bind:innerWidth={width} />
<Modal id="menu-modal"
outsideclose
bind:open={show_menu}
size = 'xs'
placement = 'top-right'
backdropClass="bg-gray-900 bg-opacity-50 dark:bg-opacity-80 menu-bg-modal"
>
<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}>
<ul class="space-y-1 space-x-0 mb-10">
{#if $cur_branch_has_discrete}
<li>
<div class="inline-flex graph-discrete-toggle mb-2" role="group">
<button on:click={toggle_graph_discrete} disabled={$cur_tab.graph_or_discrete} type="button" style="border-top-left-radius: 0.375rem;border-bottom-left-radius: 0.375rem;" class:selected-toggle={$cur_tab.graph_or_discrete} class:unselected-toggle={!$cur_tab.graph_or_discrete} class="common-toggle" >
<Sun class="mr-2 focus:outline-none"/> {$t("doc.graph")}
</button>
<button on:click={toggle_graph_discrete} disabled={!$cur_tab.graph_or_discrete} type="button" style="border-top-right-radius: 0.375rem;border-bottom-right-radius: 0.375rem;" class:selected-toggle={!$cur_tab.graph_or_discrete} class:unselected-toggle={$cur_tab.graph_or_discrete} class="common-toggle">
<Cloud class="mr-2 focus:outline-none"/> {$t("doc.discrete")}
</button>
</div>
</li>
{/if}
{#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;} }>
<Eye
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white "
/>
<span class="ml-3">{$t("doc.menu.view_as")} {#if $cur_tab.view_or_edit || $available_viewers.length == 1 }{$cur_viewer["ng:n"]}{/if}</span>
</MenuItem>
{#if open_view_as && $available_viewers.length > 1 }
{#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} }>
<ZeraIcon
zera={viewer["ng:u"]}
config={{
tabindex:"-1",
class:"w-7 h-7 text-gray-700 focus:outline-none dark:text-white "
}}
/>
<span class="ml-3">{viewer["ng:n"]}</span>
</MenuItem>
{/each}
{/if}
{/if}
{#if $cur_tab.doc.can_edit}
{#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;} }>
<PencilSquare
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white "
/>
<span class="ml-3">{$t("doc.menu.edit_with")} {#if !$cur_tab.view_or_edit || $available_editors.length == 1 }{$cur_editor["ng:n"]}{/if}</span>
</MenuItem>
{#if open_edit_with && $available_editors.length > 1 }
{#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} }>
<ZeraIcon
zera={editor["ng:u"]}
config={{
tabindex:"-1",
class:"w-7 h-7 text-gray-700 focus:outline-none dark:text-white "
}}
/>
<span class="ml-3">{editor["ng:n"]}</span>
</MenuItem>
{/each}
{/if}
{#if !$cur_tab.view_or_edit || open_edit_with }
<li title={$t("doc.menu.live_editing_description")} style="margin: 7px 0; padding-left: 32px;" class="toggle">
<Toggle
on:change={ toggle_live_edit }
checked={ $cur_tab.doc.live_edit }
><span class="text-gray-700 text-base">{$t("doc.menu.live_editing")}</span>
</Toggle>
</li>
{/if}
{:else}
<MenuItem clickable={()=>launchAppStore($cur_tab.cur_branch.class)}>
<ZeraIcon
zera="app_store"
config={{tabindex:"-1",
class:"w-7 h-7 text-gray-700 focus:outline-none dark:text-white "}}
/>
<span class="ml-3">{$t("doc.menu.install_app_to_edit")}</span>
</MenuItem>
{/if}
{/if}
{#if $cur_tab.doc.can_edit}
<MenuItem title={$t("doc.menu.items.new_block.desc")} clickable={ ()=> openAction("new_block") }>
<PlusCircle
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.new_block.label")}</span>
</MenuItem>
{/if}
{#if $has_editor_chat}
<MenuItem title={$t("doc.menu.items.editor_chat.desc")} clickable={ ()=> openPane("chat") }>
<ChatBubbleLeftRight
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.editor_chat.label")}</span>
</MenuItem>
{/if}
<MenuItem title={$t("doc.menu.items.folders.desc")} clickable={ ()=> openPane("folders") }>
<FolderOpen
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.folders.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.toc.desc")} clickable={ ()=> openPane("toc") }>
<BookOpen
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.toc.label")}</span>
</MenuItem>
<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.share.desc")} clickable={ () => open_share = !open_share }>
<Share
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.share.label")}</span>
</MenuItem>
{#if open_share }
{#each share_items as share}
<MenuItem title={$t(`doc.menu.items.${share.n}.desc`)} extraClass="submenu" clickable={ () => openShare(share.n) }>
<Icon tabindex="-1" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white " variation="outline" color="currentColor" icon={share.i} />
<span class="ml-3">{$t(`doc.menu.items.${share.n}.label`)}</span>
</MenuItem>
{/each}
{/if}
<MenuItem title={$t("doc.menu.items.comments.desc")} clickable={ ()=> openPane("comments") }>
<ChatBubbleOvalLeft
tabindex="-1"
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>
</MenuItem>
<MenuItem title={$t("doc.menu.items.branches.desc")} clickable={ ()=> openPane("branches") }>
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512" fill="currentColor" width="24" height="24" tabindex="-1" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" >
<path d="M365.1,74.6c-43.8,0-80.2,36.4-80.2,80.2c0,38.2,27,70.9,64.3,78.3c-0.9,21.4-12.1,33.6-30.8,48.5
c-23.3,17.7-53.2,23.3-74.6,27c-46.6,8.4-71.8,30.8-83,45.7V159.5c16.8-2.8,32.6-12.1,44.8-25.2c13.1-14.9,20.5-33.6,20.5-54.1
C226.2,36.4,189.8,0,146,0S65.7,36.4,65.7,80.2c0,19.6,7.5,38.2,19.6,53.2c11.2,13.1,26.1,21.4,42.9,25.2v195.8
c-16.8,3.7-31.7,13.1-42.9,25.2c-13.1,14.9-19.6,33.6-19.6,52.2c0,43.8,36.4,80.2,80.2,80.2s80.2-36.4,80.2-80.2
c0-27-13.1-51.3-35.4-66.2c10.3-11.2,28-22.4,58.8-28c25.2-4.7,60.6-11.2,88.6-32.6c27-20.5,42-42,43.8-73.7
c37.3-7.5,64.3-40.1,64.3-78.3C445.3,110,408.9,74.6,365.1,74.6L365.1,74.6z M97.5,81.1c0-26.1,21.4-48.5,48.5-48.5
c26.1,0,48.5,21.4,48.5,48.5S173,129.6,146,129.6C118.9,129.6,97.5,107.2,97.5,81.1z M193.5,433.7c0,26.1-21.4,48.5-48.5,48.5
c-26.1,0-48.5-21.4-48.5-48.5s21.4-48.5,48.5-48.5C172.1,386.1,193.5,407.5,193.5,433.7z M365.1,202.4c-26.1,0-48.5-21.4-48.5-48.5
c0-26.1,21.4-48.5,48.5-48.5c26.1,0,48.5,21.4,48.5,48.5C412.7,180.9,391.2,202.4,365.1,202.4z"/>
</svg>
<span class="ml-3">{$t("doc.menu.items.branches.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.history.desc")} clickable={ ()=> openPane("history") }>
<Clock
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.history.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.find.desc")} clickable={ find }>
<MagnifyingGlass
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.find.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.bookmark.desc")} clickable={ bookmark }>
<Bookmark
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.bookmark.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.annotate.desc")} clickable={ annotate }>
<ChatBubbleLeftEllipsis
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.annotate.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.info.desc")} clickable={ ()=> openPane("info") }>
<InformationCircle
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.info.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.notifs.desc")} clickable={ ()=> openAction("notifs") }>
<Bell
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.notifs.label")}</span>
</MenuItem>
{#if $cur_tab.doc.is_member}
<MenuItem title={$t("doc.menu.items.permissions.desc")} clickable={ ()=> openAction("permissions") }>
<LockOpen
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.permissions.label")}</span>
</MenuItem>
{/if}
<MenuItem title={$t("doc.menu.items.settings.desc")} clickable={ ()=> openAction("settings") }>
<Cog6Tooth
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.settings.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.tools.desc")} clickable={ () => open_tools = !open_tools }>
<WrenchScrewdriver
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
/>
<span class="ml-3">{$t("doc.menu.items.tools.label")}</span>
</MenuItem>
{#if open_tools }
{#each tools_items as tool}
<MenuItem title={$t(`doc.menu.items.${tool.n}.desc`)} extraClass="submenu" clickable={ () => openAction(tool.n) }>
<Icon tabindex="-1" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white " variation="outline" color="currentColor" icon={tool.i} />
<span class="ml-3">{$t(`doc.menu.items.${tool.n}.label`)}</span>
</MenuItem>
{/each}
{/if}
</ul>
</div>
</aside>
</Modal>
{#if mobile}
<div class="full-layout">
<main class="pb-14" bind:this={top}>
@ -106,7 +470,7 @@
<svelte:fragment slot="icon">
<Home
tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
class="w-7 h-7 text-black focus:outline-none dark:text-white group-hover:text-gray-900 "
/>
</svelte:fragment>
</SidebarItem>
@ -118,7 +482,7 @@
<svelte:fragment slot="icon">
<Bolt
tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
class="w-7 h-7 text-black focus:outline-none dark:text-white group-hover:text-gray-900 "
/>
</svelte:fragment>
</SidebarItem>
@ -130,7 +494,7 @@
<svelte:fragment slot="icon">
<MagnifyingGlass
tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
class="w-7 h-7 text-black focus:outline-none dark:text-white group-hover:text-gray-900 "
/>
</svelte:fragment>
</SidebarItem>
@ -142,7 +506,7 @@
<svelte:fragment slot="icon">
<PlusCircle
tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
class="w-7 h-7 text-black focus:outline-none dark:text-white group-hover:text-gray-900 "
/>
</svelte:fragment>
</SidebarItem>
@ -154,7 +518,7 @@
<svelte:fragment slot="icon">
<Users
tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
class="w-7 h-7 text-black focus:outline-none dark:text-white group-hover:text-gray-900 "
/>
</svelte:fragment>
</SidebarItem>
@ -166,7 +530,7 @@
<svelte:fragment slot="icon">
<User
tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
class="w-7 h-7 text-black focus:outline-none dark:text-white group-hover:text-gray-900 "
/>
</svelte:fragment>
</SidebarItem>
@ -178,7 +542,7 @@
<svelte:fragment slot="icon">
<PaperAirplane
tabindex="-1"
class="-rotate-45 w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
class="-rotate-45 w-7 h-7 text-black focus:outline-none dark:text-white group-hover:text-gray-900 "
/>
<span
class="inline-flex justify-center items-center p-3 mt-1 -ml-3 w-3 h-3 text-sm font-medium text-primary-600 bg-primary-200 rounded-full dark:bg-primary-900 dark:text-primary-200"
@ -195,7 +559,7 @@
<svelte:fragment slot="icon">
<Bell
tabindex="-1"
class="w-7 h-7 text-black transition duration-75 focus:outline-none dark:text-white group-hover:text-gray-900 dark:group-hover:text-white"
class="w-7 h-7 text-black focus:outline-none dark:text-white group-hover:text-gray-900 "
/>
<span
class="inline-flex justify-center items-center p-3 mt-1 -ml-3 w-3 h-3 text-sm font-medium text-primary-600 bg-primary-200 rounded-full dark:bg-primary-900 dark:text-primary-200"
@ -215,11 +579,35 @@
{/if}
<style>
.full-layout {
height: 100vh;
overflow: auto;
}
main {
overflow: hidden;
overflow-wrap: break-word;
}
.graph-discrete-toggle button {
border-radius: 0 ;
border: 0 ;
}
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.selected-toggle {
@apply bg-primary-700 text-white;
}
.unselected-toggle {
@apply text-gray-900 hover:bg-gray-100 hover:text-blue-700;
}
.common-toggle {
@apply inline-flex items-center border border-gray-200 text-base font-medium px-2 py-2 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 pr-3;
}
}
</style>

@ -36,12 +36,12 @@
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"
>
<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 xxs:px-8 xs:px-10"
>
<a href="#/user" class="flex items-center" on:click>
<Logo className="w-7 h-7 tall:w-10 tall:h-10" />
<span
class="ml-2 self-center text-lg font-normal text-gray-900 rounded-lg dark:text-white whitespace-nowrap"
class="ml-2 self-center text-base font-normal text-gray-900 rounded-lg dark:text-white whitespace-nowrap"
>NextGraph</span
>
</a>
@ -79,7 +79,6 @@
</div>
</nav>
{/if}
<div />
<Test />
</FullLayout>

@ -87,7 +87,7 @@
invoke: Play,
ontology_viewer: ArrowsPointingOut,
download: DocumentArrowDown,
post_edit: PencilSquare,
edit: PencilSquare,
file: Document,
source: CodeBracket,
post: DocumentText,
@ -117,4 +117,4 @@
};
</script>
<Icon {...config} variation="outline" color="black" icon={find(zera)} />
<Icon {...config} variation="outline" color="currentColor" icon={find(zera)} />

@ -0,0 +1,32 @@
<!--
// 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.
-->
<script lang="ts">
export let clickable;
export let extraClass = "";
export let selected = false;
export let title = "";
</script>
{#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}
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();} }}>
<slot />
</li>
{:else}
<li class="{extraClass} select-none flex items-center px-2 py-1 text-base font-normal text-primary-600 rounded-lg dark:text-primary-300 mt-1">
<slot />
</li>
{/if}

@ -1,4 +1,157 @@
{
"doc": {
"graph" : "Graph",
"discrete" : "Document",
"menu" : {
"edit_with": "Edit with",
"view_as": "View as",
"install_app_to_edit": "Install App to edit",
"live_editing": "Live editing (real-time)",
"live_editing_description": "Collaborate in real-time with other users. If deactivated, you will have to save manually your edits",
"items": {
"new_block": {
"label": "New Block",
"desc": "Create a new block that can be embedded/included in this doc or other docs"
},
"editor_chat": {
"label": "Editors' Chat",
"desc": "Chat with other Editors about the Document you are editing"
},
"folders": {
"label": "Folders",
"desc": "Organize your documents in folders and platos"
},
"toc": {
"label": "Table of Content",
"desc": "Table of Content for Graph and Document"
},
"share": {
"label": "Share",
"desc": "Share with others, or react"
},
"comments": {
"label": "Comments",
"desc": "See comments or annotations, replies, and write your own."
},
"branches": {
"label": "Branches",
"desc": "View, edit or fork branches and blocks"
},
"history": {
"label": "History",
"desc": "Open history of modifications, and travel back in time, to previous revisions"
},
"find": {
"label": "Find",
"desc": "Information about the document, statistics, and keywords"
},
"bookmark": {
"label": "Save",
"desc": "Keep a bookmark of this Document in your private store."
},
"annotate": {
"label": "Annotate",
"desc": "Write private annotations on this Document. Only you can see those annotations. You will also have an option to share them with others."
},
"info": {
"label": "Information",
"desc": "Information about the document, statistics, and keywords"
},
"repost": {
"label": "Post in my Stream",
"desc": "Post in your Stream (publish, repost, reply, boost)"
},
"dm": {
"label": "Send in Direct Message",
"desc": "Send as Direct Message to a contact or in a group chat"
},
"react": {
"label": "Like and React",
"desc": "Like, react, rate"
},
"author": {
"label": "Reply to Author(s)",
"desc": "Sends a private message to the author(s) in reply to this Document"
},
"quote": {
"label": "Quote/Mention in new Post",
"desc": "Write a Post that quotes/cites this Document"
},
"forward": {
"label": "Share via other apps",
"desc": "Share this document to users with other platforms and apps"
},
"link": {
"label": "Links",
"desc": "Get the links to access this Document on the web"
},
"qr": {
"label": "QR-Code",
"desc": "Display or download a QR-Code that links to this Document"
},
"download": {
"label": "Export and Download",
"desc": "Export to several formats and Download the file, or create a self-contained HTML file of this Document that works offline"
},
"notifs": {
"label": "Notifications",
"desc": "Change your notification settings for this Document"
},
"permissions": {
"label": "Permissions",
"desc": "See and change permissions and members for this Document"
},
"settings": {
"label": "Settings",
"desc": "Change settings for this Document"
},
"copy": {
"label": "Copy or Move",
"desc": "Copy, Move, Duplicate, Fork"
},
"embed": {
"label": "Embed",
"desc": "Embed this Document or Block into another Document, or insert a Block into this Document"
},
"schema": {
"label": "Schema",
"desc": "See and manage the Schema of this Document (Model, Ontology, Vocabulary)"
},
"signature": {
"label": "Signature",
"desc": "Obtain and verify the Signature of the Document to prove its authenticity. Or request a signature if there isn't any."
},
"services": {
"label": "Services",
"desc": "See and invoke services available for this Document. Services can be read-only, or read-write"
},
"print": {
"label": "Print",
"desc": "Print or save to PDF"
},
"console": {
"label": "Console",
"desc": "Open a console and run interactive commands"
},
"source": {
"label": "Source",
"desc": "View and Download the source code of this Document"
},
"dev": {
"label": "Developer",
"desc": "Open the developer toolbox"
},
"tools": {
"label": "Tools",
"desc": "Select a tool"
},
"mc": {
"label": "Magic Carpet",
"desc": "Opens the Magic Carpet (like a clipboard, but better)"
}
}
}
},
"pages": {
"not_found": {
"title": "Page Not Found",

@ -361,7 +361,5 @@
</CenteredLayout>
<style>
li.clickable {
cursor: pointer;
}
</style>

@ -384,9 +384,7 @@
</CenteredLayout>
<style>
li.clickable {
cursor: pointer;
}
.site-cnx-details {
@apply mt-0 !important;
}

@ -652,7 +652,5 @@
</CenteredLayout>
<style>
li.clickable {
cursor: pointer;
}
</style>

@ -17,8 +17,6 @@ import {
} from "svelte/store";
import { register, init, locale, format } from "svelte-i18n";
import ng from "./api";
import { official_classes } from "./classes";
import { official_apps, official_services } from "./zeras";
let all_branches = {};
@ -70,95 +68,6 @@ export const select_default_lang = async () => {
}
};
let loaded_external_apps = {};
export const load_app = async (appName: string) => {
if (appName.startsWith("n:g:z")) {
let app = official_apps[appName];
if (!app) throw new Error("Unknown official app");
return await import(`./apps/${app["ng:b"]}.svelte`);
} else {
//TODO: load external app from its repo
// TODO: return IFrame component
}
};
export const invoke_service = async (serviceName: string, nuri: string, args: object) => {
if (serviceName.startsWith("n:g:z")) {
let service = official_services[serviceName];
if (!service) throw new Error("Unknown official service");
// TODO: do this in WebWorker
// TODO: if on native app or CLI: use deno
//return await ng.app_invoke(serviceName[6..], nuri, args);
} else {
// TODO: if on webapp: only allow those invocations from IFrame of external app or from n:g:z:external_service_invoke (which runs in an IFrame) and run it from webworker
// TODO: if on native app or CLI: use deno
// TODO: load external service from its repo
}
};
export const cur_tab = writable({
cur_store: {
has_outer: {
nuri_trail: ":v:l"
},
type: "public", // "protected", "private", "group", "dialog",
favicon: "",
title: "Group B",
},
cur_branch: {
b: "b:xxx", //branch id (can be null if not of type "branch")
c: "c:xxx", //commit(s) id
type: "main", // "stream", "detached", "branch", "in_memory" (does not save)
display: "c:X", // or main or stream or a:xx or branch:X (only 7 chars)
attachments: 1,
class: "data/graph",
title: false,
icon: false,
description: "",
app: "n:g:z:json_ld_editor", // current app being used
},
view_or_edit: false,
graph_viewer: "n:g:z:json_ld_editor", // selected viewer
graph_editor: "n:g:z:json_ld_editor", // selected editor
discrete_viewer: "n:g:z:json_ld_editor", // selected viewer
discrete_editor: "n:g:z:json_ld_editor", // selected editor
graph_viewers: ["n:g:z:json_ld_editor"], // list of available viewers
graph_editors: ["n:g:z:json_ld_editor"], // list of available editors
discrete_viewers: [], // list of available viewers
discrete_editors: [], // list of available editors
find: false,//or string to find
graph_or_discrete: true,
read_cap: 'r:',
doc: {
is_store: false,
is_member: false,
can_edit: false,
live_edit: true,
title: "Doc A",
authors: "",
icon: "",
description: "",
stream: {
notif: 1,
last: "",
},
live_editors: {
},
},
folders_pane: false,
toc_pane: false,
right_pane: false, // "folders", "toc", "branches", "files", "history", "comments", "info", "chat"
action: false, // "view_as", "edit_with", "share", "react", "repost", "copy", "dm_author", "new_block", "notifs", "schema", "signature", "permissions", "query",
});
export const scanned_qr_code = writable("");
export const wallet_from_import = writable<null | object>(null);

@ -15,6 +15,32 @@
background-color: rgba(73, 114, 165, 0.1);
}
.menu-bg-modal + div {
padding: 0 !important;
height: 100%;
}
.menu-bg-modal + div > div {
width: 320px !important;
height: 100%;
}
#menu-modal {
border-radius: 0;
}
#menu-modal div {
padding: 5px;
}
#menu-modal > button {
margin-right: 10px;
}
#menu-modal li {
margin: 0;
}
#menu-modal li.submenu {
padding-left: 30px;
}
.toggle * {
cursor: pointer;
}
/*
#scanner-div {
border: none !important;
@ -96,6 +122,10 @@ div[role="alert"] div {
min-width: 320px;
}
li.clickable {
cursor: pointer;
}
.row {
display: flex;
justify-content: center;

@ -0,0 +1,317 @@
// 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.
import {
writable,
readable,
readonly,
derived,
get,
type Writable,
} from "svelte/store";
import { official_classes } from "./classes";
import { official_apps, official_services } from "./zeras";
let loaded_external_apps = {};
export const load_app = async (appName: string) => {
if (appName.startsWith("n:g:z")) {
let app = official_apps[appName];
if (!app) throw new Error("Unknown official app");
return await import(`./apps/${app["ng:b"]}.svelte`);
} else {
//TODO: load external app from its repo
// TODO: return IFrame component
}
};
export const get_app = (appName: string) => {
if (appName.startsWith("n:g:z")) {
let app = official_apps[appName];
if (!app) throw new Error("Unknown official app");
return app;
} else {
//TODO: load external app from its repo
// TODO: keep it in cache in loaded_external_apps
}
};
export const invoke_service = async (serviceName: string, nuri: string, args: object) => {
if (serviceName.startsWith("n:g:z")) {
let service = official_services[serviceName];
if (!service) throw new Error("Unknown official service");
// TODO: do this in WebWorker
// TODO: if on native app or CLI: use deno
//return await ng.app_invoke(serviceName[6..], nuri, args);
} else {
// TODO: if on webapp: only allow those invocations from IFrame of external app or from n:g:z:external_service_invoke (which runs in an IFrame) and run it from webworker
// TODO: if on native app or CLI: use deno
// TODO: load external service from its repo
}
};
export const get_class = (class_name) => {
if (class_name.startsWith("app/") && class_name !== "app/z") {
//TODO: load external app from its repo
// cache it in loaded_external_apps
// return the class
} else {
return official_classes[class_name];
}
};
const find_viewers_for_class = (class_name: string) => {
let found = [];
for (const zera of Object.entries(official_apps)) {
if (zera[0].includes("dump") || zera[0].includes("source")) continue;
let viewers = zera[1]["ng:o"];
if (viewers && viewers.includes(class_name)) {
found.push(zera[0]);
}
}
return found;
}
const find_editors_for_class = (class_name: string) => {
let found = [];
for (const zera of Object.entries(official_apps)) {
let viewers = zera[1]["ng:w"];
if (viewers && viewers.includes(class_name)) {
found.push(zera[0]);
}
}
return found;
}
const find_source_viewer_for_class = (class_def) => {
switch (class_def["ng:crdt"]) {
case 'Graph':
return "n:g:z:crdt_source_viewer:rdf";
case 'YMap':
case 'YArray':
case 'Automerge':
case 'Elmer':
return "n:g:z:crdt_source_viewer:json";
case 'YXml':
return "n:g:z:crdt_source_viewer:xml";
case 'YText':
return "n:g:z:crdt_source_viewer:text";
}
}
const class_to_viewers_editors = (class_name: string) => {
let class_def = get_class(class_name);
let has_discrete = class_def["ng:crdt"] !== "Graph";
let discrete_viewer = has_discrete ? class_def["ng:o"] : undefined;
let discrete_editor = has_discrete ? class_def["ng:w"] : undefined;
let graph_viewers = [];
let graph_editors = [];
if (!has_discrete) {
if (class_def["ng:o"]) graph_viewers.push(class_def["ng:o"]);
if (class_def["ng:w"]) graph_editors.push(class_def["ng:w"]);
}
graph_viewers.push.apply(graph_viewers, find_viewers_for_class("data/graph"));
graph_editors.push.apply(graph_editors, find_editors_for_class("data/graph"));
let graph_viewer = graph_viewers[0];
let graph_editor = graph_editors[0];
let discrete_viewers = [];
let discrete_editors = [];
if (has_discrete) {
if (discrete_viewer) discrete_viewers.push(discrete_viewer);
if (discrete_editor) discrete_editors.push(discrete_editor);
for (const v of find_viewers_for_class(class_name)) {
if (v!==discrete_viewer) discrete_viewers.push(v);
}
for (const e of find_editors_for_class(class_name)) {
if (e!==discrete_editor) discrete_editors.push(e);
}
discrete_viewers.push(find_source_viewer_for_class(class_def));
if (!discrete_viewer) discrete_viewer = discrete_viewers[0];
}
return {
graph_viewers,
graph_editors,
discrete_viewers,
discrete_editors,
graph_viewer,
graph_editor,
discrete_viewer,
discrete_editor
}
}
export const open_branch = async (nuri: string) => {
let class_name = "post/rich";
}
export const open_doc = async (nuri: string) => {
//let class_name = "doc/viz/plotly";
let class_name = "post/md";
cur_tab.update(ct => {
return {...ct, ...class_to_viewers_editors(class_name)};
});
}
export const cur_tab = writable({
cur_store: {
has_outer: {
nuri_trail: ":v:l"
},
type: "public", // "protected", "private", "group", "dialog",
favicon: "",
title: "Group B",
is_member: true,
},
cur_branch: {
b: "b:xxx", //branch id (can be null if not of type "branch")
c: "c:xxx", //commit(s) id
type: "main", // "stream", "detached", "branch", "in_memory" (does not save)
display: "c:X", // or main or stream or a:xx or branch:X (only 7 chars)
attachments: 1,
files: 1,
comments: 2,
class: "post/rich",
title: false,
icon: false,
description: "",
app: "n:g:z:json_ld_editor", // current app being used
},
view_or_edit: true,
graph_viewer: "", // selected viewer
graph_editor: "", // selected editor
discrete_viewer: "", // selected viewer
discrete_editor: "", // selected editor
graph_viewers: [], // list of available viewers
graph_editors: [], // list of available editors
discrete_viewers: [], // list of available viewers
discrete_editors: [], // list of available editors
find: false,//or string to find
graph_or_discrete: false, // set to cur_branch.class === "Graph"
read_cap: 'r:',
doc: {
is_store: false,
is_member: true,
can_edit: true,
live_edit: false,
title: "Doc A",
authors: "",
icon: "",
description: "",
stream: {
notif: 1,
last: "",
},
live_editors: {
},
},
folders_pane: false,
toc_pane: false,
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",
});
export const has_editor_chat = derived(cur_tab, ($cur_tab) => {
return $cur_tab.doc.can_edit && $cur_tab.cur_store.type !== "private" && $cur_tab.cur_store.type !== "dialog";
});
export const toggle_live_edit = () => {
cur_tab.update(ct => {
ct.doc.live_edit = !ct.doc.live_edit;
return ct;
});
}
export const set_viewer = (app_name: string) => {
if (get(cur_tab).graph_or_discrete) {
cur_tab.update(ct => {ct.graph_viewer = app_name; ct.cur_branch.app = app_name; return ct;});
} else {
cur_tab.update(ct => {ct.discrete_viewer = app_name; ct.cur_branch.app = app_name; return ct;});
}
}
export const set_editor = (app_name: string) => {
if (get(cur_tab).graph_or_discrete) {
cur_tab.update(ct => {ct.graph_editor = app_name; ct.cur_branch.app = app_name; return ct;});
} else {
cur_tab.update(ct => {ct.discrete_editor = app_name; ct.cur_branch.app = app_name; return ct;});
}
}
export const toggle_graph_discrete = () => {
cur_tab.update(ct => {
ct.graph_or_discrete = !ct.graph_or_discrete;
return ct;
});
}
export const set_graph_discrete = (val:boolean) => {
cur_tab.update(ct => {
ct.graph_or_discrete = val;
return ct;
});
}
export const set_view_or_edit = (val:boolean) => {
cur_tab.update(ct => {
ct.view_or_edit = val;
return ct;
});
}
export const cur_viewer = derived(cur_tab, ($cur_tab) => {
let app_name = $cur_tab.graph_or_discrete ? $cur_tab.graph_viewer : $cur_tab.discrete_viewer;
if (app_name) {
let app = get_app(app_name);
return app;
}
});
export const cur_editor = derived(cur_tab, ($cur_tab) => {
let app_name = $cur_tab.graph_or_discrete ? $cur_tab.graph_editor : $cur_tab.discrete_editor;
if (app_name) {
let app = get_app(app_name);
return app;
}
});
export const available_viewers = derived(cur_tab, ($cur_tab) => {
let list = $cur_tab.graph_or_discrete ? $cur_tab.graph_viewers : $cur_tab.discrete_viewers;
return list.map((viewer) => {
let app = { ...get_app(viewer) };
if (!app["ng:u"]) app["ng:u"] = "view";
return app
});
});
export const available_editors = derived(cur_tab, ($cur_tab) => {
let list = $cur_tab.graph_or_discrete ? $cur_tab.graph_editors : $cur_tab.discrete_editors;
return list.map((editor) => {
let app = { ...get_app(editor) };
if (!app["ng:u"]) app["ng:u"] = "edit";
return app
});
});
export const cur_branch_has_discrete = derived(cur_tab, ($cur_tab) => (get_class($cur_tab.cur_branch.class)["ng:crdt"]) !== "Graph");

@ -9,9 +9,10 @@
// according to those terms.
// "n:g:z:hide" >> hides when in viewer mode
// "n:g:z:compose" >> a viewer made of a list of viewers (useful when different views on the same branch needs to be aggregated, or when the discrete is not composable - i.e it is not a Post)
//"n:g:z:json_ld_editor", "n:g:z:json_editor", "n:g:z:triple_editor", "n:g:z:rdf_viewer:turtle", "n:g:z:rdf_viewer:n3", "n:g:z:rdf_viewer:json_ld", "n:g:z:rdf_viewer:graph",
//"n:g:z:sparql_query:yasgui", "n:g:z:sparql_query:sparnatural", "n:g:z:graphql_query", "n:g:z:sparql_update:yasgui", "n:g:z:ontology_editor", "n:g:z:owl_viewer", "n:g:z:sparql:invoke", "n:g:z:graphql:invoke", "n:g:z:dump_download",
// "n:g:z:post_rich_editor", "n:g:z:post_md_editor", "n:g:z:code_editor", "n:g:z:file_viewer", "n:g:z:file_source", "n:g:z:crdt_source_viewer:xml", "n:g:z:crdt_source_viewer:json", "n:g:z:crdt_source_viewer:text", "n:g:z:crdt_source_viewer:rdf"
// "n:g:z:post_rich_editor", "n:g:z:post_md_editor", "n:g:z:code_editor", "n:g:z:file_viewer", "n:g:z:file_source", "n:g:z:crdt_source_viewer:xml", "n:g:z:crdt_source_viewer:md", "n:g:z:crdt_source_viewer:json", "n:g:z:crdt_source_viewer:text", "n:g:z:crdt_source_viewer:rdf"
//"n:g:z:post:rich", "n:g:z:post:md", "n:g:z:text", "n:g:z:pre", "n:g:z:pad", "n:g:z:card", "n:g:z:gallery", "n:g:z:columns", "n:g:z:tree", "n:g:z:summary", "n:g:z:list", "n:g:z:grid", "n:g:z:list_n_post", "n:g:z:grid_n_post", "n:g:z:board",
//"n:g:z:map", "n:g:z:chart", "n:g:z:pivot", "n:g:z:timeline", "n:g:z:email", "n:g:z:web_archive", "n:g:z:diagram_editor", "n:g:z:pdf", "n:g:z:latex", "n:g:z:media", "n:g:z:media_editor",
//"n:g:z:service_editor", "n:g:z:service_invoke", "n:g:z:external_service_invoke", "n:g:z:contract", "n:g:z:text_query", "n:g:z:web_query", "n:g:z:scan_qrcode", "n:g:z:upload_file",
@ -21,68 +22,44 @@
export const official_apps = {
"n:g:z:json_ld_editor": {
"ng:n": "JSON-LD editor",
"ng:a": "View and edit the RDF Graph as JSON-LD",
"ng:n": "JSON-LD Editor",
"ng:a": "Edit the RDF Graph as JSON-LD",
"ng:c": "app",
"ng:u": "json_ld_editor",//favicon. can be a did:ng:j
"ng:g": "n:g:z:json_ld_editor",
"ng:b": "JsonLdEditor",
"ng:o": ["data/graph"],
"ng:w": ["data/graph"],
},
"n:g:z:json_editor": {
"ng:n": "JSON editor",
"ng:a": "View and edit your JSON data",
"ng:n": "JSON Editor",
"ng:a": "Edit the JSON data",
"ng:c": "app",
"ng:u": "json_editor",//favicon. can be a did:ng:j
"ng:g": "n:g:z:json_editor",
"ng:b": "JsonEditor",
"ng:o": ["data/json","data/array","data/map"],
"ng:w": ["data/json","data/array","data/map"],
},
"n:g:z:triple_editor": {
"ng:n": "Graph triples",
"ng:a": "Edit your RDF Graph as triples",
"ng:n": "Graph Triples Editor",
"ng:a": "Edit the RDF Graph as triples",
"ng:c": "app",
"ng:u": "triple_editor",//favicon. can be a did:ng:j
"ng:g": "n:g:z:triple_editor",
"ng:b": "TripleEditor",
"ng:o": ["data/graph"],
"ng:w": ["data/graph"],
},
"n:g:z:rdf_viewer:turtle": { // https://github.com/highlightjs/highlightjs-turtle/tree/master
"ng:n": "Turtle",
"ng:a": "View your RDF Graph in Turtle format",
"ng:c": "app",
"ng:u": "rdf_viewer",//favicon. can be a did:ng:j
"ng:g": "n:g:z:rdf_viewer:turtle",
"ng:b": "TurtleViewer",
"ng:o": ["data/graph"],
"ng:w": [],
},
"n:g:z:rdf_viewer:n3": { // ?
"ng:n": "N3",
"ng:a": "View your RDF Graph in N3 format",
"ng:c": "app",
"ng:u": "rdf_viewer",//favicon. can be a did:ng:j
"ng:g": "n:g:z:rdf_viewer:n3",
"ng:b": "N3Viewer",
"ng:o": ["data/graph"],
"ng:w": [],
},
"n:g:z:rdf_viewer:json_ld": { // highlight.js JSON
"n:g:z:json_ld_viewer": {
"ng:n": "JSON-LD",
"ng:a": "View your RDF Graph in N3 format",
"ng:a": "View the RDF Graph as JSON-LD",
"ng:c": "app",
"ng:u": "rdf_viewer",//favicon. can be a did:ng:j
"ng:g": "n:g:z:rdf_viewer:json_ld",
"ng:u": "json_ld_editor",//favicon. can be a did:ng:j
"ng:g": "n:g:z:json_ld_viewer",
"ng:b": "JsonLdViewer",
"ng:o": ["data/graph"],
"ng:w": [],
},
"n:g:z:rdf_viewer:graph": {
"ng:n": "Graph Explorer",
"ng:a": "View your RDF Graph as interactive visualization",
"ng:a": "View the RDF Graph as interactive visualization",
"ng:c": "app",
"ng:u": "graph_viewer",//favicon. can be a did:ng:j
"ng:g": "n:g:z:rdf_viewer:graph",
@ -90,49 +67,97 @@ export const official_apps = {
"ng:o": ["data/graph"],
"ng:w": [],
},
"n:g:z:json_viewer": {
"ng:n": "JSON",
"ng:a": "View the JSON data",
"ng:c": "app",
"ng:u": "json_editor",//favicon. can be a did:ng:j
"ng:g": "n:g:z:json_viewer",
"ng:b": "JsonViewer",
"ng:o": ["data/json","data/array","data/map"],
},
"n:g:z:triple_viewer": {
"ng:n": "Graph Triples",
"ng:a": "View the RDF Graph as triples",
"ng:c": "app",
"ng:u": "triple_editor",//favicon. can be a did:ng:j
"ng:g": "n:g:z:triple_viewer",
"ng:b": "TripleViewer",
"ng:o": ["data/graph"],
},
"n:g:z:sparql_query:yasgui": {
"ng:n": "SPARQL Query",
"ng:a": "View, edit and invoke your Graph SPARQL query",
"ng:a": "View, edit and invoke the Graph SPARQL query",
"ng:c": "app",
"ng:u": "sparql_query",//favicon. can be a did:ng:j
"ng:g": "n:g:z:sparql_query:yasgui",
"ng:b": "SparqlQueryEditor", // YASGUI of Zazuko https://github.com/zazuko/trifid/tree/main/packages/yasgui
"ng:o": [],
"ng:o": ["data/graph"],
"ng:w": ["query/sparql"],
},
"n:g:z:sparql_query:sparnatural": {
"ng:n": "SPARQL natural Query",
"ng:a": "View, edit and invoke your Graph SPARQL query with SPARnatural tool",
"ng:n": "SPARNatural Query",
"ng:a": "View, edit and invoke the Graph SPARQL query with SPARnatural tool",
"ng:c": "app",
"ng:u": "sparnatural",//favicon. can be a did:ng:j
"ng:g": "n:g:z:sparql_query:sparnatural",
"ng:b": "SparNaturalEditor",
"ng:o": [],
"ng:o": ["data/graph"],
"ng:w": ["query/sparql"],
},
"n:g:z:graphql_query": {
"ng:n": "GraphQL Query",
"ng:a": "View, edit and invoke your GraphQL query",
"ng:a": "View, edit and invoke the GraphQL query",
"ng:c": "app",
"ng:u": "graphql",//favicon. can be a did:ng:j
"ng:g": "n:g:z:graphql_query",
"ng:b": "GraphqlEditor",
"ng:o": [],
"ng:o": ["data/graph"],
"ng:w": ["query/graphql"],
},
"n:g:z:sparql_update:yasgui": {
"ng:n": "SPARQL Update",
"ng:a": "View, edit and invoke your Graph SPARQL Update",
"ng:a": "View, edit and invoke a Graph SPARQL Update",
"ng:c": "app",
"ng:u": "sparql_query",//favicon. can be a did:ng:j
"ng:g": "n:g:z:sparql_update:yasgui",
"ng:b": "SparqlUpdateEditor", // YASGUI of Zazuko https://github.com/zazuko/trifid/tree/main/packages/yasgui
"ng:o": [],
"ng:w": ["query/sparql_update"],
"ng:w": ["query/sparql_update","data/graph"],
},
"n:g:z:rdf_viewer:turtle": { // https://github.com/highlightjs/highlightjs-turtle/tree/master
"ng:n": "Turtle",
"ng:a": "View the RDF Graph in Turtle format",
"ng:c": "app",
"ng:u": "rdf_viewer",//favicon. can be a did:ng:j
"ng:g": "n:g:z:rdf_viewer:turtle",
"ng:b": "TurtleViewer",
"ng:o": ["data/graph"],
"ng:w": [],
},
"n:g:z:rdf_viewer:n3": { // ?
"ng:n": "N3",
"ng:a": "View the RDF Graph in N3 format",
"ng:c": "app",
"ng:u": "rdf_viewer",//favicon. can be a did:ng:j
"ng:g": "n:g:z:rdf_viewer:n3",
"ng:b": "N3Viewer",
"ng:o": ["data/graph"],
"ng:w": [],
},
"n:g:z:rdf_viewer:json_ld": { // highlight.js JSON
"ng:n": "JSON-LD Source",
"ng:a": "View the RDF Graph in N3 format",
"ng:c": "app",
"ng:u": "rdf_viewer",//favicon. can be a did:ng:j
"ng:g": "n:g:z:rdf_viewer:json_ld",
"ng:b": "JsonLdViewer",
"ng:o": ["data/graph"],
"ng:w": [],
},
"n:g:z:ontology_editor": {
"ng:n": "Ontology editor",
"ng:a": "Edit your Ontology",
"ng:n": "Ontology Editor",
"ng:a": "Edit the Ontology",
"ng:c": "app",
"ng:u": "json_ld_editor",//favicon. can be a did:ng:j
"ng:g": "n:g:z:ontology_editor",
@ -142,7 +167,7 @@ export const official_apps = {
},
"n:g:z:owl_viewer": {
"ng:n": "OWL Ontology",
"ng:a": "View your OWL Ontology",
"ng:a": "View the OWL Ontology",
"ng:c": "app",
"ng:u": "ontology_viewer",//favicon. can be a did:ng:j
"ng:g": "n:g:z:owl_viewer",
@ -152,7 +177,7 @@ export const official_apps = {
},
"n:g:z:sparql:invoke": { // displayed with highlight.js https://github.com/highlightjs/highlightjs-turtle/tree/master
"ng:n": "SPARQL Invoke",
"ng:a": "View and invoke your saved SPARQL query",
"ng:a": "View and invoke the saved SPARQL query",
"ng:c": "app",
"ng:u": "invoke",//favicon. can be a did:ng:j
"ng:g": "n:g:z:sparql:invoke",
@ -162,7 +187,7 @@ export const official_apps = {
},
"n:g:z:graphql:invoke": {
"ng:n": "GraphQL Invoke",
"ng:a": "View and invoke your saved GraphQL query",
"ng:a": "View and invoke the saved GraphQL query",
"ng:c": "app",
"ng:u": "invoke",//favicon. can be a did:ng:j
"ng:g": "n:g:z:graphql:invoke",
@ -172,7 +197,7 @@ export const official_apps = {
},
"n:g:z:dump_download": {
"ng:n": "Download",
"ng:a": "Download a file containing a document export data",
"ng:a": "Download a file containing a document exported data",
"ng:c": "app",
"ng:u": "download",//favicon. can be a did:ng:j
"ng:g": "n:g:z:dump_download",
@ -182,19 +207,19 @@ export const official_apps = {
},
"n:g:z:post_rich_editor": {
"ng:n": "Post Editor",
"ng:a": "Edit your post with ProseMirror",
"ng:a": "Edit the post with ProseMirror",
"ng:c": "app",
"ng:u": "post_edit",//favicon. can be a did:ng:j
"ng:u": "edit",//favicon. can be a did:ng:j
"ng:g": "n:g:z:post_rich_editor",
"ng:b": "ProseMirrorEditor",
"ng:o": [],
"ng:w": ["post/rich"],
},
"n:g:z:post_md_editor": {
"ng:n": "Post Editor",
"ng:a": "Edit your post with MilkDown",
"ng:n": "Post MD Editor",
"ng:a": "Edit the post with MilkDown",
"ng:c": "app",
"ng:u": "post_edit",//favicon. can be a did:ng:j
"ng:u": "edit",//favicon. can be a did:ng:j
"ng:g": "n:g:z:post_md_editor",
"ng:b": "MilkDownEditor",
"ng:o": [],
@ -202,9 +227,9 @@ export const official_apps = {
},
"n:g:z:code_editor": {
"ng:n": "Code and Text Editor",
"ng:a": "Edit your code/text with CodeMirror",
"ng:a": "Edit the code/text with CodeMirror",
"ng:c": "app",
"ng:u": "post_edit",//favicon. can be a did:ng:j
"ng:u": "edit",//favicon. can be a did:ng:j
"ng:g": "n:g:z:code_editor",
"ng:b": "CodeMirrorEditor",
"ng:o": [],
@ -240,6 +265,16 @@ export const official_apps = {
"ng:o": ["post/rich","post/md","post/html","page","data/xml", "doc/diagram/drawio"],
"ng:w": [],
},
"n:g:z:viewer:md": {
"ng:n": "MarkDown source",
"ng:a": "See the MarkDown source of this document",
"ng:c": "app",
"ng:u": "source",//favicon. can be a did:ng:j
"ng:g": "n:g:z:viewer:md",
"ng:b": "MdSource", // displayed with highlight.js , with option to download
"ng:o": ["post/md"],
"ng:w": [],
},
"n:g:z:crdt_source_viewer:json": {
"ng:n": "JSON source",
"ng:a": "See the source code of this document, in JSON",
@ -353,7 +388,7 @@ export const official_apps = {
},
"n:g:z:app_editor": {
"ng:n": "App editor",
"ng:a": "Create and modify your App with NextGraph IDE",
"ng:a": "Create and modify Apps with NextGraph IDE",
"ng:c": "app",
"ng:u": "app_editor",//favicon. can be a did:ng:j
"ng:g": "n:g:z:app_editor",
@ -368,8 +403,8 @@ export const official_apps = {
"ng:u": "list",//favicon. can be a did:ng:j
"ng:g": "n:g:z:list",
"ng:b": "ListView",
"ng:o": ["data/graph"],
"ng:w": ["data/graph"],
"ng:o": ["data/collection","data/container"],
"ng:w": ["data/collection","data/container"],
},
"n:g:z:grid": {
"ng:n": "Grid view",
@ -378,8 +413,8 @@ export const official_apps = {
"ng:u": "grid",//favicon. can be a did:ng:j
"ng:g": "n:g:z:grid",
"ng:b": "GridView",
"ng:o": ["data/graph"],
"ng:w": ["data/graph"],
"ng:o": ["data/grid"],
"ng:w": ["data/grid"],
},
"n:g:z:media": {
"ng:n": "Media view",
@ -393,9 +428,9 @@ export const official_apps = {
},
"n:g:z:service_editor": {
"ng:n": "Service Editor",
"ng:a": "Write and define your Service in Rust or JS/Deno",
"ng:a": "Write and define a Service in Rust or JS/Deno",
"ng:c": "app",
"ng:u": "post_edit",//favicon. can be a did:ng:j
"ng:u": "edit",//favicon. can be a did:ng:j
"ng:g": "n:g:z:service_editor",
"ng:b": "CodeMirrorEditor",
"ng:o": [],
@ -422,8 +457,8 @@ export const official_apps = {
"ng:w": [],
},
"n:g:z:upload_file": {
"ng:n": "Upload file",
"ng:a": "Upload a binary file into a document",
"ng:n": "Upload binary file",
"ng:a": "Upload a binary file into the Document",
"ng:c": "app",
"ng:u": "load",//favicon. can be a did:ng:j
"ng:g": "n:g:z:upload_file",
@ -431,6 +466,16 @@ export const official_apps = {
"ng:o": [],
"ng:w": ["data/graph"],
},
"n:g:z:import_file": {
"ng:n": "Import from external file",
"ng:a": "Import an external file with compatible format",
"ng:c": "app",
"ng:u": "load_graph",//favicon. can be a did:ng:j
"ng:g": "n:g:z:import_file",
"ng:b": "UploadFile",
"ng:o": [],
"ng:w": ["data/graph"],
},
// TODO: "n:g:z:columns", "n:g:z:tree", "n:g:z:summary", "n:g:z:list_n_post", "n:g:z:grid_n_post", "n:g:z:board",
// TODO: "n:g:z:map", "n:g:z:chart", "n:g:z:pivot", "n:g:z:timeline", "n:g:z:email", "n:g:z:web_archive", "n:g:z:diagram_editor", "n:g:z:pdf", "n:g:z:latex", "n:g:z:media_editor",
// TODO: "n:g:z:contract", "n:g:z:text_query", "n:g:z:web_query", "n:g:z:scan_qrcode",

@ -5,7 +5,6 @@ const config = {
"./src/**/*.{html,js,svelte,ts}",
"./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}",
],
theme: {
extend: {
colors: {

@ -29,6 +29,12 @@ export default defineConfig(async () => {
postcss: true,
}),
],
onwarn: (warning, handler) => {
if (warning.code === 'css-unused-selector') {
return;
}
handler(warning);
},
}),
svelteSVG({
svgoConfig: {

@ -77,7 +77,6 @@ pub enum TargetBranchV0 {
Comments,
BackLinks,
Context,
Ontology,
BranchId(BranchId),
Named(String), // branch or commit
Commits(Vec<ObjectId>), // only possible if access to their branch is given. must belong to the same branch.

Loading…
Cancel
Save