parent
ea38ac7d2a
commit
456ddf7e30
@ -0,0 +1,130 @@ |
||||
<!-- |
||||
// 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 { onMount, tick, onDestroy } from "svelte"; |
||||
import { Button, Progressbar, Spinner, Alert } from "flowbite-svelte"; |
||||
import { |
||||
toast_error, |
||||
toast_success, |
||||
reset_toasts, |
||||
display_error, |
||||
live_discrete_update, |
||||
discrete_update |
||||
} from "../store"; |
||||
import { |
||||
cur_tab_register_on_save, |
||||
cur_tab_deregister_on_save, |
||||
cur_tab_branch_class |
||||
} from "../tab"; |
||||
import { t } from "svelte-i18n"; |
||||
import wasmUrl from "@automerge/automerge/automerge.wasm?url"; |
||||
import { next as A } from "@automerge/automerge/slim"; |
||||
|
||||
import AMap from "./automerge/AMap.svelte"; |
||||
|
||||
export let commits = {}; |
||||
|
||||
export let readonly = false; |
||||
|
||||
let doc = {}; |
||||
|
||||
let safari_error = false; |
||||
|
||||
function concatenate(uint8arrays) { |
||||
const totalLength = uint8arrays.reduce( |
||||
(total, uint8array) => total + uint8array.byteLength, |
||||
0 |
||||
); |
||||
|
||||
const result = new Uint8Array(totalLength); |
||||
|
||||
let offset = 0; |
||||
uint8arrays.forEach((uint8array) => { |
||||
result.set(uint8array, offset); |
||||
offset += uint8array.byteLength; |
||||
}); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
let root_proxy; |
||||
|
||||
onMount(async ()=>{ |
||||
try { |
||||
await A.initializeWasm(wasmUrl); |
||||
} catch (e) { |
||||
toast_error($t("errors.no_wasm_on_old_safari")); |
||||
safari_error = true; |
||||
return; |
||||
} |
||||
doc = A.init(); |
||||
if (!readonly) { |
||||
cur_tab_register_on_save(async (updates)=>{ |
||||
|
||||
let update = concatenate(updates); |
||||
await live_discrete_update(update, "Automerge", commits.heads); |
||||
}); |
||||
} |
||||
|
||||
let history = commits.discrete?.registerOnUpdate((update) => { |
||||
doc = A.loadIncremental(doc, update.Automerge); |
||||
}); |
||||
for (const h of history) { |
||||
doc = A.loadIncremental(doc, h.Automerge); |
||||
} |
||||
|
||||
A.change(doc, (d) => { |
||||
root_proxy = d; |
||||
}); |
||||
|
||||
}); |
||||
|
||||
async function update(event) { |
||||
//console.log("got update", event) |
||||
doc = event.detail.d; |
||||
try { |
||||
await discrete_update(event.detail.u, "Automerge", commits.heads); |
||||
} catch (e){ |
||||
toast_error(display_error(e)); |
||||
} |
||||
} |
||||
|
||||
onDestroy(async ()=>{ |
||||
commits.discrete?.deregisterOnUpdate(); |
||||
if (!readonly) { |
||||
await cur_tab_deregister_on_save(); |
||||
} |
||||
}); |
||||
|
||||
async function updateText(event) { |
||||
doc = A.change(doc, (d) => { |
||||
A.updateText(d, event.detail.p, event.detail.s) |
||||
}); |
||||
let update = A.getLastLocalChange(doc); |
||||
try { |
||||
await discrete_update(update, "Automerge", commits.heads); |
||||
} catch (e){ |
||||
toast_error(display_error(e)); |
||||
} |
||||
} |
||||
|
||||
</script> |
||||
{#if safari_error} |
||||
<Alert class="m-2" color="red">{$t("errors.no_wasm_on_old_safari")}</Alert> |
||||
{:else} |
||||
<div class="grow mb-20" style="min-height:300px;"> |
||||
<AMap {readonly} value={doc} {doc} on:update={update} on:updateText={updateText} proxy={root_proxy}/> |
||||
</div> |
||||
{/if} |
||||
<style> |
||||
|
||||
</style> |
@ -0,0 +1,74 @@ |
||||
<!-- |
||||
// 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 { onMount, tick, onDestroy } from "svelte"; |
||||
import { Button, Progressbar, Spinner, Alert } from "flowbite-svelte"; |
||||
import { |
||||
toast_error, |
||||
toast_success, |
||||
reset_toasts, |
||||
display_error, |
||||
live_discrete_update, |
||||
discrete_update |
||||
} from "../store"; |
||||
import { |
||||
cur_tab_register_on_save, |
||||
cur_tab_deregister_on_save, |
||||
cur_tab_branch_class |
||||
} from "../tab"; |
||||
import { t } from "svelte-i18n"; |
||||
import wasmUrl from "@automerge/automerge/automerge.wasm?url"; |
||||
import { next as A } from "@automerge/automerge/slim"; |
||||
import Highlight, { LineNumbers } from "svelte-highlight"; |
||||
import json from "svelte-highlight/languages/json"; |
||||
import "svelte-highlight/styles/github.css"; |
||||
|
||||
export let commits = {}; |
||||
|
||||
let doc = {}; |
||||
let source = ""; |
||||
|
||||
let safari_error = false; |
||||
|
||||
onMount(async ()=>{ |
||||
try { |
||||
await A.initializeWasm(wasmUrl); |
||||
} catch (e) { |
||||
toast_error($t("errors.no_wasm_on_old_safari")); |
||||
safari_error = true; |
||||
return; |
||||
} |
||||
doc = A.init(); |
||||
|
||||
let history = commits.discrete?.registerOnUpdate((update) => { |
||||
doc = A.loadIncremental(doc, update.Automerge); |
||||
source = JSON.stringify(doc,null , 4 ); |
||||
}); |
||||
for (const h of history) { |
||||
doc = A.loadIncremental(doc, h.Automerge); |
||||
} |
||||
source = JSON.stringify(doc,null , 4 ); |
||||
}); |
||||
|
||||
onDestroy(async ()=>{ |
||||
commits.discrete?.deregisterOnUpdate(); |
||||
}); |
||||
|
||||
</script> |
||||
|
||||
{#if safari_error} |
||||
<Alert class="m-2" color="red">{$t("errors.no_wasm_on_old_safari")}</Alert> |
||||
{:else if source} |
||||
<Highlight language={json} code={source} class="mb-10" let:highlighted > |
||||
<LineNumbers {highlighted} wrapLines hideBorder /> |
||||
</Highlight> |
||||
{/if} |
@ -0,0 +1,19 @@ |
||||
<!-- |
||||
// 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 AutomergeEditor from "./AutomergeEditor.svelte"; |
||||
|
||||
export let commits = {}; |
||||
|
||||
</script> |
||||
|
||||
<AutomergeEditor {commits} readonly={true}/> |
@ -0,0 +1,36 @@ |
||||
|
||||
<!-- |
||||
// 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 { createEventDispatcher } from 'svelte'; |
||||
import { Toggle } from 'flowbite-svelte'; |
||||
const dispatch = createEventDispatcher(); |
||||
|
||||
export let value; |
||||
|
||||
function update() { |
||||
temp_val = value; |
||||
} |
||||
|
||||
let temp_val; |
||||
$: value, update(); |
||||
|
||||
const change = (event) => { |
||||
dispatch('updateScalar', { |
||||
v: temp_val, |
||||
}); |
||||
} |
||||
|
||||
</script> |
||||
|
||||
<Toggle bind:checked={temp_val} on:change={change} /> |
@ -0,0 +1,65 @@ |
||||
|
||||
<!-- |
||||
// 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 { createEventDispatcher } from 'svelte'; |
||||
const dispatch = createEventDispatcher(); |
||||
|
||||
import { next as A } from "@automerge/automerge/slim"; |
||||
|
||||
export let value; |
||||
|
||||
export let proxy; |
||||
|
||||
export let doc; |
||||
|
||||
async function increment(val) { |
||||
|
||||
doc = A.change(doc, (d) => { |
||||
proxy.increment(val); |
||||
}); |
||||
let update = A.getLastLocalChange(doc); |
||||
dispatch('update', { |
||||
u: update, |
||||
d: doc, |
||||
}); |
||||
|
||||
} |
||||
|
||||
function update() { |
||||
temp_val = value.value; |
||||
previous_val = value.value; |
||||
} |
||||
|
||||
let temp_val; |
||||
let previous_val; |
||||
$: value, update(); |
||||
|
||||
const inc = async () => { temp_val+=1; await increment(1) } |
||||
const dec = async () => { temp_val-=1; await increment(-1) } |
||||
const change = async () => { let diff = Math.round(temp_val - previous_val); if (diff !==0) await increment(diff); else temp_val = previous_val; } |
||||
|
||||
</script> |
||||
|
||||
<div class="relative flex items-center max-w-[8rem]"> |
||||
<button type="button" on:click={dec} class="bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 hover:bg-gray-200 border border-gray-300 rounded-s-lg p-2 h-7 focus:ring-gray-100 dark:focus:ring-gray-700 focus:ring-2 focus:outline-none"> |
||||
<svg class="w-3 h-3 text-gray-900 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 2"> |
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h16"/> |
||||
</svg> |
||||
</button> |
||||
<input bind:value={temp_val} on:change={change} type="text" id="quantity-input" data-input-counter aria-describedby="helper-text-explanation" style="max-width:70px;" class="bg-gray-50 border-x-0 border-gray-300 h-7 text-center text-gray-900 text-sm focus:ring-blue-500 focus:border-blue-500 block w-full py-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="999" required /> |
||||
<button type="button" on:click={inc} class="bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-600 dark:border-gray-600 hover:bg-gray-200 border border-gray-300 rounded-e-lg p-2 h-7 focus:ring-gray-100 dark:focus:ring-gray-700 focus:ring-2 focus:outline-none"> |
||||
<svg class="w-3 h-3 text-gray-900 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18"> |
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 1v16M1 9h16"/> |
||||
</svg> |
||||
</button> |
||||
</div> |
@ -0,0 +1,73 @@ |
||||
|
||||
<!-- |
||||
// 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 { onMount } from "svelte"; |
||||
import { createEventDispatcher } from 'svelte'; |
||||
const dispatch = createEventDispatcher(); |
||||
import "flowbite/dist/flowbite.min.js" |
||||
|
||||
export let value; |
||||
|
||||
function update() { |
||||
time = value.toLocaleTimeString([],{ |
||||
hour: "2-digit", |
||||
minute: "2-digit" |
||||
}); |
||||
date = value.toLocaleDateString([],{ |
||||
year: "numeric", |
||||
month: "numeric", |
||||
day: "numeric", |
||||
}); |
||||
} |
||||
|
||||
let time; |
||||
let date; |
||||
$: value, update(); |
||||
|
||||
const change = (event) => { |
||||
|
||||
let newval = new Date(date.split('/').reverse().join('/')+" "+time); |
||||
console.log(time, date, newval) |
||||
|
||||
dispatch('updateScalar', { |
||||
v: newval, |
||||
}); |
||||
} |
||||
|
||||
|
||||
</script> |
||||
|
||||
<div class="flex flex-wrap"> |
||||
|
||||
<div class="relative" style="max-width: 129px;"> |
||||
|
||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none"> |
||||
<svg class="w-4 h-4 text-primary-700 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"> |
||||
<path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/> |
||||
</svg> |
||||
</div> |
||||
<input type="text" style="max-width: 129px;cursor:pointer;" on:change={change} bind:value={date} datepicker-format="dd/mm/yyyy" |
||||
class="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 ps-10 p-2.5 px-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Select date"> |
||||
|
||||
</div> |
||||
|
||||
<div class="relative" style="max-width: 129px;"> |
||||
<div class="absolute inset-y-0 end-0 top-0 flex items-center pe-3.5 pointer-events-none"> |
||||
<svg class="w-4 h-4 text-primary-700 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24"> |
||||
<path fill-rule="evenodd" d="M2 12C2 6.477 6.477 2 12 2s10 4.477 10 10-4.477 10-10 10S2 17.523 2 12Zm11-4a1 1 0 1 0-2 0v4a1 1 0 0 0 .293.707l3 3a1 1 0 0 0 1.414-1.414L13 11.586V8Z" clip-rule="evenodd"/> |
||||
</svg> |
||||
</div> |
||||
<input bind:value={time} on:change={change} type="time" class="bg-gray-50 border leading-none 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-white dark:focus:ring-blue-500 dark:focus:border-blue-500" /> |
||||
</div> |
||||
</div> |
@ -0,0 +1,118 @@ |
||||
|
||||
<!-- |
||||
// 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 { new_value, find_type, new_prop_types } from "./utils"; |
||||
|
||||
import AValue from "./AValue.svelte"; |
||||
import { createEventDispatcher } from 'svelte'; |
||||
const dispatch = createEventDispatcher(); |
||||
|
||||
import { next as A } from "@automerge/automerge/slim"; |
||||
|
||||
export let value; |
||||
|
||||
export let proxy; |
||||
|
||||
export let doc; |
||||
|
||||
export let path = undefined; |
||||
|
||||
export let readonly = false; |
||||
|
||||
let props = []; |
||||
$: props = value.map((v,i)=> { |
||||
let ar = [i]; |
||||
ar.push(v); |
||||
let type = find_type(v); |
||||
ar.push(type); |
||||
const with_proxy = type == "counter" || type == "map" || type == "list" ; |
||||
if (with_proxy) { |
||||
ar.push(proxy[i]); |
||||
} |
||||
return ar; |
||||
}); |
||||
|
||||
function add_prop() { |
||||
|
||||
doc = A.change(doc, (d) => { |
||||
proxy.push(new_value(new_prop_type_selected)) |
||||
}); |
||||
let update = A.getLastLocalChange(doc); |
||||
dispatch('update', { |
||||
u: update, |
||||
d: doc, |
||||
}); |
||||
|
||||
} |
||||
|
||||
let new_prop_type_selected = 'text'; |
||||
|
||||
function updateText(event) { |
||||
if (path !== undefined) event.detail.p.unshift(path); |
||||
dispatch('updateText', { |
||||
s: event.detail.s, |
||||
p: event.detail.p, |
||||
}); |
||||
} |
||||
|
||||
function updateScalar(prop, event) { |
||||
doc = A.change(doc, (d) => { |
||||
proxy[prop] = event.detail.v; |
||||
}); |
||||
let update = A.getLastLocalChange(doc); |
||||
dispatch('update', { |
||||
u: update, |
||||
d: doc, |
||||
}); |
||||
} |
||||
</script> |
||||
|
||||
<table class="border-collapse border border-slate-400"> |
||||
<thead> |
||||
<tr class="bg-slate-100"> |
||||
<th>List</th> |
||||
<th class="text-sm"> |
||||
{#if !readonly} |
||||
<span class="ml-2">Push entry at the end of list:</span> |
||||
<select bind:value={new_prop_type_selected}> |
||||
{#each new_prop_types as value}<option value={value.value}>{value.name}</option>{/each} |
||||
</select> |
||||
<button on:click={add_prop}>Add</button> |
||||
{/if} |
||||
</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
{#each props as prop} |
||||
<tr> |
||||
<td>{prop[0]}</td> |
||||
<!-- <td>{prop[2]}</td> --> |
||||
<td> |
||||
<AValue {readonly} type={prop[2]} value={prop[1]} {doc} on:updateText={updateText} on:update proxy={prop[3]} path={prop[0]} on:updateScalar={(event)=>updateScalar(prop[0],event)} /> |
||||
</td> |
||||
<!-- <td>{prop[3]?.constructor.name || ""}</td> --> |
||||
</tr> |
||||
{/each} |
||||
</tbody> |
||||
</table> |
||||
|
||||
<style> |
||||
td { |
||||
padding:5px; |
||||
} |
||||
tr { |
||||
border-bottom: 1px; |
||||
border-style: dashed; |
||||
border-top: none; |
||||
} |
||||
</style> |
@ -0,0 +1,131 @@ |
||||
|
||||
<!-- |
||||
// 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 AValue from "./AValue.svelte"; |
||||
import { createEventDispatcher } from 'svelte'; |
||||
import { new_value, find_type, new_prop_types } from "./utils"; |
||||
|
||||
const dispatch = createEventDispatcher(); |
||||
|
||||
import { next as A } from "@automerge/automerge/slim"; |
||||
|
||||
export let value; |
||||
|
||||
export let proxy; |
||||
|
||||
export let doc; |
||||
|
||||
export let path = undefined; |
||||
|
||||
export let readonly = false; |
||||
|
||||
let props = []; |
||||
$: props = Object.entries(value).map((ar)=> { |
||||
|
||||
let type = find_type(ar[1]); |
||||
ar.push(type); |
||||
const with_proxy = type == "counter" || type == "map" || type == "list" ; |
||||
if (with_proxy) { |
||||
ar.push(proxy[ar[0]]); |
||||
} |
||||
return ar; |
||||
}); |
||||
|
||||
let new_prop = ""; |
||||
function add_prop() { |
||||
if (new_prop.trim().length > 0) { |
||||
doc = A.change(doc, (d) => { |
||||
proxy[new_prop] = new_value(new_prop_type_selected); |
||||
}); |
||||
let update = A.getLastLocalChange(doc); |
||||
dispatch('update', { |
||||
u: update, |
||||
d: doc, |
||||
}); |
||||
new_prop = ""; |
||||
} |
||||
} |
||||
|
||||
let new_prop_type_selected = 'text'; |
||||
|
||||
function updateText(event) { |
||||
if (path!== undefined) event.detail.p.unshift(path); |
||||
dispatch('updateText', { |
||||
s: event.detail.s, |
||||
p: event.detail.p, |
||||
}); |
||||
} |
||||
|
||||
function updateScalar(prop, event) { |
||||
|
||||
doc = A.change(doc, (d) => { |
||||
proxy[prop] = event.detail.v; |
||||
}); |
||||
let update = A.getLastLocalChange(doc); |
||||
dispatch('update', { |
||||
u: update, |
||||
d: doc, |
||||
}); |
||||
} |
||||
|
||||
</script> |
||||
|
||||
<table class="border-collapse border border-slate-400"> |
||||
<thead> |
||||
<tr class="bg-slate-100"> |
||||
<th>Map</th> |
||||
<th class="text-sm"> |
||||
{#if !readonly} |
||||
<span>Add property:</span> |
||||
<input placeholder="Enter the name of property" bind:value={new_prop} class="prop-input"/> |
||||
<select bind:value={new_prop_type_selected}> |
||||
{#each new_prop_types as value}<option value={value.value}>{value.name}</option>{/each} |
||||
</select> |
||||
<button on:click={add_prop}>Add</button> |
||||
{/if} |
||||
</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
{#each props as prop} |
||||
<tr> |
||||
<td>{prop[0]}</td> |
||||
<!-- <td>{prop[2]}</td> --> |
||||
<td> |
||||
<AValue {readonly} type={prop[2]} value={prop[1]} {doc} on:updateText={updateText} on:update proxy={prop[3]} path={prop[0]} on:updateScalar={(event)=>updateScalar(prop[0],event)} /> |
||||
</td> |
||||
<!-- <td>{prop[3]?.constructor.name || ""}</td> --> |
||||
</tr> |
||||
{/each} |
||||
</tbody> |
||||
</table> |
||||
|
||||
|
||||
<style> |
||||
td { |
||||
padding:5px; |
||||
min-width:80px; |
||||
} |
||||
tr { |
||||
border-bottom: 1px; |
||||
border-style: dashed; |
||||
border-top: none; |
||||
|
||||
} |
||||
@screen xs { |
||||
.prop-input { |
||||
min-width: 250px; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,42 @@ |
||||
|
||||
<!-- |
||||
// 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 { createEventDispatcher } from 'svelte'; |
||||
import { Input } from 'flowbite-svelte'; |
||||
const dispatch = createEventDispatcher(); |
||||
|
||||
export let value; |
||||
|
||||
function update() { |
||||
temp_val = value; |
||||
previous_val = value; |
||||
} |
||||
|
||||
let temp_val; |
||||
let previous_val; |
||||
$: value, update(); |
||||
|
||||
const change = (event) => { |
||||
|
||||
let newval = parseFloat(event.target.value.replace(",", ".")); |
||||
//console.log(previous_val, temp_val, newval) |
||||
if (isNaN(newval) || previous_val === newval) return; |
||||
dispatch('updateScalar', { |
||||
v: newval, |
||||
}); |
||||
} |
||||
|
||||
</script> |
||||
|
||||
<Input style="max-width: 129px;" bind:value={temp_val} on:change={change} on:keyup={change} type="number" /> |
@ -0,0 +1,32 @@ |
||||
|
||||
<!-- |
||||
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers |
||||
// All rights reserved. |
||||
// Licensed under the Apache License, Version 2.0 |
||||
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0> |
||||
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>, |
||||
// at your option. All files in the project carrying such |
||||
// notice may not be copied, modified, or distributed except |
||||
// according to those terms. |
||||
--> |
||||
|
||||
<script lang="ts"> |
||||
|
||||
import { createEventDispatcher } from 'svelte'; |
||||
import { Input } from 'flowbite-svelte'; |
||||
const dispatch = createEventDispatcher(); |
||||
|
||||
export let value; |
||||
|
||||
export let path; |
||||
|
||||
const change = (event) => { |
||||
dispatch('updateText', { |
||||
s: event.target.value, |
||||
p: [path] |
||||
}); |
||||
} |
||||
|
||||
</script> |
||||
|
||||
<Input bind:value={value} on:keyup={change} type="text" placeholder="Enter some text" /> |
@ -0,0 +1,87 @@ |
||||
|
||||
<!-- |
||||
// 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 AMap from "./AMap.svelte"; |
||||
import AList from "./AList.svelte"; |
||||
import ACounter from "./ACounter.svelte"; |
||||
import AString from "./AString.svelte"; |
||||
import ABoolean from "./ABoolean.svelte"; |
||||
import ANumber from "./ANumber.svelte"; |
||||
import ADate from "./ADate.svelte"; |
||||
|
||||
export let value; |
||||
|
||||
export let type; |
||||
|
||||
export let doc; |
||||
|
||||
export let proxy; |
||||
|
||||
export let path; |
||||
|
||||
export let readonly = false; |
||||
|
||||
function render_date(value) { |
||||
let time = value.toLocaleTimeString([],{ |
||||
hour: "2-digit", |
||||
minute: "2-digit" |
||||
}); |
||||
let date = value.toLocaleDateString([],{ |
||||
year: "numeric", |
||||
month: "numeric", |
||||
day: "numeric", |
||||
}); |
||||
return `${date} ${time}`; |
||||
} |
||||
|
||||
</script> |
||||
|
||||
|
||||
{#if type==="map"} |
||||
<AMap {readonly} {value} {doc} on:updateText on:update {proxy} {path}/> |
||||
{:else if type==="list"} |
||||
<AList {readonly} {value} {doc} on:updateText on:update {proxy} {path}/> |
||||
{:else if type==="counter"} |
||||
{#if !readonly} |
||||
<ACounter {value} {doc} on:update {proxy} /> |
||||
{:else} |
||||
: {value} |
||||
{/if} |
||||
{:else if type==="text"} |
||||
{#if !readonly} |
||||
<AString {value} on:updateText {path}/> |
||||
{:else} |
||||
: {value} |
||||
{/if} |
||||
{:else if type==="boolean"} |
||||
{#if !readonly} |
||||
<ABoolean {value} on:updateScalar/> |
||||
{:else} |
||||
: {value} |
||||
{/if} |
||||
{:else if type==="number"} |
||||
{#if !readonly} |
||||
<ANumber {value} on:updateScalar/> |
||||
{:else} |
||||
: {value} |
||||
{/if} |
||||
{:else if value?.toDateString || type==="timestamp"} |
||||
{#if !readonly} |
||||
<ADate {value} on:updateScalar/> |
||||
{:else} |
||||
: {render_date(value)} |
||||
{/if} |
||||
{:else} |
||||
: {value} |
||||
{/if} |
@ -0,0 +1,81 @@ |
||||
// Copyright (c) 2022-2024 Niko Bonnieure, Par le Peuple, NextGraph.org developers
|
||||
// All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
|
||||
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
import { next as A } from "@automerge/automerge/slim"; |
||||
|
||||
const UINT = Symbol.for("_am_uint") |
||||
const INT = Symbol.for("_am_int") |
||||
const F64 = Symbol.for("_am_f64") |
||||
const COUNTER = Symbol.for("_am_counter") |
||||
const TEXT = Symbol.for("_am_text") |
||||
|
||||
export function find_type(value) { |
||||
switch (typeof value) { |
||||
case "object": |
||||
if (value == null) { |
||||
return "null" |
||||
} else if (value[UINT]) { |
||||
return "uint" |
||||
} else if (value[INT]) { |
||||
return "number" |
||||
} else if (value[F64]) { |
||||
return "number" |
||||
} else if (value[COUNTER]) { |
||||
return "counter" |
||||
} else if (value instanceof Date) { |
||||
return "timestamp" |
||||
} else if (value instanceof A.RawString) { |
||||
return "str" |
||||
} else if (value instanceof Text) { |
||||
return "text" |
||||
} else if (value instanceof Uint8Array) { |
||||
return "bytes" |
||||
} else if (value instanceof Array) { |
||||
return "list" |
||||
} else if (Object.getPrototypeOf(value) === Object.getPrototypeOf({})) { |
||||
return "map" |
||||
} |
||||
case "boolean": |
||||
return "boolean" |
||||
case "number": |
||||
if (Number.isInteger(value)) { |
||||
return "number" |
||||
} else { |
||||
return "number" |
||||
} |
||||
case "string": |
||||
return "text" |
||||
} |
||||
} |
||||
|
||||
export const new_prop_types = [ |
||||
{value:'text',name:"text"}, |
||||
{value:'number',name:"number"}, |
||||
{value:'counter',name:"counter"}, |
||||
{value:'boolean',name:"boolean"}, |
||||
{value:'null',name:"null"}, |
||||
{value:'timestamp',name:"timestamp"}, |
||||
{value:'map',name:"map"}, |
||||
{value:'list',name:"list"}, |
||||
{value:'bytes',name:"bytes"} |
||||
]; |
||||
|
||||
export function new_value(new_prop_type_selected) { |
||||
switch (new_prop_type_selected) { |
||||
case 'text': return ''; |
||||
case 'map': return {}; |
||||
case 'list': return []; |
||||
case 'counter': return new A.Counter(); |
||||
case 'number': return 0; |
||||
case 'boolean': return false; |
||||
case 'null': return null; |
||||
case 'timestamp': return new Date(); |
||||
case 'bytes': return new Uint8Array(0); |
||||
} |
||||
} |
Loading…
Reference in new issue