Initial commit: DashCaddy v1.0

Full codebase including API server (32 modules + routes), dashboard frontend,
DashCA certificate distribution, installer script, and deployment skills.
This commit is contained in:
2026-03-05 02:26:12 -08:00
commit f61e85d9a7
337 changed files with 75282 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
// ========== 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 };
})();