edit title and intro

master
Niko PLP 3 months ago
parent 711fa42621
commit 254ad56e5b
  1. 1
      Cargo.lock
  2. 1
      RELEASE-NOTE.md
  3. 9
      ng-app/index-web.html
  4. 49
      ng-app/src-tauri/src/lib.rs
  5. 2
      ng-app/src/api.ts
  6. 34
      ng-app/src/apps/ContainerView.svelte
  7. 4
      ng-app/src/apps/SparqlQueryEditor.svelte
  8. 77
      ng-app/src/classes.ts
  9. 4
      ng-app/src/lib/Document.svelte
  10. 123
      ng-app/src/lib/FullLayout.svelte
  11. 10
      ng-app/src/lib/icons/DataClassIcon.svelte
  12. 70
      ng-app/src/lib/popups/Header.svelte
  13. 13
      ng-app/src/locales/en.json
  14. 4
      ng-app/src/routes/WalletInfo.svelte
  15. 42
      ng-app/src/routes/WalletLogin.svelte
  16. 61
      ng-app/src/store.ts
  17. 6
      ng-app/src/styles.css
  18. 7
      ng-app/src/tab.ts
  19. 32
      ng-app/src/zeras.ts
  20. 56
      ng-net/src/app_protocol.rs
  21. 26
      ng-oxigraph/src/oxigraph/sparql/dataset.rs
  22. 12
      ng-oxigraph/src/oxigraph/storage/mod.rs
  23. 11
      ng-repo/src/repo.rs
  24. 90
      ng-repo/src/store.rs
  25. 17
      ng-repo/src/types.rs
  26. 64
      ng-sdk-js/app-node/index.js
  27. 110
      ng-sdk-js/src/lib.rs
  28. 1
      ng-verifier/Cargo.toml
  29. 99
      ng-verifier/src/commits/transaction.rs
  30. 159
      ng-verifier/src/request_processor.rs
  31. 2
      ng-verifier/src/site.rs
  32. 13
      ng-verifier/src/types.rs
  33. 100
      ng-verifier/src/verifier.rs

1
Cargo.lock generated

@ -3507,6 +3507,7 @@ dependencies = [
"either",
"futures",
"getrandom 0.2.10",
"lazy_static",
"ng-net",
"ng-oxigraph",
"ng-repo",

@ -40,6 +40,5 @@ The `ngcli` daemon is release with the basic features listed in `ngcli --help`.
- you cannot share documents with other users. Everything is ready for this internally, but there is still some wiring to do that will take some more time.
- the Rich text editors (both for normal Post/Article and in Markdown) do not let you insert images nor links to other documents.
- your documents listed in your 3 stores do not display any title or content type, making it difficult to understand which document is which by just reading the 7-character ID of the documents. This will be addressed very quickly, as soon as the "Header branch" feature will be implemented. For the same reason (lack of this feature), and in the web-app only, when you will have created many docs with many modifications, the loading of your app can take some time because it is loading all the content of all the docs at startup. The native apps are already working well and do not suffer from this caveat. For the web-app, it is not the intended behaviour of course, but we need the "Header branch" feature to fix this.
- The webapp has some limitation for now when it is offline, because it doesn't have a UserStorage. it works differently than the native apps, as it has to replay all the commits at every load. This will stay like that for now, as the feature "Web UserStorage" based on IndexedDB will take some time to be coded.
- JSON-LD isn't ready yet as we need the "Context branch" feature in order to enter the list of ontologies each document is based on.

@ -116,19 +116,24 @@
</div>
<script>
const supported = (() => {
if (RegExp().hasIndices === undefined) return false;
if (RegExp().hasIndices === undefined) {console.log("no RegExp().hasIndices");return false;}
try {
if (Worker === undefined) return false;
if (Worker === undefined) {console.log("no Worker");return false;}
new Worker(URL.createObjectURL(new Blob([';'], {type: 'application/javascript'})));
if (typeof WebAssembly === "object"
&& typeof WebAssembly.instantiate === "function") {
const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
if (module instanceof WebAssembly.Module)
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
else {
console.log("no WebAssembly module");
}
}
} catch (e) {
{console.log(e);return false;}
}
console.log("no WebAssembly");
return false;
})();
if (!supported ) {

@ -551,6 +551,53 @@ async fn branch_history(session_id: u64, nuri: String) -> Result<AppHistoryJs, S
}
}
#[tauri::command(rename_all = "snake_case")]
async fn update_header(
session_id: u64,
nuri: String,
title: Option<String>,
about: Option<String>,
) -> Result<(), String> {
let nuri = NuriV0::new_from(&nuri).map_err(|e| e.to_string())?;
let request = AppRequest::V0(AppRequestV0 {
command: AppRequestCommandV0::new_header(),
nuri,
payload: Some(AppRequestPayload::new_header(title, about)),
session_id,
});
let res = nextgraph::local_broker::app_request(request)
.await
.map_err(|e: NgError| e.to_string())?;
if let AppResponse::V0(AppResponseV0::Error(e)) = res {
Err(e)
} else {
Ok(())
}
}
#[tauri::command(rename_all = "snake_case")]
async fn fetch_header(session_id: u64, nuri: String) -> Result<AppHeader, String> {
let nuri = NuriV0::new_from(&nuri).map_err(|e| e.to_string())?;
let request = AppRequest::V0(AppRequestV0 {
command: AppRequestCommandV0::new_fetch_header(),
nuri,
payload: None,
session_id,
});
let res = nextgraph::local_broker::app_request(request)
.await
.map_err(|e: NgError| e.to_string())?;
match res {
AppResponse::V0(AppResponseV0::Error(e)) => Err(e),
AppResponse::V0(AppResponseV0::Header(h)) => Ok(h),
_ => Err("invalid response".to_string()),
}
}
#[tauri::command(rename_all = "snake_case")]
async fn sparql_update(
session_id: u64,
@ -1023,6 +1070,8 @@ impl AppBuilder {
signature_status,
signature_request,
signed_snapshot_request,
update_header,
fetch_header,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");

@ -53,6 +53,8 @@ const mapping = {
"signature_status": ["session_id", "nuri"],
"signed_snapshot_request": ["session_id", "nuri"],
"signature_request": ["session_id", "nuri"],
"update_header": ["session_id","nuri","title","about"],
"fetch_header": ["session_id", "nuri"]
}

@ -11,8 +11,7 @@
<script lang="ts">
import {
} from "../store";
import ng from "../api";
import { link } from "svelte-spa-router";
import { Button, Progressbar, Spinner, Alert } from "flowbite-svelte";
import{ PlusCircle } from "svelte-heros-v2";
@ -20,9 +19,16 @@
import {
in_memory_discrete, open_viewer, set_viewer, set_editor, set_view_or_edit, cur_tab_branch_class, cur_tab_doc_can_edit, cur_tab
} from "../tab";
import DataClassIcon from "../lib/icons/DataClassIcon.svelte";
import {
openModalCreate
openModalCreate,
sparql_query,
active_session
} from "../store";
import {
Clipboard
} from "svelte-heros-v2";
export let commits;
function contained(graph) {
@ -30,23 +36,41 @@
for (const g of graph) {
if (g.substring(57,90) === "http://www.w3.org/ns/ldp#contains") {
let nuri = g.substring(93,146);
let repo = nuri;
nuri = nuri + ":" + $cur_tab.store.overlay;
let hash = nuri.substring(9,16);
ret.push({nuri,hash});
ret.push({nuri,hash,repo});
}
}
ret.sort((a, b) => a.hash.localeCompare(b.hash));
return ret;
}
async function fetch_header(repo) {
try {
let res = await ng.fetch_header($active_session.session_id, repo);
return res;
}catch(e){
console.error(e);
return {};
}
}
const create = () => {
openModalCreate();
}
const config = {
class: "mr-2 w-6 h-6 shrink-0 focus:outline-none"
}
</script>
<div class="flex-col p-5">
{#each contained(commits.graph) as doc}
<div class="flex font-mono mb-3"> <a use:link href="/{doc.nuri}">{doc.hash}</a> </div>
{#await fetch_header(doc.repo)}
<div class="flex"> <Clipboard tabindex="-1" class="mr-2 w-6 h-6 shrink-0 focus:outline-none"/><div class="flex font-mono mb-3"> <a use:link href="/{doc.nuri}">{doc.hash}</a> </div> </div>
{:then header}
<div class="flex" title="{header.about || ''}"> {#if header.class}<DataClassIcon {config} dataClass={header.class}/>{:else}<Clipboard tabindex="-1" class="mr-2 w-6 h-6 shrink-0 focus:outline-none"/>{/if}<div class="flex font-mono mb-3"> <a use:link href="/{doc.nuri}">{header.title || doc.hash}</a> </div></div>
{/await}
{/each}
{#if commits.graph.length == 0 || contained(commits.graph).length == 0}
<p>{$t("doc.empty_container")}</p>

@ -55,7 +55,7 @@
await reset_toasts();
results = await sparql_query($in_memory_discrete, union);
} catch(e) {
console.log(e)
console.error(e)
toast_error(display_error(e));
}
}
@ -112,7 +112,7 @@
{#each results.results.bindings as row}
<TableBodyRow>
{#each results.head.vars as variable}
<TableBodyCell class="px-6 py-4 whitespace-break-spaces font-medium">{row[variable].value}</TableBodyCell>
<TableBodyCell class="px-6 py-4 whitespace-break-spaces font-medium">{#if row[variable]} {row[variable].value }{/if}</TableBodyCell>
{/each}
</TableBodyRow>
{/each}

@ -12,7 +12,7 @@
// "data:graph", "data:json", "data:array", "data:map", "data:xml", "data:table", "data:collection", "data:board", "data:grid", "data:geomap",
// "e:email", "e:web", "e:http://[url of class in ontology]", "e:rdf" (read-only cache of RDF fetched from web2.0)
// "mc:text", "mc:link", "mc:card", "mc:pad",
// "doc:diagram","doc:chart", "doc:pdf", "doc:odf", "doc:latex", "doc:ps", "doc:music", "doc:maths", "doc:chemistry", "doc:braille", "doc:ancientscript",
// "diagram","chart", "doc:pdf", "doc:odf", "doc:latex", "doc:ps", "doc:music", "doc:maths", "doc:chemistry", "doc:braille", "doc:ancientscript",
// "media:image", "media:reel", "media:album", "media:video", "media:audio", "media:song", "media:subtitle", "media:overlay",
// "social:channel", "social:stream", "social:contact", "social:event", "social:calendar", "social:scheduler", "social:reaction", "social:chatroom",
// "prod:task", "prod:project", "prod:issue", "prod:form", "prod:filling", "prod:cad", "prod:slides", "prod:question", "prod:answer", "prod:poll", "prod:vote"
@ -165,35 +165,24 @@ export const official_classes = {
},
"ng:compat": ["rdfs:Class"],
},
"schema:rdfs": {
"schema": { // display with https://github.com/VisualDataWeb/WebVOWL
"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_viewer", // default viewer
"ng:n": "Schema - RDFS/OWL",
"ng:a": "Define the Schema, Ontology or Vocabulary for your data and the relations between them, with RDFS and/or OWL",
"ng:o": "n:g:z:ontology_viewer", // default viewer
"ng:w": "n:g:z:ontology_editor", // default editor
"ng:x": {
"rdfs":true,
},
"ng:include": ["data:graph"],
"ng:compat": ["rdfs:*","class"],
},
"schema:owl": { // display with https://github.com/VisualDataWeb/WebVOWL
"ng:crdt": "Graph",
"ng:n": "Schema - OWL",
"ng:a": "Define the Schema, Ontology or Vocabulary for your data and the relations between them, with OWL",
"ng:o": "n:g:z:owl_viewer", // default viewer
"ng:w": "n:g:z:ontology_editor", // default editor
"ng:x": {
"owl":true,
},
"ng:include": ["data:graph"],
"ng:compat": ["owl:Ontology"],
"ng:compat": ["rdfs:*","class","owl:Ontology"],
},
"schema:shacl": {
"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_viewer", // default viewer
"ng:a": "Define the rules for your data with SHACL",
"ng:o": "n:g:z:ontology_viewer", // default viewer
"ng:w": "n:g:z:ontology_editor", // default editor
"ng:x": {
"sh":true,
@ -204,8 +193,8 @@ export const official_classes = {
"schema:shex": {
"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_viewer", // default viewer
"ng:a": "Define the rules for your data with SHEX",
"ng:o": "n:g:z:ontology_viewer", // default viewer
"ng:w": "n:g:z:ontology_editor", // default editor
"ng:x": {
"shex":true,
@ -426,13 +415,13 @@ export const official_classes = {
"ng:n": "Link",
"ng:a": "Link to a document. kept in Magic Carpet",
},
"plato/card": {
"plato:card": {
"ng:crdt": "Graph",
"ng:n": "Card",
"ng:a": "Card representation of a document",
"ng:o": "n:g:z:card",
},
"plato/pad": {
"plato:pad": {
"ng:crdt": "Graph",
"ng:n": "Pad",
"ng:a": "Pad representation of a document",
@ -445,62 +434,62 @@ export const official_classes = {
"ng:o": "n:g:z:compose:viewer",
"ng:w": "n:g:z:compose:editor",
},
"doc:diagram:mermaid" : {
"diagram:mermaid" : {
"ng:crdt": "YText",
"ng:n": "Diagram - Mermaid",
"ng:a": "Describe Diagrams with Mermaid",
"ng:compat": ["file:iana:application:vnd.mermaid"]
},
"doc:diagram:drawio" : {
"diagram:drawio" : {
"ng:crdt": "YXml",
"ng:n": "Diagram - DrawIo",
"ng:a": "Draw Diagrams with DrawIo",
"ng:compat": ["file:iana:application:vnd.jgraph.mxfile","file:iana:application:x-drawio"]
},
"doc:diagram:graphviz" : {
"diagram:graphviz" : {
"ng:crdt": "YText",
"ng:n": "Diagram - Graphviz",
"ng:a": "Describe Diagrams with Graphviz",
"ng:compat": ["file:iana:text:vnd.graphviz"]
},
"doc:diagram:excalidraw" : {
"diagram:excalidraw" : {
"ng:crdt": "Automerge",
"ng:n": "Diagram - Excalidraw",
"ng:a": "Collaborate on Diagrams with Excalidraw",
"ng:compat": ["file:iana:application:vnd.excalidraw+json"]
},
"doc:diagram:gantt" : { //https://github.com/frappe/gantt
"diagram:gantt" : { //https://github.com/frappe/gantt
"ng:crdt": "Automerge",
"ng:n": "Diagram - Gantt",
"ng:a": "Interactive gantt chart",
"ng:compat": []
},
"doc:diagram:flowchart" : { //https://github.com/adrai/flowchart.js
"diagram:flowchart" : { //https://github.com/adrai/flowchart.js
"ng:crdt": "YText",
"ng:n": "Diagram - Flowchart",
"ng:a": "flow chart diagrams",
"ng:compat": []
},
"doc:diagram:sequence" : { //https://github.com/bramp/js-sequence-diagrams
"diagram:sequence" : { //https://github.com/bramp/js-sequence-diagrams
"ng:crdt": "YText",
"ng:n": "Diagram - Sequence",
"ng:a": "sequence diagrams",
"ng:compat": []
},
// checkout https://www.mindmaps.app/ but it is AGPL
"doc:diagram:markmap" : { //https://github.com/markmap/markmap
"diagram:markmap" : { //https://github.com/markmap/markmap
"ng:crdt": "YText",
"ng:n": "Diagram - Markmap",
"ng:a": "mindmaps with markmap",
"ng:compat": []
},
"doc:diagram:mymind" : { //https://github.com/markmap/markmap
"diagram:mymind" : { //https://github.com/markmap/markmap
"ng:crdt": "YText", // see MyMind format, MindMup JSON, FreeMind XML and MindMap Architect XML
"ng:n": "Diagram - Mymind",
"ng:a": "mindmaps with mymind",
"ng:compat": [] // https://github.com/ondras/my-mind/wiki/Saving-and-loading#file-formats
},
"doc:diagram:jsmind" : { //https://github.com/hizzgdev/jsmind
"diagram:jsmind" : { //https://github.com/hizzgdev/jsmind
"ng:crdt": "Automerge",
"ng:n": "Diagram - jsmind",
"ng:a": "mindmaps with jsmind",
@ -514,69 +503,69 @@ export const official_classes = {
// https://github.com/Rich-Harris/pancake
// https://github.com/williamngan/pts
// https://visjs.org/
"doc:viz:cytoscape" : {
"viz:cytoscape" : {
"ng:crdt": "Automerge",
"ng:n": "Viz - Cytoscape",
"ng:a": "Graph theory (network) visualization",
"ng:compat": [] // https://github.com/cytoscape/cytoscape.js
},
"doc:viz:vega" : {
"viz:vega" : {
"ng:crdt": "Automerge",
"ng:n": "Viz - Vega",
"ng:a": "Grammar for interactive graphics",
"ng:compat": [] // https://vega.github.io/vega-lite/docs/ https://github.com/vega/editor
},
"doc:viz:vizzu" : {
"viz:vizzu" : {
"ng:crdt": "Automerge",
"ng:n": "Viz - Vizzu",
"ng:a": "Animated data visualizations and data stories",
"ng:compat": [] // https://github.com/vizzuhq/vizzu-lib
},
"doc:viz:plotly" : { //https://github.com/plotly/plotly.js
"viz:plotly" : { //https://github.com/plotly/plotly.js
"ng:crdt": "Automerge",
"ng:n": "Viz - Plotly",
"ng:a": "Declarative charts",
"ng:compat": [] // https://github.com/cytoscape/cytoscape.js
},
"doc:viz:avail" : {
"viz:avail" : {
"ng:crdt": "Automerge",
"ng:n": "Viz - Avail",
"ng:a": "Time Data Availability Visualization",
"ng:compat": [] // https://github.com/flrs/visavail
},
"doc:chart:frappecharts" : {
"chart:frappecharts" : {
"ng:crdt": "Automerge",
"ng:n": "Charts - Frappe",
"ng:a": "GitHub-inspired responsive charts",
"ng:compat": [] // https://github.com/frappe/charts
},
"doc:chart:financial" : {
"chart:financial" : {
"ng:crdt": "Automerge",
"ng:n": "Charts - Financial",
"ng:a": "Financial charts",
"ng:compat": [] //https://github.com/tradingview/lightweight-charts
},
// have a look at https://github.com/cube-js/cube and https://awesome.cube.dev/ and https://frappe.io/products
"doc:chart:apexcharts" : {
"chart:apexcharts" : {
"ng:crdt": "Automerge",
"ng:n": "Charts - ApexCharts",
"ng:a": "Interactive data visualizations",
"ng:compat": [] // https://github.com/apexcharts/apexcharts.js
},
//realtime data with https://github.com/square/cubism
"doc:chart:billboard" : {
"chart:billboard" : {
"ng:crdt": "Automerge",
"ng:n": "Charts - BillBoard",
"ng:a": "Interactive data visualizations based on D3",
"ng:compat": [] // https://github.com/naver/billboard.js
},
"doc:chart:echarts" : {
"chart:echarts" : {
"ng:crdt": "Automerge",
"ng:n": "Charts - ECharts",
"ng:a": "Interactive charting and data visualization with Apache ECharts",
"ng:compat": [] // https://github.com/apache/echarts
},
"doc:chart:chartjs" : {
"chart:chartjs" : {
"ng:crdt": "Automerge",
"ng:n": "Charts - Chart.js",
"ng:a": "Simple yet flexible charting for designers & developers with Chart.js",

@ -14,7 +14,7 @@
branch_subscribe,
active_session,
cannot_load_offline,
online,
open_doc_popup
} from "../store";
import {
@ -42,7 +42,7 @@
const inview_options = {};//{rootMargin: "-44px"};
function openEditHeader() {
//TODO
open_doc_popup("header");
}
</script>

@ -34,7 +34,6 @@
import BranchIcon from "./icons/BranchIcon.svelte";
import Message from "./components/Message.svelte";
import Signature from "./popups/Signature.svelte";
import {
get,
} from "svelte/store";
@ -47,11 +46,11 @@
has_editor_chat, all_files_count, all_comments_count, hideMenu, show_modal_menu, show_modal_create,
cur_tab_branch_nuri, cur_tab_doc_can_edit, cur_tab_doc_is_member, cur_tab_right_pane, cur_tab_folders_pane,
cur_tab_toc_pane, cur_tab_show_menu, cur_tab_branch_has_discrete, cur_tab_graph_or_discrete, cur_tab_view_or_edit, show_spinner,
in_private_store, show_doc_popup, cur_doc_popup, open_doc_popup } from "../tab";
in_private_store, show_doc_popup, cur_doc_popup } from "../tab";
import {
active_session, redirect_after_login, toasts, check_has_camera, toast_error,
reset_toasts, redirect_if_wallet_is, active_wallet,
display_error, openModalCreate
display_error, openModalCreate, open_doc_popup
} from "../store";
import ZeraIcon from "./icons/ZeraIcon.svelte";
import ng from "../api";
@ -300,33 +299,33 @@
];
const create_chart_items = [
"doc:chart:frappecharts",
"doc:chart:financial",
"doc:chart:apexcharts",
"doc:chart:billboard",
"doc:chart:echarts",
"doc:chart:chartjs",
"chart:frappecharts",
"chart:financial",
"chart:apexcharts",
"chart:billboard",
"chart:echarts",
"chart:chartjs",
];
const create_viz_items = [
"doc:viz:cytoscape",
"doc:viz:vega",
"doc:viz:vizzu",
"doc:viz:plotly",
"doc:viz:avail",
"viz:cytoscape",
"viz:vega",
"viz:vizzu",
"viz:plotly",
"viz:avail",
];
const create_diagram_items = [
"doc:diagram:mermaid",
"doc:diagram:drawio",
"doc:diagram:graphviz",
"doc:diagram:excalidraw",
"doc:diagram:gantt",
"doc:diagram:flowchart",
"doc:diagram:sequence",
"doc:diagram:markmap",
"doc:diagram:mymind",
"doc:diagram:jsmind",
"diagram:mermaid",
"diagram:drawio",
"diagram:graphviz",
"diagram:excalidraw",
"diagram:gantt",
"diagram:flowchart",
"diagram:sequence",
"diagram:markmap",
"diagram:mymind",
"diagram:jsmind",
];
const create_doc_items = [
@ -367,6 +366,19 @@
"app:n:xxx.xx.xx",
];
import Signature from "./popups/Signature.svelte";
import Header from "./popups/Header.svelte";
const doc_popups = {
"signature": Signature,
"header": Header,
}
const doc_popups_size = {
"signature": "xs",
"header": "md",
}
let top;
let shareMenu;
let toolsMenu;
@ -428,7 +440,7 @@
const openAction = (action:string) => {
hideMenu();
if (doc_popups[action]) open_doc_popup(action);
open_doc_popup(action);
}
const openPane = (pane:string) => {
@ -564,10 +576,6 @@
"mc":Sparkles,
};
const doc_popups = {
"signature": Signature,
}
let destination = "store";
$: destination = $cur_tab_branch_nuri === "" ? "mc" : destination == "mc" ? "store" : destination;
@ -755,7 +763,8 @@
{/if}
{#if $cur_tab_doc_can_edit}
<MenuItem title={$t("doc.menu.items.new_block.desc")} clickable={ ()=> openAction("new_block") }>
<!-- ()=> openAction("new_block") -->
<MenuItem title={$t("doc.menu.items.new_block.desc")} clickable={ undefined }>
<PlusCircle
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
@ -764,7 +773,8 @@
</MenuItem>
{/if}
{#if $has_editor_chat}
<MenuItem title={$t("doc.menu.items.editor_chat.desc")} selected={$cur_tab_right_pane == "chat"} clickable={ ()=> openPane("chat") }>
<!-- ()=> openPane("chat") -->
<MenuItem title={$t("doc.menu.items.editor_chat.desc")} selected={$cur_tab_right_pane == "chat"} clickable={ undefined }>
<Icon tabindex="-1" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" variation="outline" color="currentColor" icon={pane_items["chat"]} />
<span class="ml-3">{$t("doc.menu.items.editor_chat.label")}</span>
</MenuItem>
@ -794,14 +804,16 @@
</MenuItem>
{#if open_share }
{#each share_items as share}
<MenuItem title={$t(`doc.menu.items.${share.n}.desc`)} extraClass="submenu" clickable={ () => openShare(share.n) }>
<!-- () => openShare(share.n) -->
<MenuItem title={$t(`doc.menu.items.${share.n}.desc`)} extraClass="submenu" clickable={ undefined }>
<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}
{:else}
<MenuItem title={$t(`doc.menu.items.download.desc`)} clickable={ () => openShare("download") }>
<!-- () => openShare("download") -->
<MenuItem title={$t(`doc.menu.items.download.desc`)} clickable={ undefined }>
<Icon tabindex="-1" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white " variation="outline" color="currentColor" icon={DocumentArrowDown} />
<span class="ml-3">{$t(`doc.menu.items.download.label`)}</span>
</MenuItem>
@ -823,37 +835,37 @@
<Icon tabindex="-1" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" variation="outline" color="currentColor" icon={pane_items["history"]} />
<span class="ml-3">{$t("doc.menu.items.history.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.find.desc")} clickable={ find }>
<!-- find -->
<MenuItem title={$t("doc.menu.items.find.desc")} clickable={ undefined }>
<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 -->
<MenuItem title={$t("doc.menu.items.bookmark.desc")} clickable={ undefined }>
<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 }>
<!-- annotate -->
<MenuItem title={$t("doc.menu.items.annotate.desc")} clickable={ undefined }>
<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")} selected={$cur_tab_right_pane == "info"} clickable={ ()=> openPane("info") }>
<!-- ()=> openPane("info") -->
<MenuItem title={$t("doc.menu.items.info.desc")} selected={$cur_tab_right_pane == "info"} clickable={ undefined }>
<Icon tabindex="-1" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" variation="outline" color="currentColor" icon={pane_items["info"]} />
<span class="ml-3">{$t("doc.menu.items.info.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.notifs.desc")} clickable={ ()=> openAction("notifs") }>
<!-- ()=> openAction("notifs") -->
<MenuItem title={$t("doc.menu.items.notifs.desc")} clickable={ undefined }>
<Bell
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
@ -861,7 +873,8 @@
<span class="ml-3">{$t("doc.menu.items.notifs.label")}</span>
</MenuItem>
{#if $cur_tab_doc_is_member && !$in_private_store}
<MenuItem title={$t("doc.menu.items.permissions.desc")} clickable={ ()=> openAction("permissions") }>
<!-- ()=> openAction("permissions") -->
<MenuItem title={$t("doc.menu.items.permissions.desc")} clickable={ undefined }>
<LockOpen
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
@ -869,7 +882,8 @@
<span class="ml-3">{$t("doc.menu.items.permissions.label")}</span>
</MenuItem>
{/if}
<MenuItem title={$t("doc.menu.items.settings.desc")} clickable={ ()=> openAction("settings") }>
<!-- ()=> openAction("settings") -->
<MenuItem title={$t("doc.menu.items.settings.desc")} clickable={ undefined }>
<Cog6Tooth
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
@ -887,7 +901,8 @@
{#if open_tools }
{#each tools_items as tool}
{#if !$in_private_store || tool.n !== "signature" }
<MenuItem title={$t(`doc.menu.items.${tool.n}.desc`)} extraClass="submenu" clickable={ () => openAction(tool.n) }>
<!-- () => openAction(tool.n) -->
<MenuItem title={$t(`doc.menu.items.${tool.n}.desc`)} extraClass="submenu" clickable={ tool.n === "signature" ? () => openAction(tool.n) : undefined }>
<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>
@ -895,11 +910,13 @@
{/each}
{/if}
{/if}
<MenuItem title={$t("doc.menu.items.mc.desc")} selected={$cur_tab_right_pane == "mc"} clickable={ ()=> openPane("mc") }>
<!-- ()=> openPane("mc") -->
<MenuItem title={$t("doc.menu.items.mc.desc")} selected={$cur_tab_right_pane == "mc"} clickable={ undefined }>
<Icon tabindex="-1" class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white" variation="outline" color="currentColor" icon={pane_items["mc"]} />
<span class="ml-3">{$t("doc.menu.items.mc.label")}</span>
</MenuItem>
<MenuItem title={$t("doc.menu.items.archive.desc")} clickable={ ()=> openArchive() }>
<!-- ()=> openArchive() -->
<MenuItem title={$t("doc.menu.items.archive.desc")} clickable={ undefined }>
<ArchiveBox
tabindex="-1"
class="w-7 h-7 text-gray-700 focus:outline-none dark:text-white"
@ -945,12 +962,12 @@
<Modal class="document-popup"
outsideclose
bind:open={$show_doc_popup}
size = 'xs'
size = {doc_popups_size[$cur_doc_popup]}
placement = 'center'
defaultClass="bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-400 rounded-lg border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md relative flex flex-col mx-auto w-full"
backdropClass="bg-gray-900 bg-opacity-50 dark:bg-opacity-80 popup-bg-modal"
>
<svelte:component this={doc_popups[$cur_doc_popup]}/>
{#if doc_popups[$cur_doc_popup]}<svelte:component this={doc_popups[$cur_doc_popup]}/>{/if}
</Modal>
<Modal class="menu-modal"
outsideclose
@ -1121,7 +1138,7 @@
<div style="padding:0;" bind:this={createMenu.chart}></div>
<MenuItem title={$t("doc.chart")} dropdown={createMenuOpened.chart} clickable={ () => { createMenuOpened.chart = !createMenuOpened.chart; scrollToCreateMenu("chart"); } }>
<DataClassIcon dataClass="doc:chart" {config}/>
<DataClassIcon dataClass="chart" {config}/>
<span class="ml-3">{$t("doc.chart")}</span>
</MenuItem>
{#if createMenuOpened.chart }
@ -1136,7 +1153,7 @@
<div style="padding:0;" bind:this={createMenu.viz}></div>
<MenuItem title={$t("doc.viz")} dropdown={createMenuOpened.viz} clickable={ () => { createMenuOpened.viz = !createMenuOpened.viz; scrollToCreateMenu("viz"); } }>
<DataClassIcon dataClass="doc:viz" {config}/>
<DataClassIcon dataClass="viz" {config}/>
<span class="ml-3">{$t("doc.viz")}</span>
</MenuItem>
{#if createMenuOpened.viz }
@ -1151,7 +1168,7 @@
<div style="padding:0;" bind:this={createMenu.diagram}></div>
<MenuItem title={$t("doc.diagram")} dropdown={createMenuOpened.diagram} clickable={ () => { createMenuOpened.diagram = !createMenuOpened.diagram; scrollToCreateMenu("diagram"); } }>
<DataClassIcon dataClass="doc:diagram" {config}/>
<DataClassIcon dataClass="diagram" {config}/>
<span class="ml-3">{$t("doc.diagram")}</span>
</MenuItem>
{#if createMenuOpened.diagram }

@ -116,8 +116,8 @@
"e:link": Link,
"mc:text": Bars3BottomLeft,
"mc:link": Link,
"plato/card": Clipboard,
"plato/pad": Square2Stack,
"plato:card": Clipboard,
"plato:pad": Square2Stack,
"media:image": Photo,
"media:reel": VideoCamera,
"media:video": Film,
@ -171,9 +171,9 @@
"app:": StopCircle,
"query:": RocketLaunch,
"data:": CircleStack,
"doc:diagram": DocumentChartBar,
"doc:chart": ChartPie,
"doc:viz": ArrowTrendingUp,
"diagram": DocumentChartBar,
"chart": ChartPie,
"viz": ArrowTrendingUp,
"doc:": ClipboardDocumentList,
file: Document,
};

@ -0,0 +1,70 @@
<!--
// 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">
import {
branch_subscribe,
active_session,
toast_error,
toast_success,
display_error,
online,
change_header
} from "../../store";
import {
cur_tab,
show_doc_popup
} from "../../tab";
import { get } from "svelte/store";
import { onMount, onDestroy, tick } from "svelte";
import ng from "../../api";
import { t } from "svelte-i18n";
import {
CheckCircle
} from "svelte-heros-v2";
import {
} from "flowbite-svelte";
let is_tauri = import.meta.env.TAURI_PLATFORM;
onMount(()=>{
title = $cur_tab.doc.title;
about = $cur_tab.doc.description;
});
async function update_header() {
await change_header(title,about);
$show_doc_popup = false;
}
let title;
let about;
</script>
<div class="flex flex-col">
<span class="font-bold text-xl mb-3">{$t("doc.header.buttons.edit_intro")}</span>
{$t("doc.header.doc.title")} :
<input placeholder="Enter the title of the document" bind:value={title} class="mb-3"/>
{$t("doc.header.doc.about")} :
<textarea rows=6 class="my-4 col-span-6 pr-11 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Enter the introduction" bind:value={about}/>
<button
style="width:120px;"
on:click|once={update_header}
class="mt-4 text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-700/50 font-medium rounded-lg text-lg px-3 py-2.5 text-center inline-flex items-center dark:focus:ring-primary-700/55 mb-2"
>
<CheckCircle class="w-8 h-8 mr-3"/>
{$t("doc.header.buttons.save")}
</button>
</div>

@ -21,7 +21,7 @@
"chart": "Chart",
"viz": "Visualization",
"diagram": "Diagram",
"other": "Other file formats",
"other": "Other formats",
"data": "Data",
"code": "Code",
"apps": "Apps",
@ -71,7 +71,16 @@
"groups": "Groups",
"channels": "Channels",
"inbox": "Inbox",
"chat": "Chat"
"chat": "Chat",
"save": "Save"
},
"doc":{
"title": "Title",
"about": "Introduction"
},
"profile": {
"title": "Name",
"about": "Bio"
}
},
"signature": {

@ -357,7 +357,7 @@
{/if}
<!-- Remove Wallet -->
<li
<!-- <li
tabindex="0"
role="menuitem"
class="text-left flex items-center p-2 text-base font-normal text-gray-900 clickable rounded-lg dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700"
@ -372,7 +372,7 @@
</div>
<span class="ml-3">{$t("pages.wallet_info.remove_wallet")}</span
>
</li>
</li> -->
<!-- Confirm Remove Wallet Modal -->
<Modal
autoclose

@ -147,6 +147,9 @@
async function gotWallet(event) {
try {
if (importing) {
step = "loggedin";
$redirect_after_login=undefined;
$redirect_if_wallet_is=undefined;
let in_memory = !event.detail.trusted;
//console.log("IMPORTING", in_memory, event.detail.wallet, wallet);
let client = await ng.wallet_import(
@ -188,6 +191,7 @@
if (importing) {wallet = undefined;}
importing = false;
error = e;
step = "open";
return;
}
//await tick();
@ -252,6 +256,25 @@
{$t("buttons.start_over")}
</button>
</div>
{:else if step == "loggedin"}
<div class=" max-w-6xl lg:px-8 mx-auto px-4 text-green-800">
{@html $t("pages.wallet_login.logged_in")}...
<svg
class="my-10 h-16 w-16 mx-auto"
fill="none"
stroke="currentColor"
stroke-width="1.5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M9 12.75L11.25 15 15 9.75M21 12c0 1.268-.63 2.39-1.593 3.068a3.745 3.745 0 01-1.043 3.296 3.745 3.745 0 01-3.296 1.043A3.745 3.745 0 0112 21c-1.268 0-2.39-.63-3.068-1.593a3.746 3.746 0 01-3.296-1.043 3.745 3.745 0 01-1.043-3.296A3.745 3.745 0 013 12c0-1.268.63-2.39 1.593-3.068a3.745 3.745 0 011.043-3.296 3.746 3.746 0 013.296-1.043A3.746 3.746 0 0112 3c1.268 0 2.39.63 3.068 1.593a3.746 3.746 0 013.296 1.043 3.746 3.746 0 011.043 3.296A3.745 3.745 0 0121 12z"
/>
</svg>
</div>
{:else if $wallet_from_import}
<!-- Imported a wallet -->
@ -437,25 +460,6 @@
</a>
</div>
</div>
{:else if step == "loggedin"}
<div class=" max-w-6xl lg:px-8 mx-auto px-4 text-green-800">
{@html $t("pages.wallet_login.logged_in")}...
<svg
class="my-10 h-16 w-16 mx-auto"
fill="none"
stroke="currentColor"
stroke-width="1.5"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M9 12.75L11.25 15 15 9.75M21 12c0 1.268-.63 2.39-1.593 3.068a3.745 3.745 0 01-1.043 3.296 3.745 3.745 0 01-3.296 1.043A3.745 3.745 0 0112 21c-1.268 0-2.39-.63-3.068-1.593a3.746 3.746 0 01-3.296-1.043 3.745 3.745 0 01-1.043-3.296A3.745 3.745 0 013 12c0-1.268.63-2.39 1.593-3.068a3.745 3.745 0 011.043-3.296 3.746 3.746 0 013.296-1.043A3.746 3.746 0 0112 3c1.268 0 2.39.63 3.068 1.593a3.746 3.746 0 013.296 1.043 3.746 3.746 0 011.043 3.296A3.745 3.745 0 0121 12z"
/>
</svg>
</div>
{/if}
</CenteredLayout>
</div>

@ -17,7 +17,7 @@ import {
} from "svelte/store";
import { register, init, locale, format } from "svelte-i18n";
import ng from "./api";
import { persistent_error, update_class, update_branch_display, open_branch, tab_update, change_nav_bar, cur_branch, cur_tab, show_modal_create, save, nav_bar,in_memory_save } from "./tab";
import { persistent_error, update_class, update_branch_display, open_branch, tab_update, change_nav_bar, cur_branch, cur_tab, show_modal_create, save, nav_bar,in_memory_save, cur_doc_popup, show_doc_popup } from "./tab";
import { encode } from "./base64url";
let all_branches = {};
@ -423,6 +423,43 @@ export const discrete_update = async (update, crdt, heads) => {
// the editor then process those updates and calls live_discrete_update
}
export const open_doc_popup = async (popup_name) => {
await reset_toasts();
cur_doc_popup.set(popup_name);
show_doc_popup.set(true);
}
export const change_header = async (title_, about_) => {
let session = get(active_session);
if (!session) {
persistent_error(get(cur_branch), {
title: get(format)("doc.errors.no_session"),
desc: get(format)("doc.errors_details.no_session")
});
throw new Error("no session");
}
let nuri = "did:ng:"+get(cur_tab).doc.nuri+":"+get(cur_tab).store.overlay;
let title = undefined;
let about = undefined;
if ( get(cur_tab).doc.title != title_ ) {
title = title_;
}
if ( get(cur_tab).doc.description != about_ ) {
about = about_;
}
if (title === undefined && about === undefined) {
//console.log("identical");
return;
}
try {
await ng.update_header(session.session_id, nuri, title, about);
}
catch (e) {
toast_error(display_error(e));
}
}
export const live_discrete_update = async (update, crdt, heads) => {
// send directly to verifier with AppRequest Update
let session = get(active_session);
@ -552,7 +589,7 @@ export const branch_subscribe = function(nuri:string, in_tab:boolean) {
req.V0.session_id = session.session_id;
unsub = await ng.app_request_stream(req,
async (response) => {
//console.log("GOT APP RESPONSE", response);
console.log("GOT APP RESPONSE", response);
if (response.V0.TabInfo) {
tab_update(nuri, ($cur_tab) => {
if (response.V0.TabInfo.branch?.id) {
@ -568,15 +605,21 @@ export const branch_subscribe = function(nuri:string, in_tab:boolean) {
if (response.V0.TabInfo.doc?.nuri) {
$cur_tab.doc.nuri = response.V0.TabInfo.doc.nuri;
}
if (response.V0.TabInfo.doc?.can_edit) {
if (typeof response.V0.TabInfo.doc?.can_edit === "boolean" ) {
$cur_tab.doc.can_edit = response.V0.TabInfo.doc.can_edit;
}
if (response.V0.TabInfo.doc?.is_store) {
if (typeof response.V0.TabInfo.doc?.is_store === "boolean") {
$cur_tab.doc.is_store = response.V0.TabInfo.doc.is_store;
}
if (response.V0.TabInfo.doc?.is_member) {
$cur_tab.doc.is_member = response.V0.TabInfo.doc.is_member;
}
if (response.V0.TabInfo.doc?.title !== undefined && response.V0.TabInfo.doc?.title !== null) {
$cur_tab.doc.title = response.V0.TabInfo.doc.title;
}
if (response.V0.TabInfo.doc?.description !== undefined && response.V0.TabInfo.doc?.description !== null) {
$cur_tab.doc.description = response.V0.TabInfo.doc.description;
}
if (response.V0.TabInfo.store?.overlay) {
$cur_tab.store.overlay = response.V0.TabInfo.store.overlay;
}
@ -643,13 +686,17 @@ export const branch_subscribe = function(nuri:string, in_tab:boolean) {
onUpdate(response.V0.Patch.discrete);
}
if (response.V0.Patch.graph) {
//console.log(response.V0.Patch.graph)
let duplicates = [];
for (let i = 0; i < old.graph.length; i++) {
if (response.V0.Patch.graph.inserts.includes(old.graph[i])) {
duplicates.push(old.graph[i])
} else
if (response.V0.Patch.graph.removes.includes(old.graph[i])) {//TODO: optimization: remove this triple from the removes list.
old.graph.splice(i, 1);
} else {
//console.log("remove?", i, old.graph[i], JSON.stringify(old.graph))
if (response.V0.Patch.graph.removes.includes(old.graph[i])) {//TODO: optimization: remove this triple from the removes list.
old.graph.splice(i, 1);
//console.log("yes",JSON.stringify(old.graph))
}
}
}
for (const insert of response.V0.Patch.graph.inserts){

@ -220,13 +220,17 @@ td.hljs {
.container3 {
margin: 0;
min-width: 280px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.container3 aside {
width: 20rem !important;
}
div[role="alert"] div {
display: block;
}

@ -208,11 +208,6 @@ export const show_doc_popup = writable(false);
export const cur_doc_popup = writable("");
export const show_modal_create = writable(false);
export const open_doc_popup = (popup_name) => {
cur_doc_popup.set(popup_name);
show_doc_popup.set(true);
}
export const in_memory_graph = writable("");
export const in_memory_discrete = writable("");
@ -351,7 +346,7 @@ export const cur_branch = writable("");
export const cur_tab = derived([cur_branch, all_tabs], ([cb, all]) => {return all[cb];});
export const can_have_header = derived(cur_tab, ($cur_tab) => {
return !($cur_tab.doc.is_store && ( $cur_tab.store.store_type === "private" || $cur_tab.store.store_type === "dialog"));
return !($cur_tab.doc.is_store); // && ( $cur_tab.store.store_type === "private" || $cur_tab.store.store_type === "dialog"));
});
export const cur_tab_branch_nuri = derived(cur_tab, ($cur_tab) => {
return $cur_tab.branch.nuri;

@ -210,16 +210,16 @@ export const official_apps = {
"ng:g": "n:g:z:ontology_editor",
"ng:b": "JsonLdEditor",
"ng:o": [],
"ng:w": ["schema:*"],
"ng:w": ["schema*"],
},
"n:g:z:owl_viewer": {
"ng:n": "OWL Ontology",
"n:g:z:ontology_viewer": {
"ng:n": "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",
"ng:b": "OwlViewer", // display with https://github.com/VisualDataWeb/WebVOWL
"ng:o": ["schema:owl"],
"ng:g": "n:g:z:ontology_viewer",
"ng:b": "OntologyViewer", // display with https://github.com/VisualDataWeb/WebVOWL
"ng:o": ["schema*"],
"ng:w": [],
},
"n:g:z:sparql:invoke": { // displayed with highlight.js https://github.com/highlightjs/highlightjs-turtle/tree/master
@ -313,7 +313,7 @@ export const official_apps = {
"ng:u": "source",//favicon. can be a did:ng:j
"ng:g": "n:g:z:crdt_source_viewer:xml",
"ng:b": "XmlSource", // displayed with highlight.js , with option to download
"ng:o": ["post:rich","post:md","post:html","page","data:xml", "doc:diagram:drawio"],
"ng:o": ["post:rich","post:md","post:html","page","data:xml", "diagram:drawio"],
"ng:w": [],
implemented: true,
},
@ -335,7 +335,7 @@ export const official_apps = {
"ng:u": "source",//favicon. can be a did:ng:j
"ng:g": "n:g:z:crdt_source_viewer:json",
"ng:b": "AutomergeJsonSource", // displayed with highlight.js , with option to download
"ng:o": ["data:json", "data:table", "doc:diagram:jsmind", "doc:diagram:gantt", "doc:diagram:excalidraw", "doc:viz:*", "doc:chart:*", "prod:cad"],
"ng:o": ["data:json", "data:table", "diagram:jsmind", "diagram:gantt", "diagram:excalidraw", "viz:*", "chart:*", "prod:cad"],
"ng:w": [],
"full_width": true,
implemented: true,
@ -369,8 +369,8 @@ export const official_apps = {
"ng:u": "source",//favicon. can be a did:ng:j
"ng:g": "n:g:z:crdt_source_viewer:text",
"ng:b": "TextViewer", // displayed with highlight.js , with option to download and copy paste
"ng:o": ["post:asciidoc", "service*", "contract", "query:sparql*","query:graphql","doc:diagram:mermaid","doc:diagram:graphviz","doc:diagram:flowchart",
"doc:diagram:sequence","doc:diagram:markmap","doc:diagram:mymind","doc:music*", "doc:maths", "doc:chemistry", "doc:ancientscript", "doc:braille", "media:subtitle"],
"ng:o": ["post:asciidoc", "service*", "contract", "query:sparql*","query:graphql","diagram:mermaid","diagram:graphviz","diagram:flowchart",
"diagram:sequence","diagram:markmap","diagram:mymind","doc:music*", "doc:maths", "doc:chemistry", "doc:ancientscript", "doc:braille", "media:subtitle"],
"ng:w": [],
implemented: true,
},
@ -454,7 +454,7 @@ export const official_apps = {
"ng:u": "pad",//favicon. can be a did:ng:j
"ng:g": "n:g:z:pad",
"ng:b": "Pad",
"ng:o": ["plato/pad"],
"ng:o": ["plato:pad"],
"ng:w": [],
},
"n:g:z:card": {
@ -464,7 +464,7 @@ export const official_apps = {
"ng:u": "card",//favicon. can be a did:ng:j
"ng:g": "n:g:z:card",
"ng:b": "Card",
"ng:o": ["plato/card"],
"ng:o": ["plato:card"],
"ng:w": [],
},
"n:g:z:gallery": {
@ -673,7 +673,7 @@ export const official_services = {