ed8ac34542
TaxBaik CI/CD / build-and-deploy (push) Successful in 1m46s
V018 had PostgreSQL quote escaping issues with long content strings. V019 uses 1256 quoting to avoid escaping problems and cleanly inserts all 12 blog posts (5 updates + 7 new) with middle-school level language. Deletes V018, commits V019 as replacement.
157 lines
5.6 KiB
JavaScript
157 lines
5.6 KiB
JavaScript
window.taxbaikAdminSession = {
|
|
syncRouteClass: function () {
|
|
document.documentElement.classList.toggle(
|
|
'admin-login-route',
|
|
window.location.pathname.toLowerCase().endsWith('/admin/login'));
|
|
},
|
|
|
|
getViewportWidth: function () {
|
|
return window.innerWidth || document.documentElement.clientWidth || 0;
|
|
},
|
|
|
|
clearAuthToken: function () {
|
|
try {
|
|
localStorage.removeItem('accessToken');
|
|
localStorage.removeItem('refreshToken');
|
|
localStorage.removeItem('tokenExpiry');
|
|
localStorage.removeItem('auth_token');
|
|
} catch {
|
|
// Ignore storage errors; redirect still recovers the session.
|
|
}
|
|
},
|
|
|
|
showLoading: function () {
|
|
if (document.documentElement.classList.contains('admin-login-route')) {
|
|
window.taxbaikAdminSession.hideLoading();
|
|
return;
|
|
}
|
|
|
|
const overlay = document.getElementById('blazor-loading');
|
|
if (!overlay) return;
|
|
|
|
// Show overlay immediately
|
|
overlay.classList.add('show');
|
|
|
|
// Check if page is already ready (cached state on fast nav)
|
|
const pageReady =
|
|
document.querySelector('.admin-page-hero') !== null ||
|
|
document.querySelector('.admin-login-page') !== null;
|
|
if (pageReady) {
|
|
// Page already rendered, hide immediately
|
|
window.taxbaikAdminSession.hideLoading();
|
|
return;
|
|
}
|
|
|
|
// Start observer to catch future mutations
|
|
if (window._taxbaikLoadingObserver) {
|
|
window._taxbaikLoadingObserver.disconnect();
|
|
}
|
|
window._taxbaikLoadingObserver = new MutationObserver(function () {
|
|
const pageReady =
|
|
document.querySelector('.admin-page-hero') !== null ||
|
|
document.querySelector('.admin-login-page') !== null;
|
|
if (pageReady) {
|
|
window.taxbaikAdminSession.hideLoading();
|
|
}
|
|
});
|
|
window._taxbaikLoadingObserver.observe(document.body, {
|
|
childList: true,
|
|
subtree: true
|
|
});
|
|
|
|
// Safety fallback: hide after 3 seconds regardless.
|
|
if (window._taxbaikLoadingTimeout) {
|
|
clearTimeout(window._taxbaikLoadingTimeout);
|
|
}
|
|
window._taxbaikLoadingTimeout = setTimeout(function () {
|
|
window.taxbaikAdminSession.hideLoading();
|
|
}, 3000);
|
|
},
|
|
|
|
hideLoading: function () {
|
|
const overlay = document.getElementById('blazor-loading');
|
|
if (overlay) {
|
|
overlay.classList.remove('show');
|
|
}
|
|
|
|
if (window._taxbaikLoadingTimeout) {
|
|
clearTimeout(window._taxbaikLoadingTimeout);
|
|
window._taxbaikLoadingTimeout = null;
|
|
}
|
|
|
|
if (window._taxbaikLoadingObserver) {
|
|
window._taxbaikLoadingObserver.disconnect();
|
|
window._taxbaikLoadingObserver = null;
|
|
}
|
|
},
|
|
|
|
watchReconnect: function () {
|
|
window.taxbaikAdminSession.syncRouteClass();
|
|
window.addEventListener('popstate', window.taxbaikAdminSession.syncRouteClass);
|
|
|
|
if (document.documentElement.classList.contains('admin-login-route')) {
|
|
window.taxbaikAdminSession.hideLoading();
|
|
}
|
|
|
|
// Show loading on initial page load — overlay has 'show' from HTML,
|
|
// but we still need to set up the observer to detect when to hide it.
|
|
window.taxbaikAdminSession.showLoading();
|
|
|
|
const modal = document.getElementById('components-reconnect-modal');
|
|
if (!modal) return;
|
|
|
|
const reloadOnRejectedCircuit = function () {
|
|
const className = modal.className || '';
|
|
if (className.includes('components-reconnect-failed') ||
|
|
className.includes('components-reconnect-rejected')) {
|
|
window.setTimeout(function () { window.location.reload(); }, 1500);
|
|
}
|
|
};
|
|
|
|
new MutationObserver(reloadOnRejectedCircuit)
|
|
.observe(modal, { attributes: true, attributeFilter: ['class'] });
|
|
}
|
|
};
|
|
|
|
// 더존 ERP 스타일 엔터 키 포커스 이동 및 단축키 바인딩
|
|
document.addEventListener('keydown', function (e) {
|
|
if (e.key === 'Enter') {
|
|
const active = document.activeElement;
|
|
if (!active) return;
|
|
|
|
// 특정 영역(편집 폼 또는 다이얼로그) 내의 입력 필드만 포커스 이동 처리
|
|
const container = active.closest('.admin-editor-panel, .mud-form, .mud-dialog');
|
|
if (!container) return;
|
|
|
|
// textarea나 button, submit 타입 등은 기본 동작(줄바꿈/제출) 유지
|
|
if (active.tagName === 'TEXTAREA' ||
|
|
active.tagName === 'BUTTON' ||
|
|
active.getAttribute('type') === 'submit' ||
|
|
active.classList.contains('mud-button-root')) {
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
|
|
// 포커스 이동 가능한 모든 입력 요소 수집
|
|
const focusables = Array.from(container.querySelectorAll('input, select, textarea, button'))
|
|
.filter(el => {
|
|
const style = window.getComputedStyle(el);
|
|
return el.tabIndex >= 0 &&
|
|
!el.disabled &&
|
|
el.getAttribute('aria-disabled') !== 'true' &&
|
|
style.display !== 'none' &&
|
|
style.visibility !== 'hidden';
|
|
});
|
|
|
|
const index = focusables.indexOf(active);
|
|
if (index > -1 && index < focusables.length - 1) {
|
|
const nextEl = focusables[index + 1];
|
|
nextEl.focus();
|
|
if (typeof nextEl.select === 'function') {
|
|
nextEl.select();
|
|
}
|
|
}
|
|
}
|
|
});
|