diff --git a/.gitignore b/.gitignore index 33d7186..f1e389f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ node_modules */tests/*.mnemonic */ng-example/* .vscode/settings.json +.env.local diff --git a/Cargo.lock b/Cargo.lock index 4b1ef7d..f550fea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3290,6 +3290,7 @@ dependencies = [ "serde", "serde_bytes", "serde_json", + "sys-locale", "tauri", "tauri-build", "tauri-plugin-window", @@ -3408,7 +3409,7 @@ dependencies = [ "serde", "sha1", "sha2 0.10.8", - "siphasher 0.3.10", + "siphasher 1.0.1", "thiserror", "zstd", ] @@ -3449,7 +3450,7 @@ dependencies = [ [[package]] name = "ng-rocksdb" version = "0.21.0-ngpreview.4" -source = "git+https://git.nextgraph.org/NextGraph/rust-rocksdb.git?branch=master#e566341c319eead6637b1aecce5e92136e946ae5" +source = "git+https://git.nextgraph.org/NextGraph/rust-rocksdb.git?branch=master#f1ce2e345f3d729350a02bcffb47c526674edd85" dependencies = [ "bindgen", "bzip2-sys", @@ -3482,6 +3483,7 @@ dependencies = [ "serde_bare", "serde_bytes", "serde_json", + "sys-locale", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test", @@ -5352,6 +5354,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "sys-locale" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" +dependencies = [ + "js-sys", + "libc", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "system-configuration" version = "0.6.0" diff --git a/Cargo.toml b/Cargo.toml index bc843f9..aaca5cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,9 @@ documentation = "https://docs.nextgraph.org/" lto = true opt-level = 's' +[profile.dev] +opt-level = 2 + [patch.crates-io] # tauri = { git = "https://github.com/simonhyll/tauri.git", branch="fix/ipc-mixup"} # tauri = { git = "https://git.nextgraph.org/NextGraph/tauri.git", branch="alpha.11-nextgraph", features = ["no-ipc-custom-protocol"] } diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine new file mode 100644 index 0000000..c77517c --- /dev/null +++ b/docker/Dockerfile.alpine @@ -0,0 +1,36 @@ +# Use rust's latest alpine image as base image. +FROM rust:alpine + +ENV LD_LIBRARY_PATH=/lib:$LD_LIBRARY_PATH + +RUN apk add git nodejs npm llvm-static llvm-dev clang-static clang-dev openssl openssl-dev perl gtk+3.0-dev webkit2gtk-dev librsvg-dev curl wget pkgconf eudev-dev build-base zlib-static bzip2-static build-base ncursers-static && \ + # Install Rust and Node.js tools + cargo install cargo-watch && \ + cargo install wasm-pack --git https://github.com/rustwasm/wasm-pack.git --rev c2b663f25abe50631a236d57a8c6d7fd806413b2 && \ + cargo install tauri-cli --version "2.0.0-alpha.11" --locked && \ + npm install -g pnpm + +# Clone the nextgraph-rs repository +RUN git clone https://git.nextgraph.org/NextGraph/nextgraph-rs.git && \ + cd /nextgraph-rs/ng-sdk-js && \ + wasm-pack build --target bundler && npm install --no-save pkg && + # Build ng-app web version + cd /nextgraph-rs/ng-app && pnpm install && pnpm webfilebuild + +# From here the build fails due to llvm / clang linking issues... +# +# WORKDIR /nextgraph-rs +## Build the nextgraph-rs project and its subprojects +# RUN cd /nextgraph-rs && git pull && cargo update -p ng-rocksdb && \ +# cargo build -r && \ +# cargo build -r -p ngd && \ +# cargo build -r -p ngcli + +# TODO: Build the platform-specific ng-app versions +# cd /nextgraph-rs/ng-app && cargo tauri build --target x86_64-unknown-linux-gnu +# ... + +# TODO: To remove the image size, remove ~/.cargo, ~/.rustup, and the build dependencies + +# To build the image, run: +# docker build -t nextgraph-rs:alpine -f docker/Dockerfile.alpine . diff --git a/docker/Dockerfile.fedora b/docker/Dockerfile.fedora new file mode 100644 index 0000000..c8b65d8 --- /dev/null +++ b/docker/Dockerfile.fedora @@ -0,0 +1,46 @@ +# Use fedora:40 as base image +FROM fedora:40 + +# Set the environment variable to ensure cargo is available in the PATH +ENV PATH="/root/.cargo/bin:${PATH}" +SHELL ["/bin/bash", "-c"] + +# Install the required packages and Rust + +RUN dnf install -y git clang-devel webkit2gtk4.1-devel openssl openssl-devel curl wget file libappindicator-gtk3-devel librsvg2-devel perl && \ + dnf group install -y "C Development Tools and Libraries" && \ + # Rust + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y && \ + # Node.js + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash && \ + export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" && \ + nvm install 22 && \ + npm install -g pnpm && \ + # Clear Cache + rm -rf /var/cache/dnf && \ + # Install Rust and Node.js tools + cargo install cargo-watch && \ + cargo install wasm-pack --git https://github.com/rustwasm/wasm-pack.git --rev c2b663f25abe50631a236d57a8c6d7fd806413b2 && \ + cargo install tauri-cli --version "2.0.0-alpha.11" --locked && \ + # Clone the nextgraph-rs repository (TODO: It might be better to put this into a seperate RUN command to avoid rebuilding the image if the repository changes) + git clone https://git.nextgraph.org/NextGraph/nextgraph-rs.git && \ + # Build sdk and ng-app web version + cd /nextgraph-rs/ng-sdk-js && wasm-pack build --target bundler && npm install --no-save pkg && \ + cd /nextgraph-rs/ng-app && pnpm install && pnpm webfilebuild + +# Build the nextgraph-rs project +RUN export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" && \ + cd /nextgraph-rs && git pull && cargo update -p ng-rocksdb && \ + cargo build -r && \ + cargo build -r -p ngd && \ + cargo build -r -p ngcli + + +# TODO: Build the platform-specific ng-app versions +# cd /nextgraph-rs/ng-app && cargo tauri build --target x86_64-unknown-linux-gnu +# ... + +# TODO: To remove the image size, remove ~/.cargo, ~/.rustup, and the build dependencies + +# To build the image, run: +# docker build -t nextgraph-rs:fedora -f docker/Dockerfile.fedora . diff --git a/docker/Dockerfile.ubuntu b/docker/Dockerfile.ubuntu new file mode 100644 index 0000000..60deb3e --- /dev/null +++ b/docker/Dockerfile.ubuntu @@ -0,0 +1,47 @@ +# Use ubuntu 22.04 as base image +FROM ubuntu:22.04 + +SHELL ["/bin/bash", "-c"] + +# Set the environment variable to ensure cargo is available in the PATH +ENV PATH="/root/.cargo/bin:${PATH}" + +# Install the required packages and Rust +RUN apt update && \ + apt upgrade -y && \ + apt install -y git llvm-dev libclang-dev clang libssl-dev perl libappindicator3-dev libwebkit2gtk-4.0-dev librsvg2-dev curl wget pkg-config libudev-dev build-essential && \ + rm -rf /var/cache/apt && \ + # Rust + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \ + # Node.js + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash && \ + export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" && \ + nvm install 22 && \ + npm install -g pnpm && \ + # Install Rust and Node.js tools + cargo install cargo-watch && \ + cargo install wasm-pack --git https://github.com/rustwasm/wasm-pack.git --rev c2b663f25abe50631a236d57a8c6d7fd806413b2 && \ + cargo install tauri-cli --version "2.0.0-alpha.11" --locked && \ + npm install -g pnpm && \ + # Clone the nextgraph-rs repository (TODO: It might be better to put this into a seperate RUN command to avoid rebuilding the image if the repository changes) + git clone https://git.nextgraph.org/NextGraph/nextgraph-rs.git && \ + # Build sdk and ng-app web version + cd /nextgraph-rs/ng-sdk-js && wasm-pack build --target bundler && npm install --no-save pkg && \ + cd /nextgraph-rs/ng-app && \ + pnpm install && pnpm webfilebuild + +# Build the nextgraph-rs project and its subprojects +WORKDIR /nextgraph-rs +RUN cargo build -r && \ + cargo build -r -p ngd && \ + cargo build -r -p ngcli + + +# TODO: Build the platform-specific ng-app versions +# WORKDIR /nextgraph-rs/ng-app +# RUN cargo tauri build --target x86_64-unknown-linux-gnu + +# TODO: To remove the image size, remove ~/.cargo, ~/.rustup, and the build dependencies + +# To build the image, run: +# docker build -t nextgraph-rs:ubuntu -f docker/Dockerfile.ubuntu . diff --git a/nextgraph/src/local_broker.rs b/nextgraph/src/local_broker.rs index 79725c0..edf7e60 100644 --- a/nextgraph/src/local_broker.rs +++ b/nextgraph/src/local_broker.rs @@ -40,6 +40,7 @@ use ng_verifier::types::*; use ng_verifier::verifier::Verifier; use ng_wallet::emojis::encode_pazzle; +use ng_wallet::bip39::encode_mnemonic; use ng_wallet::{create_wallet_first_step_v0, create_wallet_second_step_v0, types::*}; #[cfg(not(target_family = "wasm"))] @@ -1555,6 +1556,27 @@ pub fn wallet_open_with_pazzle( Ok(opened_wallet) } +#[doc(hidden)] +/// This is a bit hard to use as the mnemonic words are encoded in u16. +/// prefer the function wallet_open_with_mnemonic_words +pub fn wallet_open_with_mnemonic( + wallet: &Wallet, + mnemonic: Vec, + pin: [u8; 4], +) -> Result { + if mnemonic.len() != 12 { + return Err(NgError::InvalidMnemonic); + } + // Convert from vec to array. + let mut mnemonic_arr = [0u16; 12]; + for (place, element) in mnemonic_arr.iter_mut().zip(mnemonic.iter()) { + *place = *element; + } + let opened_wallet = ng_wallet::open_wallet_with_mnemonic(wallet, mnemonic_arr, pin)?; + + Ok(opened_wallet) +} + /// Opens a wallet by providing an ordered list of words, and the pin. /// /// If you are opening a wallet that is already known to the LocalBroker, you must then call [wallet_was_opened]. @@ -1569,6 +1591,21 @@ pub fn wallet_open_with_pazzle_words( wallet_open_with_pazzle(wallet, encode_pazzle(pazzle_words)?, pin) } + +/// Opens a wallet by providing an ordered list of mnemonic words, and the pin. +/// +/// If you are opening a wallet that is already known to the LocalBroker, you must then call [wallet_was_opened]. +/// Otherwise, if you are importing, then you must call [wallet_import]. +pub fn wallet_open_with_mnemonic_words( + wallet: &Wallet, + mnemonic: &Vec, + pin: [u8; 4], +) -> Result { + let encoded: Vec = encode_mnemonic(mnemonic)?; + + wallet_open_with_mnemonic(wallet, encoded, pin) +} + /// Imports a wallet into the LocalBroker so the user can then access its content. /// /// the wallet should have been previous opened with [wallet_open_with_pazzle_words]. diff --git a/ng-app/src-tauri/Cargo.toml b/ng-app/src-tauri/Cargo.toml index 8db8c84..0c9ba1a 100644 --- a/ng-app/src-tauri/Cargo.toml +++ b/ng-app/src-tauri/Cargo.toml @@ -27,7 +27,8 @@ tauri-build = { version = "2.0.0-alpha.8", features = [] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_bytes = "0.11.7" -async-std = { version = "1.12.0", features = ["attributes", "unstable"] } +async-std = { version = "1.12.0", features = ["attributes", "unstable"] } +sys-locale = { version = "0.3.1" } ng-async-tungstenite = { git = "https://git.nextgraph.org/NextGraph/async-tungstenite.git", branch = "nextgraph", features = ["async-std-runtime", "async-native-tls"] } tauri = { version = "2.0.0-alpha.14", features = [] } tauri-plugin-window = "2.0.0-alpha.1" diff --git a/ng-app/src-tauri/gen/android/buildSrc/src/main/java/org/nextgraph/ng_app_native/kotlin/BuildTask.kt b/ng-app/src-tauri/gen/android/buildSrc/src/main/java/org/nextgraph/ng_app_native/kotlin/BuildTask.kt index c5a8b39..5c71d63 100644 --- a/ng-app/src-tauri/gen/android/buildSrc/src/main/java/org/nextgraph/ng_app_native/kotlin/BuildTask.kt +++ b/ng-app/src-tauri/gen/android/buildSrc/src/main/java/org/nextgraph/ng_app_native/kotlin/BuildTask.kt @@ -16,7 +16,8 @@ open class BuildTask : DefaultTask() { @TaskAction fun assemble() { - val executable = """/Users/nl/.cargo/bin/cargo-tauri"""; + val homePath = System.getProperty("user.home"); + val executable = "$homePath/.cargo/bin/cargo-tauri"; try { runTauriCli(executable) } catch (e: Exception) { diff --git a/ng-app/src-tauri/src/lib.rs b/ng-app/src-tauri/src/lib.rs index 8a28099..e5684af 100644 --- a/ng-app/src-tauri/src/lib.rs +++ b/ng-app/src-tauri/src/lib.rs @@ -13,6 +13,7 @@ use std::fs::write; use async_std::stream::StreamExt; use serde::{Deserialize, Serialize}; use serde_json::Value; +use sys_locale::get_locales; use tauri::scope::ipc::RemoteDomainAccessScope; use tauri::utils::config::WindowConfig; use tauri::{path::BaseDirectory, App, Manager}; @@ -38,6 +39,27 @@ pub use mobile::*; pub type SetupHook = Box Result<(), Box> + Send>; +#[tauri::command(rename_all = "snake_case")] +async fn locales() -> Result, ()> { + Ok(get_locales() + .filter_map(|lang| { + if lang == "C" || lang == "c" { + None + } else { + let mut split = lang.split('.'); + let code = split.next().unwrap(); + let code = code.replace("_", "-"); + let mut split = code.rsplitn(2, '-'); + let country = split.next().unwrap(); + Some(match split.next() { + Some(next) => format!("{}-{}", next, country.to_uppercase()), + None => country.to_string(), + }) + } + }) + .collect()) +} + #[tauri::command(rename_all = "snake_case")] async fn test(app: tauri::AppHandle) -> Result<(), ()> { let path = app @@ -86,6 +108,30 @@ async fn wallet_open_with_pazzle( Ok(wallet) } +#[tauri::command(rename_all = "snake_case")] +async fn wallet_open_with_mnemonic( + wallet: Wallet, + mnemonic: Vec, + pin: [u8; 4], + _app: tauri::AppHandle, +) -> Result { + let wallet = nextgraph::local_broker::wallet_open_with_mnemonic(&wallet, mnemonic, pin) + .map_err(|e| e.to_string())?; + Ok(wallet) +} + +#[tauri::command(rename_all = "snake_case")] +async fn wallet_open_with_mnemonic_words( + wallet: Wallet, + mnemonic_words: Vec, + pin: [u8; 4], + _app: tauri::AppHandle, +) -> Result { + let wallet = nextgraph::local_broker::wallet_open_with_mnemonic_words(&wallet, &mnemonic_words, pin) + .map_err(|e| e.to_string())?; + Ok(wallet) +} + #[tauri::command(rename_all = "snake_case")] async fn wallet_get_file(wallet_name: String, app: tauri::AppHandle) -> Result<(), String> { let ser = nextgraph::local_broker::wallet_get_file(&wallet_name) @@ -490,9 +536,12 @@ impl AppBuilder { .plugin(tauri_plugin_window::init()) .invoke_handler(tauri::generate_handler![ test, + locales, wallet_gen_shuffle_for_pazzle_opening, wallet_gen_shuffle_for_pin, wallet_open_with_pazzle, + wallet_open_with_mnemonic, + wallet_open_with_mnemonic_words, wallet_was_opened, wallet_create, wallet_read_file, diff --git a/ng-app/src/App.svelte b/ng-app/src/App.svelte index 82d63c4..e757fb3 100644 --- a/ng-app/src/App.svelte +++ b/ng-app/src/App.svelte @@ -19,19 +19,20 @@ active_session, close_active_session, disconnections_subscribe, + select_default_lang, } from "./store"; import Home from "./routes/Home.svelte"; import Test from "./routes/Test.svelte"; - import URI from "./routes/URI.svelte"; + import NURI from "./routes/NURI.svelte"; import NotFound from "./routes/NotFound.svelte"; import WalletCreate from "./routes/WalletCreate.svelte"; import Invitation from "./routes/Invitation.svelte"; import WalletLogin from "./routes/WalletLogin.svelte"; import User from "./routes/User.svelte"; import UserRegistered from "./routes/UserRegistered.svelte"; - import Install from "./lib/Install.svelte"; + import Install from "./routes/Install.svelte"; import ng from "./api"; @@ -44,7 +45,7 @@ routes.set("/user", User); routes.set("/user/registered", UserRegistered); if (import.meta.env.NG_APP_WEB) routes.set("/install", Install); - routes.set(/^\/ng(.*)/i, URI); + routes.set(/^\/did:ng(.*)/i, NURI); routes.set("*", NotFound); let unsubscribe = () => {}; @@ -60,7 +61,9 @@ onMount(async () => { try { await disconnections_subscribe(); + await select_default_lang(); } catch (e) { + console.error(e); //console.log("called disconnections_subscribe twice"); } let tauri_platform = import.meta.env.TAURI_PLATFORM; diff --git a/ng-app/src/api.ts b/ng-app/src/api.ts index 9d7da81..cd12c30 100644 --- a/ng-app/src/api.ts +++ b/ng-app/src/api.ts @@ -16,6 +16,7 @@ const mapping = { "wallet_gen_shuffle_for_pazzle_opening": ["pazzle_length"], "wallet_gen_shuffle_for_pin": [], "wallet_open_with_pazzle": ["wallet","pazzle","pin"], + "wallet_open_with_mnemonic_words": ["wallet","mnemonic_words","pin"], "wallet_was_opened": ["opened_wallet"], "wallet_create": ["params"], "wallet_read_file": ["file"], @@ -97,6 +98,19 @@ const handler = { }; //console.log(info,res); return res; + } else if (path[0] === "locales") { + let from_rust = await tauri.invoke("locales",{}); + let from_js = window.navigator.languages; + console.log(from_rust,from_js); + for (let lang of from_js) { + let split = lang.split("-"); + if (split[1]) { + lang = split[0] + "-" + split[1].toUpperCase(); + } + if (!from_rust.includes(lang)) { from_rust.push(lang);} + } + return from_rust; + } else if (path[0] === "disconnections_subscribe") { let { getCurrent } = await import("@tauri-apps/plugin-window"); let callback = args[0]; @@ -169,7 +183,7 @@ const handler = { return false; } else if (path[0] === "get_local_url") { return false; - } else if (path[0] === "wallet_open_with_pazzle") { + } else if (path[0] === "wallet_open_with_pazzle" || path[0] === "wallet_open_with_mnemonic_words") { let arg:any = {}; args.map((el,ix) => arg[mapping[path[0]][ix]]=el) let img = Array.from(new Uint8Array(arg.wallet.V0.content.security_img)); @@ -177,9 +191,8 @@ const handler = { arg.wallet = {V0:{id:arg.wallet.V0.id, sig:arg.wallet.V0.sig, content:{}}}; Object.assign(arg.wallet.V0.content,old_content); arg.wallet.V0.content.security_img = img; - return tauri.invoke(path[0],arg) - } - else { + return tauri.invoke(path[0],arg); + } else { let arg = {}; args.map((el,ix) => arg[mapping[path[0]][ix]]=el) return tauri.invoke(path[0],arg) diff --git a/ng-app/src/apps/JsonLdEditor.svelte b/ng-app/src/apps/JsonLdEditor.svelte new file mode 100644 index 0000000..e69de29 diff --git a/ng-app/src/assets/nextgraph-gray.svg b/ng-app/src/assets/nextgraph-nofill.svg similarity index 96% rename from ng-app/src/assets/nextgraph-gray.svg rename to ng-app/src/assets/nextgraph-nofill.svg index a403f35..2cf436e 100644 --- a/ng-app/src/assets/nextgraph-gray.svg +++ b/ng-app/src/assets/nextgraph-nofill.svg @@ -11,6 +11,6 @@ style="fill:#ffffff;stroke:none;stroke-width:0.268375" /> + /> \ No newline at end of file diff --git a/ng-app/src/classes.ts b/ng-app/src/classes.ts new file mode 100644 index 0000000..26f4642 --- /dev/null +++ b/ng-app/src/classes.ts @@ -0,0 +1,873 @@ +// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers +// All rights reserved. +// Licensed under the Apache License, Version 2.0 +// +// or the MIT license , +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +// "post/rich", "post/md", "post/text", "post/html", "post/asciidoc", "page", "code", "code/*", "app", "app/z", "class", "schema", "schema/owl|rdfs|shacl|shex", "service", "service/rust", "service/deno", "contract", "app/n:xxx.xx.xx:", "app/o:", +// "query/sparql", "query/graphql", "query/text", "query/web", +// "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", +// "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" +// "prod/task", "prod/project", "prod/issue", "prod/form", "prod/filling", "prod/cad", "prod/slides", "prod/question", "prod/answer", "prod/poll", "prod/vote" +// "file", "file/iana/*", "file/gimp", "file/inkscape", "file/kdenlive", "file/blender", "file/openscad", "file/lyx", "file/scribus", "file/libreoffice", + + +// application/vnd.api+json + +// application/activity+json + +// epub, dejavu, +// animation: snap, lottie, smil editor: https://github.com/HaikuTeam/animator/ + +export const official_classes = { + "post/rich": { + "ng:crdt": "YXml", + "ng:n": "Post - Rich Text", // editor: y-ProseMirror, viewer: https://www.npmjs.com/package/prosemirror-to-html-js or https://prosemirror.net/docs/ref/version/0.4.0.html#toDOM https://prosemirror.net/docs/ref/version/0.4.0.html#toHTML + "ng:a": "A Post with Rich Text, including images, links, formatted text, and embeds of other content", + "ng:o": "n:g:z:post:rich", + "ng:w": "n:g:z:post_rich_editor", + "ng:x": { + "as":true, + }, + "ng:compat": ["as:Article"], + }, + "post/md": { + "ng:crdt": "YXml", + "ng:n": "Post - MarkDown", // editor y-MilkDown, viewer: https://github.com/wooorm/markdown-rs + "ng:a": "A Post with MarkDown, including images, links, formatted text, and embeds of other content", + "ng:o": "n:g:z:post:md", + "ng:w": "n:g:z:post_md_editor", + "ng:x": { + "as":true, + }, + "ng:compat": ["file/iana/text/markdown", "code/markdown","as:Article"], + }, + "post/text": { + "ng:crdt": "YText", + "ng:n": "Post - Plain Text", + "ng:a": "A Post with Plain Text", + "ng:o": "n:g:z:post:text", + "ng:w": "n:g:z:code_editor", + "ng:x": { + "as":true, + }, + "ng:compat": ["file/iana/text/plain", "code/plaintext","as:Article"], + }, + "post/html": { + "ng:crdt": "YXml", + "ng:n": "Post - TinyMCE", + "ng:x": { + "as":true, + }, + "ng:a": "A Post based on TinyMCE, including images, links, formatted text, and embeds of other content", + "ng:compat": ["as:Article"], + }, + "post/asciidoc": { // display with https://github.com/asciidoctor/asciidoctor.js/ + "ng:crdt": "YText", + "ng:n": "Post - AsciiDoc", + "ng:a": "A Post based on AsciiDoc format", + "ng:x": { + "as":true, + }, + "ng:compat": ["as:Article"], + }, + "page": { + "ng:crdt": "YXml", + "ng:n": "Page", // based on GrapeJS, VvvebJs, or Astro ? + "ng:a": "A Page and Site builder", + "ng:compat": [], + }, + "code": { + "ng:crdt": "YText", + "ng:n": "Source Code", // edited with CodeMirror, displayed with highlight.js + "ng:a": "A Source Code file. many languages supported", + "ng:o": "n:g:z:pre", + "ng:w": "n:g:z:code_editor", + "ng:compat": ["code/*","file/iana/text/javascript","file/iana/text/css","file/iana/text/html","file/iana/text/markdown", "file/iana/application/xml", "file/iana/application/yaml", "file/iana/text/xml", "file/iana/application/xhtml+xml"], + }, + "app": { + "ng:n": "Official App", + "ng:a": "App provided by NextGraph platform", + }, + "app/z": { + "ng:crdt": "Elmer", + "ng:n": "Application", // Editor: Monaco + "ng:a": "Create an Application based on NextGraph Framework", + "ng:o": "n:g:z:app_store", + "ng:w": "n:g:z:app_editor", + "ng:include": ["schema/*","service/*","code","file"], + "ng:compat": ["code/svelte"], + }, + "class": { + "ng:crdt": "Graph", + "ng:n": "Class", + "ng:a": "Define a custom Class for your data", + "ng:x": { + "rdfs":true, + }, + "ng:compat": ["rdfs:Class"], + }, + "schema/rdfs": { + "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: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"], + }, + "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_editor", // default viewer + "ng:w": "n:g:z:ontology_editor", // default editor + "ng:x": { + "sh":true, + }, + "ng:include": ["data/graph"], + "ng:compat": ["sh:Shape", "file/iana/text/shaclc" ], + }, + "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_editor", // default viewer + "ng:w": "n:g:z:ontology_editor", // default editor + "ng:x": { + "shex":true, + }, + "ng:include": ["data/graph"], + "ng:compat": ["shex:*", "file/iana/text/shex", "code/shexc" ], + }, + "service": { + "ng:n": "Internal Service", + "ng:a": "Service provided by NextGraph framework", + "ng:o": "n:g:z:service_invoke", // default viewer + }, + "service/rust": { + "ng:crdt": "YText", + "ng:n": "Service - Rust", // edited with CodeMirror, displayed with highlight.js + "ng:a": "Service written in Rust and compiled to WASM", + "ng:o": "external_service_invoke", // default viewer + "ng:w": "n:g:z:service_editor", // default editor + "ng:compat": ["code/rust", "file/iana/application/wasm"], + }, + "service/deno": { + "ng:crdt": "YText", + "ng:n": "Service - Deno/JS", // edited with CodeMirror, displayed with highlight.js + "ng:a": "Service written in JS/TS for Deno or NodeJS", + "ng:o": "external_service_invoke", // default viewer + "ng:w": "n:g:z:service_editor", // default editor + "ng:compat": ["code/javascript", "code/typescript", "file/iana/text/javascript", "file/iana/application/node"], + }, + "contract": { + "ng:crdt": "YText", + "ng:n": "Contract", // edited with CodeMirror, displayed with highlight.js + "ng:a": "Smart Contract with Rust or JS code", + "ng:compat": ["code/rust", "file/iana/application/wasm", "code/javascript", "code/typescript", "file/iana/text/javascript", "file/iana/application/node"], + }, + "query/sparql": { + "ng:crdt": "YText",// uses ng:default_graph and ng:named_graph predicates + "ng:n": "SPARQL Query", // edited with YASGUI or Sparnatural, displayed with highlight.js https://github.com/highlightjs/highlightjs-turtle/tree/master + "ng:a": "Saved SPARQL Query that can be invoked", + "ng:o": "n:g:z:sparql:invoke", + "ng:w": "n:g:z:sparql_query:yasgui", + "ng:compat": ["code/sparql", "file/iana/application/sparql-query"], + }, + "query/sparql_update": { + "ng:crdt": "YText",// uses ng:default_graph and ng:named_graph predicates + "ng:n": "SPARQL Update", // edited with YASGUI, displayed with highlight.js https://github.com/highlightjs/highlightjs-turtle/tree/master + "ng:a": "Saved SPARQL Update that can be invoked", + "ng:o": "n:g:z:sparql:invoke", + "ng:w": "n:g:z:sparql_update:yasgui", + "ng:compat": ["code/sparql", "file/iana/application/sparql-update"], + }, + "query/graphql": { + "ng:crdt": "YText", // uses ng:default_graph predicate + "ng:n": "GraphQL Query", // edited with https://github.com/graphql/graphiql or https://github.com/graphql-editor/graphql-editor, displayed with highlight.js + "ng:a": "Saved GraphQL Query that can be invoked", + "ng:o": "n:g:z:graphql:invoke", + "ng:w": "n:g:z:graphql_query", + "ng:compat": ["code/graphql", "file/iana/application/graphql+json"], + }, + "query/text": { + "ng:crdt": "Graph", + "ng:n": "Text Search", + "ng:a": "Saved Text Search and its results", + "ng:compat": [], + }, + "query/web": { + "ng:crdt": "Graph", + "ng:n": "Web Search", + "ng:a": "Saved Web Search and its results", + "ng:compat": [], + }, + "data/graph": { + "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:w": "n:g:z:json_ld_editor", // default editor + "ng:x": { + "rdf":true, + "xsd":true, + }, + "ng:compat": [ "rdf:*", "xsd:*", "file/iana/text/n3", "file/iana/text/rdf+n3", "file/iana/text/turtle", "file/iana/application/n-quads", "file/iana/application/trig", "file/iana/application/n-triples", "file/iana/application/rdf+xml", "file/iana/application/ld+json"], + }, + "data/json": { + "ng:crdt": "Automerge", + "ng:n": "JSON", + "ng:a": "JSON Data CRDT", + "ng:o": "n:g:z:json_editor", // default viewer + "ng:w": "n:g:z:json_editor", // default editor + "ng:compat": ["file/iana/application/json", "code:json"], + }, + "data/array": { + "ng:crdt": "YArray", + "ng:n": "JSON Array", + "ng:a": "JSON Array CRDT", + "ng:o": "n:g:z:json_editor", // default viewer + "ng:w": "n:g:z:json_editor", // default editor + "ng:compat": ["file/iana/application/json", "code:json"], + }, + "data/map": { + "ng:crdt": "YMap", + "ng:n": "JSON Map", + "ng:a": "JSON Map CRDT", + "ng:o": "n:g:z:json_editor", // default viewer + "ng:w": "n:g:z:json_editor", // default editor + "ng:compat": ["file/iana/application/json", "code:json"], + }, + "data/xml": { + "ng:crdt": "YXml", + "ng:n": "XML", + "ng:a": "XML Data CRDT", + "ng:compat": ["file/iana/text/xml","file/iana/application/xml", "code:xml"], + }, + "data/table": { + "ng:crdt": "Automerge", // see https://github.com/frappe/datatable + "ng:n": "Table", // see https://specs.frictionlessdata.io/table-schema displayed with pivot table see https://activetable.io/docs/data https://www.npmjs.com/package/pivottable https://socket.dev/npm/package/svelte-pivottable/alerts/0.2.0?tab=dependencies + "ng:a": "Data in a Table (columns and rows)", + "ng:o": "n:g:z:pivot", + "ng:compat": ["file/iana/application/sparql-results+json","file/iana/application/sparql-results+xml","file/iana/text/csv"], + }, + "data/collection": { + "ng:crdt": "Graph", + "ng:n": "Collection", + "ng:a": "An ordered list of items", + "ng:o": "n:g:z:list", + "ng:x": { + "as": true, + "rdf": true, + }, + "ng:compat": ["as:Collection","rdf:List","rdf:Seq"], + }, + "data/container": { + "ng:crdt": "Graph", + "ng:n": "Container", + "ng:a": "An unordered list of items", + "ng:o": "n:g:z:list", + "ng:x": { + "rdf": true, + "rdfs": true, + "ldp": true, + }, + "ng:compat": ["rdfs:member","ldp:contains","rdf:Bag","rdf:Alt"], + }, + "data/board": { + "ng:crdt": "Graph", + "ng:n": "Board", + "ng:a": "Whiteboard, infinite canvas to arrange your content in 2D", + "ng:o": "n:g:z:board", + "ng:include": [], + "ng:compat": [], //https://jsoncanvas.org/ https://www.canvasprotocol.org/ https://github.com/orgs/ocwg/discussions/25 https://infinitecanvas.tools/gallery/ + }, + "data/grid": { + "ng:crdt": "Graph", + "ng:n": "Grid", + "ng:a": "Grid representation of a collection or container", + "ng:o": "n:g:z:grid", + "ng:include": ["data/container","data/collection","data/table","media/album"], + "ng:compat": [], + }, + "data/geomap": { // https://github.com/leaflet/leaflet + "ng:crdt": "Graph", + "ng:n": "Geo Map", + "ng:a": "Geographical Map", + "ng:x": { + "wgs": true, + "gn": true, + "as": true, + }, + "ng:compat": ["as:Place","wgs:*","gn:*", "file/iana/application/geo+json", "file/iana/application/vnd.mapbox-vector-tile"], // see also https://github.com/topojson/topojson + }, + "e/email": { + "ng:crdt": "Graph", + "ng:n": "Email", + "ng:a": "Email content and headers", + "ng:x": { + "email": "http://www.invincea.com/ontologies/icas/1.0/email#" //https://raw.githubusercontent.com/twosixlabs/icas-ontology/master/ontology/email.ttl + }, + "ng:compat": ["file/iana/message/rfc822","file/iana/multipart/related"], + }, + "e/web": { + "ng:crdt": "Graph", + //https://www.npmjs.com/package/warcio https://github.com/N0taN3rd/node-warc + "ng:n": "Web Archive", + "ng:a": "Archive the content of a web page", + "ng:compat": ["file/iana/application/warc","file/iana/multipart/related"], + }, + "e/rdf": { + "ng:crdt": "Graph", + "ng:n": "RDF Archive", + "ng:a": "Archive the triples of an RDF resource dereferenced with HTTP", + "ng:include": ["data/graph"], + }, + "mc/text": { + "ng:crdt": "Graph", + "ng:n": "Text Selection", + "ng:a": "Text Selection copied into Magic Carpet", + }, + "mc/link": { + "ng:crdt": "Graph", + "ng:n": "Link", + "ng:a": "Link to a document kept in Magic Carpet", + }, + "plato/card": { + "ng:crdt": "Graph", + "ng:n": "Card", + "ng:a": "Card representation of a document", + "ng:o": "n:g:z:card", + }, + "plato/pad": { + "ng:crdt": "Graph", + "ng:n": "Pad", + "ng:a": "Pad representation of a document", + "ng:o": "n:g:z:pad", + }, + "doc/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" : { + "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" : { + "ng:crdt": "YText", + "ng:n": "Diagram - Graphviz", + "ng:a": "Describe Diagrams with Graphviz", + "ng:compat": ["file/iana/text/vnd.graphviz"] + }, + "doc/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 + "ng:crdt": "Automerge", + "ng:n": "Diagram - Gantt", + "ng:a": "Interactive gantt chart", + "ng:compat": [] + }, + "doc/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 + "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 + "ng:crdt": "YText", + "ng:n": "Diagram - Markmap", + "ng:a": "mindmaps with markmap", + "ng:compat": [] + }, + "doc/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 + "ng:crdt": "Automerge", + "ng:n": "Diagram - jsmind", + "ng:a": "mindmaps with jsmind", + "ng:compat": [] // https://hizzgdev.github.io/jsmind/docs/en/1.usage.html + }, + // DC and C3 have Crossfilter https://github.com/dc-js/dc.js http://crossfilter.github.io/crossfilter/ https://github.com/c3js/c3 http://dc-js.github.io/dc.js/ + // take inspiration from https://github.com/metabase/metabase + // have a look at https://github.com/observablehq + // another open source dashboard with many data sources https://github.com/getredash/redash + // and another one https://github.com/apache/superset + // https://github.com/Rich-Harris/pancake + // https://github.com/williamngan/pts + // https://visjs.org/ + "doc/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" : { + "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" : { + "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 + "ng:crdt": "Automerge", + "ng:n": "Viz - Plotly", + "ng:a": "Declarative charts", + "ng:compat": [] // https://github.com/cytoscape/cytoscape.js + }, + "doc/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" : { + "ng:crdt": "Automerge", + "ng:n": "Charts - Frappe", + "ng:a": "GitHub-inspired responsive charts", + "ng:compat": [] // https://github.com/frappe/charts + }, + "doc/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" : { + "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" : { + "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" : { + "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" : { + "ng:crdt": "Automerge", + "ng:n": "Charts - Chart.js", + "ng:a": "Simple yet flexible charting for designers & developers with Chart.js", + "ng:compat": [] // https://github.com/chartjs/Chart.js + }, + // see if to provide plain D3, and also all the https://github.com/antvis libraries: G2, G6, L7, S2, X6. Have a look at AVA + "doc/pdf": { + "ng:crdt": "Graph", + "ng:n": "PDF", + "ng:a": "upload and display a PDF file", + "ng:compat": ["file/iana/application/pdf"] // https://github.com/mozilla/pdf.js https://viewerjs.org/ + }, + "doc/odf": { //!!! becareful: AGPL + "ng:crdt": "Graph", + "ng:n": "OpenDocumentFormat (ODF)", + "ng:a": "upload and display an ODF file", + "ng:compat": ["file/iana/application/vnd.oasis.opendocument*"] // https://webodf.org/ https://github.com/webodf/WebODF https://viewerjs.org/ + }, + // see also https://github.com/Mathpix/mathpix-markdown-it + "doc/latex": { + "ng:crdt": "Graph", + "ng:n": "Latex", + "ng:a": "upload and display a Latex or Tex file", + "ng:compat": ["file/iana/application/x-tex","file/iana/text/x-tex"] // https://github.com/michael-brade/LaTeX.js https://github.com/mathjax/MathJax + }, + "doc/ps": { //!!! becareful: AGPL https://github.com/ochachacha/ps-wasm + "ng:crdt": "Graph", + "ng:n": "Postscript", + "ng:a": "upload and display a PostScript file", + "ng:compat": ["file/iana/application/postscript"] // https://www.npmjs.com/package/ghostscript4js + }, + "doc/music/abc": { //https://github.com/paulrosen/abcjs + "ng:crdt": "YText", + "ng:n": "Music ABC", + "ng:a": "sheet music notation", + "ng:compat": [] + }, + "doc/music/guitar": { //https://github.com/birdca/fretboard + "ng:crdt": "YText", + "ng:n": "Music - Guitar", + "ng:a": "charts for guitar chords and scales", + "ng:compat": [] + }, + "doc/maths": { //https://github.com/KaTeX/KaTeX + "ng:crdt": "YText", + "ng:n": "Maths", + "ng:a": "TeX math rendering", + "ng:compat": ["file/iana/application/x-tex","file/iana/text/x-tex"] + }, + "doc/chemistry": { //GPL!! https://github.com/aeris-data/ChemDoodle/tree/master/ChemDoodleWeb-8.0.0 or https://github.com/aseevia/smiles-3d-vue + "ng:crdt": "YText", + "ng:n": "Chemical", + "ng:a": "simplified molecular-input line-entry system (SMILES)", + "ng:compat": ["file/iana/chemical/x-daylight-smiles"] // https://en.wikipedia.org/wiki/SYBYL_line_notation and http://fileformats.archiveteam.org/wiki/Chemical_data + }, + "doc/ancientscript": { //https://dn-works.com/ufas/ + "ng:crdt": "YText", // use Unicode and special fonts + "ng:n": "Ancient Script", + "ng:a": "Ancient Script", + "ng:compat": [] + }, + "doc/braille": { //https://en.wikipedia.org/wiki/Braille_Patterns + "ng:crdt": "YText", // use Unicode and special fonts + "ng:n": "Braille Patterns", + "ng:a": "Braille Patterns", + "ng:compat": [] + }, + "media/image": { + "ng:crdt": "Graph", + "ng:n": "Image", + "ng:a": "upload and display an image", + "ng:o": "n:g:z:media", + "ng:x": { + "as":true, + }, + "ng:compat": ["file/iana/image*","as:Image"] + }, + "media/reel": { + "ng:crdt": "Graph", + "ng:n": "Reel", + "ng:a": "upload and display a Reel (video from mobile)", + "ng:o": "n:g:z:media", + "ng:compat": ["file/iana/video*"] + }, + "media/video": { + "ng:crdt": "Graph", + "ng:n": "Video", + "ng:a": "upload and display a Video (and film)", + "ng:o": "n:g:z:media", + "ng:x": { + "as":true, + }, + "ng:compat": ["file/iana/video*","as:Video"] + }, + "media/album": { + "ng:crdt": "Graph", + "ng:n": "Album", + "ng:a": "Assemble several images and/or videos into an ordered Album", + "ng:o": "n:g:z:gallery", + "ng:include": ["data/collection"], + "ng:compat": [] + }, + "media/audio": { + "ng:crdt": "Graph", + "ng:n": "Audio", + "ng:a": "upload and play an Audio file, Audio note or Voice message", + "ng:o": "n:g:z:media", + "ng:x": { + "as":true, + }, + "ng:compat": ["file/iana/audio*","as:Audio"] + }, + "media/song": { + "ng:crdt": "Graph", + "ng:n": "Song", + "ng:a": "A song from an artist,album and/or lyrics", + "ng:o": "n:g:z:media", + "ng:x": { + "music": "http://purl.org/ontology/mo/", + }, + "ng:compat": ["music:MusicalWork","music:MusicArtist", "music:Lyrics"] + // see also https://polifonia-project.eu/wp-content/uploads/2022/01/Polifonia_D2.1_V1.0.pdf + // Music ontology http://musicontology.com/docs/faq.html with data based on existing databases https://musicbrainz.org/doc/MusicBrainz_Database/Schema https://github.com/megaconfidence/open-song-database https://www.discogs.com/developers + }, + "media/subtitle": { //https://captioneasy.com/subtitle-file-formats/ + "ng:crdt": "YText", + "ng:n": "Subtitles", + "ng:a": "Subtitles", + "ng:compat": [] // TBD + }, + "media/overlay": { + "ng:crdt": "Graph", + "ng:n": "Overlay", + "ng:a": "Composition of an image, reel, text, icon, link, mention or other content into a layered content", + "ng:o": "n:g:z:media", + "ng:compat": [] + }, + "social/channel": { + "ng:crdt": "Graph", + "ng:n": "Channel", + "ng:a": "Broadcast channel with subscribers", + "ng:compat": [] + }, + "social/stream": { + "ng:crdt": "Graph", + "ng:n": "Stream", + "ng:a": "A document or store's stream branch", + "ng:compat": [] + }, + "social/contact": { + "ng:crdt": "Graph", + "ng:n": "Contact", + "ng:a": "Contact: an Individual, Organization or Group", + "ng:x": { + "vcard":true, + "foaf": true, + }, + "ng:include": ["data/graph"], + "ng:compat": ["foaf:Person","foaf:Agent","vcard:Individual", "vcard:Organization", "vcard:Group", "file/iana/text/vcard", "file/iana/application/vcard+json", "file/iana/application/vcard+xml" ], + }, + "social/event": { + "ng:crdt": "Graph", + "ng:n": "Event", + "ng:a": "An event occuring in specific location and time", + "ng:x": { + "as":true, + }, + "ng:include": ["post/*"], + "ng:compat": ["as:Event"] + }, + "social/calendar": { + "ng:crdt": "Graph", + "ng:n": "Calendar", + "ng:a": "A calendar where events are gathered", + "ng:x": { + "as":true, + "time": true, + }, + "ng:include": ["data/collection"], + "ng:compat": ["time:TemporalEntity", "file/iana/text/calendar", "file/iana/application/calendar+xml", "file/iana/application/calendar+json"] //https://www.rfc-editor.org/rfc/rfc5545 + }, + "social/scheduler": { + "ng:crdt": "Graph", + "ng:n": "Scheduler", + "ng:a": "Helps finding a common time slot for several participants to a future event", + "ng:x": { + "as":true, + }, + "ng:compat": ["as:Invite","as:Reject","as:Accept","as:TentativeAccept","as:TentativeReject"] + }, + "social/reaction": { + "ng:crdt": "Graph", + "ng:n": "Reaction", + "ng:a": "A reaction by user to some content", + "ng:x": { + "as":true, + }, + "ng:compat": ["as:Like", "as:Dislike", "as:Listen", "as:Read", "as:View"] + }, + "prod/task": { + "ng:crdt": "Graph", + "ng:n": "Task", + "ng:a": "A task to be done", + "ng:x": { + "as":true, + "pair": "http://virtual-assembly.org/ontologies/pair#", + }, + "ng:include": ["post/*"], + "ng:compat": ["pair:Task"] //see VTODO in iCalendar https://www.cs.utexas.edu/~mfkb/RKF/tree/components/specs/ontologies/Calendar-onto.html + // see todo and todoList of Mobilizon https://framagit.org/framasoft/mobilizon/-/blob/main/lib/federation/activity_stream/converter/todo.ex + // https://framagit.org/framasoft/mobilizon/-/blob/main/lib/federation/activity_stream/converter/todo_list.ex + }, + "prod/project": { + "ng:crdt": "Graph", + "ng:n": "Project", + "ng:a": "A project management / KanBan", + "ng:x": { + "as":true, + "pair": "http://virtual-assembly.org/ontologies/pair#", + }, + "ng:include": ["post/*"], + "ng:compat": ["pair:Project"] + }, + // see SRO https://www.researchgate.net/publication/350158531_From_a_Scrum_Reference_Ontology_to_the_Integration_of_Applications_for_Data-Driven_Software_Development + // https://ceur-ws.org/Vol-1442/paper_4.pdf + // see focalbaord, specially for their import scripts https://github.com/mattermost/focalboard/tree/main/import + // and their data model https://github.com/mattermost/focalboard/tree/main/server/model + // https://github.com/leif81/bzkanban + // https://github.com/HigorLoren/donko (react) + // https://github.com/trobonox/kanri (GPL, Vue) + // https://github.com/waterrmalann/kards (vanilla JS) + // see also https://github.com/wekan/wekan + // see also https://taiga.io/ (for inspiration. as it is AGPL and python) + // see also https://github.com/plankanban/planka (for inspiration. as it is AGPL and React) + // see also https://kolaente.dev/vikunja/vikunja (for inspiration. AGPL. Vue and Go) + // see also https://github.com/laurent22/joplin/ (for inspiration. AGPL) + // see also https://github.com/SrGMC/kanbana + /// svelte: https://github.com/V-Py/svelte-kanban + // https://github.com/supabase-community/svelte-kanban + // https://github.com/therosbif/kanban + "prod/issue": { + "ng:crdt": "Graph", + "ng:n": "Issue", + "ng:a": "An issue to be solved", + "ng:x": { + "as":true, + "pair": "http://virtual-assembly.org/ontologies/pair#", + }, + "ng:include": ["prod/task"], + "ng:compat": ["pair:Challenge"] + }, + //https://github.com/go-gitea/gitea/issues/20232 + // datamodel of gitea issues: https://github.com/go-gitea/gitea/blob/165346c15c6d021028a65121e692a17ffc927e2c/models/issue.go#L35-L79 + "prod/form": { + "ng:crdt": "Graph", + "ng:n": "Form", + "ng:a": "A form to be filled-in", + "ng:x": { + "form" : "http://rdf.danielbeeke.nl/form/form-dev.ttl#", + }, + "ng:compat": ["form:*","file/iana/application/schema+json"] + }, + // https://jsonforms.io/docs/ + // https://github.com/jsonform/jsonform + // https://jsonforms.io/docs/integrations/vue + // >>> https://github.com/json-editor/json-editor + // or >>> https://github.com/webgme/svelte-jsonschema-form + // or >>> https://github.com/restspace/svelte-schema-form + // see https://ceur-ws.org/Vol-1515/regular14.pdf + // and https://github.com/protegeproject/facsimile + // https://www.drupal.org/project/webform + // see https://www.semantic-mediawiki.org/wiki/Extension:Page_Forms + // https://www.mediawiki.org/wiki/Extension:Page_Forms + // https://rdf-form.danielbeeke.nl/ + // consider using Shapes + "prod/filling": { + "ng:crdt": "Graph", + "ng:n": "Form filling", + "ng:a": "A form that has been filled-in", + "ng:compat": [] + }, + "prod/cad": { // https://mattferraro.dev/posts/cadmium + "ng:crdt": "Automerge", + "ng:n": "CAD", + "ng:a": "CADmium", + "ng:compat": [] + }, + "prod/slides": { //https://github.com/hakimel/reveal.js + //https://pandoc.org/MANUAL.html#slide-shows + "ng:crdt": "Graph", + "ng:n": "Slides", + "ng:a": "Slides and presentations", + "ng:include": ["post/*"], + "ng:compat": [] + }, + "prod/question" : { + "ng:crdt": "Graph", + "ng:n": "Question", + "ng:a": "A question that needs answers", + "ng:x": { + "as":true, + }, + "ng:include": ["post/*"], + "ng:compat": ["as:Question"] + }, + "prod/answer" :{ + "ng:crdt": "Graph", + "ng:n": "Answer", + "ng:a": "An answer to a question", + "ng:x": { + "as":true, + }, + "ng:include": ["post/*"], + "ng:compat": ["as:Note"] + }, + "prod/poll" : { + "ng:crdt": "Graph", + "ng:n": "Poll", + "ng:a": "A poll where people will vote", + "ng:x": { + "as":true, + }, + "ng:include": ["post/*"], + "ng:compat": ["as:Question"] + }, + "prod/vote" : { + "ng:crdt": "Graph", + "ng:n": "Vote", + "ng:a": "A vote cast for a Poll", + "ng:x": { + "as":true, + }, + "ng:compat": ["as:Note"] + }, + "file" : { + "ng:crdt": "Graph", + "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" : { + "ng:n": "NextGraph Wallet File", + "ng:a": "NextGraph Wallet File (.ngw)", + "ng:compat": [] + }, + "file/ng/doc" : { + "ng:n": "NextGraph Document File", + "ng:a": "NextGraph Document File (.ngd)", + "ng:compat": [] + }, + "file/ng/html" : { + "ng:n": "NextGraph Document Html", + "ng:a": "NextGraph Document Html standalone file", + "ng:compat": [] + }, + "file/text" : { + "ng:crdt": "Graph", + "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/*", "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", + "file/iana/application/vcard+json", "file/iana/application/vcard+xml", "file/iana/text/calendar", "file/iana/application/calendar+xml", "file/iana/application/calendar+json", + "file/iana/application/schema+json", "file/iana/application/geo+json", "file/iana/application/json" ] + }, + +}; \ No newline at end of file diff --git a/ng-app/src/lib/CenteredLayout.svelte b/ng-app/src/lib/CenteredLayout.svelte index 80fe9bd..42d7abf 100644 --- a/ng-app/src/lib/CenteredLayout.svelte +++ b/ng-app/src/lib/CenteredLayout.svelte @@ -9,8 +9,91 @@ // according to those terms. --> -
- + + +
+ {#if !changingLang} +
+ +
+ {#if displayFooter} +
+
+ +
+ +
+
+ {/if} + {:else} +
+
    + {#each Object.entries(available_languages) as lang} + + {/each} +
+
+ {/if}
diff --git a/ng-app/src/lib/DataClassIcon.svelte b/ng-app/src/lib/DataClassIcon.svelte new file mode 100644 index 0000000..263fbfb --- /dev/null +++ b/ng-app/src/lib/DataClassIcon.svelte @@ -0,0 +1,187 @@ + + + + + + diff --git a/ng-app/src/lib/FullLayout.svelte b/ng-app/src/lib/FullLayout.svelte index 9cebc77..a56fa0b 100644 --- a/ng-app/src/lib/FullLayout.svelte +++ b/ng-app/src/lib/FullLayout.svelte @@ -21,6 +21,8 @@ import MobileBottomBar from "./MobileBottomBar.svelte"; import Logo from "./components/Logo.svelte"; + import { connection_status } from "../store"; + import { onMount, tick } from "svelte"; import { @@ -87,9 +89,9 @@
- + @@ -99,60 +101,64 @@ label="Home" href="#/" on:click={scrollToTop} - class="py-1 tall:p-2" + class="py-1 tall-xs:p-2" > - + - + - + - + - + - + NextGraph @@ -52,7 +52,7 @@ class="w-7 h-7 text-black transition duration-75 dark:text-white group-hover:text-gray-900 dark:group-hover:text-white focus:outline-none" /> - + + + -{#if step == "load"} -
-

How to open your wallet, step by step :

-
    -
  • - For each one of the 9 categories of images, you will be presented with - the 15 possible image choices. The categories are shuffled at every - login. They will not always appear in the same order. -
  • -
  • - At each category, only one of the 15 displayed choices is the correct - image that belongs to your pazzle. Find it and tap or click on that one. - The 15 images are shuffled too, they will not appear at the same - position at each login. On a computer, you can also use the tab key on - your keyboard to move to the desired item on the screen, then press the - space bar to select each one. -
  • -
  • - Once you completed the last category, you will be presented with all the - images you have previously selected. Their order is displayed as it was - when you picked them. But this is not the correct order of the images in - your pazzle. You now have to order them correctly. -
  • -
  • - You must remember which image should be the first one in your pazzle. - Find it on the screen and click or tap on it. It will be greyed out and - the number 1 will appear on top of it. -
  • -
  • - Move on to the second image of your pazzle (that you memorized). Find it - on the screen and tap on it. Repeat this step until you reached the last - image. -
  • -
  • - Finally, your PIN code will be asked. enter it by clicking or tapping on - the digits. -
  • -
-
-
- {#if !loaded} - Loading pazzle... +
660} + class:flex={height > 660} + bind:this={top} +> + {#if step == "load"} +
+

+ How to open your wallet? You have 2 options: +

+

With your Pazzle

+
    +
  • + For each one of the 9 categories of images, you will be presented with + the 15 possible image choices. The categories are shuffled at every + login. They will not always appear in the same order. +
  • +
  • + At each category, only one of the 15 displayed choices is the correct + image that belongs to your pazzle. Find it and tap or click on that + one. The 15 images are shuffled too, they will not appear at the same + position at each login. On a computer, you can also use the tab key on + your keyboard to move to the desired item on the screen, then press + the space bar to select each one. +
  • +
  • + Once you completed the last category, you will be presented with all + the images you have previously selected. Their order is displayed as + it was when you picked them. But this is not the correct order of the + images in your pazzle. You now have to order them correctly. +
  • +
  • + You must remember which image should be the first one in your pazzle. + Find it on the screen and click or tap on it. It will be greyed out + and the number 1 will appear on top of it. +
  • +
  • + Move on to the second image of your pazzle (that you memorized). Find + it on the screen and tap on it. Repeat this step until you reached the + last image. +
  • +
  • + Finally, your PIN code will be asked. enter it by clicking or tapping + on the digits. +
  • +
+ +

+ With your 12 words Mnemonic (passphrase) +

+
    +
  • + Enter your twelve words mnemonic in the input field. The words must be + separated by spaces. +
  • +
  • Enter the PIN code that you chose when you created your wallet.
  • +
+ + + {#if for_import} +
+ Do you trust this device?
+

+ If you do, if this device is yours or is used by few trusted persons + of your family or workplace, and you would like to login again from + this device in the future, then you can save your wallet on this + device. To the contrary, if this device is public and shared by + strangers, do not save your wallet here. {#if !tauri_platform}By + selecting this option, you agree to saving some cookies on your + browser.{/if}
+

+
+ Yes, save my wallet on this device +
+
+ {/if} + +
+
+ {#if !loaded} + Loading pazzle... + + + + + {:else} + + {/if} + + + Open with Mnemonic instead + +
+
+
+ + {:else if step == "pazzle" || step == "order" || step == "pin" || step == "mnemonic"} +
660} + class:min-w-[310px]={mobile} + class:min-w-[500px]={!mobile} + class:max-w-[370px]={mobile} + class:max-w-[600px]={!mobile} + > +
+ + + {#if step == "mnemonic"} +
+ + +
+ +
+ + {:else if step == "pazzle"} +

+ + + Select your emoji of category:
{emoji_cat[ + shuffle.category_indices[pazzlePage] + ]}
+

+ {#each [0, 1, 2, 3, 4] as row} +
+ {#each emojis2[pazzlePage]?.slice(0 + row * 3, 3 + row * 3) || [] as emoji, i (pazzlePage + "-" + row + "-" + i)} +
select(row * 3 + i)} + on:keypress={() => select(row * 3 + i)} + > + +
+ {/each} +
+ {/each} + {:else if step == "order"} +

+ Select each image in the correct order +

+ {#each [0, 1, 2] as row} +
+ {#each selection.slice(0 + row * 3, 3 + row * 3) || [] as emoji, i} + {#if !emoji.sel} +
select_order(emoji)} + on:keypress={() => select_order(emoji)} + > + +
+ {:else} +
+ + {emoji.sel} +
+ {/if} + {/each} +
+ {/each} + {:else if step == "pin"} +

+ Enter your PIN code +

+ + {#each [0, 1, 2] as row} +
+ {#each shuffle_pin.slice(0 + row * 3, 3 + row * 3) as num} + + {/each} +
+ {/each} +
+
+ + +
+ {#each pin_code as pin_key}*{/each} + {/if} +
+ +
+ + +
+
+ {:else if step == "opening"} +
+ Opening your wallet...
+ Please wait - {:else} - - {/if} -
- {#if for_import} -
- Do you trust this device?
-
- Yes, save my wallet on this device -
-

- If you do, if this device is yours or is used by few trusted persons of - your family or workplace, and you would like to login again from this - device in the future, then you can save your wallet on this device. To - the contrary, if this device is public and shared by strangers, do not - save your wallet here. {#if !tauri_platform}By selecting this option, - you agree to save some cookies on your browser.{/if}
-

- {/if} -{:else if step == "pazzle"} -
- {#each [0, 1, 2, 3, 4] as row} -
- {#each emojis2[display]?.slice(0 + row * 3, 3 + row * 3) || [] as emoji, i} -
select(row * 3 + i)} - on:keypress={() => select(row * 3 + i)} + {:else if step == "end"} + {#if error} +
+
+ An error occurred ! +
- {/each} + + + + {error} + +
+
+ + +
- {/each} -
-{:else if step == "order"} - -
- {#each [0, 1, 2] as row} -
- {#each selection.slice(0 + row * 3, 3 + row * 3) || [] as emoji, i} - {#if !emoji.sel} -
select_order(emoji, row * 3 + i)} - on:keypress={() => select_order(emoji, row * 3 + i)} - > - -
- {:else} -
- - {emoji.sel} -
- {/if} - {/each} + {:else} +
+ Your wallet is opened!
Please wait while the app is loading... +
- {/each} -
-{:else if step == "pin"} -
-

- Enter your PIN code -

-
- {#each [0, 1, 2] as row} -
- {#each shuffle_pin.slice(0 + row * 3, 3 + row * 3) as num} - - {/each} -
- {/each} - -
-
-{:else if step == "opening"} -
- Opening your wallet...
- Please wait - - - - -
-{:else if step == "end"} - {#if error} -
- An error occurred ! - - - {error} - - - -
- {:else} -
- Your wallet is opened!
Please wait while the app is loading... - -
+ {/if} {/if} -{/if} +
+ + diff --git a/ng-app/src/lib/components/PasswordInput.svelte b/ng-app/src/lib/components/PasswordInput.svelte new file mode 100644 index 0000000..62210f4 --- /dev/null +++ b/ng-app/src/lib/components/PasswordInput.svelte @@ -0,0 +1,76 @@ + + +
+ + +
+ + + + + + + + + +
+
diff --git a/ng-app/src/routes/Home.svelte b/ng-app/src/routes/Home.svelte index 8cd1425..905161e 100644 --- a/ng-app/src/routes/Home.svelte +++ b/ng-app/src/routes/Home.svelte @@ -9,18 +9,28 @@ // according to those terms. --> + + - + diff --git a/ng-app/src/routes/URI.svelte b/ng-app/src/routes/NURI.svelte similarity index 95% rename from ng-app/src/routes/URI.svelte rename to ng-app/src/routes/NURI.svelte index dbfa686..3aa692f 100644 --- a/ng-app/src/routes/URI.svelte +++ b/ng-app/src/routes/NURI.svelte @@ -19,6 +19,6 @@
-

nextgraph URI {params[1]}

+

Nextgraph URI {params[1]}

diff --git a/ng-app/src/routes/NotFound.svelte b/ng-app/src/routes/NotFound.svelte index 906e146..4b233b9 100644 --- a/ng-app/src/routes/NotFound.svelte +++ b/ng-app/src/routes/NotFound.svelte @@ -14,7 +14,7 @@ import CenteredLayout from "../lib/CenteredLayout.svelte"; - +
404 Page not found. diff --git a/ng-app/src/routes/User.svelte b/ng-app/src/routes/User.svelte index 753fb83..709bc18 100644 --- a/ng-app/src/routes/User.svelte +++ b/ng-app/src/routes/User.svelte @@ -8,6 +8,13 @@ // notice may not be copied, modified, or distributed except // according to those terms. --> + + + - +
diff --git a/ng-app/src/routes/WalletCreate.svelte b/ng-app/src/routes/WalletCreate.svelte index 0e0dfa1..23ed52f 100644 --- a/ng-app/src/routes/WalletCreate.svelte +++ b/ng-app/src/routes/WalletCreate.svelte @@ -9,10 +9,19 @@ // according to those terms. --> + + + + - {#if wait} -
- {#if wait === true} - Please wait... - {:else} - {wait} - {/if} - - - - -
- {:else} -
- - {#if registration_error} -
- - {#if registration_error == "AlreadyExists"} -

- The user is already registered with the selected broker.
Try - logging in instead -

- - - - {:else} -

- An error occurred during registration:
{registration_error} -

- - - - {/if} -
- {:else if intro} -
-

- A NextGraph Wallet is unique to each person. It stores your - credentials and authorizations to access documents. You need one in - order to start using NextGraph.

If you already have a - wallet, you should not create a new one, instead, - login here with your existing wallet. - If you never created a NextGraph Wallet before, please follow the instructions - below in order to create your unique personal wallet. -

-
- {#if $has_wallets} - - Some wallets are saved on this device,
to log in with one of - them, - click here. -
+
+ {#if wait} +
+ {#if wait === true} + Please wait... + {:else} + {wait} {/if} -
-
-

- What is a wallet? Please read -

-
    -
  • - - - It is a secure and encrypted small file that contains some - important information that only you should have access to. -
  • -
  • - - - In your wallet, we store all the permissions to access - documents you have been granted with, or that you have created - yourself. -
  • -
  • - - - In order to open it, you will need to enter your pazzle - and a - PIN code of 4 digits. Your personal pazzle (contraction - of puzzle and password) is composed of 9 images you should remember. - The order of the images is important too. -
  • -
  • - - - - Don't worry, it is easier to remember 9 images than a - password like "69$g&ms%C*%", and it has the same strength as a - complex password. The entropy of your pazzle is 66bits, - which is considered very high by all standards. -
  • - -
  • - - - You should only create one unique wallet for yourself. - All your accounts, identities and permissions will be added to - this unique wallet later on. Do not create another wallet if - you already have one. Instead, you will - import your existing wallet in all the apps and websites - where you need it -
  • -
  • - - - Your wallet can be imported with the help of a small file - that you download, or with a QRcode. In any case, you should - never share this file or QRcode with anybody else. -
  • -
  • - - - We at NextGraph will never see the content of your wallet. It - is encrypted and we do not know your pazzle, so we cannot see - what is inside. -
  • -
  • - - - For the same reason, we won't be able to help you if you - forget your pazzle or PIN code, or if you loose the wallet - file. There is no "password recovery" option in this case. You - can note your pazzle down on a piece of paper until you - remember it, but don't forget to destroy this note after a - while. -
  • -
-
+ + + +
+ {:else} +
+ -
- -
- {:else if !invitation} -
-

- NextGraph is based on an efficient decentralized P2P network, and in - order to join this network and start using the app, you need to - first select a broker server. -

-
-
-
-

- What is a broker? Please read -

-
    -
  • - - - The broker helps you keep all your data in sync, as it - is connected to the internet 24/7 and keeps a copy of the - updates for you. This way, even if the devices of the other - participants are offline, you can still see their changes -
  • -
  • - - - All your data is secure and end-to-end encrypted, and - the broker cannot see the content of the documents as it does - not have the keys to decrypt them. -
  • -
  • - - - The broker helps you enforce your privacy as it hides your - internet address (IP) from other users you share documents with. -
  • -
  • - - - - It will be possible in the future to use NextGraph without any - broker and to have direct connections between peers, but this - will imply a less smooth experience. -
  • -
  • -
    Try + logging in instead +

    + +
  • -
  • + Go back to homepage + + + {/if} +
+ {:else if intro} +
+

+ A NextGraph Wallet is unique to each person. It stores your + credentials and authorizations to access documents. You need one + in order to start using NextGraph.

If you already have + a wallet, you should not create a new one. Instead, + login here with your existing wallet. + If you never created a NextGraph Wallet before, please follow the instructions + below in order to create your unique personal wallet. +

+
+ {#if $has_wallets} + + Some wallets are saved on this device,
to log in with one of + them, + click here. +
+ {/if} +
+
+

+ What is a wallet? Please read +

+
    +
  • + + + It is a secure and encrypted small file that contains some + important information that only you should have access to. +
  • +
  • + + + In your wallet, we store all the permissions to access + documents you have been granted with, or that you have + created yourself. +
  • +
  • + + + In order to open it, you will need to enter your pazzle + and a + PIN code of 4 digits. Your personal pazzle (contraction + of puzzle and password) is composed of 9 images you should remember. + The order of the images is important too. +
  • +
  • + + + + Don't worry, it is easier to remember 9 images than a + password like "69$g&ms%C*%", and it has the same strength as + a complex password. The entropy of your pazzle is 66bits, which is considered very high by all standards. +
  • + +
  • + + + You should only create one unique wallet for yourself. All your accounts, identities and permissions will be + added to this unique wallet later on. Do not create another + wallet if you already have one. Instead, you will + import your existing wallet in all the apps and websites + where you need it +
  • +
  • + + + Your wallet can be imported with the help of a small file + that you download, or with a QRcode. In any case, you should + never share this file or QRcode with anybody else. +
  • +
  • + + + We at NextGraph will never see the content of your wallet. + It is encrypted and we do not know your pazzle, so we cannot + see what is inside. +
  • +
  • + + + For the same reason, we won't be able to help you if you + forget your pazzle or PIN code, or if you loose the wallet + file. + There is no "password recovery" option in this case. You can note your pazzle down on a piece of paper + until you remember it, but don't forget to destroy this note + after a while. +
  • +
+
+
+
+ +
+ {:else if !invitation} +
+

+ NextGraph is based on an efficient decentralized P2P network, and + in order to join this network and start using the app, you need to + first select a broker server. +

+
+
+
+

+ What is a broker? Please read +

+
    +
  • + + + The broker helps you keep all your data in sync, as + it is connected to the internet 24/7 and keeps a copy of the + updates for you. This way, even if the devices of the other + participants are offline, you can still see their changes +
  • +
  • + + + All your data is secure and end-to-end encrypted, and + the broker cannot see the content of the documents as it + does not have the keys to decrypt them. +
  • +
  • + + + The broker helps you enforce your privacy as it hides + your internet address (IP) from other users you share documents + with. +
  • +
  • + + + + It will be possible in the future to use NextGraph without + any broker and to have direct connections between peers, but + this will imply a less smooth experience. +
  • +
  • + + + At anytime you can decide to switch to another broker + service provider or host it yourself. Your data is totally portable + and can freely move to another broker. +
  • +
  • + + + + Soon we will offer you the opportunity to host your own + broker at home + or office. Instead of using a "broker service + provider", you will own a small device that you connect + behind your internet router. It is called NG Box and will + be available soon. +
  • +
  • + + + + Organizations and companies have the opportunity to host a + broker on-premise + or in the cloud, as the software is open source. + Individuals can also + self-host a broker on any VPS server or at home, on their + dedicated hardware. +
  • +
+

+ Please choose one broker among the list +

+
+
+ {#if pre_invitation} +
+ +
+ {:else} +
+ +
- - Soon we will offer you the opportunity to host your own broker - at home - or office. Instead of using a "broker service - provider", you will own a small device that you connect behind - your internet router. It is called NG Box and will be available - soon. - -
  • +
    + +
    + {/if} - - Organizations and companies have the opportunity to host a - broker on-premise - or in the cloud, as the software is open source. - Individuals can also - self-host a broker on any VPS server or at home, on their - dedicated hardware. -
  • - -

    - Please choose one broker among the list -

    -
    -
    - {#if pre_invitation}
    - -
    - {:else} -
    - + + Enter an invitation link +
    + {#if false && mobile} +
    + +
    + {/if}
    - {/if} - -
    - +
    + {:else if pin.length < 4} +
    + {#if registration_success} + + You have been successfully registered to {registration_success} + + {/if} +

    + Let's start creating your wallet by choosing a PIN code + + We recommend you to choose a PIN code that you already know very + well. +
    + Your credit card PIN, by example, is a good choice.
    We at + NextGraph will never see your PIN. +
    +

    +

    Here are the rules for the PIN :

    +
      +
    • It cannot be a series like 1234 or 8765
    • +
    • + The same digit cannot repeat more than once. By example 4484 is + invalid +
    • +
    • + Try to avoid birth date, last digits of phone number, or zip + code +
    • +
    - Enter an invitation link - -
    - {#if false && mobile} -
    + + You have chosen: {#each pin as digit}{digit}{/each} + +
    + {#each [0, 1, 2] as row} +
    + {#each [1, 2, 3] as num} + + {/each} +
    + {/each} + +
    +
    + {:else if pin_confirm.length < 4} +
    +

    + Please confirm your PIN code. + Enter the same PIN again +

    + + You have chosen: {#each pin_confirm as digit}{digit}{/each} + +
    + {#each [0, 1, 2] as row} +
    + {#each [1, 2, 3] as num} + + {/each} +
    + {/each} + +
    +
    + {:else if !options} +
    + {#if pin.toString() === pin_confirm.toString()} + + Your PIN is confirmed as : {#each pin_confirm as digit}{digit}{/each} + +

    + Now let's enter a security phrase and a security image +

    +

    + As a verification step, this phrase and image will be presented + to you every time you are about to enter your pazzle and PIN in + order to unlock your wallet.
    + This security measure will prevent you from entering your pazzle + and PIN on malicious sites and apps. + + Every time you will use your wallet, if you do not see and + recognize your own security phrase and image before entering + your pazzle, please stop and DO NOT enter your pazzle, as you + would be the victim of a phishing attempt. + +

    +

    + Here are the rules for the security phrase and image : +

    +
      +
    • The phrase should be at least 10 characters long
    • +
    • + It should be something you will remember, but not something + too personal. +
    • +
    • + Do not enter your full name, nor address, nor phone number. +
    • +
    • + Instead, you can enter a quote, a small sentence that you + like, or something meaningless to others, but unique to you. +
    • +
    • + The image should be minimum 150x150px. There is no need to + provide more than 400x400px as it will be scaled down anyway. +
    • +
    • + We accept several formats like JPEG, PNG, GIF, WEBP and more. +
    • +
    • + The image should be unique to you. But it should not be too + personal neither. +
    • +
    • + Do not upload your face picture, this is not a profile pic. +
    • +
    • + The best would be a landscape you like or any other picture + that you will recognize as unique. +
    • +
    • + Please be aware that other people who are sharing this device + with you, will be able to see this image and phrase. +
    • +
    + +
    + {#if security_txt && security_img} + + {/if} + { + event.preventDefault(); + }} + on:change={handleChange} + > +

    + {#if is_touch_device} + Tap to upload an image + {:else} + Click to select an image or + drag and drop + {/if} +

    + +
    + your security + {:else} + + You didn't enter the same PIN twice + + + {/if} +
    + {:else if !creating} +
    +

    + We are almost done !
    + There are 4 options to choose before we can create your wallet. Those + options can help you to use and keep your wallet. But we also want + to be careful with your security and privacy.

    + Remember that in any case, once your wallet will be created, you will + download a file that you should keep privately somewhere on your device, + USB key or hard-disk. This is the default way you can use and keep + your wallet. Now let's look at some options that can make your life + a bit easier. +

    +

    + Do you trust this device?
    + If you do, if this device is yours or is used by few trusted persons + of your family or workplace, and you would like to login again from + this device in the future, then you can save your wallet on this device. + To the contrary, if this device is public and shared by strangers, + do not save your wallet here. {#if !tauri_platform}By selecting + this option, you agree to save some cookies on your browser.{/if}
    + Save my wallet on this device? +

    +

    + Keep a copy in the cloud?
    + Are you afraid that you will loose the file containing your wallet? + If this would happen, your wallet would be lost forever, together with + all your documents. We can keep an encrypted copy of your wallet in + our cloud. Only you will be able to download it with a special link. + You would have to keep this link safely though. By selecting this option, + you agree to the + Terms of Service of our cloud. +
    + Save my wallet in the cloud? +

    +

    + Create a PDF file of your wallet? +
    + We can prepare for you a PDF file containing all the information of + your wallet, unencrypted. You should print this file and then delete + the PDF (and empty the trash). Keep this printed document in a safe + place. It contains all the information to regenerate your wallet in + case you lost access to it. +
    + Create a PDF of my wallet? +

    + {#if !options.cloud} +

    + Create a link to access your wallet easily? +
    + When you want to use your wallet on the web or from other devices, + we can help you find your wallet by creating a simple link accessible + from anywhere. Only you will have access to this link. In order to + do so, we will keep your wallet ID and some information about your + broker on our cloud servers. If you prefer to opt out, just uncheck + this option. By selecting this option, you agree to the + Terms of Service of our cloud. +
    + Create a link to my wallet? +

    + {/if} -
    - {/if} -
    - -
    -
    - -
    - {:else if pin.length < 4} -
    - {#if registration_success} - - You have been successfully registered to {registration_success} - - {/if} -

    - Let's start creating your wallet by choosing a PIN code - - We recommend you to choose a PIN code that you already know very - well. -
    - Your credit card PIN, by example, is a good choice.
    We at - NextGraph will never see your PIN. -
    -

    -

    Here are the rules for the PIN :

    -
      -
    • It cannot be a series like 1234 or 8765
    • -
    • - The same digit cannot repeat more than once. By example 4484 is - invalid -
    • -
    • - Try to avoid birth date, last digits of phone number, or zip code -
    • -
    - - - You have chosen: {#each pin as digit}{digit}{/each} - -
    - {#each [0, 1, 2] as row} -
    - {#each [1, 2, 3] as num} - - {/each} -
    - {/each} - -
    -
    - {:else if pin_confirm.length < 4} -
    -

    - Please confirm your PIN code. - Enter the same PIN again -

    - - You have chosen: {#each pin_confirm as digit}{digit}{/each} - -
    - {#each [0, 1, 2] as row} -
    - {#each [1, 2, 3] as num} - - {/each} -
    - {/each} -
    -
    - {:else if !options} -
    - {#if pin.toString() === pin_confirm.toString()} - - Your PIN is confirmed as : {#each pin_confirm as digit}{digit}{/each} - -

    - Now let's enter a security phrase and a security image -

    -

    - As a verification step, this phrase and image will be presented to - you every time you are about to enter your pazzle and PIN in order - to unlock your wallet.
    - This security measure will prevent you from entering your pazzle and - PIN on malicious sites and apps. - - Every time you will use your wallet, if you do not see and - recognize your own security phrase and image before entering - your pazzle, please stop and DO NOT enter your pazzle, as you - would be the victim of a phishing attempt. - -

    -

    - Here are the rules for the security phrase and image : -

    -
      -
    • The phrase should be at least 10 characters long
    • -
    • - It should be something you will remember, but not something too - personal. -
    • -
    • - Do not enter your full name, nor address, nor phone number. -
    • -
    • - Instead, you can enter a quote, a small sentence that you like, - or something meaningless to others, but unique to you. -
    • -
    • - The image should be minimum 150x150px. There is no need to - provide more than 400x400px as it will be scaled down anyway. -
    • -
    • - We accept several formats like JPEG, PNG, GIF, WEBP and more. -
    • -
    • - The image should be unique to you. But it should not be too - personal neither. -
    • -
    • - Do not upload your face picture, this is not a profile pic. -
    • -
    • - The best would be a landscape you like or any other picture that - you will recognize as unique. -
    • -
    • - Please be aware that other people who are sharing this device - with you, will be able to see this image and phrase. -
    • -
    - -
    - {#if security_txt && security_img} -
    + {:else} +
    +
    +
    Your wallet is ready!
    +
    +
    + {#if download_link} + Please download your wallet and keep it in a safe location
    + + - {/if} - { - event.preventDefault(); - }} - on:change={handleChange} - > -

    - {#if mobile} - Tap to upload an image - {:else} - Click to select an image or - drag and drop + Download my wallet + + + +
    + {:else if !options.trusted} + Your wallet file has been downloaded into your "Downloads" + folder, with the name
    + {download_name}
    + Please move it to a safe and durable place.
    {/if} -

    - + Here below is your Pazzle. +
    + The order of each image is + important ! +
    +
    - - your security - {:else} - - You didn't enter the same PIN twice - - - {/if} -
    - {:else if !creating} -
    -

    - We are almost done !
    - There are 4 options to choose before we can create your wallet. Those - options can help you to use and keep your wallet. But we also want to - be careful with your security and privacy.

    - Remember that in any case, once your wallet will be created, you will - download a file that you should keep privately somewhere on your device, - USB key or hard-disk. This is the default way you can use and keep your - wallet. Now let's look at some options that can make your life a bit - easier. -

    -

    - Do you trust this device?
    - If you do, if this device is yours or is used by few trusted persons - of your family or workplace, and you would like to login again from this - device in the future, then you can save your wallet on this device. To - the contrary, if this device is public and shared by strangers, do not - save your wallet here. {#if !tauri_platform}By selecting this - option, you agree to save some cookies on your browser.{/if}
    - Save my wallet on this device? -

    -

    - Keep a copy in the cloud?
    - Are you afraid that you will loose the file containing your wallet? If - this would happen, your wallet would be lost forever, together with all - your documents. We can keep an encrypted copy of your wallet in our cloud. - Only you will be able to download it with a special link. You would have - to keep this link safely though. By selecting this option, you agree - to the - Terms of Service of our cloud. -
    - Save my wallet in the cloud? -

    -

    - Create a PDF file of your wallet? -
    - We can prepare for you a PDF file containing all the information of your - wallet, unencrypted. You should print this file and then delete the PDF - (and empty the trash). Keep this printed document in a safe place. It - contains all the information to regenerate your wallet in case you lost - access to it. -
    - Create a PDF of my wallet? -

    - {#if !options.cloud} -

    - Create a link to access your wallet easily? -
    - When you want to use your wallet on the web or from other devices, - we can help you find your wallet by creating a simple link accessible - from anywhere. Only you will have access to this link. In order to - do so, we will keep your wallet ID and some information about your - broker on our cloud servers. If you prefer to opt out, just uncheck - this option. By selecting this option, you agree to the - Terms of Service of our cloud. + {#each pazzle_emojis as emoji, index} +

    +
    + {index + 1} +
    +
    + +
    +
    +
    + {emoji.cat} +
    +
    + {emoji.code} +
    +
    +
    + {/each} +
    +
    - Create a link to my wallet? + -

    - {/if} - -
    - {:else if !error} - {#if !ready} -
    - Your wallet is being created... - - - - -
    - {:else} -
    - Your wallet is ready! - - {#if download_link} - Please download your wallet and keep it in a safe location
    - + Copy both on a piece of paper. + You should try to memorize the pazzle. Once you did, you won't need + the paper anymore. + +

    + Now click on "Continue to Login" and select your new wallet. +
    + It is important that you login with + this wallet + at least once + from this {#if tauri_platform}device{:else}browser tab{/if},
    + while connected to the internet, so your personal site can be created + on your broker.

    +
    -
    - {:else if !options.trusted} - Your wallet file has been downloaded into your "Downloads" folder, - with the name
    - {download_name}
    - Please move it to a safe and durable place.

    - {/if} - Here is your Pazzle:

    - {#each display_pazzle(ready.pazzle) as emoji} - {emoji}
    - {/each} -

    - Copy it on a piece of paper. Use that until you memorized it, then throw - it away.
    The order of each image is important!
    - Now click on "Continue to Login" and select your wallet.

    It is important that you login with this wallet at least once from - this {#if tauri_platform}device{:else}browser tab{/if},
    - while connected to the internet, so your personal site can be created - on your broker.

    - - - + + The pazzle and the mnemonic + will not be shown to you again. Please make sure, you have written them down. + +
    + + + + + +
    + +
    + {/if} + {:else} +
    + An error occurred ! + + + {error} + +
    {/if} - {:else} -
    - An error occurred ! - - - {error} - - -
    - {/if} -
    - {/if} +
    + {/if} +