Full codebase including API server (32 modules + routes), dashboard frontend, DashCA certificate distribution, installer script, and deployment skills.
57 lines
2.1 KiB
JavaScript
57 lines
2.1 KiB
JavaScript
// ========== SKELETON LOADING PLACEHOLDERS ==========
|
|
(function () {
|
|
|
|
function createSkeletonCard() {
|
|
const card = document.createElement('div');
|
|
card.className = 'skeleton-card';
|
|
card.innerHTML =
|
|
'<div style="display:flex;align-items:center;gap:12px;margin-bottom:12px">' +
|
|
'<div class="skeleton-bar" style="width:48px;height:48px;border-radius:8px;flex-shrink:0"></div>' +
|
|
'<div style="flex:1">' +
|
|
'<div class="skeleton-bar" style="width:60%;height:14px;margin-bottom:6px"></div>' +
|
|
'<div class="skeleton-bar" style="width:35%;height:10px"></div>' +
|
|
'</div>' +
|
|
'<div class="skeleton-bar" style="width:42px;height:22px;border-radius:11px"></div>' +
|
|
'</div>' +
|
|
'<div class="skeleton-bar" style="width:45%;height:12px;margin-bottom:10px"></div>' +
|
|
'<div style="display:flex;gap:8px;margin-top:auto">' +
|
|
'<div class="skeleton-bar" style="width:64px;height:28px;border-radius:8px"></div>' +
|
|
'<div class="skeleton-bar" style="width:64px;height:28px;border-radius:8px"></div>' +
|
|
'</div>';
|
|
return card;
|
|
}
|
|
|
|
function showSkeletons(count) {
|
|
const grid = document.getElementById('cards');
|
|
if (!grid || grid.querySelector('.card')) return; // Don't show if real cards exist
|
|
count = count || 6;
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
const sk = createSkeletonCard();
|
|
grid.appendChild(sk);
|
|
// Stagger fade-in
|
|
setTimeout(function () { sk.classList.add('loaded'); }, i * 60);
|
|
}
|
|
}
|
|
|
|
function hideSkeletons() {
|
|
const grid = document.getElementById('cards');
|
|
if (!grid) return;
|
|
var skeletons = grid.querySelectorAll('.skeleton-card');
|
|
if (!skeletons.length) return;
|
|
|
|
skeletons.forEach(function (sk, i) {
|
|
setTimeout(function () {
|
|
sk.style.opacity = '0';
|
|
sk.style.transform = 'translateY(-10px)';
|
|
}, i * 25);
|
|
});
|
|
// Remove after animation
|
|
setTimeout(function () {
|
|
skeletons.forEach(function (sk) { if (sk.parentNode) sk.remove(); });
|
|
}, skeletons.length * 25 + 300);
|
|
}
|
|
|
|
window.SkeletonLoader = { show: showSkeletons, hide: hideSkeletons };
|
|
})();
|