error and success toasts in SPARQL Update Editor

pull/37/head
Niko PLP 4 months ago
parent 263df00e93
commit 95ed77e414
  1. 26
      ng-app/src/apps/SparqlUpdateEditor.svelte
  2. 38
      ng-app/src/lib/FullLayout.svelte
  3. 5
      ng-app/src/locales/en.json
  4. 59
      ng-app/src/store.ts
  5. 7
      ng-app/src/styles.css
  6. 4
      ng-app/src/tab.ts
  7. 7
      ng-sdk-js/src/lib.rs

@ -13,11 +13,14 @@
import { onMount, tick, onDestroy } from "svelte";
import {
sparql_update,
toast_error,
toast_success
} from "../store";
import {
in_memory_discrete, cur_tab
in_memory_discrete, open_viewer
} from "../tab";
import{ RocketLaunch } from "svelte-heros-v2";
import{ Sun, RocketLaunch } from "svelte-heros-v2";
import { t } from "svelte-i18n";
import { Button, Progressbar, Spinner, Alert } from "flowbite-svelte";
@ -35,17 +38,20 @@
}
});
const run = async () => {
try{
await sparql_update($in_memory_discrete);
toast_success($t("app.sparql_update_editor.success"));
} catch(e) {
toast_error(e);
}
}
</script>
<div class="flex-col">
<CodeMirror bind:value={$in_memory_discrete} lineWrapping extensions={[basicSetup,StreamLanguage.define(sparql)]} styles={{
<CodeMirror bind:value={$in_memory_discrete} lineWrapping useTab={false} extensions={[basicSetup,StreamLanguage.define(sparql)]} styles={{
"&": {
maxWidth: "100%",
},
}}/>
<button
@ -53,9 +59,17 @@
on:keypress={run}
class="select-none ml-2 mt-2 mb-10 text-white bg-primary-700 hover:bg-primary-700/90 focus:ring-4 focus:ring-primary-500/50 rounded-lg text-base p-2 text-center inline-flex items-center dark:focus:ring-primary-700/55"
>
<RocketLaunch class="mr-2 focus:outline-none" />
<RocketLaunch tabindex="-1" class="mr-2 focus:outline-none" />
Run Update
</button>
<button
on:click={open_viewer}
on:keypress={open_viewer}
class="select-none ml-2 mt-2 mb-10 text-gray-600 focus:ring-4 focus:ring-primary-500/50 rounded-lg text-base p-2 text-center inline-flex items-center dark:focus:ring-primary-700/55"
>
<Sun class="mr-2 focus:outline-none" tabindex="-1" />
View Graph
</button>
</div>

@ -17,6 +17,7 @@
SidebarWrapper,
Modal,
Toggle,
Toast,
} from "flowbite-svelte";
import { link, location, push } from "svelte-spa-router";
import MobileBottomBarItem from "./MobileBottomBarItem.svelte";
@ -34,7 +35,7 @@
available_editors, available_viewers, set_editor, set_viewer, set_view_or_edit, toggle_live_edit,
has_editor_chat, all_files_count, all_comments_count, nav_bar, save, hideMenu, show_modal_menu } from "../tab";
import {
active_session, redirect_after_login,
active_session, redirect_after_login, toasts, remove_toast
} from "../store";
import ZeraIcon from "./ZeraIcon.svelte";
@ -85,6 +86,9 @@
XMark,
ArrowLeft,
ArchiveBox,
CheckCircle,
XCircle,
ExclamationCircle,
} from "svelte-heros-v2";
import NavBar from "./components/NavBar.svelte";
@ -366,6 +370,27 @@
"mc":Sparkles,
};
const toast_color = {
"error":"red",
"warning":"orange",
"success":"green",
"info":"blue"
};
const toast_icon = {
"error": XCircle,
"warning": ExclamationCircle,
"success": CheckCircle,
"info": InformationCircle,
}
const customEv = new CustomEvent('loaded', {});
async function addLoaded(node) {
await tick()
node.dispatchEvent(customEv)
}
let asideClass = "w-48";
let spanClass = "flex-1 ml-3 whitespace-nowrap";
let nonActiveClass =
@ -647,6 +672,15 @@
</div>
</Modal>
{#each $toasts as toast, i}
<div class="toast fixed flex w-full max-w-xs" style="top:{16+i*74}px;" on:click|capture|stopPropagation={()=>{if (toast.timer) {clearTimeout(toast.timer);}; remove_toast(i);}}
use:addLoaded on:loaded={()=>{if (toast.level=="success") {toast.timer = setTimeout(()=>{remove_toast(i);}, toast.timeout || 10000);}}} >
<Toast color="{toast_color[toast.level]}" >
<Icon tabindex="-1" slot="icon" class="w-8 h-8 p-1 focus:outline-none" variation="outline" color="currentColor" icon={toast_icon[toast.level]} />
{toast.text}
</Toast>
</div>
{/each}
{#if mobile}
<div class="full-layout">
{#if !withoutNavBar}
@ -825,6 +859,7 @@
</div>
<div bind:this={top}></div>
<main class="mt-11 bg-white dark:bg-black" >
<slot />
</main>
</div>
@ -869,5 +904,4 @@
@apply inline-flex items-center border border-gray-200 text-base font-medium px-2 py-2 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 pr-3;
}
}
</style>

@ -1,4 +1,9 @@
{
"app": {
"sparql_update_editor" : {
"success": "SPARQL Update successful!"
}
},
"doc": {
"doc": "Document",
"protected_store": "Protected Profile",

@ -70,6 +70,62 @@ export const select_default_lang = async () => {
}
}
};
/**
* {
* level:"error",//"warning","success","info"
* text: ""
* }
*/
export const toasts = writable([
// {
// level:"error",
// text: "this is a serious error",
// },
// {
// level:"info",
// text: "this is an information for you that is very long long long and so long it doesnt fit",
// },
// {
// level:"warning",
// text: "this is a warning. be warned!",
// },
// {
// level:"success",
// text: "this is a success story",
// timeout: 5000,
// }
]);
export const remove_toast = function(idx) {
toasts.update((old)=>{
old.splice(idx,1);
return old;
});
}
export const toast = function(level, text) {
toasts.update((old)=>{
old.push({level,text});
return old;
});
}
export const toast_error = (text) => {
toast("error", text);
}
export const toast_info = (text) => {
toast("info", text);
}
export const toast_warning = (text) => {
toast("warning", text);
}
export const toast_success = (text) => {
toast("success", text);
}
export const scanned_qr_code = writable("");
export const wallet_from_import = writable<null | object>(null);
@ -324,8 +380,7 @@ export const digest_to_string = function(digest) {
export const sparql_update = async function(sparql:string) {
let session = get(active_session);
if (!session) {
console.error("no session");
return;
throw new Error("no session");
}
let nuri = "did:ng:"+get(cur_tab).branch.nuri;
await ng.sparql_update(session.session_id, nuri, sparql);

@ -197,6 +197,13 @@ h1 {
line-height: 1.1;
}
.toast {
left: 50%;
transform: translateX(-50%);
z-index: 49;
cursor: pointer;
}
input,
button {
border-radius: 8px;

@ -481,6 +481,10 @@ export const set_view_or_edit = (val:boolean) => {
});
}
export const open_viewer = () => {
set_view_or_edit(true);
}
export const cur_viewer = derived(cur_tab, ($cur_tab) => {
let app_name = $cur_tab.graph_or_discrete ? $cur_tab.graph_viewer : $cur_tab.discrete_viewer;
if (app_name) {

@ -319,11 +319,14 @@ pub async fn sparql_update(
session_id,
});
let _ = nextgraph::local_broker::app_request(request)
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(())
}
}
#[cfg(wasmpack_target = "nodejs")]

Loading…
Cancel
Save