1import{r as e,j as s}from"./vendor-react-BH6F5oQJ.js";import{t as r,f as t,H as a,C as i,M as l,N as n,O as d,m as c,B as o,G as m}from"./index-dRqPaCFl.js";import{L as h}from"./label-RVODh2pd.js";import{S as x,a as u,b as p,c as j,d as f}from"./select-DsVkFSYt.js";import{T as v,a as g,b,c as N,d as y,e as w}from"./table-C7ziGuLk.js";import{D as _,f as C,a as L,b as k,c as R,d as S,e as P}from"./dialog-5O1RHm7r.js";import{b as I,c as V,d as U,e as T,f as A,g as M}from"./useRedirects-CEa7XKDu.js";import{A as D}from"./AdminLayout-CKCESQT6.js";import{A as F,a as $}from"./alert-Bi7u5HD8.js";import{c as E,P as O}from"./vendor-ui-B4WC06Sp.js";import{x as q,D as z,ae as B,H,J as W,aa as G,S as X,Z as J}from"./vendor-icons-CaI5__By.js";import{f as Z}from"./format-hXGQLsWs.js";import"./vendor-query-CC4VRGyP.js";import"./vendor-supabase-COwyE4EW.js";import"./index-B3FPD4RS.js";import"./Combination-DzDAyqvK.js";import"./index-CCdGLatk.js";import"./separator-KtQ1mSuG.js";import"./en-US-DUAJ-5Wt.js";var K=Object.defineProperty,Q=(e,s)=>K(e,"name",{value:s,configurable:!0}),Y="Progress",[ee,se]=E(Y),[re,te]=ee(Y),ae=e.forwardRef(Q(function(e,r){const{__scopeProgress:t,value:a=null,max:i,getValueLabel:l=le,...n}=e;(i||0===i)&&ce(i);const d=ce(i)?i:100;null!==a&&oe(a,d);const c=oe(a,d)?a:null,o=de(c)?l(c,d):void 0;return s.jsx(re,{scope:t,value:c,max:d,children:s.jsx(O.div,{"aria-valuemax":d,"aria-valuemin":0,"aria-valuenow":de(c)?c:void 0,"aria-valuetext":o,role:"progressbar","data-state":ne(c,d),"data-value":c??void 0,"data-max":d,...n,ref:r})})},"Progress")),ie=e.forwardRef(Q(function(e,r){const{__scopeProgress:t,...a}=e,i=te("ProgressIndicator",t);return s.jsx(O.div,{"data-state":ne(i.value,i.max),"data-value":i.value??void 0,"data-max":i.max,...a,ref:r})},"ProgressIndicator"));function le(e,s){return`${Math.round(e/s*100)}%`}function ne(e,s){return null==e?"indeterminate":e===s?"complete":"loading"}function de(e){return"number"==typeof e}function ce(e){return de(e)&&!isNaN(e)&&e>0}function oe(e,s){return de(e)&&!isNaN(e)&&e<=s&&e>=0}Q(le,"defaultGetValueLabel"),Q(ne,"getProgressState"),Q(de,"isNumber"),Q(ce,"isValidMaxNumber"),Q(oe,"isValidValueNumber"),Q(function(e,s){return`Invalid prop \`max\` of value \`${e}\` supplied to \`${s}\`. Only numbers greater than 0 are valid max values. Defaulting to \`100\`.`},"getInvalidMaxError"),Q(function(e,s){return`Invalid prop \`value\` of value \`${e}\` supplied to \`${s}\`. The \`value\` prop must be:\n - a positive number\n - less than the value passed to \`max\` (or 100 if no \`max\` prop is set)\n - \`null\` or \`undefined\` if the progress is indeterminate.\n\nDefaulting to \`null\`.`},"getInvalidValueError");var me=ae,he=ie;const xe=e.forwardRef(({className:e,value:t,...a},i)=>s.jsx(me,{ref:i,className:r("relative h-4 w-full overflow-hidden rounded-full bg-secondary",e),...a,children:s.jsx(he,{className:"h-full w-full flex-1 bg-primary transition-all",style:{transform:`translateX(-${100-(t||0)}%)`}})}));xe.displayName=me.displayName;const ue=()=>{const[r,a]=e.useState(!1),[i,l]=e.useState(null),[n,d]=e.useState([]),[c,o]=e.useState([]),[m,h]=e.useState(!1),x=e.useRef(null),u=I(),p=(e,s)=>{if(!e.from_path||!e.from_path.trim())return{row:s,error:"from_path is required"};if(!e.to_path||!e.to_path.trim())return{row:s,error:"to_path is required"};if(!e.from_path.startsWith("/"))return{row:s,error:"from_path must start with /"};if(!e.to_path.startsWith("/"))return{row:s,error:"to_path must start with /"};const r=parseInt(e.redirect_type);return 301!==r&&302!==r?{row:s,error:"redirect_type must be 301 or 302"}:null};return s.jsxs(_,{open:r,onOpenChange:e=>{a(e),e||(l(null),d([]),o([]),x.current&&(x.current.value=""))},children:[s.jsx(C,{asChild:!0,children:s.jsxs(t,{variant:"outline",children:[s.jsx(q,{className:"h-4 w-4 mr-2"}),"Bulk Import CSV"]})}),s.jsxs(L,{className:"max-w-2xl max-h-[80vh] overflow-y-auto",children:[s.jsxs(k,{children:[s.jsx(R,{children:"Bulk Import Redirects"}),s.jsx(S,{children:"Upload a CSV file with redirect rules. Download the template to see the required format."})]}),s.jsxs("div",{className:"space-y-4",children:[s.jsxs("div",{className:"flex items-center justify-between p-4 bg-muted rounded-lg",children:[s.jsxs("div",{className:"flex-1",children:[s.jsx("p",{className:"text-sm font-medium",children:"Download CSV Template"}),s.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Required columns: from_path, to_path, redirect_type (301 or 302), is_active (optional)"})]}),s.jsxs(t,{variant:"outline",size:"sm",onClick:()=>{const e=new Blob(["from_path,to_path,redirect_type,is_active\n/old-page,/new-page,301,true\n/another-old,/another-new,302,false"],{type:"text/csv"}),s=URL.createObjectURL(e),r=document.createElement("a");r.href=s,r.download="redirect-import-template.csv",r.click(),URL.revokeObjectURL(s)},children:[s.jsx(z,{className:"h-4 w-4 mr-2"}),"Template"]})]}),s.jsxs("div",{className:"space-y-2",children:[s.jsx("input",{ref:x,type:"file",accept:".csv",onChange:async e=>{var s;const r=null==(s=e.target.files)?void 0:s[0];if(r)if(r.name.endsWith(".csv")){l(r),h(!0);try{const e=await r.text(),{data:s,errors:t}=(e=>{var s;const r=e.split("\n").filter(e=>e.trim());if(r.length<2)return{data:[],errors:[{row:0,error:"CSV file must have a header and at least one data row"}]};const t=r[0].split(",").map(e=>e.trim().toLowerCase()),a=["from_path","to_path","redirect_type"].filter(e=>!t.includes(e));if(a.length>0)return{data:[],errors:[{row:0,error:`Missing required headers: ${a.join(", ")}`}]};const i=[],l=[];for(let n=1;n<r.length;n++){const e=r[n].split(",").map(e=>e.trim()),a={};t.forEach((s,r)=>{a[s]=e[r]||""});const d=p(a,n+1);d?l.push(d):i.push({from_path:a.from_path.trim(),to_path:a.to_path.trim(),redirect_type:parseInt(a.redirect_type),is_active:"true"===(null==(s=a.is_active)?void 0:s.toLowerCase())||"1"===a.is_active||!a.is_active,rowNumber:n+1})}return{data:i,errors:l}})(e);d(s),o(t)}catch(t){o([{row:0,error:"Failed to parse CSV file"}])}finally{h(!1)}}else o([{row:0,error:"Please upload a CSV file"}])},className:"block w-full text-sm file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-primary file:text-primary-foreground hover:file:bg-primary/90"}),i&&s.jsxs("p",{className:"text-sm text-muted-foreground",children:["Selected: ",i.name]})]}),m&&s.jsxs("div",{className:"space-y-2",children:[s.jsx(xe,{value:void 0,className:"w-full"}),s.jsx("p",{className:"text-sm text-muted-foreground text-center",children:"Processing file..."})]}),!m&&(n.length>0||c.length>0)&&s.jsxs("div",{className:"space-y-3",children:[n.length>0&&s.jsxs(F,{children:[s.jsx(B,{className:"h-4 w-4"}),s.jsxs($,{children:["Successfully parsed ",n.length," redirect",1!==n.length?"s":""," from CSV"]})]}),c.length>0&&s.jsxs(F,{variant:"destructive",children:[s.jsx(H,{className:"h-4 w-4"}),s.jsx($,{children:s.jsxs("div",{className:"space-y-1",children:[s.jsxs("p",{className:"font-semibold",children:["Found ",c.length," error",1!==c.length?"s":"",":"]}),s.jsxs("ul",{className:"list-disc list-inside text-sm max-h-32 overflow-y-auto",children:[c.slice(0,10).map((e,r)=>s.jsxs("li",{children:["Row ",e.row,": ",e.error]},r)),c.length>10&&s.jsxs("li",{className:"text-muted-foreground",children:["...and ",c.length-10," more"]})]})]})})]}),n.length>0&&s.jsxs("div",{className:"border rounded-lg overflow-hidden",children:[s.jsx("div",{className:"bg-muted px-4 py-2",children:s.jsx("p",{className:"text-sm font-medium",children:"Preview (showing first 5 rows)"})}),s.jsx("div",{className:"overflow-x-auto",children:s.jsxs("table",{className:"w-full text-sm",children:[s.jsx("thead",{className:"bg-muted/50",children:s.jsxs("tr",{children:[s.jsx("th",{className:"px-4 py-2 text-left font-medium",children:"From"}),s.jsx("th",{className:"px-4 py-2 text-left font-medium",children:"To"}),s.jsx("th",{className:"px-4 py-2 text-left font-medium",children:"Type"}),s.jsx("th",{className:"px-4 py-2 text-left font-medium",children:"Active"})]})}),s.jsx("tbody",{children:n.slice(0,5).map((e,r)=>s.jsxs("tr",{className:"border-t",children:[s.jsx("td",{className:"px-4 py-2 font-mono text-xs",children:e.from_path}),s.jsx("td",{className:"px-4 py-2 font-mono text-xs",children:e.to_path}),s.jsx("td",{className:"px-4 py-2",children:e.redirect_type}),s.jsx("td",{className:"px-4 py-2",children:e.is_active?s.jsx(B,{className:"h-4 w-4 text-green-500"}):s.jsx(W,{className:"h-4 w-4 text-muted-foreground"})})]},r))})]})})]})]})]}),s.jsxs(P,{children:[s.jsx(t,{variant:"outline",onClick:()=>a(!1),children:"Cancel"}),s.jsx(t,{onClick:async()=>
1{if(0!==n.length){h(!0);try{const e=n.map(({rowNumber:e,...s})=>s);await u.mutateAsync(e),l(null),d([]),o([]),a(!1),x.current&&(x.current.value="")}catch(e){}finally{h(!1)}}},disabled:0===n.length||m||u.isPending,children:u.isPending?"Importing...":`Import ${n.length} Redirect${1!==n.length?"s":""}`})]})]})]})},pe=()=>{const[r,I]=e.useState(30),[F,$]=e.useState(!1),[E,O]=e.useState(null),[q,z]=e.useState(""),[B,W]=e.useState(""),[K,Q]=e.useState("301"),{data:Y,isLoading:ee}=V(r),{data:se,isLoading:re}=U(),te=T(),ae=A(),ie=M(),le=e=>{e&&z(e),O(null),$(!0)};return s.jsxs(D,{children:[s.jsxs(a,{children:[s.jsx("meta",{name:"robots",content:"noindex,nofollow"}),s.jsx("title",{children:"404 Logs & Redirects - Admin - Delphi Global Research Center"})]}),s.jsx("div",{className:"p-8",children:s.jsxs("div",{className:"max-w-7xl mx-auto space-y-8",children:[s.jsx("div",{className:"flex justify-between items-center",children:s.jsxs("div",{children:[s.jsx("h1",{className:"text-3xl font-bold",children:"404 Error Logs & Redirects"}),s.jsx("p",{className:"text-muted-foreground",children:"Monitor broken links and manage URL redirects"})]})}),s.jsxs(i,{children:[s.jsx(l,{children:s.jsxs("div",{className:"flex justify-between items-center",children:[s.jsxs("div",{children:[s.jsxs(n,{className:"flex items-center gap-2",children:[s.jsx(H,{className:"h-5 w-5"}),"404 Error Logs"]}),s.jsx(d,{children:"Track which pages users are trying to access but don't exist. Legacy URLs are highlighted."})]}),s.jsxs(x,{value:r.toString(),onValueChange:e=>I(parseInt(e)),children:[s.jsx(u,{className:"w-[180px]",children:s.jsx(p,{})}),s.jsxs(j,{children:[s.jsx(f,{value:"7",children:"Last 7 days"}),s.jsx(f,{value:"30",children:"Last 30 days"}),s.jsx(f,{value:"90",children:"Last 90 days"})]})]})]})}),s.jsx(c,{children:ee?s.jsx("p",{children:"Loading..."}):Y&&Y.length>0?s.jsxs(s.Fragment,{children:[(()=>{const e=["/publications/","/articles/","/analysis/","/delphigrc.org"],r=Y.filter(s=>e.some(e=>s.path.includes(e))),t=r.reduce((e,s)=>e+(s.count||1),0);return r.length>0?s.jsx("div",{className:"mb-6 p-4 bg-amber-50 dark:bg-amber-950/20 border border-amber-200 dark:border-amber-800 rounded-lg",children:s.jsxs("div",{className:"flex items-start gap-3",children:[s.jsx(H,{className:"h-5 w-5 text-amber-600 dark:text-amber-400 mt-0.5"}),s.jsxs("div",{className:"flex-1",children:[s.jsx("h3",{className:"font-semibold text-amber-900 dark:text-amber-100 mb-1",children:"Legacy URL Patterns Detected"}),s.jsxs("p",{className:"text-sm text-amber-800 dark:text-amber-200 mb-3",children:["Found ",r.length," unique legacy URL patterns with"," ",t," total hits. Consider creating redirects to improve SEO and user experience."]}),s.jsx("div",{className:"flex flex-wrap gap-2",children:e.map(e=>{const r=Y.filter(s=>s.path.includes(e)).length;return r>0?s.jsxs(o,{variant:"outline",className:"bg-amber-100 dark:bg-amber-900/30 text-amber-800 dark:text-amber-200 border-amber-300 dark:border-amber-700",children:[e,": ",r," URLs"]},e):null})})]})]})}):null})(),s.jsxs(v,{children:[s.jsx(g,{children:s.jsxs(b,{children:[s.jsx(N,{children:"Path"}),s.jsx(N,{children:"Count"}),s.jsx(N,{children:"Last Seen"}),s.jsx(N,{children:"Referrer"}),s.jsx(N,{children:"Actions"})]})}),s.jsx(y,{children:Y.map(e=>{const r=["/publications/","/articles/","/analysis/","delphigrc.org"].some(s=>e.path.includes(s));return s.jsxs(b,{className:r?"bg-amber-50/50 dark:bg-amber-950/10":"",children:[s.jsx(w,{className:"font-mono text-sm",children:s.jsxs("div",{className:"flex items-center gap-2",children:[r&&s.jsx(o,{variant:"outline",className:"bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 border-amber-300 dark:border-amber-700 text-xs",children:"Legacy"}),s.jsx("span",{className:r?"font-semibold":"",children:e.path})]})}),s.jsx(w,{children:s.jsx(o,{variant:e.count&&e.count>10?"destructive":"secondary",children:e.count||1})}),s.jsx(w,{className:"text-sm text-muted-foreground",children:Z(new Date(e.created_at),"MMM d, yyyy HH:mm")}),s.jsx(w,{className:"text-sm text-muted-foreground truncate max-w-xs",children:e.referrer||"Direct"}),s.jsx(w,{children:s.jsxs(t,{size:"sm",variant:"outline",onClick:()=>le(e.path),children:[s.jsx(G,{className:"h-4 w-4 mr-1"}),"Create Redirect"]})})]},e.id)})})]})]}):s.jsx("p",{className:"text-center text-muted-foreground py-8",children:"No 404 errors recorded"})})]}),s.jsxs(i,{children:[s.jsx(l,{children:s.jsxs("div",{className:"flex justify-between items-center",children:[s.jsxs("div",{children:[s.jsx(n,{children:"URL Redirects"}),s.jsx(d,{children:"Manage permanent and temporary redirects"})]}),s.jsxs("div",{className:"flex gap-2",children:[s.jsx(ue,{}),s.jsxs(_,{open:F,onOpenChange:$,children:[s.jsx(C,{asChild:!0,children:s.jsxs(t,{onClick:()=>le(),children:[s.jsx(G,{className:"h-4 w-4 mr-2"}),"Add Redirect"]})}),s.jsxs(L,{children:[s.jsxs(k,{children:[s.jsx(R,{children:E?"Edit Redirect":"Create New Redirect"}),s.jsx(S,{children:"Set up a redirect from an old URL to a new one"})]}),s.jsxs("div",{className:"space-y-4",children:[s.jsxs("div",{className:"space-y-2",children:[s.jsx(h,{htmlFor:"from_path",children:"From Path"}),s.jsx(m,{id:"from_path",placeholder:"/old-page",value:q,onChange:e=>z(e.target.value)})]}),s.jsxs("div",{className:"space-y-2",children:[s.jsx(h,{htmlFor:"to_path",children:"To Path"}),s.jsx(m,{id:"to_path",placeholder:"/new-page",value:B,onChange:e=>W(e.target.value)})]}),s.jsxs("div",{className:"space-y-2",children:[s.jsx(h,{htmlFor:"redirect_type",children:"Redirect Type"}),s.jsxs(x,{value:K,onValueChange:e=>Q(e),children:[s.jsx(u,{children:s.jsx(p,{})}),s.jsxs(j,{children:[s.jsx(f,{value:"301",children:"301 - Permanent"}),s.jsx(f,{value:"302",children:"302 - Temporary"})]})]})]})]}),s.jsxs(P,{children:[s.jsx(t,{variant:"outline",onClick:()=>$(!1),children:"Cancel"}),s.jsx(t,{onClick:()=>{q&&B&&(E?ae.mutate({id:E.id,from_path:q,to_path:B,redirect_type:parseInt(K)}):te.mutate({from_path:q,to_path:B,redirect_type:parseInt(K),is_active:!0}),$(!1),z(""),W(""),Q("301"),O(null))},children:E?"Update":"Create"})]})]})]})]})]})}),s.jsx(c,{children:re?s.jsx("p",{children:"Loading..."}):se&&se.length>0?s.jsxs(v,{children:[s.jsx(g,{children:s.jsxs(b,{children:[s.jsx(N,{children:"From"}),s.jsx(N,{children:"To"}),s.jsx(N,{children:"Type"}),s.jsx(N,{children:"Status"}),s.jsx(N,{children:"Actions"})]})}),s.jsx(y,{children:se.map(e=>s.jsxs(b,{children:[s.jsx(w,{className:"font-mono text-sm",children:e.from_path}),s.jsx(w,{className:"font-mono text-sm",children:e.to_path}),s.jsx(w,{children:s.jsx(o,{variant:"outline",children:e.redirect_type})}),s.jsx(w,{children:s.jsx(t,{size:"sm",variant:"ghost",onClick:()=>(e=>{ae.mutate({id:e.id,is_active:!e.is_active})})(e),children:s.jsx(o,{variant:e.is_active?"default":"secondary",children:e.is_active?"Active":"Inactive"})})}),s.jsx(w,{children:s.jsxs("div",{className:"flex gap-2",children:[s.jsx(t,{size:"sm",variant:"ghost",onClick:()=>(e=>{O(e),z(e.from_path),W(e.to_path),Q(301===e.redirect_type?"301":"302"),$(!0)})(e),children:s.jsx(X,{className:"h-4 w-4"})}),s.jsx(t,{size:"sm",variant:"ghost",onClick:()=>{return s=e.id,void(confirm("Are you sure you want to delete this redirect?")&&ie.mutate(s));var s},children:s.jsx(J,{className:"h-4 w-4"})})]})})]},e.id))})]}):s.jsx("p",{className:"text-center text-muted-foreground py-8",children:"No redirects configured"})})]})]})})]})};export{pe as default};
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.