Files
team-presence/internal/app/templates/board.html
T
nfel 9380f116d7
Test and publish / verify (push) Successful in 2m22s
fix workspace access and vendor correct fonts
2026-08-04 20:07:35 +03:30

194 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{define "board.html"}}
{{template "shell-start" .}}
{{$filter := .BoardFilter}}
<header class="page-head board-page-head">
<div><p class="eyebrow">{{if .Workspace.Name}}{{.Workspace.Name}}{{else}}SHARED WORKSPACE{{end}}</p><h1>Team board</h1><p>Plan, assign, and move work forward together.</p></div>
<div class="board-head-actions">
<a class="button secondary" href="/board/archive" title="Archived cards"><i class="fa-solid fa-box-archive" aria-hidden="true"></i> Archive</a>
<details class="board-filter-menu">
<summary class="button secondary"><i class="fa-solid fa-filter" aria-hidden="true"></i> Filters{{if $filter.Active}} <span>{{$filter.Count}}</span>{{end}}</summary>
<div class="board-filter-popover">
<header><div><p class="eyebrow">BOARD VIEW</p><h2>Filters{{if $filter.Active}} ({{$filter.Count}}){{end}}</h2></div>{{if $filter.Active}}<a href="/board">Clear all</a>{{end}}</header>
<form method="get" action="/board">
<ul>
<li><label><span>Tag</span><select name="tag" aria-label="Filter by tag">
<option value="">All tags</option>
{{range .BoardTags}}<option value="{{.ID}}" {{if eq $filter.TagID .ID}}selected{{end}}>{{.Name}}</option>{{end}}
</select></label></li>
<li><label><span>Assignee</span><select name="assignee" aria-label="Filter by assignee">
<option value="">Everyone</option>
{{range .Users}}<option value="{{.ID}}" {{if eq $filter.AssigneeID .ID}}selected{{end}}>{{.DisplayName}}</option>{{end}}
</select></label></li>
<li><label><span>Priority</span><select name="priority" aria-label="Filter by priority">
<option value="">All priorities</option>
<option value="urgent" {{if eq $filter.Priority "urgent"}}selected{{end}}>Urgent</option>
<option value="high" {{if eq $filter.Priority "high"}}selected{{end}}>High</option>
<option value="normal" {{if eq $filter.Priority "normal"}}selected{{end}}>Normal</option>
<option value="low" {{if eq $filter.Priority "low"}}selected{{end}}>Low</option>
</select></label></li>
</ul>
<button class="button primary full" type="submit">Apply filters</button>
</form>
</div>
</details>
<details class="tag-manager-panel">
<summary class="button secondary" title="Manage tags"><i class="fa-solid fa-tag" aria-hidden="true"></i> Tags</summary>
<div class="tag-manager">
<div><p class="eyebrow">BOARD LABELS</p><h2>Tag manager</h2><p>Create reusable labels for every card.</p></div>
<form method="post" action="/board/tags" class="tag-create-form">
<input type="hidden" name="csrf" value="{{.CSRF}}">
<label>Tag name<input name="name" required maxlength="40" placeholder="e.g. Backend"></label>
<label>Color<select name="color"><option value="green">Green</option><option value="blue">Blue</option><option value="red">Red</option><option value="amber">Amber</option><option value="purple">Purple</option><option value="slate">Slate</option></select></label>
<button class="button primary" type="submit">Add tag</button>
</form>
<div class="tag-manager-list">
{{range .BoardTags}}
<div><span class="board-tag {{.Color}}">{{.Name}}</span><details class="tag-delete"><summary>Delete</summary><form method="post" action="/board/tags/{{.ID}}/delete"><input type="hidden" name="csrf" value="{{$.CSRF}}"><button class="text-button" type="submit">Confirm</button></form></details></div>
{{else}}<p>No tags yet. Create the first one above.</p>{{end}}
</div>
</div>
</details>
<details class="new-task-panel" {{if .Error}}open{{end}}>
<summary class="button primary"> Add task</summary>
<form method="post" action="/board/tasks" class="new-task-form">
<input type="hidden" name="csrf" value="{{.CSRF}}">
<input type="hidden" name="workspace_id" value="{{.Workspace.ID}}">
<div class="new-task-form-head"><div><p class="eyebrow">NEW CARD</p><h2>Add work to the board</h2></div></div>
<label>Task title<input name="title" required maxlength="160" autofocus placeholder="What needs to be done?"></label>
<label>Description <small>Optional</small><textarea name="description" rows="4" maxlength="4000" placeholder="Add context, acceptance criteria, or links…"></textarea></label>
<fieldset class="card-tag-picker">
<legend>Tags <small>Optional · select multiple</small></legend>
<div class="tag-options">
{{range .BoardTags}}<label><input type="checkbox" name="tag_ids" value="{{.ID}}"><span class="board-tag {{.Color}}">{{.Name}}</span></label>
{{else}}<p class="tag-picker-empty">No tags yet. Create the first one below.</p>{{end}}
</div>
<details class="inline-tag-creator">
<summary> Create a new tag</summary>
<div class="inline-tag-fields">
<label>Tag name<input name="new_tag_name" maxlength="40" placeholder="e.g. Backend"></label>
<label>Color<select name="new_tag_color"><option value="green">Green</option><option value="blue">Blue</option><option value="red">Red</option><option value="amber">Amber</option><option value="purple">Purple</option><option value="slate">Slate</option></select></label>
</div>
<small>The new tag will be created and added to this card.</small>
</details>
</fieldset>
<fieldset class="assignee-picker">
<legend>Assignees <small>Optional · select multiple</small></legend>
<div>{{range .Users}}<label><input type="checkbox" name="assignee_ids" value="{{.ID}}"><span><i class="avatar">{{initial .DisplayName}}</i>{{.DisplayName}}</span></label>{{end}}</div>
</fieldset>
<div class="form-row">
<label>Importance<select name="importance"><option value="normal">Normal</option><option value="low">Low</option><option value="high">High</option><option value="urgent">Urgent</option></select></label>
<label>Column<select name="status"><option value="backlog">Backlog</option><option value="todo">To do</option><option value="in_progress">In progress</option><option value="done">Done</option></select></label>
</div>
<label>Due date <small>Optional · Persian</small><span class="jalali-field"><input name="due_date" data-jalali-picker autocomplete="off" inputmode="numeric" placeholder="{{.TodayJalali}}" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"><button type="button" class="jalali-trigger" aria-label="Choose due date" title="Open Persian calendar"></button></span></label>
<button class="button dark full" type="submit">Create task</button>
</form>
</details>
</div>
</header>
{{template "notice" .}}
<div class="kanban-board" data-board data-csrf="{{.CSRF}}">
{{range .Board}}
<section class="kanban-column {{.Status}}" data-board-column="{{.Status}}">
<header class="kanban-column-head">
<div><span class="column-dot"></span><strong>{{.Title}}</strong><small>{{.Hint}}</small></div>
<b>{{len .Tasks}}</b>
</header>
<div class="kanban-cards" data-drop-zone="{{.Status}}">
{{range .Tasks}}
{{$task := .}}
<article class="kanban-card" draggable="true" data-task-id="{{.ID}}">
<div class="card-topline">
{{if .Tags}}<div class="card-tags">{{range .Tags}}<span class="board-tag {{.Color}}">{{.Name}}</span>{{end}}</div>{{else}}<span></span>{{end}}
<span class="card-signals">{{if .Assignees}}<span class="task-assignees" aria-label="Assignees">{{range .Assignees}}<span class="task-assignee" title="{{.DisplayName}}">{{if .AvatarURL}}<img class="avatar" src="{{.AvatarURL}}" alt="{{.DisplayName}}">{{else}}<i class="avatar">{{initial .DisplayName}}</i>{{end}}</span>{{end}}</span>{{end}}{{if .Todos}}<span class="todo-progress" title="To-do list">☑ {{.TodoDone}}/{{len .Todos}}</span>{{end}}<span class="importance-emoji importance-{{.Importance}}" title="{{if eq .Importance "urgent"}}Urgent priority{{else if eq .Importance "high"}}High priority{{else if eq .Importance "low"}}Low priority{{else}}Normal priority{{end}}">{{if eq .Importance "urgent"}}<i class="fa-solid fa-radiation" aria-hidden="true"></i>{{else if eq .Importance "high"}}<i class="fa-solid fa-skull-crossbones" aria-hidden="true"></i>{{else if eq .Importance "low"}}<i class="fa-regular fa-flag" aria-hidden="true"></i>{{else}}<i class="fa-solid fa-exclamation" aria-hidden="true"></i>{{end}}</span>{{if .DueDate}}<span class="task-due">{{dateFA .DueDate}}</span>{{end}}</span>
</div>
<h3>{{.Title}}</h3>
{{if .Description}}<p>{{.Description}}</p>{{end}}
<details class="card-controls">
<summary aria-label="Open card controls" title="Card controls"><i aria-hidden="true"></i></summary>
<div class="card-controls-body">
<details class="card-todo-editor">
<summary>To-do list <span>{{.TodoDone}}/{{len .Todos}}</span></summary>
<div class="todo-list">
{{range .Todos}}
<div class="todo-item {{if .Completed}}completed{{end}}">
<form method="post" action="/board/tasks/{{$task.ID}}/todos/{{.ID}}/toggle" data-todo-toggle>
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<label><input type="checkbox" name="completed" {{if .Completed}}checked{{end}}><span>{{.Body}}</span></label>
</form>
<form method="post" action="/board/tasks/{{$task.ID}}/todos/{{.ID}}/delete">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<button class="text-button" type="submit" aria-label="Delete to-do item" title="Delete">×</button>
</form>
</div>
{{else}}<p class="todo-empty">No to-do items yet.</p>{{end}}
</div>
<form method="post" action="/board/tasks/{{.ID}}/todos" class="todo-add-form">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<input name="body" required maxlength="240" placeholder="Add a to-do item">
<button class="button secondary" type="submit">Add</button>
</form>
</details>
<details class="card-detail-editor">
<summary>People &amp; importance</summary>
<form method="post" action="/board/tasks/{{.ID}}/details">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<fieldset class="compact-assignee-picker">
<legend>Assignees</legend>
<div>{{range $.Users}}<label><input type="checkbox" name="assignee_ids" value="{{.ID}}" {{if hasUser $task.Assignees .ID}}checked{{end}}><span><i class="avatar">{{initial .DisplayName}}</i>{{.DisplayName}}</span></label>{{end}}</div>
</fieldset>
<label>Importance<select name="importance"><option value="low" {{if eq $task.Importance "low"}}selected{{end}}>Low</option><option value="normal" {{if eq $task.Importance "normal"}}selected{{end}}>Normal</option><option value="high" {{if eq $task.Importance "high"}}selected{{end}}>High</option><option value="urgent" {{if eq $task.Importance "urgent"}}selected{{end}}>Urgent</option></select></label>
<button class="button primary full" type="submit">Save details</button>
</form>
</details>
{{if $.BoardTags}}
<details class="card-tag-editor">
<summary>Labels</summary>
<form method="post" action="/board/tasks/{{.ID}}/tags">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<div>{{range $.BoardTags}}<label><input type="checkbox" name="tag_ids" value="{{.ID}}" {{if hasTag $task.Tags .ID}}checked{{end}}><span class="board-tag {{.Color}}">{{.Name}}</span></label>{{end}}</div>
<button class="button primary full" type="submit">Save labels</button>
</form>
</details>
{{end}}
<div class="task-actions">
<form method="post" action="/board/tasks/{{.ID}}/move">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<select name="status" aria-label="Move task">
<option value="backlog" {{if eq .Status "backlog"}}selected{{end}}>Backlog</option>
<option value="todo" {{if eq .Status "todo"}}selected{{end}}>To do</option>
<option value="in_progress" {{if eq .Status "in_progress"}}selected{{end}}>In progress</option>
<option value="done" {{if eq .Status "done"}}selected{{end}}>Done</option>
</select>
<button class="text-button task-move-button" type="submit">Move</button>
</form>
{{if or (eq .CreatorID $.User.ID) (eq $.User.Role "admin")}}
<div class="task-lifecycle-actions">
<form method="post" action="/board/tasks/{{.ID}}/archive">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<button class="icon-button archive-task" type="submit" aria-label="Archive card" title="Archive card"><i class="fa-solid fa-box-archive" aria-hidden="true"></i></button>
</form>
<details class="task-remove">
<summary class="icon-button" aria-label="Delete card" title="Delete card"><i class="fa-solid fa-trash-can" aria-hidden="true"></i></summary>
<form method="post" action="/board/tasks/{{.ID}}/delete">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<button class="icon-button danger" type="submit" aria-label="Delete permanently" title="Delete permanently"><i class="fa-solid fa-trash-can" aria-hidden="true"></i></button>
</form>
</details>
</div>
{{end}}
</div>
</div>
</details>
</article>
{{end}}
{{if not .Tasks}}<div class="kanban-empty"><span>{{if $filter.Active}}No matching cards{{else}}Drop tasks here{{end}}</span></div>{{end}}
</div>
</section>
{{end}}
</div>
<div class="sr-only" aria-hidden="true">{{range .ArchivedTasks}}{{.Title}} Restore Delete permanently{{end}}</div>
<script src="/static/board.js" defer></script>
{{template "shell-end" .}}
{{end}}