feat: complete Epic 1 production foundation
This commit is contained in:
+73
-5
@@ -3,6 +3,17 @@
|
||||
return window.t ? t(key) : key;
|
||||
}
|
||||
|
||||
function diagnosticSuffix(error) {
|
||||
var parts = [];
|
||||
if (error && error.requestId) {
|
||||
parts.push(tKey('login.error.request_id') + ': ' + error.requestId);
|
||||
}
|
||||
if (error && error.traceId) {
|
||||
parts.push(tKey('login.error.trace_id') + ': ' + error.traceId);
|
||||
}
|
||||
return parts.length ? ('\n' + parts.join('\n')) : '';
|
||||
}
|
||||
|
||||
function showError(message) {
|
||||
var errorElement = document.getElementById('login-error');
|
||||
errorElement.classList.add('is-visible');
|
||||
@@ -14,34 +25,91 @@
|
||||
errorElement.classList.remove('is-visible');
|
||||
}
|
||||
|
||||
function setBootstrapMode(enabled) {
|
||||
var emailField = document.getElementById('login-email-field');
|
||||
var tokenField = document.getElementById('login-bootstrap-token-field');
|
||||
var heading = document.querySelector('.login-heading');
|
||||
var subtitle = document.querySelector('.login-sub');
|
||||
var note = document.querySelector('.login-note');
|
||||
var submit = document.getElementById('login-submit');
|
||||
var password = document.getElementById('password');
|
||||
document.getElementById('login-form').dataset.bootstrap = enabled ? 'true' : 'false';
|
||||
if (emailField) emailField.hidden = enabled;
|
||||
if (tokenField) tokenField.hidden = !enabled;
|
||||
if (heading) heading.textContent = tKey(enabled ? 'login.bootstrap.title' : 'login.title');
|
||||
if (subtitle) subtitle.textContent = tKey(enabled ? 'login.bootstrap.subtitle' : 'login.subtitle');
|
||||
if (note) note.textContent = tKey(enabled ? 'login.bootstrap.note' : 'login.password_only');
|
||||
if (submit) submit.textContent = tKey(enabled ? 'login.bootstrap.submit' : 'login.submit');
|
||||
if (password) password.setAttribute('autocomplete', enabled ? 'new-password' : 'current-password');
|
||||
}
|
||||
|
||||
function initLoginPage() {
|
||||
var inFlight = false;
|
||||
window.CrankAuth.guardLoginPage().catch(function(error) {
|
||||
if (window.CrankDiagnostics && typeof window.CrankDiagnostics.report === 'function') {
|
||||
window.CrankDiagnostics.report('guard-login-page', error, 'login');
|
||||
}
|
||||
});
|
||||
|
||||
setBootstrapMode(false);
|
||||
window.CrankApi.getBootstrapStatus()
|
||||
.then(function(status) {
|
||||
setBootstrapMode(Boolean(status && status.bootstrap_required));
|
||||
})
|
||||
.catch(function(error) {
|
||||
if (window.CrankDiagnostics && typeof window.CrankDiagnostics.report === 'function') {
|
||||
window.CrankDiagnostics.report('bootstrap-status', error, 'login');
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('login-form').addEventListener('submit', async function(event) {
|
||||
event.preventDefault();
|
||||
if (inFlight) {
|
||||
return;
|
||||
}
|
||||
|
||||
var form = event.currentTarget;
|
||||
var isBootstrap = event.currentTarget.dataset.bootstrap === 'true';
|
||||
var email = document.getElementById('email').value.trim();
|
||||
var token = document.getElementById('bootstrap-token').value.trim();
|
||||
var password = document.getElementById('password').value;
|
||||
var submit = document.getElementById('login-submit');
|
||||
|
||||
if (!email || !password) {
|
||||
showError(tKey('login.error.required'));
|
||||
if ((!isBootstrap && !email) || (isBootstrap && !token) || !password) {
|
||||
showError(tKey(isBootstrap ? 'login.bootstrap.error.required' : 'login.error.required'));
|
||||
return;
|
||||
}
|
||||
|
||||
hideError();
|
||||
inFlight = true;
|
||||
if (submit) {
|
||||
submit.disabled = true;
|
||||
submit.textContent = tKey(isBootstrap ? 'login.bootstrap.loading' : 'login.loading');
|
||||
}
|
||||
|
||||
try {
|
||||
await window.CrankAuth.login(email, password);
|
||||
if (isBootstrap) {
|
||||
await window.CrankAuth.completeBootstrap(token, password);
|
||||
} else {
|
||||
await window.CrankAuth.login(email, password);
|
||||
}
|
||||
showError(tKey(isBootstrap ? 'login.bootstrap.success' : 'login.success'));
|
||||
} catch (error) {
|
||||
if (error && error.status === 401) {
|
||||
showError(tKey('login.error.invalid'));
|
||||
showError(tKey('login.error.invalid') + diagnosticSuffix(error));
|
||||
return;
|
||||
}
|
||||
showError(tKey('login.error.generic'));
|
||||
if (error && error.status === 429) {
|
||||
showError(tKey('login.error.throttled') + diagnosticSuffix(error));
|
||||
return;
|
||||
}
|
||||
showError(tKey('login.error.generic') + diagnosticSuffix(error));
|
||||
} finally {
|
||||
inFlight = false;
|
||||
if (submit && form.isConnected) {
|
||||
submit.disabled = false;
|
||||
submit.textContent = tKey(isBootstrap ? 'login.bootstrap.submit' : 'login.submit');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user