Files
team-presence/internal/app/templates/board.html
T
nfel b0f486f026
Test and publish / verify (push) Successful in 2m41s
Remove blocked column from kanban board
2026-08-02 12:52:08 +03:30

227 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">SHARED WORKSPACE</p><h1>Team board</h1><p>Plan, assign, and move work forward together.</p></div>
<div class="board-head-actions">
<details class="board-filter-menu">
<summary class="button secondary">⌕ 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">◉ Manage 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}}">
<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 .Todos}}<span class="todo-progress" title="To-do list">☑ {{.TodoDone}}/{{len .Todos}}</span>{{end}}<span class="importance-emoji {{.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"}}🚨{{else if eq .Importance "high"}}🔶{{else if eq .Importance "low"}}🟢{{else}}⚪{{end}}</span>{{if .DueDate}}<span class="task-due">{{dateFA .DueDate}}</span>{{end}}</span>
</div>
<h3>{{.Title}}</h3>
{{if .Description}}<p>{{.Description}}</p>{{end}}
<div class="task-meta">
{{if .Assignees}}<span class="task-assignees">{{range .Assignees}}<span class="task-assignee"><i class="avatar">{{initial .DisplayName}}</i><span>{{.DisplayName}}</span></span>{{end}}</span>{{else}}<span class="task-assignee unassigned"><i>?</i><span>Unassigned</span></span>{{end}}
<span class="task-creator">by {{.CreatorName}}</span>
</div>
<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="text-button archive-task" type="submit">Archive</button>
</form>
<details class="task-remove">
<summary>Delete</summary>
<form method="post" action="/board/tasks/{{.ID}}/delete">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<button class="text-button" type="submit">Delete permanently</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>
{{if .ArchivedTasks}}
<details class="archived-cards-panel">
<summary>Archived cards <span>{{len .ArchivedTasks}}</span></summary>
<div class="archived-card-list">
{{range .ArchivedTasks}}
<article class="archived-card">
<div>
{{if .Tags}}<div class="card-tags">{{range .Tags}}<span class="board-tag {{.Color}}">{{.Name}}</span>{{end}}</div>{{end}}
<span class="archived-status">{{.Status}}</span>
<h3>{{.Title}}</h3>
<small>Originally created by {{.CreatorName}}</small>
</div>
{{if or (eq .CreatorID $.User.ID) (eq $.User.Role "admin")}}
<div class="archived-card-actions">
<form method="post" action="/board/tasks/{{.ID}}/restore">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<button class="button secondary" type="submit">Restore</button>
</form>
<details class="archived-delete">
<summary class="text-button">Delete</summary>
<form method="post" action="/board/tasks/{{.ID}}/delete">
<input type="hidden" name="csrf" value="{{$.CSRF}}">
<button class="text-button" type="submit">Delete permanently</button>
</form>
</details>
</div>
{{end}}
</article>
{{end}}
</div>
</details>
{{end}}
<script src="/static/board.js" defer></script>
{{template "shell-end" .}}
{{end}}