ops design and app

add more comments feature, more tags feature, and other frontend updates
This commit is contained in:
2026-06-09 18:27:59 -04:00
parent 1e939f307d
commit 04a1f2bb6d
33 changed files with 3276 additions and 113 deletions

View File

@@ -62,6 +62,8 @@
{{ template "document_edit_content" .Data }}
{{ else if eq .BodyTemplate "search_content" }}
{{ template "search_content" .Data }}
{{ else if eq .BodyTemplate "tag_content" }}
{{ template "tag_content" .Data }}
{{ else if eq .BodyTemplate "login_content" }}
{{ template "login_content" .Data }}
{{ else if eq .BodyTemplate "setup_content" }}
@@ -72,6 +74,8 @@
{{ template "account_content" .Data }}
{{ else if eq .BodyTemplate "token_create_content" }}
{{ template "token_create_content" .Data }}
{{ else if eq .BodyTemplate "permissions_content" }}
{{ template "permissions_content" .Data }}
{{ else if eq .BodyTemplate "device_verify_content" }}
{{ template "device_verify_content" .Data }}
{{ else if eq .BodyTemplate "error_content" }}
@@ -108,6 +112,8 @@
<script src="/static/render.js" defer></script>
<script src="/static/comments.js" defer></script>
<script src="/static/archive.js" defer></script>
<script src="/static/permissions.js" defer></script>
<script src="/static/tags.js" defer></script>
</body>
</html>

View File

@@ -2,8 +2,18 @@
{{ define "document_content" }}
<section class="workspace-shell workspace-shell--document">
<div class="mobile-drawer-backdrop" data-mobile-drawer-backdrop aria-hidden="true"></div>
{{ template "browser" .Browser }}
<article class="document-shell" data-document-path="{{ .Path }}" data-document-hash="{{ .Hash }}">
<article class="document-shell" data-document-path="{{ .Path }}" data-document-hash="{{ .Hash }}" data-can-comment="{{ .CanComment }}">
<div class="document-mobile-bar">
<button class="document-mobile-bar__btn document-mobile-bar__btn--picker" type="button" data-toggle-picker aria-label="Open file picker" aria-expanded="false">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="6" x2="20" y2="6"></line><line x1="4" y1="12" x2="20" y2="12"></line><line x1="4" y1="18" x2="20" y2="18"></line></svg>
</button>
<span class="document-mobile-bar__title" aria-hidden="true">{{ .Title }}</span>
<button class="document-mobile-bar__btn document-mobile-bar__btn--meta" type="button" data-toggle-meta aria-label="Open document info" aria-expanded="false">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>
</button>
</div>
<nav class="breadcrumbs" aria-label="Breadcrumb">
<ol>
{{ $lastIdx := sub (len .Breadcrumbs) 1 }}
@@ -18,15 +28,21 @@
{{ end }}
</ol>
</nav>
<div class="document-meta">
<div class="document-meta" data-meta-drawer>
<button class="mobile-drawer-close mobile-drawer-close--inside" type="button" data-close-meta aria-label="Close document info">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
</button>
<div class="document-meta__header">
<h1>{{ .Title }}</h1>
{{ if .CanWrite }}
<div class="document-actions">
<a class="document-edit-link" href="/docs/{{ trimMd .Path }}/edit">Edit</a>
<button class="document-archive-btn" type="button" data-archive-path="{{ .Path }}" aria-label="Archive document">Archive</button>
{{ if .CanWrite }}
<a class="document-edit-link" href="/docs/{{ trimMd .Path }}/edit">Edit</a>
{{ if .CanAdmin }}
<a class="document-edit-link" href="/permissions?resourceType=document&resourceId={{ .Path }}">Permissions</a>
{{ end }}
<button class="document-archive-btn" type="button" data-archive-path="{{ .Path }}" aria-label="Archive document">Archive</button>
{{ end }}
</div>
{{ end }}
</div>
<details class="document-meta-panel">
<summary>
@@ -61,18 +77,74 @@
{{ .HTML }}
</div>
</article>
<aside class="document-comments-aside" data-comments-aside aria-label="Comments">
<div class="document-comments-strip" data-comments-strip>
<button
class="document-comments-strip__toggle"
type="button"
data-comment-toggle
aria-pressed="false"
aria-label="Toggle comments panel"
title="Toggle comments"
>
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15a2 2 0 0 1-2 2H8l-5 4V7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z"></path>
</svg>
</button>
<div class="document-comments-strip__track" data-comments-strip-track></div>
</div>
<div class="document-comments-panel">
<div class="document-comments-panel__list" data-comments-aside-list></div>
</div>
<!-- Mobile bottom sheet -->
<div class="document-comments-sheet" data-comments-sheet>
<div class="document-comments-sheet__handle">
<button class="document-comments-sheet__toggle" type="button" data-toggle-comments aria-expanded="false" aria-label="Toggle comments">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 15a2 2 0 0 1-2 2H8l-5 4V7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z"></path>
</svg>
<span>Comments</span>
</button>
<button class="mobile-drawer-close mobile-drawer-close--inside" type="button" data-close-comments aria-label="Close comments">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div class="document-comments-sheet__panel">
<div class="document-comments-panel__list" data-comments-aside-list-mobile></div>
</div>
</div>
</aside>
</section>
{{ end }}
{{ define "browser" }}
<nav class="miller-browser" aria-label="Documents">
<nav class="miller-browser" aria-label="Documents" data-picker-drawer>
<button class="mobile-drawer-close mobile-drawer-close--inside" type="button" data-close-picker aria-label="Close file picker">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
</button>
{{ range .Columns }}
<section class="miller-column {{ if eq .Title "Content" }}miller-column--root{{ end }}" aria-label="{{ .Title }}">
<h2 title="{{ .Title }}">
{{ if eq .Title "Content" }}
{{ template "icon-library" }}
<h2 title="{{ .Title }}" {{ if $.CanWrite }}class="has-actions"{{ end }}>
<span class="miller-column-title-wrap">
{{ if eq .Title "Content" }}
{{ template "icon-library" }}
{{ end }}
<span class="miller-column-title-text">{{ .Title }}</span>
</span>
{{ if $.CanWrite }}
<span class="miller-column-actions">
<button type="button" class="miller-column-new-file" data-folder-path="{{ .Path }}" aria-label="New file in {{ .Title }}">
{{ template "icon-file-plus" }}
</button>
<button type="button" class="miller-column-add-folder" data-folder-path="{{ .Path }}" aria-label="Add folder to {{ .Title }}">
{{ template "icon-folder-plus" }}
</button>
</span>
{{ end }}
<span class="miller-column-title-text">{{ .Title }}</span>
</h2>
<ul>
{{ range .Items }}
@@ -117,6 +189,23 @@
</svg>
{{ end }}
{{ define "icon-folder-plus" }}
<svg class="browser-icon browser-icon--folder" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"></path>
<line x1="12" y1="11" x2="12" y2="17"></line>
<line x1="9" y1="14" x2="15" y2="14"></line>
</svg>
{{ end }}
{{ define "icon-file-plus" }}
<svg class="browser-icon browser-icon--page" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round">
<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"></path>
<path d="M14 2v4a2 2 0 0 0 2 2h4"></path>
<line x1="12" y1="11" x2="12" y2="17"></line>
<line x1="9" y1="14" x2="15" y2="14"></line>
</svg>
{{ end }}
{{ define "icon-chevron-right" }}
<svg class="browser-item-chevron" aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round">
<path d="m9 18 6-6-6-6"></path>

View File

@@ -0,0 +1,71 @@
{{ define "permissions.gohtml" }}{{ template "base" . }}{{ end }}
{{ define "permissions_content" }}
<section class="permissions-shell">
<header class="permissions-header">
<div>
<p class="eyebrow">Access control</p>
<h1>{{ .Title }}</h1>
</div>
{{ if eq .ResourceType "document" }}
<a class="account-action" href="/docs/{{ trimMd .ResourceID }}">Back to page</a>
{{ end }}
</header>
<form class="permissions-form" method="post" action="/permissions">
<input type="hidden" name="resourceType" value="{{ .ResourceType }}" />
<input type="hidden" name="resourceId" value="{{ .ResourceID }}" />
<section class="permissions-panel">
<header class="permissions-panel__header">
<div>
<p class="account-section__kicker">People</p>
<h2>User permissions</h2>
</div>
<div class="permission-bulk-actions" data-permission-bulk>
<label class="permission-select-all">
<input type="checkbox" data-permission-select-all />
<span>Select all</span>
</label>
<select data-permission-bulk-level aria-label="Access level for selected users">
<option value="">No access</option>
<option value="read">View</option>
<option value="write">Edit</option>
<option value="admin">Admin</option>
</select>
<button class="btn-secondary permission-apply" type="button" data-permission-apply>Apply</button>
</div>
</header>
<div class="permission-user-list">
{{ range .Users }}
<label class="permission-user-row">
<input class="permission-user-check" type="checkbox" data-permission-user />
<span class="permission-user-main">
<span class="permission-user-name">
<strong>{{ .DisplayName }}</strong>
<em>{{ .Role }}</em>
</span>
<span class="permission-user-email">{{ .Email }}</span>
<span class="permission-user-meta">Created {{ .CreatedAt }} · Last seen {{ .LastSeenAt }}</span>
</span>
<span class="permission-grant-meta">
<strong>{{ .PermissionText }}</strong>
<small>{{ .GrantSummary }}</small>
</span>
<span class="permission-select-wrap">
<select name="permission:{{ .ID }}" aria-label="Permission for {{ .DisplayName }}" data-permission-select>
<option value="" {{ if eq .Permission "" }}selected{{ end }}>No access</option>
<option value="read" {{ if eq .Permission "read" }}selected{{ end }}>View</option>
<option value="write" {{ if eq .Permission "write" }}selected{{ end }}>Edit</option>
<option value="admin" {{ if eq .Permission "admin" }}selected{{ end }}>Admin</option>
</select>
</span>
</label>
{{ end }}
</div>
<div class="permissions-footer">
<button class="btn-primary" type="submit">Save permissions</button>
</div>
</section>
</form>
</section>
{{ end }}

View File

@@ -0,0 +1,12 @@
{{ define "tag.gohtml" }}{{ template "base" . }}{{ end }}
{{ define "tag_content" }}
<section class="workspace-shell workspace-shell--empty">
{{ template "browser" .Browser }}
<section class="tag-preview">
<p class="eyebrow">Tag</p>
<h1>#{{ .Tag }}</h1>
<p class="lede">{{ len .Results }} document{{ if ne (len .Results) 1 }}s{{ end }} found</p>
</section>
</section>
{{ end }}