Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Assisted-by: GLM 5.3
146 lines
7.2 KiB
HTML
146 lines
7.2 KiB
HTML
{{define "title"}}{{ tr "Set up Volumen" }} · {{ tr "Volumen admin" }}{{end}}
|
|
{{define "login_content"}}
|
|
<div class="login__card setup">
|
|
<h1 class="login__title" data-i18n="Welcome to Volumen">{{ tr "Welcome to Volumen" }}</h1>
|
|
<p class="login__pitch" data-i18n="Set up the administrator account to open this installation.">{{ tr "Set up the administrator account to open this installation." }}</p>
|
|
|
|
{{if .Error}}
|
|
<div class="status status--error" role="alert">
|
|
<svg aria-hidden="true"><use href="/admin/assets/graphis.svg#alert-circle"></use></svg>
|
|
<div>{{ .Error }}</div>
|
|
</div>
|
|
{{end}}
|
|
|
|
<form method="post" action="/admin/setup" class="stack">
|
|
<input type="hidden" name="_csrf" value="{{ .CSRFToken }}">
|
|
<input type="hidden" name="language" id="setup-language" value="{{ .Lang }}">
|
|
|
|
<fieldset class="setup__group">
|
|
<legend data-i18n="Account">{{ tr "Account" }}</legend>
|
|
<div class="grid-2">
|
|
<div class="field">
|
|
<label class="field__label" for="username" data-i18n="Username">{{ tr "Username" }}</label>
|
|
<input id="username" class="control mono" type="text" name="username" value="admin"
|
|
autocomplete="username" required autofocus>
|
|
</div>
|
|
<div class="field">
|
|
<label class="field__label" for="name" data-i18n="Display name">{{ tr "Display name" }}</label>
|
|
<input id="name" class="control" type="text" name="name" autocomplete="name"
|
|
placeholder="{{ tr "Your real name" }}" data-i18n-placeholder="Your real name">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="field">
|
|
<label class="field__label" for="password" data-i18n="Password">{{ tr "Password" }}</label>
|
|
<div class="pw">
|
|
<input id="password" class="control" type="password" name="password"
|
|
autocomplete="new-password" required data-pw-meter
|
|
data-min-length="{{ .Config.Admin.MinPasswordLength }}"
|
|
aria-describedby="pw-strength-text">
|
|
<button type="button" class="pw__toggle" id="pw-toggle" aria-label="{{ tr "Show password" }}">
|
|
<svg aria-hidden="true"><use href="/admin/assets/graphis.svg#eye"></use></svg>
|
|
</button>
|
|
</div>
|
|
<div class="pw-level" id="pw-level" data-level="0">
|
|
<div class="pw-level__bar" aria-hidden="true"><i></i><i></i><i></i><i></i></div>
|
|
<span class="pw-level__label" id="pw-strength-text" role="status" aria-live="polite"></span>
|
|
</div>
|
|
<p class="field__hint" data-i18n="password.hint">{{ trn .Config.Admin.MinPasswordLength "password.min" }}</p>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset class="setup__group">
|
|
<legend data-i18n="Language">{{ tr "Language" }}</legend>
|
|
<div class="pill-group">
|
|
<a class="chip chip--switch" lang="en" href="/admin/setup?lang=en" data-lang-chip="en"
|
|
{{if eq .Lang "en"}}aria-current="true"{{end}}>English</a>
|
|
<a class="chip chip--switch" lang="cs" href="/admin/setup?lang=cs" data-lang-chip="cs"
|
|
{{if eq .Lang "cs"}}aria-current="true"{{end}}>Čeština</a>
|
|
</div>
|
|
</fieldset>
|
|
|
|
<fieldset class="setup__group">
|
|
<legend data-i18n="Colour scheme">{{ tr "Colour scheme" }}</legend>
|
|
<div class="pill-group pill-group--themes">
|
|
<label class="chip chip--radio chip--theme">
|
|
<input type="radio" name="theme" value="viridis" {{if eq .Theme "viridis"}}checked{{end}}>
|
|
<span class="chip__swatch chip__swatch--viridis" aria-hidden="true"></span><span>Viridis</span>
|
|
</label>
|
|
<label class="chip chip--radio chip--theme">
|
|
<input type="radio" name="theme" value="plasma" {{if eq .Theme "plasma"}}checked{{end}}>
|
|
<span class="chip__swatch chip__swatch--plasma" aria-hidden="true"></span><span>Plasma</span>
|
|
</label>
|
|
<label class="chip chip--radio chip--theme">
|
|
<input type="radio" name="theme" value="magma" {{if eq .Theme "magma"}}checked{{end}}>
|
|
<span class="chip__swatch chip__swatch--magma" aria-hidden="true"></span><span>Magma</span>
|
|
</label>
|
|
</div>
|
|
<p class="field__hint" data-i18n="The page takes the colours as you choose.">{{ tr "The page takes the colours as you choose." }}</p>
|
|
</fieldset>
|
|
|
|
<button type="submit" class="btn btn--primary login__submit">
|
|
<span data-i18n="Create account">{{ tr "Create account" }}</span>
|
|
<svg aria-hidden="true"><use href="/admin/assets/graphis.svg#arrow-right"></use></svg>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<script nonce="{{ .CSPNonce }}">
|
|
(() => {
|
|
const btn = document.getElementById("pw-toggle");
|
|
const input = document.getElementById("password");
|
|
btn.addEventListener("click", () => {
|
|
const show = input.type === "password";
|
|
input.type = show ? "text" : "password";
|
|
btn.setAttribute("aria-label", window.__(show ? "Hide password" : "Show password"));
|
|
});
|
|
|
|
/* The wizard previews its own choices: the palette rides the same
|
|
html attribute the sheets read, and the language swaps the page
|
|
text from the bundle the server carried. The chips are real
|
|
links to the same page with ?lang=, so both choices survive a
|
|
browser without JavaScript: the link reloads, the theme radios
|
|
submit. */
|
|
const BUNDLE = {{ .SetupI18n }};
|
|
const apply = (lang) => {
|
|
document.documentElement.lang = lang;
|
|
document.querySelectorAll("[data-i18n]").forEach((el) => {
|
|
const pair = BUNDLE.ui[el.dataset.i18n];
|
|
if (pair && pair[lang]) el.textContent = pair[lang];
|
|
});
|
|
document.querySelectorAll("[data-i18n-placeholder]").forEach((el) => {
|
|
const pair = BUNDLE.ui[el.dataset.i18nPlaceholder];
|
|
if (pair && pair[lang]) el.placeholder = pair[lang];
|
|
});
|
|
window.__volumen.i18n = BUNDLE.js[lang];
|
|
btn.setAttribute("aria-label",
|
|
window.__(input.type === "password" ? "Show password" : "Hide password"));
|
|
/* The meter's label comes from the shared catalogue: re-score
|
|
the field so the word follows the language swap. */
|
|
input.dispatchEvent(new Event("input"));
|
|
document.getElementById("setup-language").value = lang;
|
|
document.querySelectorAll("[data-lang-chip]").forEach((chip) => {
|
|
if (chip.dataset.langChip === lang) chip.setAttribute("aria-current", "true");
|
|
else chip.removeAttribute("aria-current");
|
|
});
|
|
};
|
|
document.querySelectorAll("[data-lang-chip]").forEach((chip) => {
|
|
chip.addEventListener("click", (event) => {
|
|
event.preventDefault();
|
|
apply(chip.dataset.langChip);
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('input[name="theme"]').forEach((radio) => {
|
|
radio.addEventListener("change", () => {
|
|
document.documentElement.dataset.palette = radio.value;
|
|
});
|
|
});
|
|
|
|
/* The strength meter itself is the shared one the layout wires
|
|
for every input[data-pw-meter]; only the label refresh on a
|
|
language switch is local to this page. */
|
|
})();
|
|
</script>
|
|
{{end}}
|