fix: Skip Setup button no longer traps users when unauthenticated
CI / Test & Lint (push) Canceled after 0s
CI / Security audit (push) Canceled after 0s

The Skip button awaited saveConfigToServer() which fails with 403
when TOTP is required, preventing the wizard from dismissing.
Fix: hide wizard FIRST (localStorage-only), then fire server save
as fire-and-forget with .catch().
This commit is contained in:
Hermes committed 2026-08-13 14:34:00 -07:00
1 parent 56c976a935
commit 70209cdf0c
2 files changed
+5 -4

No files matched your search

+2 -2
View File
@@ -127,7 +127,7 @@ This will reset the logo, favicon, title, and position.`))try{if((await secureFe
<div style="margin-top: 8px; padding-top: 12px; border-top: 1px solid var(--border);">
<div style="font-size: 0.95rem;"><strong>Timezone:</strong> ${f.replace(/_/g," ")}</div>
</div>
`,u+="</div>",p.innerHTML=u,D("setup-step-summary")}async function H(p){try{const u=await secureFetch("/api/v1/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(p)});return u.ok?(await u.json(),!0):(errorHandler.logError("[SetupWizard] Save Config",new Error(`Server returned ${u.status}`),{function:"saveConfigToServer"}),!1)}catch(u){return errorHandler.logError("[SetupWizard] Save Config",u,{function:"saveConfigToServer"}),!1}}async function P(){const p={setupComplete:!0,configurationType:h,timestamp:new Date().toISOString(),timezone:document.getElementById("setup-timezone")?.value||Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"};if(h==="homelab"){p.tld=document.getElementById("setup-tld")?.value?.trim()||".home",p.caName=document.getElementById("setup-ca-name")?.value?.trim()||"";const z=document.getElementById("setup-dns-provider")?.value||"technitium";p.dns={provider:z,ip:document.getElementById("setup-dns-ip")?.value?.trim()||"",port:document.getElementById("setup-dns-port")?.value?.trim()||DC.DEFAULTS.DNS_PORT,token:document.getElementById("setup-dns-token")?.value?.trim()||""},p.defaults={dnsType:"private",sslType:"internal",targetIP:"localhost"}}else h==="simple"?(p.defaultIP=document.getElementById("setup-simple-ip")?.value?.trim()||"localhost",p.defaults={dnsType:"none",sslType:"none",targetIP:p.defaultIP}):h==="public"&&(p.domain=document.getElementById("setup-public-domain")?.value?.trim()||"",p.email=document.getElementById("setup-public-email")?.value?.trim()||"",p.routingMode=document.querySelector('input[name="routing-mode"]:checked')?.value||"subdirectory",p.defaults={dnsType:p.routingMode==="subdirectory"?"none":"public",sslType:"letsencrypt",targetIP:"localhost"});const u=await H(p);safeSet("dashcaddy-config",JSON.stringify(p)),safeSet("dashcaddy-setup","completed"),document.getElementById("setup-wizard").style.display="none";const f=h==="homelab"?"Professional Home Lab":h==="simple"?"Simple Setup":"Public Server",g=u?"server (shared across all devices)":"locally (this browser only)";showNotification(`Setup Complete! Configured for: ${f}. Settings saved to: ${g}`,"success",5e3),setTimeout(()=>location.reload(),500)}const v=document.getElementById("setup-step-1-next");v&&(v.onclick=function(p){p.preventDefault();const u=document.querySelector('input[name="config-type"]:checked');u&&(h=u.value),D(h==="homelab"?"setup-step-homelab":h==="simple"?"setup-step-simple":h==="public"?"setup-step-public":"setup-step-homelab")});const C=document.getElementById("setup-skip");C&&(C.onclick=async function(p){p.preventDefault(),confirm("Skip setup? You can run it later from Settings.")&&(await H({setupComplete:!0,skipped:!0,timestamp:new Date().toISOString()}),safeSet("dashcaddy-setup","skipped"),document.getElementById("setup-wizard").style.display="none")});const x=document.getElementById("setup-tld");x&&(x.oninput=function(p){const u=p.target.value||".home",f=document.getElementById("tld-preview"),g=document.getElementById("tld-preview-2");f&&(f.textContent=u),g&&(g.textContent=u)});const $=document.getElementById("setup-homelab-back");$&&($.onclick=function(p){p.preventDefault(),D("setup-step-1")});const E=document.getElementById("setup-homelab-next");E&&(E.onclick=function(p){p.preventDefault();const u=document.getElementById("setup-tld")?.value?.trim()||"",f=document.getElementById("setup-ca-name")?.value?.trim()||"",g=document.getElementById("setup-dns-ip")?.value?.trim()||"";if(!u||!u.startsWith(".")){showNotification("Please enter a valid TLD starting with a dot (e.g., .home)","warning");return}if(!f){showNotification("Please enter a Certificate Authority name","warning");return}if(!g){showNotification("Please enter your DNS server IP address","warning");return}R()});const M=document.getElementById("setup-simple-back");M&&(M.onclick=function(p){p.preventDefault(),D("setup-step-1")});const S=document.getElementById("setup-simple-next");S&&(S.onclick=function(p){p.preventDefault(),R()}),document.querySelectorAll('input[name="routing-mode"]').forEach(function(p){p.onchange=function(){var u=document.getElementById("dns-requirement-note");u&&(u.textContent=this.value==="subdirectory"?"Only one DNS record needed (for the main domain)":"You'll need to configure DNS manually for each subdomain")}});const B=document.getElementById("setup-public-back");B&&(B.onclick=function(p){p.preventDefault(),D("setup-step-1")});const U=document.getElementById("setup-public-next");U&&(U.onclick=function(p){p.preventDefault();const u=document.getElementById("setup-public-domain")?.value?.trim()||"",f=document.getElementById("setup-public-email")?.value?.trim()||"";if(!u){showNotification("Please enter your domain name","warning");return}if(!f||!f.includes("@")){showNotification("Please enter a valid email address","warning");return}R()});const T=document.getElementById("setup-summary-back");T&&(T.onclick=function(p){p.preventDefault(),h==="homelab"?D("setup-step-homela Line truncated
`,u+="</div>",p.innerHTML=u,D("setup-step-summary")}async function H(p){try{const u=await secureFetch("/api/v1/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(p)});return u.ok?(await u.json(),!0):(errorHandler.logError("[SetupWizard] Save Config",new Error(`Server returned ${u.status}`),{function:"saveConfigToServer"}),!1)}catch(u){return errorHandler.logError("[SetupWizard] Save Config",u,{function:"saveConfigToServer"}),!1}}async function P(){const p={setupComplete:!0,configurationType:h,timestamp:new Date().toISOString(),timezone:document.getElementById("setup-timezone")?.value||Intl.DateTimeFormat().resolvedOptions().timeZone||"UTC"};if(h==="homelab"){p.tld=document.getElementById("setup-tld")?.value?.trim()||".home",p.caName=document.getElementById("setup-ca-name")?.value?.trim()||"";const z=document.getElementById("setup-dns-provider")?.value||"technitium";p.dns={provider:z,ip:document.getElementById("setup-dns-ip")?.value?.trim()||"",port:document.getElementById("setup-dns-port")?.value?.trim()||DC.DEFAULTS.DNS_PORT,token:document.getElementById("setup-dns-token")?.value?.trim()||""},p.defaults={dnsType:"private",sslType:"internal",targetIP:"localhost"}}else h==="simple"?(p.defaultIP=document.getElementById("setup-simple-ip")?.value?.trim()||"localhost",p.defaults={dnsType:"none",sslType:"none",targetIP:p.defaultIP}):h==="public"&&(p.domain=document.getElementById("setup-public-domain")?.value?.trim()||"",p.email=document.getElementById("setup-public-email")?.value?.trim()||"",p.routingMode=document.querySelector('input[name="routing-mode"]:checked')?.value||"subdirectory",p.defaults={dnsType:p.routingMode==="subdirectory"?"none":"public",sslType:"letsencrypt",targetIP:"localhost"});const u=await H(p);safeSet("dashcaddy-config",JSON.stringify(p)),safeSet("dashcaddy-setup","completed"),document.getElementById("setup-wizard").style.display="none";const f=h==="homelab"?"Professional Home Lab":h==="simple"?"Simple Setup":"Public Server",g=u?"server (shared across all devices)":"locally (this browser only)";showNotification(`Setup Complete! Configured for: ${f}. Settings saved to: ${g}`,"success",5e3),setTimeout(()=>location.reload(),500)}const v=document.getElementById("setup-step-1-next");v&&(v.onclick=function(p){p.preventDefault();const u=document.querySelector('input[name="config-type"]:checked');u&&(h=u.value),D(h==="homelab"?"setup-step-homelab":h==="simple"?"setup-step-simple":h==="public"?"setup-step-public":"setup-step-homelab")});const C=document.getElementById("setup-skip");C&&(C.onclick=async function(p){p.preventDefault(),confirm("Skip setup? You can run it later from Settings.")&&(safeSet("dashcaddy-setup","skipped"),document.getElementById("setup-wizard").style.display="none",H({setupComplete:!0,skipped:!0,timestamp:new Date().toISOString()}).catch(()=>{}))});const x=document.getElementById("setup-tld");x&&(x.oninput=function(p){const u=p.target.value||".home",f=document.getElementById("tld-preview"),g=document.getElementById("tld-preview-2");f&&(f.textContent=u),g&&(g.textContent=u)});const $=document.getElementById("setup-homelab-back");$&&($.onclick=function(p){p.preventDefault(),D("setup-step-1")});const E=document.getElementById("setup-homelab-next");E&&(E.onclick=function(p){p.preventDefault();const u=document.getElementById("setup-tld")?.value?.trim()||"",f=document.getElementById("setup-ca-name")?.value?.trim()||"",g=document.getElementById("setup-dns-ip")?.value?.trim()||"";if(!u||!u.startsWith(".")){showNotification("Please enter a valid TLD starting with a dot (e.g., .home)","warning");return}if(!f){showNotification("Please enter a Certificate Authority name","warning");return}if(!g){showNotification("Please enter your DNS server IP address","warning");return}R()});const M=document.getElementById("setup-simple-back");M&&(M.onclick=function(p){p.preventDefault(),D("setup-step-1")});const S=document.getElementById("setup-simple-next");S&&(S.onclick=function(p){p.preventDefault(),R()}),document.querySelectorAll('input[name="routing-mode"]').forEach(function(p){p.onchange=function(){var u=document.getElementById("dns-requirement-note");u&&(u.textContent=this.value==="subdirectory"?"Only one DNS record needed (for the main domain)":"You'll need to configure DNS manually for each subdomain")}});const B=document.getElementById("setup-public-back");B&&(B.onclick=function(p){p.preventDefault(),D("setup-step-1")});const U=document.getElementById("setup-public-next");U&&(U.onclick=function(p){p.preventDefault();const u=document.getElementById("setup-public-domain")?.value?.trim()||"",f=document.getElementById("setup-public-email")?.value?.trim()||"";if(!u){showNotification("Please enter your domain name","warning");return}if(!f||!f.includes("@")){showNotification("Please enter a valid email address","warning");return}R()});const T=document.getElementById("setup-summary-back");T&&(T.onclick=function(p){p.preventDefault(),h==="homelab"?D("setup-ste Line truncated
<div class="app-selector-content">
<h2 style="margin: 0 0 24px; color: var(--fg); text-align: center;">Choose an App</h2>
<div id="app-selector-grid" class="app-selector-grid"></div>
@@ -1982,4 +1982,4 @@ To endpoint: POST /api/v1/security/events/ingest or /events/batch`),u()}catch(w)
</button>
</div>
`}).join(""),C.querySelectorAll(".share-revoke").forEach(i=>{i.addEventListener("click",()=>r(i.dataset.shareId))})}catch{C.innerHTML='<span style="color: var(--muted);">Could not load outstanding shares.</span>'}}async function r(t){try{const e=await fetch(`/api/v1/share/${encodeURIComponent(t)}`,{method:"DELETE",credentials:"same-origin"});if(!e.ok){const a=await e.json().catch(()=>({}));b(a&&a.error||`Revoke failed (HTTP ${e.status}).`);return}N("Share revoked."),z()}catch{b("Network error while revoking.")}}async function c(){if(!B)return;T(),$.disabled=!0;const t=$.textContent;$.textContent="Creating\u2026";try{const e=parseInt(S.value,10),a=await fetch("/api/v1/share",{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify({serviceId:B.id,ttlMs:e})}),o=await a.json().catch(()=>({}));if(!a.ok||!o.success){w(a.status,o);return}const i=o.data.urlPath;D.value=p(i),H.textContent=`Public link \xB7 expires ${u(o.data.expiresAt)}`,I.style.display="block",N("Share link created."),z()}catch{b("Network error while creating share.")}finally{$.disabled=!1,$.textContent=t}}async function d(){if(!B)return;const t=(M.value||"").trim();if(!t||!t.includes("@")){b("A valid recipient email is required.");return}T(),E.disabled=!0;const e=E.textContent;E.textContent="Creating\u2026";try{const a=await fetch("/api/v1/share/tailscale",{method:"POST",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify({serviceId:B.id,email:t})}),o=await a.json().catch(()=>({}));if(!a.ok||!o.success){w(a.status,o);return}const i=o.data&&o.data.urlPath;i?(D.value=p(i),H.textContent=`Tailscale invite \xB7 emailed to ${t} (or use this URL manually if delivery failed).`):(D.value="",H.textContent=`Tailscale invite sent to ${t}.`),I.style.display="block",N("Tailscale invite created."),M.value="",z()}catch{b("Network error while creating Tailscale invite.")}finally{E.disabled=!1,E.textContent=e}}function w(t,e){const a=e&&e.error||"";if(t===402){b("Share is a Pro feature. Activate a license to unlock.");return}if(t===400&&/tailscale/i.test(a)){b("Tailscale is not configured on this host. Set up Tailscale in the dashboard first.");return}if(t===403){b("You do not have permission to share services.");return}if(t===404){b("Service not found. It may have been deleted.");return}b(a||`Request failed (HTTP ${t}).`)}function y(t){!t||!t.id||(B={id:t.id,name:t.name||t.id},A.textContent=B.name,T(),g("public"),M.value="",S.value=String(h[1].ms),L.classList.add("show"),z())}L.querySelectorAll(".share-tab").forEach(t=>{t.addEventListener("click",()=>g(t.dataset.tab))}),$.addEventListener("click",c),E.addEventListener("click",d),x.addEventListener("click",()=>L.classList.remove("show")),wireModal(L,x),R.addEventListener("click",async()=>{const t=D.value;if(t)try{navigator.clipboard&&navigator.clipboard.writeText?await navigator.clipboard.writeText(t):(D.select(),document.execCommand("copy"));const e=R.textContent;R.textContent="Copied!",setTimeout(()=>{R.textContent=e},1200)}catch{b("Could not copy to clipboard. Select the URL manually.")}}),window.openShareModal=y})(),(function(){"use strict";const h="dashcaddy-language",A=["en","ar","bn","cs","da","de","el","es","fa","fi","fr","hi","hu","id","it","ja","ko","ms","nl","no","pl","pt","ro","ru","sv","th","tr","uk","ur","vi","zh"],I={en:"English",ar:"\u0627\u0644\u0639\u0631\u0628\u064A\u0629",bn:"\u09AC\u09BE\u0982\u09B2\u09BE",cs:"\u010Ce\u0161tina",da:"Dansk",de:"Deutsch",el:"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC",es:"Espa\xF1ol",fa:"\u0641\u0627\u0631\u0633\u06CC",fi:"Suomi",fr:"Fran\xE7ais",hi:"\u0939\u093F\u0928\u094D\u0926\u0940",hu:"Magyar",id:"Bahasa Indonesia",it:"Italiano",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",ms:"Bahasa Melayu",nl:"Nederlands",no:"Norsk",pl:"Polski",pt:"Portugu\xEAs",ro:"Rom\xE2n\u0103",ru:"\u0420\u0443\u0441\u0441\u043A\u0438\u0439",sv:"Svenska",th:"\u0E44\u0E17\u0E22",tr:"T\xFCrk\xE7e",uk:"\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430",ur:"\u0627\u0631\u062F\u0648",vi:"Ti\u1EBFng Vi\u1EC7t",zh:"\u4E2D\u6587"},D=new Set(["ar","fa","ur"]);function R(){try{const b=localStorage.getItem(h);if(b&&A.includes(b))return b}catch{}return"en"}let H=R(),P={},v=!1,C=0;async function x(b,N){if(N===void 0&&(N=++C),b==="en"){P={},v=!0;return}try{const O=await fetch(`/api/v1/i18n/translations/${b}`);if(N!==C)return;if(O.ok){const p=await O.json();if(N!==C)return;P=p.translations||{},v=!0}else P={},v=!1}catch(O){console.warn("[i18n] Failed to load translations for",b,O),N===C&&(P={},v=!1)}}function $(b){return H==="en"?b:P[b]||b}function E(b){if(!A.includes(b))return;H=b;try{localStorage.setItem(h,b)}catch{}const N=D.has(b);document.documentElement.dir=N?"rtl":"ltr",document.documentElement.lang=b;const O=++C;x(b,O).then(()=>{O===C&&S()})}function M(){return H}function S(){document.querySelectorAll("[data-i18n]").forEach(b=>{const N=b.getAttribute("data-i18n");b.textContent=$Line truncated
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiPHN0ZGluPiJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLy8gTG9nbyBDdXN0b21pemF0aW9uIFN5c3RlbVxuKGZ1bmN0aW9uKCkge1xuICAvLyBJbmplY3QgbW9kYWwgSFRNTFxuICBpbmplY3RNb2RhbCgnbG9nby1tb2RhbCcsIGA8ZGl2IGlkPVwibG9nby1tb2RhbFwiIGNsYXNzPVwid2VhdGhlci1tb2RhbFwiPlxuICAgIDxkaXYgY2xhc3M9XCJ3ZWF0aGVyLW1vZGFsLWNvbnRlbnRcIiBzdHlsZT1cIm1pbi13aWR0aDogNDAwcHg7IG1heC13aWR0aDogNTIwcHg7XCI+XG4gICAgICA8aDM+RGFzaGJvYXJkIFNldHRpbmdzPC9oMz5cbiAgICAgIDxwIHN0eWxlPVwiZm9udC1zaXplOiAwLjg1cmVtOyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBtYXJnaW46IDAgMCAxNnB4O1wiPlxuICAgICAgICBDdXN0b21pemUgeW91ciBkYXNoYm9hcmQncyBhcHBlYXJhbmNlIGFuZCBzeXN0ZW0gcHJlZmVyZW5jZXMuXG4gICAgICA8L3A+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0xNlwiPlxuICAgICAgICA8bGFiZWwgZm9yPVwiZGFzaGJvYXJkLXRpdGxlXCIgY2xhc3M9XCJmb3JtLWxhYmVsLWJvbGRcIj5EYXNoYm9hcmQgVGl0bGU6PC9sYWJlbD5cbiAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgaWQ9XCJkYXNoYm9hcmQtdGl0bGVcIiBwbGFjZWhvbGRlcj1cIkRhc2hDYWRkeVwiIG1heGxlbmd0aD1cIjUwXCIgc3R5bGU9XCJ3aWR0aDogMTAwJTsgcGFkZGluZzogMTBweCAxMnB4OyBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpOyBib3JkZXItcmFkaXVzOiA0cHg7IGJhY2tncm91bmQ6IHZhcigtLWNhcmQtYmcpOyBjb2xvcjogdmFyKC0tZmcpOyBmb250LXNpemU6IDFyZW07XCIgLz5cbiAgICAgICAgPHAgY2xhc3M9XCJ0aW55LWhpbnRcIj5TaG93biBpbiBicm93c2VyIHRhYiBhbmQgaGVhZGVyIChtYXggNTAgY2hhcmFjdGVycyk8L3A+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGhyIGNsYXNzPVwiaHItZGl2aWRlclwiIC8+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0xNlwiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsLWJvbGRcIj5Mb2dvOjwvbGFiZWw+XG4gICAgICAgIDxwIGNsYXNzPVwidGlueS1oaW50XCIgc3R5bGU9XCJtYXJnaW4tdG9wOiAycHg7XCI+U2VwYXJhdGUgbG9nb3MgZm9yIGRhcmsgYW5kIGxpZ2h0IHRoZW1lcywgb3IgdXNlIHRoZSBzYW1lIGZvciBib3RoLjwvcD5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IHN0eWxlPVwiZGlzcGxheTogZmxleDsgZ2FwOiAxMnB4OyBtYXJnaW4tYm90dG9tOiAxMnB4O1wiPlxuICAgICAgICA8ZGl2IHN0eWxlPVwiZmxleDogMTsgdGV4dC1hbGlnbjogY2VudGVyOyBwYWRkaW5nOiAxNnB4IDEwcHg7IGJvcmRlci1yYWRpdXM6IDhweDsgYmFja2dyb3VuZDogIzFhMWEyZTsgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyNTUsMjU1LDI1NSwuMSk7XCI+XG4gICAgICAgICAgPGltZyBpZD1cImxvZ28tcHJldmlldy1kYXJrXCIgc3JjPVwiL2Fzc2V0cy9kYXNoY2FkZHktbG9nby1kYXJrLnBuZ1wiIGFsdD1cIkRhcmsgdGhlbWUgbG9nb1wiIHN0eWxlPVwibWF4LWhlaWdodDogNjBweDsgbWF4LXdpZHRoOiAxMDAlO1wiIC8+XG4gICAgICAgICAgPHAgc3R5bGU9XCJmb250LXNpemU6IDAuNjVyZW07IGNvbG9yOiAjOWFhNmJmOyBtYXJnaW4tdG9wOiA2cHg7XCI+RGFyayB0aGVtZXM8L3A+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IHN0eWxlPVwiZmxleDogMTsgdGV4dC1hbGlnbjogY2VudGVyOyBwYWRkaW5nOiAxNnB4IDEwcHg7IGJvcmRlci1yYWRpdXM6IDhweDsgYmFja2dyb3VuZDogI2YwZjBmMDsgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLDAsMCwuMSk7XCI+XG4gICAgICAgICAgPGltZyBpZD1cImxvZ28tcHJldmlldy1saWdodFwiIHNyYz1cIi9hc3NldHMvZGFzaGNhZGR5LWxvZ28tbGlnaHQucG5nXCIgYWx0PVwiTGlnaHQgdGhlbWUgbG9nb1wiIHN0eWxlPVwibWF4LWhlaWdodDogNjBweDsgbWF4LXdpZHRoOiAxMDAlO1wiIC8+XG4gICAgICAgICAgPHAgc3R5bGU9XCJmb250LXNpemU6IDAuNjVyZW07IGNvbG9yOiAjNWY2YjdhOyBtYXJnaW4tdG9wOiA2cHg7XCI+TGlnaHQgdGhlbWVzPC9wPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPHAgaWQ9XCJsb2dvLXN0YXR1c1wiIHN0eWxlPVwiZm9udC1zaXplOiAwLjc1cmVtOyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBtYXJnaW4tYm90dG9tOiAxMnB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7XCI+VXNpbmcgZGVmYXVsdCBsb2dvczwvcD5cblxuICAgICAgPGRpdiBjbGFzcz1cIm1iLTE2XCI+XG4gICAgICAgIDxsYWJlbCBzdHlsZT1cImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGdhcDogOHB4OyBmb250LXNpemU6IDAuODJyZW07IGN1cnNvcjogcG9pbnRlcjsgdXNlci1zZWxlY3Q6IG5vbmU7XCI+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGlkPVwibG9nby1zYW1lLWJvdGhcIiAvPiBVc2Ugc2FtZSBsb2dvIGZvciBib3RoXG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBpZD1cImxvZ28tZHVhbC11cGxvYWRzXCIgY2xhc3M9XCJtYi0xNlwiIHN0eWxlPVwiZGlzcGxheTogZmxleDsgZ2FwOiAxMnB4O1wiPlxuICAgICAgICA8ZGl2IHN0eWxlPVwiZmxleDogMTtcIj5cbiAgICAgICAgICA8bGFiZWwgZm9yPVwibG9nby11cGxvYWQtZGFya1wiIHN0eWxlPVwiZGlzcGxheTogYmxvY2s7IG1hcmdpbi1ib3R0b206IDZweDsgZm9udC1zaXplOiAwLjhyZW07XCI+RGFyayB0aGVtZSBsb2dvOjwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJmaWxlXCIgaWQ9XCJsb2dvLXVwbG9hZC1kYXJrXCIgYWNjZXB0PVwiaW1hZ2UvKlwiIGNsYXNzPVwiaW5wdXQtY2FyZC1hbHRcIiBzdHlsZT1cImZvbnQtc2l6ZTogMC43NXJlbTtcIiAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBzdHlsZT1cImZsZXg6IDE7XCI+XG4gICAgICAgICAgPGxhYmVsIGZvcj1cImxvZ28tdXBsb2FkLWxpZ2h0XCIgc3R5bGU9XCJkaXNwbGF5OiBibG9jazsgbWFyZ2luLWJvdHRvbTogNnB4OyBmb250LXNpemU6IDAuOHJlbTtcIj5MaWdodCB0aGVtZSBsb2dvOjwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJmaWxlXCIgaWQ9XCJsb2dvLXVwbG9hZC1saWdodFwiIGFjY2VwdD1cImltYWdlLypcIiBjbGFzcz1cImlucHV0LWNhcmQtYWx0XCIgc3R5bGU9XCJmb250LXNpemU6IDAuNzVyZW07XCIgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBpZD1cImxvZ28tc2luZ2xlLXVwbG9hZFwiIGNsYXNzPVwibWItMTZcIiBzdHlsZT1cImRpc3BsYXk6IG5vbmU7XCI+XG4gICAgICAgIDxsYWJlbCBmb3I9XCJsb2dvLXVwbG9hZC1zaW5nbGVcIiBzdHlsZT1cImRpc3BsYXk6IGJsb2NrOyBtYXJnaW4tYm90dG9tOiA2cHg7IGZvbnQtc2l6ZTogMC44cmVtO1wiPlVwbG9hZCBsb2dvOjwvbGFiZWw+XG4gICAgICAgIDxpbnB1dCB0eXBlPVwiZmlsZVwiIGlkPVwibG9nby11cGxvYWQtc2luZ2xlXCIgYWNjZXB0PVwiaW1hZ2UvKlwiIGNsYXNzPVwiaW5wdXQtY2FyZC1hbHRcIiAvPlxuICAgICAgICA8cCBjbGFzcz1cInRpbnktaGludFwiPlRoaXMgbG9nbyB3aWxsIGJlIHVzZWQgb24gYWxsIHRoZW1lc Line truncated
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiPHN0ZGluPiJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLy8gTG9nbyBDdXN0b21pemF0aW9uIFN5c3RlbVxuKGZ1bmN0aW9uKCkge1xuICAvLyBJbmplY3QgbW9kYWwgSFRNTFxuICBpbmplY3RNb2RhbCgnbG9nby1tb2RhbCcsIGA8ZGl2IGlkPVwibG9nby1tb2RhbFwiIGNsYXNzPVwid2VhdGhlci1tb2RhbFwiPlxuICAgIDxkaXYgY2xhc3M9XCJ3ZWF0aGVyLW1vZGFsLWNvbnRlbnRcIiBzdHlsZT1cIm1pbi13aWR0aDogNDAwcHg7IG1heC13aWR0aDogNTIwcHg7XCI+XG4gICAgICA8aDM+RGFzaGJvYXJkIFNldHRpbmdzPC9oMz5cbiAgICAgIDxwIHN0eWxlPVwiZm9udC1zaXplOiAwLjg1cmVtOyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBtYXJnaW46IDAgMCAxNnB4O1wiPlxuICAgICAgICBDdXN0b21pemUgeW91ciBkYXNoYm9hcmQncyBhcHBlYXJhbmNlIGFuZCBzeXN0ZW0gcHJlZmVyZW5jZXMuXG4gICAgICA8L3A+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0xNlwiPlxuICAgICAgICA8bGFiZWwgZm9yPVwiZGFzaGJvYXJkLXRpdGxlXCIgY2xhc3M9XCJmb3JtLWxhYmVsLWJvbGRcIj5EYXNoYm9hcmQgVGl0bGU6PC9sYWJlbD5cbiAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgaWQ9XCJkYXNoYm9hcmQtdGl0bGVcIiBwbGFjZWhvbGRlcj1cIkRhc2hDYWRkeVwiIG1heGxlbmd0aD1cIjUwXCIgc3R5bGU9XCJ3aWR0aDogMTAwJTsgcGFkZGluZzogMTBweCAxMnB4OyBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpOyBib3JkZXItcmFkaXVzOiA0cHg7IGJhY2tncm91bmQ6IHZhcigtLWNhcmQtYmcpOyBjb2xvcjogdmFyKC0tZmcpOyBmb250LXNpemU6IDFyZW07XCIgLz5cbiAgICAgICAgPHAgY2xhc3M9XCJ0aW55LWhpbnRcIj5TaG93biBpbiBicm93c2VyIHRhYiBhbmQgaGVhZGVyIChtYXggNTAgY2hhcmFjdGVycyk8L3A+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGhyIGNsYXNzPVwiaHItZGl2aWRlclwiIC8+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0xNlwiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsLWJvbGRcIj5Mb2dvOjwvbGFiZWw+XG4gICAgICAgIDxwIGNsYXNzPVwidGlueS1oaW50XCIgc3R5bGU9XCJtYXJnaW4tdG9wOiAycHg7XCI+U2VwYXJhdGUgbG9nb3MgZm9yIGRhcmsgYW5kIGxpZ2h0IHRoZW1lcywgb3IgdXNlIHRoZSBzYW1lIGZvciBib3RoLjwvcD5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IHN0eWxlPVwiZGlzcGxheTogZmxleDsgZ2FwOiAxMnB4OyBtYXJnaW4tYm90dG9tOiAxMnB4O1wiPlxuICAgICAgICA8ZGl2IHN0eWxlPVwiZmxleDogMTsgdGV4dC1hbGlnbjogY2VudGVyOyBwYWRkaW5nOiAxNnB4IDEwcHg7IGJvcmRlci1yYWRpdXM6IDhweDsgYmFja2dyb3VuZDogIzFhMWEyZTsgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyNTUsMjU1LDI1NSwuMSk7XCI+XG4gICAgICAgICAgPGltZyBpZD1cImxvZ28tcHJldmlldy1kYXJrXCIgc3JjPVwiL2Fzc2V0cy9kYXNoY2FkZHktbG9nby1kYXJrLnBuZ1wiIGFsdD1cIkRhcmsgdGhlbWUgbG9nb1wiIHN0eWxlPVwibWF4LWhlaWdodDogNjBweDsgbWF4LXdpZHRoOiAxMDAlO1wiIC8+XG4gICAgICAgICAgPHAgc3R5bGU9XCJmb250LXNpemU6IDAuNjVyZW07IGNvbG9yOiAjOWFhNmJmOyBtYXJnaW4tdG9wOiA2cHg7XCI+RGFyayB0aGVtZXM8L3A+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IHN0eWxlPVwiZmxleDogMTsgdGV4dC1hbGlnbjogY2VudGVyOyBwYWRkaW5nOiAxNnB4IDEwcHg7IGJvcmRlci1yYWRpdXM6IDhweDsgYmFja2dyb3VuZDogI2YwZjBmMDsgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLDAsMCwuMSk7XCI+XG4gICAgICAgICAgPGltZyBpZD1cImxvZ28tcHJldmlldy1saWdodFwiIHNyYz1cIi9hc3NldHMvZGFzaGNhZGR5LWxvZ28tbGlnaHQucG5nXCIgYWx0PVwiTGlnaHQgdGhlbWUgbG9nb1wiIHN0eWxlPVwibWF4LWhlaWdodDogNjBweDsgbWF4LXdpZHRoOiAxMDAlO1wiIC8+XG4gICAgICAgICAgPHAgc3R5bGU9XCJmb250LXNpemU6IDAuNjVyZW07IGNvbG9yOiAjNWY2YjdhOyBtYXJnaW4tdG9wOiA2cHg7XCI+TGlnaHQgdGhlbWVzPC9wPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPHAgaWQ9XCJsb2dvLXN0YXR1c1wiIHN0eWxlPVwiZm9udC1zaXplOiAwLjc1cmVtOyBjb2xvcjogdmFyKC0tbXV0ZWQpOyBtYXJnaW4tYm90dG9tOiAxMnB4OyB0ZXh0LWFsaWduOiBjZW50ZXI7XCI+VXNpbmcgZGVmYXVsdCBsb2dvczwvcD5cblxuICAgICAgPGRpdiBjbGFzcz1cIm1iLTE2XCI+XG4gICAgICAgIDxsYWJlbCBzdHlsZT1cImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGdhcDogOHB4OyBmb250LXNpemU6IDAuODJyZW07IGN1cnNvcjogcG9pbnRlcjsgdXNlci1zZWxlY3Q6IG5vbmU7XCI+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiIGlkPVwibG9nby1zYW1lLWJvdGhcIiAvPiBVc2Ugc2FtZSBsb2dvIGZvciBib3RoXG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBpZD1cImxvZ28tZHVhbC11cGxvYWRzXCIgY2xhc3M9XCJtYi0xNlwiIHN0eWxlPVwiZGlzcGxheTogZmxleDsgZ2FwOiAxMnB4O1wiPlxuICAgICAgICA8ZGl2IHN0eWxlPVwiZmxleDogMTtcIj5cbiAgICAgICAgICA8bGFiZWwgZm9yPVwibG9nby11cGxvYWQtZGFya1wiIHN0eWxlPVwiZGlzcGxheTogYmxvY2s7IG1hcmdpbi1ib3R0b206IDZweDsgZm9udC1zaXplOiAwLjhyZW07XCI+RGFyayB0aGVtZSBsb2dvOjwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJmaWxlXCIgaWQ9XCJsb2dvLXVwbG9hZC1kYXJrXCIgYWNjZXB0PVwiaW1hZ2UvKlwiIGNsYXNzPVwiaW5wdXQtY2FyZC1hbHRcIiBzdHlsZT1cImZvbnQtc2l6ZTogMC43NXJlbTtcIiAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBzdHlsZT1cImZsZXg6IDE7XCI+XG4gICAgICAgICAgPGxhYmVsIGZvcj1cImxvZ28tdXBsb2FkLWxpZ2h0XCIgc3R5bGU9XCJkaXNwbGF5OiBibG9jazsgbWFyZ2luLWJvdHRvbTogNnB4OyBmb250LXNpemU6IDAuOHJlbTtcIj5MaWdodCB0aGVtZSBsb2dvOjwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0IHR5cGU9XCJmaWxlXCIgaWQ9XCJsb2dvLXVwbG9hZC1saWdodFwiIGFjY2VwdD1cImltYWdlLypcIiBjbGFzcz1cImlucHV0LWNhcmQtYWx0XCIgc3R5bGU9XCJmb250LXNpemU6IDAuNzVyZW07XCIgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBpZD1cImxvZ28tc2luZ2xlLXVwbG9hZFwiIGNsYXNzPVwibWItMTZcIiBzdHlsZT1cImRpc3BsYXk6IG5vbmU7XCI+XG4gICAgICAgIDxsYWJlbCBmb3I9XCJsb2dvLXVwbG9hZC1zaW5nbGVcIiBzdHlsZT1cImRpc3BsYXk6IGJsb2NrOyBtYXJnaW4tYm90dG9tOiA2cHg7IGZvbnQtc2l6ZTogMC44cmVtO1wiPlVwbG9hZCBsb2dvOjwvbGFiZWw+XG4gICAgICAgIDxpbnB1dCB0eXBlPVwiZmlsZVwiIGlkPVwibG9nby11cGxvYWQtc2luZ2xlXCIgYWNjZXB0PVwiaW1hZ2UvKlwiIGNsYXNzPVwiaW5wdXQtY2FyZC1hbHRcIiAvPlxuICAgICAgICA8cCBjbGFzcz1cInRpbnktaGludFwiPlRoaXMgbG9nbyB3aWxsIGJlIHVzZWQgb24gYWxsIHRoZW1lc Line truncated
+3 -2
View File
@@ -252,10 +252,11 @@ window.populateTimezoneSelect = function(selectEl, selectedTz) {
skipBtn.onclick = async function(e) {
e.preventDefault();
if (confirm('Skip setup? You can run it later from Settings.')) {
// Save skip status to server
await saveConfigToServer({ setupComplete: true, skipped: true, timestamp: new Date().toISOString() });
// Save skip status — hide wizard FIRST so it always dismisses,
// then attempt server save (fire-and-forget, never blocks UI)
safeSet('dashcaddy-setup', 'skipped');
document.getElementById('setup-wizard').style.display = 'none';
saveConfigToServer({ setupComplete: true, skipped: true, timestamp: new Date().toISOString() }).catch(() => {});
}
};
}