234 lines
9.4 KiB
HTML
234 lines
9.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Session Summary — 2 July 2026</title>
|
|
<link rel="stylesheet" href="../../../../_assets_/styles.css">
|
|
<link rel="stylesheet" href="../../../../_assets_/nav.css">
|
|
</head>
|
|
<body>
|
|
<div class="page">
|
|
|
|
<header>
|
|
<p class="date">Thursday, 2 July 2026</p>
|
|
<h1>Roject — Editor Build</h1>
|
|
<p class="subtitle">Session summary: TypeScript conversion, UUID IDs, CLAUDE.md, and a full project editor with WYSIWYG HTML editing.</p>
|
|
</header>
|
|
|
|
<section>
|
|
<h2>What we built</h2>
|
|
|
|
<div class="card">
|
|
<h3>TypeScript Conversion</h3>
|
|
<p>
|
|
All server and frontend JavaScript converted to TypeScript. Server runs via
|
|
<code>ts-node</code> using <code>tsconfig.json</code>. Frontend components
|
|
compile from <code>src/components/</code> to <code>public/components/</code>
|
|
via <code>tsconfig.client.json</code> with <code>module: none</code> — no bundler,
|
|
each component is a self-contained global script. Interfaces added for all
|
|
data shapes.
|
|
</p>
|
|
<div class="tags">
|
|
<span class="tag">typescript</span>
|
|
<span class="tag">ts-node</span>
|
|
<span class="tag">tsconfig.client.json</span>
|
|
<span class="tag">module: none</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>UUID IDs</h3>
|
|
<p>
|
|
All entity IDs (users, groups, projects, members) switched from integers to
|
|
UUIDs via <code>crypto.randomUUID()</code>. This allows multiple server instances
|
|
to generate IDs independently without collision, enabling data merging and
|
|
parallel deployments without a central ID authority.
|
|
</p>
|
|
<div class="tags">
|
|
<span class="tag">crypto.randomUUID()</span>
|
|
<span class="tag">id: string</span>
|
|
<span class="tag">no extra dependency</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>Project File Storage</h3>
|
|
<p>
|
|
Creating a project now creates a real directory structure on the server under
|
|
<code>storage/<project-id>/root/</code>. A default <code>index.html</code>
|
|
with a Hello World <code><page-content></code> element is generated automatically.
|
|
A new <code>/api/files</code> route handles tree listing and file read/write
|
|
with path traversal protection.
|
|
</p>
|
|
<div class="tags">
|
|
<span class="tag">storage/</span>
|
|
<span class="tag">GET /api/files/:id/tree</span>
|
|
<span class="tag">GET /api/files/:id/*</span>
|
|
<span class="tag">PUT /api/files/:id/*</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>Editor Page</h3>
|
|
<p>
|
|
A full editor page (<code>/editor.html</code>) with a 3-panel layout: Left
|
|
(file tree), Center (HTML editor), Right (empty, accepts dropped tabs). Panels
|
|
are resizable via drag handles. Sections within a panel are arranged
|
|
side by side and can be split using the ⊟ button on each tab container.
|
|
Portrait mode shows one panel at a time, switched via a top bar.
|
|
</p>
|
|
<div class="tags">
|
|
<span class="tag"><editor-shell></span>
|
|
<span class="tag">3-panel layout</span>
|
|
<span class="tag">resize handles</span>
|
|
<span class="tag">portrait mode</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>Tab Container</h3>
|
|
<p>
|
|
A custom <code><tab-container></code> element manages tabs within each
|
|
panel section. Tabs are draggable between containers using the HTML5 Drag and
|
|
Drop API. A dirty dot (●) appears on tabs with unsaved changes. The ⊟ split
|
|
button creates a new side-by-side section in the same panel.
|
|
</p>
|
|
<div class="tags">
|
|
<span class="tag"><tab-container></span>
|
|
<span class="tag">drag and drop</span>
|
|
<span class="tag">dirty indicator</span>
|
|
<span class="tag">section split</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>HTML Editor Panel</h3>
|
|
<p>
|
|
A WYSIWYG editor that loads HTML documents in an iframe and makes the
|
|
<code><page-content></code> element contenteditable. Changes are tracked
|
|
via MutationObserver. Includes an undo/redo stack (up to 200 steps),
|
|
Ctrl+S save, and a save button that highlights when the document is dirty.
|
|
</p>
|
|
<div class="tags">
|
|
<span class="tag"><html-editor-panel></span>
|
|
<span class="tag">iframe WYSIWYG</span>
|
|
<span class="tag">MutationObserver</span>
|
|
<span class="tag">undo/redo</span>
|
|
<span class="tag">Ctrl+S</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3>File Tree Panel</h3>
|
|
<p>
|
|
A <code><file-tree-panel></code> component fetches and renders the
|
|
project's <code>root/</code> directory structure. HTML files are clickable
|
|
and open in the HTML editor. Directories are collapsible. Non-HTML files
|
|
are shown but not openable in this version.
|
|
</p>
|
|
<div class="tags">
|
|
<span class="tag"><file-tree-panel></span>
|
|
<span class="tag">collapsible dirs</span>
|
|
<span class="tag">HTML-only editing</span>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Key Decisions</h2>
|
|
|
|
<div class="decision">
|
|
<strong>LayoutPanel sections are arranged horizontally</strong>
|
|
<p>
|
|
Sections within a panel sit side by side (not stacked), so the Right panel
|
|
can hold an object graph next to an inspector. Each section can contain
|
|
multiple TabContainers stacked vertically. Portrait mode shows one section
|
|
at a time via a secondary tab row below the main panel switcher.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="decision">
|
|
<strong>Fixed 3-column structure, flexible rows</strong>
|
|
<p>
|
|
The editor has three named panels (Left, Center, Right). The column count
|
|
is fixed because portrait mode maps each column to one top-bar button — a
|
|
clean 1-to-1 relationship. Within each column, sections and tab containers
|
|
can be freely split and resized.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="decision">
|
|
<strong>Tab drag uses HTML5 DnD, not pointer events</strong>
|
|
<p>
|
|
HTML5 Drag and Drop handles cross-container tab moves via
|
|
<code>application/editor-tab</code> in dataTransfer. The source container
|
|
exposes an <code>extractTab()</code> method and the target calls
|
|
<code>receiveTab()</code>, preserving the panel's DOM element and state
|
|
across moves.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="decision">
|
|
<strong>EditorState on window, not imported</strong>
|
|
<p>
|
|
Since <code>module: none</code> forbids imports between frontend files,
|
|
shared state lives on <code>window.editorState</code>, initialised
|
|
synchronously in <code>editor-shell</code> before any child component
|
|
connects. Other components wait via <code>customElements.whenDefined()</code>
|
|
before accessing it.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="decision">
|
|
<strong>Real-time collaboration deferred</strong>
|
|
<p>
|
|
The spec described multi-user selections but building WebSocket sync would
|
|
have consumed the full session. The document/state model is designed for it —
|
|
EditorState can emit events that a future sync layer hooks into.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>Project Structure</h2>
|
|
<div class="card">
|
|
<p>
|
|
<code>server/storage.ts</code> — project file storage helpers<br>
|
|
<code>server/routes/files.ts</code> — file tree + read/write API<br>
|
|
<code>storage/</code> — project file directories (auto-created)<br>
|
|
<code>src/components/editor-shell/</code> — main editor layout + EditorState<br>
|
|
<code>src/components/tab-container/</code> — tabbed panel with drag-drop<br>
|
|
<code>src/components/file-tree-panel/</code> — project file browser<br>
|
|
<code>src/components/html-editor-panel/</code> — WYSIWYG iframe editor<br>
|
|
<code>public/editor.html</code> — editor page entry point<br>
|
|
<code>CLAUDE.md</code> — project conventions (UUID IDs, raw CSS, custom elements)
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>What is missing</h2>
|
|
<div class="card">
|
|
<p>
|
|
Real-time multi-user collaboration and shared selections are not implemented.
|
|
The file tree is read-only — creating, renaming, and deleting files from the
|
|
editor is not yet supported. The Right panel is empty by default and requires
|
|
manual tab dragging to populate. Portrait secondary section switching (when a
|
|
panel has multiple side-by-side sections) is defined but not yet wired up as
|
|
a secondary tab row.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<footer>
|
|
Roject — session log — 2 July 2026
|
|
</footer>
|
|
|
|
</div>
|
|
<script>var NAV_ROOT = '../../../../';</script>
|
|
<script src="../../../../_assets_/nav-data.js"></script>
|
|
<script src="../../../../_assets_/nav.js"></script>
|
|
</body>
|
|
</html>
|