PageSourceSearch

https://www.panuluukka.fi/assets/admin.varmuuskopiot-CcDZ3KUh.js

js panuluukka.fi collected 2026-09-25 03:25:52 UTC 7,011 bytes, 1 lines download raw bytes

1import{J as c,at as d,K as m,H as $,au as u,r as g,w as A,I as h,j as e}from"./index-X4zOIsZb.js";import{t as r}from"./index-B_BA5Zz2.js";import{B as o}from"./button-CfWm66g7.js";import{D,b as E,c as B,d as _,e as K,f as O}from"./dialog-CYx6L36e.js";import{I as R}from"./input-B7KnWRnH.js";import{L as q}from"./label-Cor-0N_M.js";import{L as b}from"./loader-circle-D6RRSbbz.js";import{R as M}from"./refresh-cw-BCM4Dwhf.js";import{R as Q}from"./rotate-ccw-DoyI1CM3.js";import{D as U}from"./download-DobI6_Mc.js";import{T as V}from"./trash-2-Ben-lzmw.js";import"./utils-BQHNewu7.js";import"./index-D7HHJdwB.js";import"./x-CD7Vw_t5.js";import"./createLucideIcon-BG8JlC3m.js";const z=c({method:"GET"}).middleware([d]).handler(m("f2189b13ccfb2161b7b8f6ec5b5eb928d8ab4ded5f3f96885cad7e54bdc7063f")),I=c({method:"POST"}).middleware([d]).handler(m("a9cd7d33a4a5efa82d74d559fad9806166b648a2945d97868c66a53b23bdd279")),H=c({method:"POST"}).middleware([d]).handler(m("92e552c4a8cbe27646b1b5a273cf4153bfbbb9e6c200c1f64d53e1d5b953c35a")),G=c({method:"POST"}).middleware([d]).handler(m("a7205068e5801272b34d09eadd89ac045bc8166d400a0efa3cc83f49d0cd8198")),J=c({method:"POST"}).middleware([d]).handler(m("d4b62c568ba8f607ae3259f9def83d70508ab4cf24d1a6f56e9be4f8105d5ba2"));function y(s){return s==null?"—":s<1024?`${s} B`:s<1024*1024?`${(s/1024).toFixed(1)} kB`:`${(s/(1024*1024)).toFixed(2)} MB`}function W(s){if(!s)return"—";try{return new Date(s).toLocaleString("fi-FI",{dateStyle:"medium",timeStyle:"short"})}catch{return s}}function me(){const s=$(),w=u(z),N=u(I),P=u(H),S=u(G),F=u(J),[n,p]=g.useState(null),[v,l]=g.useState(""),t=A({queryKey:["site-backups"],queryFn:()=>w(),staleTime:1e4}),f=h({mutationFn:()=>N(),onSuccess:a=>{r.success(`Varmuuskopio luotu: ${a.folder} (${a.files} kuvaa, ${y(a.bytes)})`),s.invalidateQueries({queryKey:["site-backups"]})},onError:a=>{r.error(`Varmuuskopio epäonnistui: ${a instanceof Error?a.message:String(a)}`)}}),j=h({mutationFn:a=>S({data:{folder:a}}),onSuccess:()=>{r.success("Varmuuskopio poistettu"),s.invalidateQueries({queryKey:["site-backups"]})},onError:a=>{r.error(`Poisto epäonnistui: ${a instanceof Error?a.message:String(a)}`)}}),x=h({mutationFn:a=>F({data:{folder:a,confirm:"PALAUTA"}}),onSuccess:a=>{const i=Object.values(a.tables).reduce((C,L)=>C+L,0);r.success(`Palautus valmis: ${i} riviä tauluista, ${a.files} kuvaa. Skipatut taulut: ${a.skipped.join(", ")||"ei mitään"}`,{duration:8e3}),p(null),l(""),s.invalidateQueries()},onError:a=>{r.error(`Palautus epäonnistui: ${a instanceof Error?a.message:String(a)}`)}}),T=async a=>{try{const{url:i}=await P({data:{folder:a}});window.open(i,"_blank","noopener,noreferrer")}catch(i){r.error(`Latauslinkki epäonnistui: ${i instanceof Error?i.message:String(i)}`)}},k=t.data??[];return e.jsxs("div",{children:[e.jsx("h1",{className:"font-display text-3xl text-primary",children:"Varmuuskopiot"}),e.jsx("p",{className:"mt-3 max-w-2xl text-foreground/80",children:"Sivuston sisältötaulut ja blogikuvat varmuuskopioidaan automaattisesti kerran viikossa (maanantaisin klo 03:00 Suomen aikaa). Voit myös luoda tai palauttaa varmuuskopion milloin tahansa. Säilytetään 12 viimeistä kopiota."}),e.jsxs("div",{className:"mt-6 flex flex-wrap gap-3",children:[e.jsx(o,{onClick:()=>f.mutate(),disabled:f.isPending,children:f.isPending?e.jsxs(e.Fragment,{children:[e.jsx(b,{className:"mr-2 h-4 w-4 animate-spin"}),"Luodaan…"]}):"Luo varmuuskopio nyt"}),e.jsxs(o,{variant:"outline",onClick:()=>t.refetch(),disabled:t.isFetching,children:[e.jsx(M,{className:`mr-2 h-4 w-4 ${t.isFetching?"animate-spin":""}`}),"Päivitä lista"]})]}),e.jsxs("div",{className:"mt-8 border border-border bg-card",children:[e.jsx("div",{className:"border-b border-border px-4 py-3",children:e.jsx("div",{className:"eyebrow text-accent",children:"Olemassa olevat varmuuskopiot"})}),t.isLoading?e.jsx("div",{className:"px-4 py-8 text-sm text-muted-foreground",children:"Ladataan…"}):t.isError?e.jsxs("div",{className:"px-4 py-8 text-sm text-destructive",children:["Listan lataus epäonnistui:"," ",t.error instanceof Error?t.error.message:String(t.error)]}):k.length===0?e.jsx("div",{className:"px-4 py-8 text-sm text-muted-foreground",children:'Ei vielä varmuuskopioita. Klikkaa "Luo varmuuskopio nyt" luodaksesi ensimmäisen.'}):e.jsx("ul",{className:"divide-y divide-border",children:k.map(a=>e.jsxs("li",{className:"flex flex-wrap items-center justify-between gap-3 px-4 py-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"font-mono text-sm text-primary truncate",children:a.folder}),e.jsxs("div",{className:"text-xs text-muted-foreground",children:[W(a.manifest_at)," · ",y(a.size)," · ",a.file_count," kuvaa · ",a.table_count," taulua"]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(o,{size:"sm",variant:"default",onClick:()=>{p(a.folder),l("")},children:[e.jsx(Q,{className:"mr-1 h-4 w-4"}),"Palauta"]}),e.jsxs(o,{size:"sm",variant:"outline",onClick:()=>T(a.folder),children:[e.jsx(U,{className:"mr-1 h-4 w-4"}),"Lataa manifest"]}),e.jsx(o,{size:"sm",variant:"ghost",onClick:()=>{window.confirm(`Poistetaanko varmuuskopio ${a.folder}? Toimintoa ei voi peruuttaa.`)&&j.mutate(a.folder)},disabled:j.isPending,children:e.jsx(V,{className:"h-4 w-4"})})]})]},a.folder))})]}),e.jsxs("div",{className:"mt-6 text-xs text-muted-foreground max-w-2xl space-y-2",children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Sisältö:"})," pillar_content + versiohistoria, blog_posts, podcast-taulut, bi
1o_images, featured_item, user_roles, sekä blog-images-bucketin kuvat."]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Palautus:"})," palauttaa varmuuskopion taulurivit ja kuvat sivustolle. Palautus ",e.jsx("em",{children:"ei poista"})," rivejä jotka on lisätty varmuuskopion jälkeen — se yliajaa samat rivit (primary keylla) ja lisää puuttuvat. Käyttäjärooleja (user_roles) ja pilarin versiohistoriaa ei palauteta."]})]}),e.jsx(D,{open:n!==null,onOpenChange:a=>{a||(p(null),l(""))},children:e.jsxs(E,{children:[e.jsxs(B,{children:[e.jsx(_,{children:"Palauta varmuuskopio"}),e.jsxs(K,{children:["Tämä yliajaa nykyisen sivuston sisällön varmuuskopion"," ",e.jsx("span",{className:"font-mono",children:n})," tilalla. Kaikki muutokset jotka on tehty varmuuskopion jälkeen samoihin riveihin menetetään."]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(q,{htmlFor:"confirm-input",children:["Kirjoita ",e.jsx("span",{className:"font-mono font-bold",children:"PALAUTA"})," vahvistaaksesi:"]}),e.jsx(R,{id:"confirm-input",value:v,onChange:a=>l(a.target.value),placeholder:"PALAUTA",autoComplete:"off"})]}),e.jsxs(O,{children:[e.jsx(o,{variant:"outline",onClick:()=>{p(null),l("")},children:"Peruuta"}),e.jsx(o,{variant:"destructive",disabled:v!=="PALAUTA"||x.isPending||!n,onClick:()=>n&&x.mutate(n),children:x.isPending?e.jsxs(e.Fragment,{children:[e.jsx(b,{className:"mr-2 h-4 w-4 animate-spin"}),"Palautetaan…"]}):"Palauta nyt"})]})]})})]})}export{me as component};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.