Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8392edf408 | |||
| 9c80e0d77c | |||
| 0429e14715 | |||
| ff618f75fa | |||
| dbfd50bfa9 | |||
| ff65cfd958 | |||
| 877547df0d | |||
| 0db8ed4867 | |||
| 55ece851be | |||
| ed26f6e46f | |||
| c04dfe225c |
@@ -2,7 +2,15 @@
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { t } from '../translations.svelte';
|
||||
|
||||
let { classes='markdown', markdown=$bindable({source:'',rendered:''}), onclick = null, oncontextmenu = null, title='', wrapper = 'div' } = $props();
|
||||
let {
|
||||
classes='markdown',
|
||||
markdown=$bindable({source:'',rendered:''}),
|
||||
onclick = null,
|
||||
oncontextmenu = e => {},
|
||||
sheet = null,
|
||||
title='',
|
||||
wrapper = 'div'
|
||||
} = $props();
|
||||
let jspreadsheet = null;
|
||||
const regex = /@startsheet[\s\S]*?@endsheet/g;
|
||||
const number = /^[0-9.-]+$/
|
||||
@@ -31,16 +39,16 @@
|
||||
if (!markdown.rendered) return;
|
||||
let sheets = document.getElementsByClassName('spreadsheet');
|
||||
for (let i = 0; i < sheets.length; i++) {
|
||||
let sheet = sheets[i];
|
||||
let raw = sheet.innerHTML.trim();
|
||||
let current_sheet = sheets[i];
|
||||
let raw = current_sheet.innerHTML.trim();
|
||||
if (!jspreadsheet) {
|
||||
sheet.innerHTML = t('Loading spreadsheet library…');
|
||||
current_sheet.innerHTML = t('Loading spreadsheet library…');
|
||||
let module = await import('jspreadsheet-ce'); // path or package name
|
||||
await import('jspreadsheet-ce/dist/jspreadsheet.css');
|
||||
jspreadsheet = module.default ?? module;
|
||||
}
|
||||
if (!jspreadsheet) break; // break loop if library fails to load
|
||||
sheet.innerHTML = t('Processing spreadsheet data…');
|
||||
current_sheet.innerHTML = t('Processing spreadsheet data…');
|
||||
|
||||
|
||||
// Use parseCSV from the helpers
|
||||
@@ -60,14 +68,25 @@
|
||||
render: formatCell,
|
||||
width:`${len}0px`
|
||||
}});
|
||||
var w = window.innerWidth;
|
||||
if (classes == 'preview') w = w/2;
|
||||
let config = {
|
||||
worksheets : [{
|
||||
data:parsed,
|
||||
columns
|
||||
columns,
|
||||
tableOverflow: true,
|
||||
tableWidth: `${w}px`,
|
||||
}],
|
||||
onchange : (instance, cell, x, y, value) => update(instance, i)
|
||||
onchange : (instance, cell, x, y, value) => update(instance, i),
|
||||
oneditionstart : (instance, cell, x, y) => oncontextmenu({sheet:current_sheet.id, x,y})
|
||||
};
|
||||
let wb = jspreadsheet(document.getElementById(sheet.id), config);
|
||||
let wb = jspreadsheet(document.getElementById(current_sheet.id), config);
|
||||
if (sheet && sheet.sheet == current_sheet.id) {
|
||||
let cell = wb[0].getCellFromCoords(sheet.x, sheet.y);
|
||||
cell.scrollIntoView({block:'center'});
|
||||
wb[0].updateSelectionFromCoords(sheet.x, sheet.y);
|
||||
wb[0].openEditor(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
let start = 0;
|
||||
let stored_source = $state(store_id ? localStorage.getItem(store_id) : null);
|
||||
let timer = null;
|
||||
let sheet = null;
|
||||
|
||||
async function applyEdit(){
|
||||
let success = await onSet(editValue.source);
|
||||
@@ -80,8 +81,11 @@
|
||||
|
||||
|
||||
function oncontextmenu(evt){
|
||||
if (evt.target) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
}
|
||||
sheet = evt.sheet ? evt : null; // store position of activated cell to focus after editing starts
|
||||
startEdit();
|
||||
return false;
|
||||
}
|
||||
@@ -96,6 +100,10 @@
|
||||
measured(evt, evt.timeStamp - start);
|
||||
}
|
||||
|
||||
function onresize(evt){
|
||||
console.log('onresize()',evt);
|
||||
}
|
||||
|
||||
function ontouchstart(evt){
|
||||
evt.preventDefault();
|
||||
start = evt.timeStamp;
|
||||
@@ -137,8 +145,8 @@
|
||||
{#if stored_source}
|
||||
<span id="restore_markdown" onclick={restore} class="hint">{t('unsaved_content')}</span>
|
||||
{/if}
|
||||
<textarea bind:value={editValue.source} onkeyup={typed} autofocus={!simple}></textarea>
|
||||
<Display classes="preview" bind:markdown={editValue} />
|
||||
<textarea bind:value={editValue.source} onkeyup={typed} onresize={onresize} data="test" autofocus={!simple}></textarea>
|
||||
<Display classes="preview" bind:markdown={editValue} sheet={sheet} />
|
||||
{#if !simple}
|
||||
<div class="buttons">
|
||||
<button class="cancel" onclick={e => editing = false}>{t('cancel')}</button>
|
||||
|
||||
@@ -241,7 +241,7 @@
|
||||
</script>
|
||||
|
||||
<h2>{t('Stock')}</h2>
|
||||
<div class="grid3">
|
||||
<div class="stock grid3">
|
||||
<div class="locations">
|
||||
{#if top_level}
|
||||
{#each top_level as realm,idx}
|
||||
@@ -278,11 +278,11 @@
|
||||
</div>
|
||||
{#if item && data && data.users}
|
||||
<div class="tags">
|
||||
<span>{t('tags')}</span>
|
||||
<h4>{t('tags')}</h4>
|
||||
<Tags module="stock" id={item.id} user_list={data.users} />
|
||||
</div>
|
||||
<div class="notes">
|
||||
<span>{t('notes')}</span>
|
||||
<h4>{t('notes')}</h4>
|
||||
<Notes module="stock" entity_id={item.id} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
}
|
||||
|
||||
async function onCommit(wrapped){
|
||||
addTag(wrapped.display);
|
||||
addTag(wrapped.display.trim());
|
||||
}
|
||||
|
||||
function onSelect(dummy){}
|
||||
|
||||
@@ -150,6 +150,11 @@
|
||||
$effect(loadPage);
|
||||
onMount(connectToBus);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Umbrella – {t('wiki')}: {page?.title}</title>
|
||||
</svelte:head>
|
||||
|
||||
{#if page && page.versions}
|
||||
<div class="wiki page">
|
||||
<div class="versions">
|
||||
@@ -193,7 +198,10 @@
|
||||
{/if}
|
||||
{/if}
|
||||
<MarkdownEditor {editable} value={page.content} onSet={s => patch({content:s})} store_id="wiki/{page.id}/description" />
|
||||
<div class="tags">
|
||||
<h3>{t('tags')}</h3>
|
||||
<TagList module="wiki" id={page.id} user_list={Object.keys(page.members).map(id => +id)} />
|
||||
</div>
|
||||
<div class="notes">
|
||||
<h3>{t('notes')}</h3>
|
||||
<Notes module="wiki" entity_id={page.id} />
|
||||
|
||||
@@ -13,6 +13,8 @@ import de.srsoftware.umbrella.core.BaseDb;
|
||||
import de.srsoftware.umbrella.messagebus.events.Event;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
public class SqliteDb extends BaseDb implements JournalDb{
|
||||
public SqliteDb(Connection connection) {
|
||||
@@ -33,13 +35,14 @@ public class SqliteDb extends BaseDb implements JournalDb{
|
||||
var sql = """
|
||||
CREATE TABLE IF NOT EXISTS {0} (
|
||||
{1} INTEGER PRIMARY KEY,
|
||||
{2} INTEGER,
|
||||
{3} VARCHAR(255) NOT NULL,
|
||||
{4} VARCHAR(16) NOT NULL,
|
||||
{5} TEXT
|
||||
{2} LONG NOT NULL,
|
||||
{3} INTEGER,
|
||||
{4} VARCHAR(255) NOT NULL,
|
||||
{5} VARCHAR(16) NOT NULL,
|
||||
{6} TEXT
|
||||
);
|
||||
""";
|
||||
sql = format(sql,TABLE_JOURNAL,ID,USER_ID,MODULE,ACTION,DESCRIPTION);
|
||||
sql = format(sql,TABLE_JOURNAL,ID,TIMESTAMP,USER_ID,MODULE,ACTION,DESCRIPTION);
|
||||
try {
|
||||
db.prepareStatement(sql).execute();
|
||||
} catch (SQLException e) {
|
||||
@@ -50,8 +53,9 @@ public class SqliteDb extends BaseDb implements JournalDb{
|
||||
@Override
|
||||
public void logEvent(Event<?> event) {
|
||||
try {
|
||||
insertInto(TABLE_JOURNAL,USER_ID,MODULE,ACTION,DESCRIPTION)
|
||||
.values(event.initiator().id(), event.module(), event.eventType(), event.describe())
|
||||
var timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
|
||||
insertInto(TABLE_JOURNAL,TIMESTAMP,USER_ID,MODULE,ACTION,DESCRIPTION)
|
||||
.values(timestamp,event.initiator().id(), event.module(), event.eventType(), event.describe())
|
||||
.execute(db).close();
|
||||
} catch (SQLException e) {
|
||||
throw databaseException(ERROR_WRITE_EVENT,event.eventType(),event.initiator().name());
|
||||
|
||||
@@ -144,7 +144,7 @@ public class TagModule extends BaseHandler implements TagService {
|
||||
|
||||
@Override
|
||||
public void save(String module, long entityId, Collection<Long> userIds, Collection<String> tags) {
|
||||
tagDb.save(userIds,module,entityId,tags);
|
||||
tagDb.save(userIds,module,entityId,tags.stream().map(String::trim).toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -334,6 +334,10 @@ tr:hover .taglist .tag button {
|
||||
border-left: 1px solid #333 !important;
|
||||
}
|
||||
|
||||
.jss_worksheet tr:hover td input{
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
#app nav a{
|
||||
background: black;
|
||||
|
||||
@@ -325,6 +325,10 @@ tr:hover .taglist .tag button {
|
||||
border-left: 1px solid #333 !important;
|
||||
}
|
||||
|
||||
.jss_worksheet tr:hover td input{
|
||||
color: black;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
#app nav a{
|
||||
background: black;
|
||||
|
||||
@@ -524,6 +524,10 @@ a.wikilink{
|
||||
grid-template-columns: [left] 1fr [first] 1fr [second] 1fr [right]
|
||||
}
|
||||
|
||||
.stock.grid3{
|
||||
grid-template-columns: [left] 1fr [first] 1fr [second] 2fr [right]
|
||||
}
|
||||
|
||||
.grid3 .locations {
|
||||
grid-row-end: span 3;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user