{#if loading}

Loading…

{:else if !user}

task-master

Sign in to manage projects and tickets.

{#if error}

{error}

{/if}
{ e.preventDefault() doLogin() }} >
{:else}
{#if timer} ⏱ {timer.ticketId.slice(0, 8)}… {/if} {user.username}{user.isAdmin ? ' (admin)' : ''}
{#if topTab === 'projects'} {/if}
{#if error}

{error}

{/if} {#if msg}

{msg}

{/if} {#if topTab === 'dashboard'}

Projects

{#each dash.projects as p} {:else}

No projects yet.

{/each}

Open tickets

{#each dash.openTickets as t} {:else}

Nothing open.

{/each}

Time by project

{#each dash.projects as p} {/each}
ProjectTime
{p.name}{formatDuration(p.durationNs)}
{:else if topTab === 'projects' && !projectId}

Projekte

Wähle links ein Projekt oder lege ein neues an.

{:else if topTab === 'projects' && projectView === 'board'}

{projectName}

{#each boardStatuses as [st, label]}
onColumnDragOver(e, st)} ondragleave={(e) => onColumnDragLeave(e, st)} ondrop={(e) => onColumnDrop(e, st)} role="list" aria-label={label} >

{label}

{#each byStatus(st) as t}
onTicketDragStart(e, t)} ondragend={onTicketDragEnd} >
{:else}
Drop hier
{/each}
{/each}
{:else if topTab === 'projects' && projectView === 'ticket' && selected}

Time

{#each ticketTime as e} {#if editingTimeId === e.id} {:else} {/if} {:else} {/each}
WhenDurationSource
{e.start ? new Date(e.start).toLocaleString() : '—'} {formatDuration(e.duration)} {e.source}
No time yet.

History

{#each revisions as rev} {/each}
RevOpAt
{rev.rev} {rev.op} {new Date(rev.at).toLocaleString()}
{:else if topTab === 'projects' && projectView === 'report'}

Report — {projectName}

{#each [['ticket', 'Ticket'], ['status', 'Status'], ['day', 'Day']] as [g, label]} {/each}
{#if report}

{report.entryCount} entries · total {formatDuration(report.totalDurationNs)}

Summary

{#each report.rows as row} {:else} {/each}
GroupDuration
{row.label}{formatDuration(row.durationNs)}
No time logged.

Entries

{#each report.entries || [] as e} {#if editingTimeId === e.id} {:else} {/if} {:else} {/each}
WhenTicketDurationSourceNote
{e.start ? new Date(e.start).toLocaleString() : '—'} {ticketTitle(e.ticketId)} {formatDuration(e.duration)} {e.source} {e.note || ''}
No entries for this filter.
{/if}
{:else if topTab === 'projects' && projectView === 'settings'}

Settings — {projectName}

{#if groups.length}

Gruppen verwalten

{#each groups as g}
{g.name}
{/each}
{/if}

API tokens (for TUI)

Create a write token, then in `tm`: project edit → backend taskmaster → URL, token, this project id.

{#if newTokenSecret}
New token (shown once) {newTokenSecret}
{/if}
{#each tokens as t} {/each}
NameScopeCreated
{t.name}{#if t.revokedAt} (revoked){/if} {t.scope} {new Date(t.createdAt).toLocaleString()} {#if !t.revokedAt} {/if}
{:else if topTab === 'projects' && projectView === 'members'}

Members — {projectName}

{#each members as m} {/each}
UserRole
{m.username} {m.role}
{:else if topTab === 'users'}

Users

{#each users as u} {/each}
UsernameAdmin
{u.username} {#if u.id !== user.id} {/if}

Create user

{:else if topTab === 'settings'}

Settings

Globale Einstellungen folgen hier später.

{/if}
{/if}