JSON canvas initial

This commit is contained in:
2026-09-22 21:28:28 +02:00
parent 7b451bae86
commit b48d476b39
21 changed files with 3159 additions and 7 deletions
+43
View File
@@ -0,0 +1,43 @@
// canvas-actions.js — creating a canvas from a normal page.
//
// The canvas view itself owns everything else (rename, delete, editing); this
// only covers the one action that has to start from the page, since a folder
// with no canvases has no canvas view to reach.
//
// Reuses openModal and postReplace from page/actions.js, which the page
// template loads first.
// validCanvasName mirrors canvasNameRe in canvas.go. Checking here only buys a
// better error message — the server rejects the same set regardless.
function validCanvasName(name) {
if (!name || name.length > 100) return false;
if (name.charAt(0) === '.') return false;
return !/[\/\\]/.test(name);
}
function newCanvas() {
var input = document.createElement('input');
input.type = 'text';
input.className = 'input';
input.placeholder = 'Canvas name';
openModal({
title: 'New canvas',
body: input,
confirm: {
label: 'CREATE',
onConfirm: function () {
var name = input.value.trim();
if (!validCanvasName(name)) {
alert('A canvas name cannot be empty, start with a dot, or contain a slash.');
return;
}
closeModal();
var base = window.location.pathname;
if (base.slice(-1) !== '/') base += '/';
var target = base + '?canvas=' + encodeURIComponent(name);
postReplace(target + '&create=1', null, target);
}
}
});
}
+13 -1
View File
@@ -1,4 +1,5 @@
{{define "headScripts"}}<script src="/_/page/actions.js"></script>{{end}}
{{define "headScripts"}}<script src="/_/page/actions.js"></script>
<script src="/_/page/canvas-actions.js"></script>{{end}}
{{define "headerActions"}}{{if .CanEdit}}
<button class="btn btn-block" onclick="newPage()" title="New page (N)">NEW</button>
@@ -8,9 +9,20 @@
<button class="btn btn-block danger" onclick="deletePage()" title="Delete page">DELETE</button>
{{end}}
<a class="btn btn-block" href="?edit" title="Edit page (E)">EDIT</a>
<button class="btn btn-block" onclick="newCanvas()" title="New canvas">NEW CANVAS</button>
{{end}}{{end}}
{{define "content"}}
{{/* Canvases in this folder are alternative views of the same page, so they
read as a tab strip above the content rather than as rows in the file
listing (listEntries filters them out for exactly this reason). */}}
{{if .Canvases}}
<nav class="canvas-tabs row" aria-label="Page views">
<span class="canvas-tab is-active">PAGE</span>
{{range .Canvases}}<a class="canvas-tab" href="{{.URL}}">{{.Name}}</a>{{end}}
{{if .CanEdit}}<button type="button" class="canvas-tab canvas-tab-add" onclick="newCanvas()" title="New canvas">+</button>{{end}}
</nav>
{{end}}
{{if .Content}}
<div class="content">{{.Content}}</div>
{{end}}