Files
ghglance/internal/web/templates/user.html
T
tiennm99 2def27f49a feat(web): require GitHub sign-in to generate cards
The web UI now runs every job on an OAuth token from "Sign in with
GitHub". The ticked options decide the requested scopes (read:user, plus
repo for private repos, plus read:org for org repos); a grant wider than
requested is refused. The token lives only on the job and is revoked when
the job ends, on every path including shutdown.

The server no longer holds a GitHub token of its own, and the pasted-token
field and /generate are gone. -serve requires -oauth-client-id,
-oauth-client-secret and -public-url (GHGLANCE_OAUTH_* and
GHGLANCE_PUBLIC_URL), and compose.yml requires them too. The CLI and the
Action keep -token unchanged.
2026-10-07 17:50:33 +07:00

72 lines
2.7 KiB
HTML

{{define "content"}}
<section class="user-head">
<h1>{{.Login}}</h1>
<p class="meta">
{{if .Meta}}Generated {{fmtTime .Meta.GeneratedAt}}
· {{.Meta.Scope}} data
· {{.Meta.Options.TZ}}
· week starts {{.Meta.Options.StartOfWeek}}
· {{end}}<a href="https://github.com/{{.Key}}" rel="noopener">GitHub profile</a>
</p>
</section>
{{if .Notice}}<p class="alert alert-info" role="status">{{.Notice}}</p>{{end}}
{{if .Job.Active}}
<div class="alert alert-progress" id="progress" data-status-url="/u/{{.Key}}/status">
<span class="spinner" aria-hidden="true"></span>
<div>
<p id="progress-text" role="status" aria-live="polite">{{if eq .Job.State "queued"}}Queued{{if .Job.Position}}, position {{.Job.Position}}{{end}}{{else}}Running: {{.Job.Stage}}{{end}}</p>
<p class="hint" id="progress-elapsed"></p>
<p class="hint">Large profiles take a few minutes. This page refreshes when the cards are ready.</p>
</div>
</div>
{{else if eq .Job.State "failed"}}
<p class="alert alert-error" role="alert">The last generation failed: {{.Job.Error}}</p>
{{end}}
{{if .Meta}}
<form class="toolbar" method="get" action="/u/{{.Key}}">
<label for="theme">Theme</label>
<select id="theme" name="theme">
{{range .Themes}}<option value="{{.}}"{{if eq . $.Theme}} selected{{end}}>{{.}}</option>
{{end}}
</select>
<button type="submit">Apply</button>
</form>
<ul class="cards">
{{range .Cards}}
<li class="card">
<figure>
<div class="card-image"><img src="{{.Src}}" alt="{{.Name}} card for {{$.Login}}" loading="lazy" decoding="async"></div>
<figcaption>
<span class="card-name">{{.Name}}</span>
<div class="copy-row">
<input type="text" readonly value="{{.URL}}" aria-label="Embed URL for the {{.Name}} card">
<button type="button" data-copy="{{.URL}}">Copy</button>
</div>
</figcaption>
</figure>
</li>
{{end}}
</ul>
<section class="panel">
<h2>Embed every card</h2>
<label for="markdown">Markdown for a README ({{.Theme}})</label>
<textarea id="markdown" readonly rows="8" spellcheck="false">{{.Markdown}}</textarea>
<button type="button" data-copy-target="markdown">Copy Markdown</button>
</section>
{{end}}
{{if not .Job.Active}}
<section class="panel">
<h2>{{if .Meta}}Regenerate{{else}}Try again{{end}}</h2>
{{if .ExpiresIn}}<p class="hint">These cards are deleted in about {{.ExpiresIn}}; regenerate to keep embedded links working.</p>{{end}}
{{if .CooldownLeft}}<p class="hint">Signed in as another account, these cards can be regenerated in {{.CooldownLeft}}. Signed in as {{.Login}}, you can regenerate now.</p>{{end}}
{{template "form" .}}
</section>
{{end}}
{{end}}