portal: improve onboarding login UX
This commit is contained in:
parent
59830e19c8
commit
72dae3e7a2
@ -92,10 +92,17 @@ export async function initAuth() {
|
||||
return initPromise;
|
||||
}
|
||||
|
||||
export async function login(redirectPath = window.location.pathname + window.location.search + window.location.hash) {
|
||||
export async function login(
|
||||
redirectPath = window.location.pathname + window.location.search + window.location.hash,
|
||||
loginHint = "",
|
||||
) {
|
||||
if (!keycloak) return;
|
||||
const redirectUri = new URL(redirectPath, window.location.origin).toString();
|
||||
await keycloak.login({ redirectUri });
|
||||
const options = { redirectUri };
|
||||
if (typeof loginHint === "string" && loginHint.trim()) {
|
||||
options.loginHint = loginHint.trim();
|
||||
}
|
||||
await keycloak.login(options);
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
|
||||
@ -26,7 +26,10 @@
|
||||
<div v-if="requestUsername" class="status-meta">
|
||||
<div class="meta-row">
|
||||
<span class="label mono">Username</span>
|
||||
<span class="value mono">{{ requestUsername }}</span>
|
||||
<button class="copy mono" type="button" @click="copyUsername">
|
||||
{{ requestUsername }}
|
||||
<span v-if="usernameCopied" class="copied">copied</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -87,7 +90,8 @@
|
||||
<div v-if="initialPassword" class="initial-password">
|
||||
<h3>Temporary password</h3>
|
||||
<p class="muted">
|
||||
Use this password to log in for the first time. Keycloak will prompt you to change it.
|
||||
Use this password to log in for the first time. Keycloak will prompt you to change it. This password is shown
|
||||
once — copy it now.
|
||||
</p>
|
||||
<div class="request-code-row">
|
||||
<span class="label mono">Password</span>
|
||||
@ -212,6 +216,7 @@ const error = ref("");
|
||||
const onboarding = ref({ required_steps: [], completed_steps: [] });
|
||||
const initialPassword = ref("");
|
||||
const copied = ref(false);
|
||||
const usernameCopied = ref(false);
|
||||
const tasks = ref([]);
|
||||
const blocked = ref(false);
|
||||
|
||||
@ -304,8 +309,35 @@ async function copyInitialPassword() {
|
||||
}
|
||||
}
|
||||
|
||||
async function copyUsername() {
|
||||
if (!requestUsername.value) return;
|
||||
try {
|
||||
if (navigator?.clipboard?.writeText) {
|
||||
await navigator.clipboard.writeText(requestUsername.value);
|
||||
} else {
|
||||
const textarea = document.createElement("textarea");
|
||||
textarea.value = requestUsername.value;
|
||||
textarea.setAttribute("readonly", "");
|
||||
textarea.style.position = "fixed";
|
||||
textarea.style.top = "-9999px";
|
||||
textarea.style.left = "-9999px";
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
textarea.setSelectionRange(0, textarea.value.length);
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(textarea);
|
||||
}
|
||||
usernameCopied.value = true;
|
||||
setTimeout(() => (usernameCopied.value = false), 1500);
|
||||
} catch (err) {
|
||||
error.value = err?.message || "Failed to copy username";
|
||||
}
|
||||
}
|
||||
|
||||
async function loginToContinue() {
|
||||
await login(`/onboarding?code=${encodeURIComponent(requestCode.value.trim())}`);
|
||||
const trimmedCode = requestCode.value.trim();
|
||||
const hint = requestUsername.value.trim() || trimmedCode.split("~", 1)[0] || "";
|
||||
await login(`/onboarding?code=${encodeURIComponent(trimmedCode)}`, hint);
|
||||
}
|
||||
|
||||
async function toggleStep(step, event) {
|
||||
|
||||
@ -112,10 +112,6 @@
|
||||
Verifying email…
|
||||
</div>
|
||||
|
||||
<div v-if="onboardingUrl" class="actions" style="margin-top: 12px;">
|
||||
<a class="primary" :href="onboardingUrl">Continue onboarding</a>
|
||||
</div>
|
||||
|
||||
<div v-if="tasks.length" class="task-box">
|
||||
<div class="module-head" style="margin-bottom: 10px;">
|
||||
<h2>Automation</h2>
|
||||
@ -134,6 +130,13 @@
|
||||
One or more automation steps failed. Fix the error above, then check again.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="onboardingUrl && (status === 'awaiting_onboarding' || status === 'ready')"
|
||||
class="actions onboarding-actions"
|
||||
>
|
||||
<a class="primary onboarding-cta" :href="onboardingUrl">Continue onboarding</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="error" class="error-box">
|
||||
@ -429,6 +432,15 @@ h1 {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.onboarding-actions {
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.onboarding-cta {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.status-form {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user