1import{j as e,Y as L,r as h,X as Y,H as G,Q as V,V as H}from"./index-DJQ_8YOM.js";import{a as X,b as O,c as J,d as Q,u as Z,e as ee}from"./useFeeds-dRVpKQCM.js";import{u as te}from"./useIssues-BWb1Gpf1.js";import{u as ae}from"./useBackgroundTasks-DDAxvps6.js";import{P as le}from"./PageHeader-B4NRtviE.js";import{B as b}from"./Button-D1KgADC4.js";import{S as v}from"./Select-C8iEk0yj.js";import{F as se,E as re}from"./ErrorState-BKP04gIG.js";import{E as ne}from"./EmptyState-DxrPhr8a.js";import{C as ie}from"./ConfirmDialog-BJ_ebTzJ.js";import{A as C}from"./ActionIconButton-CvVXKjOt.js";import{e as I}from"./constants-CwQIYZad.js";import{T as P}from"./TimeWithRelative-Dw6wGMtq.js";import{F as oe}from"./ArrowTopRightOnSquareIcon-nXP55jbG.js";import{F as ce}from"./ClockIcon-CCJe-Tuw.js";import{a as U,u as S}from"./Toast-DqCd-Sd1.js";import{F as D,l as de,f as ue,a as me,y as xe,g as F}from"./PencilSquareIcon-BOfbd5GC.js";import{F as M}from"./TrashIcon-CFWlayzd.js";import{F as q}from"./index-GZ0RjJjP.js";import{I as m}from"./Input-BHgAne8X.js";import{h as he,z as pe,Q as ge}from"./dialog-DKCpPhY0.js";import{u as fe,P as be}from"./PanelFooter-FQ5muYiq.js";import{E as ve,P as je}from"./EditPanel-Ho0rrtGa.js";import"./useMutation-CsXOKkWa.js";import"./useJobs-BUJGQAdd.js";import"./use-resolve-button-type-DwXZFVvu.js";import"./open-closed-FLUweVDm.js";import"./floating-ui.dom-DQRglYRD.js";function ye(s){return!s||Object.keys(s).length===0?"--":Object.entries(s).sort((d,n)=>n[1]-d[1])[0][0]}function we({feeds:s,issues:d,qualityMetrics:n,onEdit:l,onCrawl:a,onDelete:i}){const c=new Map(d.map(t=>[t.id,t.name]));return e.jsx("div",{className:"overflow-x-auto bg-white rounded-lg border border-neutral-200 shadow-sm",children:e.jsxs("table",{className:"min-w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-neutral-200 bg-neutral-50",children:[e.jsx("th",{scope:"col",className:"text-left px-3 py-2 font-medium text-neutral-500",children:"Title"}),e.jsx("th",{scope:"col",className:"hidden md:table-cell text-left px-3 py-2 font-medium text-neutral-500",children:"Issue"}),e.jsx("th",{scope:"col",className:"hidden lg:table-cell text-left px-3 py-2 font-medium text-neutral-500",children:"Lang"}),e.jsx("th",{scope:"col",className:"hidden lg:table-cell text-left px-3 py-2 font-medium text-neutral-500",children:"Interval"}),e.jsx("th",{scope:"col",className:"hidden xl:table-cell text-center px-3 py-2 font-medium text-neutral-500",children:"Pub %"}),e.jsx("th",{scope:"col",className:"hidden xl:table-cell text-center px-3 py-2 font-medium text-neutral-500",children:"Avg Rel."}),e.jsx("th",{scope:"col",className:"hidden xl:table-cell text-center px-3 py-2 font-medium text-neutral-500",children:"Method"}),e.jsx("th",{scope:"col",className:"hidden md:table-cell text-left px-3 py-2 font-medium text-neutral-500",children:"Last Crawled"}),e.jsx("th",{scope:"col",className:"px-3 py-2 text-right font-medium text-neutral-500",children:"Actions"})]})}),e.jsx("tbody",{children:s.map(t=>e.jsxs("tr",{className:"border-b border-neutral-100 last:border-0 hover:bg-neutral-50",children:[e.jsxs("td",{className:"px-3 py-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(L,{feedId:t.id,size:16}),e.jsx("button",{onClick:()=>l(t.id),className:"text-left font-medium text-neutral-900 hover:text-brand-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 rounded",children:t.title}),e.jsx("a",{href:t.url||t.rssUrl,target:"_blank",rel:"noopener noreferrer",className:"shrink-0 text-neutral-400 hover:text-brand-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 rounded",title:t.url||t.rssUrl,children:e.jsx(oe,{className:"h-4 w-4"})}),t.lastCrawlError&&e.jsx("span",{title:`${t.lastCrawlError}${t.lastCrawlErrorAt?` (${I(t.lastCrawlErrorAt)})`:""}`,"aria-label":`Crawl error: ${t.lastCrawlError}`,className:"shrink-0 inline-flex items-center rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-700",children:t.lastCrawlError.length>30?t.lastCrawlError.slice(0,30)+"â¦":t.lastCrawlError}),t.isStale&&e.jsxs("span",{title:`No new articles in last ${t.consecutiveEmptyCrawls} crawls${t.lastSuccessfulCrawlAt?` (last success: ${I(t.lastSuccessfulCrawlAt)})`:""}`,"aria-label":`No new articles in last ${t.consecutiveEmptyCrawls} crawls`,className:"shrink-0 inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-700",children:[e.jsx(ce,{className:"h-3.5 w-3.5"}),t.consecutiveEmptyCrawls," empty"]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 mt-1 md:hidden",children:[e.jsx("span",{className:"text-neutral-500 text-xs",children:c.get(t.issueId)||"â"}),e.jsx("span",{className:"text-neutral-500 text-xs",children:e.jsx(P,{dateStr:t.lastCrawledAt})})]})]}),e.jsx("td",{className:"hidden md:table-cell px-3 py-2 text-neutral-600",children:c.get(t.issueId)||"â"}),e.jsx("td",{className:"hidden lg:table-cell px-3 py-2 text-neutral-600",children:t.language}),e.jsxs("td",{className:"hidden lg:table-cell px-3 py-2 text-neutral-600",children:[t.crawlIntervalHours,"h"]}),(()=>{const x=n?.[t.id];return e.jsxs(e.Fragment,{children:[e.jsx("td",{className:"hidden xl:table-cell px-3 py-2 text-center text-neutral-600 text-xs",children:x?`${Math.round(x.publishRate*100)}%`:"--"}),e.jsx("td",{className:"hidden xl:table-cell px-3 py-2 text-center text-neutral-600 text-xs",children:x?.avgRelevance?.toFixed(1)??"--"}),e.jsx("td",{className:"hidden xl:table-cell px-3 py-2 text-center text-neutral-600 text-xs",children:ye(
1x?.extractionMethods)})]})})(),e.jsx("td",{className:"hidden md:table-cell px-3 py-2 text-neutral-500 whitespace-nowrap",children:e.jsx(P,{dateStr:t.lastCrawledAt})}),e.jsxs("td",{className:"px-3 py-2",children:[e.jsxs("div",{className:"hidden md:flex items-center justify-end gap-0.5",children:[e.jsx(C,{icon:U,label:"Crawl",onClick:()=>a(t.id)}),e.jsx(C,{icon:D,label:"Edit",onClick:()=>l(t.id)}),e.jsx(C,{icon:M,label:"Delete",variant:"danger",onClick:()=>i(t.id)})]}),e.jsx("div",{className:"md:hidden flex justify-end",children:e.jsxs(de,{as:"div",className:"relative",children:[e.jsx(ue,{className:"rounded p-1 hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500",children:e.jsx(me,{className:"h-5 w-5 text-neutral-400"})}),e.jsxs(xe,{className:"absolute right-0 z-10 mt-1 w-40 rounded-md bg-white shadow-lg border border-neutral-200 py-1 focus:outline-none",children:[e.jsx(F,{children:e.jsxs("button",{onClick:()=>a(t.id),className:"flex w-full items-center gap-2 px-3 py-1.5 text-sm text-neutral-700 data-[focus]:bg-neutral-100",children:[e.jsx(U,{className:"h-4 w-4 shrink-0"}),"Crawl"]})}),e.jsx(F,{children:e.jsxs("button",{onClick:()=>l(t.id),className:"flex w-full items-center gap-2 px-3 py-1.5 text-sm text-neutral-700 data-[focus]:bg-neutral-100",children:[e.jsx(D,{className:"h-4 w-4 shrink-0"}),"Edit"]})}),e.jsx(F,{children:e.jsxs("button",{onClick:()=>i(t.id),className:"flex w-full items-center gap-2 px-3 py-1.5 text-sm text-red-600 data-[focus]:bg-red-50",children:[e.jsx(M,{className:"h-4 w-4 shrink-0"}),"Delete"]})})]})]})})]})]},t.id))})]})})}function B(s){const d=s.filter(a=>!a.parentId).sort((a,i)=>a.name.localeCompare(i.name)),n=new Map;for(const a of s)if(a.parentId){const i=n.get(a.parentId)||[];i.push(a),n.set(a.parentId,i)}const l=[];for(const a of d){l.push({value:a.id,label:a.name});const i=n.get(a.id)||[];i.sort((c,t)=>c.name.localeCompare(t.name));for(const c of i)l.push({value:c.id,label:`Â Â â ${c.name}`})}return l}function Ne({open:s,onClose:d,issues:n}){const[l,a]=h.useState({title:"",rssUrl:"",url:"",displayTitle:"",issueId:"",language:"en",region:"",crawlIntervalHours:"6",htmlSelector:"",active:!0}),i=X(),{toast:c}=S();h.useEffect(()=>{s&&a({title:"",rssUrl:"",url:"",displayTitle:"",issueId:"",language:"en",region:"",crawlIntervalHours:"6",htmlSelector:"",active:!0})},[s]);const t=(o,p)=>a(r=>({...r,[o]:p})),x=async o=>{o.preventDefault();try{await i.mutateAsync({title:l.title,rssUrl:l.rssUrl,url:l.url||null,displayTitle:l.displayTitle||null,issueId:l.issueId,language:l.language,region:l.region||null,crawlIntervalHours:Number(l.crawlIntervalHours),htmlSelector:l.htmlSelector||null,active:l.active}),c("success","Feed created"),d()}catch(p){c("error",p instanceof Error?p.message:"Failed to create feed")}};return e.jsxs(he,{open:s,onClose:d,className:"relative z-50",children:[e.jsx("div",{className:"fixed inset-0 bg-black/30","aria-hidden":"true"}),e.jsx("div",{className:"fixed inset-0 flex items-center justify-center p-4",children:e.jsxs(pe,{className:"mx-auto max-w-md w-full rounded-lg bg-white p-6 shadow-xl",children:[e.jsx(ge,{className:"text-base font-semibold text-neutral-900 mb-4",children:"Add Feed"}),e.jsxs("form",{onSubmit:x,className:"space-y-4",children:[e.jsx(m,{id:"feed-title",label:"Title",value:l.title,onChange:o=>t("title",o.target.value),required:!0}),e.jsx(m,{id:"feed-display-title",label:"Display Title (optional)",value:l.displayTitle,onChange:o=>t("displayTitle",o.target.value),placeholder:"Public-facing name"}),e.jsx(m,{id:"feed-rss-url",label:"RSS URL",type:"url",value:l.rssUrl,onChange:o=>t("rssUrl",o.target.value),required:!0}),e.jsx(m,{id:"feed-url",label:"Homepage URL (optional)",type:"url",value:l.url,onChange:o=>t("url",o.target.value),placeholder:"e.g. https://reuters.com"}),e.jsx(v,{id:"feed-issue",label:"Issue",placeholder:"Select issue",value:l.issueId,onChange:o=>t("issueId",o.target.value),options:B(n)}),e.jsx(v,{id:"feed-region",label:"Region",placeholder:"Select region (optional)",value:l.region,onChange:o=>t("region",o.target.value),options:q.map(o=>({value:o.value,label:o.label}))}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(m,{id:"feed-lang",label:"Language",value:l.language,onChange:o=>t("language",o.target.value)}),e.jsx(m,{id:"feed-interval",label:"Interval (hours)",type:"number",min:"1",value:l.crawlIntervalHours,onChange:o=>t("crawlIntervalHours",o.target.value)})]}),e.jsx(m,{id:"feed-selector",label:"HTML Selector (optional)",value:l.htmlSelector,onChange:o=>t("htmlSelector",o.target.value),placeholder:"e.g. article .content"}),e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:l.active,onChange:o=>t("active",o.target.checked),className:"rounded border-neutral-300 text-brand-600 focus:ring-brand-500"}),"Active"]}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx(b,{type:"button",variant:"secondary",onClick:d,children:"Cancel"}),e.jsx(b,{type:"submit",loading:i.isPending,children:"Create"})]})]})]})})]})}function Ce(s){return{title:s.title,rssUrl:s.rssUrl,url:s.url||"",displayTitle:s.displayTitle||"",issueId:s.issueId,language:s.language,region:s.region||"",crawlIntervalHours:String(s.crawlIntervalHours),htmlSelector:s.htmlSelector||"",active:s.active}}function Fe({feedId:s}){const[d,n]=h.useState(!1),[l,a]=h.useState(0),{toast:i}=S();return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(L,{feedId:s,imgKey:l,size:24}),e.jsx("span",{className:"text-xs text-neutral-400",children:"Fetch in dev only"})]})}function Ie({methods:s}){const d=Object.entries(s).sort((l,a)=>a[1]-l[1]);if(d.length===0)return e.jsx("span",{className:"font-medium",children:"No data yet"});const n=d.reduce((l,[,a])=>l+a,0);return e.jsx("div",{className:"flex flex-wrap gap-1",children:d.map(([l,a])=>e.jsxs("span",{className:"inline-flex items-center rounded-full bg-neutral-200 px-2 py-0.5 text-xs font-medium text-neutral-700",children:[l," ",Math.round(a/n*100),"%"]},l))})}function Se({feedId:s}){const{data:d}=Q(),n=d?.[s];return n?e.jsxs("div",{className:"rounded-md bg-neutral-50 border border-neutral-200 p-3 text-sm",children:[e.jsx("p",{className:"font-medium text-neutral-700 mb-2",children:"Feed Quality"}),e.jsxs("div",{className:"grid grid-cols-2 gap-x-4 gap-y-1 text-xs text-neutral-600",children:[e.jsx("span",{children:"Publish Rate:"}),e.jsxs("span",{className:"font-medium",children:[Math.round(n.publishRate*100),"% (",n.publishedCount," of ",n.totalCrawled,")"]}),e.jsx("span",{children:"Avg Relevance:"}),e.jsx("span",{className:"font-medium",children:n.avgRelevance?.toFixed(1)??"--"}),e.jsx("span",{children:"Extraction:"}),e.jsx(Ie,{methods:n.extractionMethods})]})]}):null}function Ee({feedId:s,issues:d,onClose:n}){const{data:l}=O(s),a=J(),i=h.useMemo(()=>Ce(l),[l]),{form:c,set:t,isDirty:x,isPending:o,handleSubmit:p}=fe({entityId:s,initialState:i,mutation:a,toPayload:r=>({title:r.title,rssUrl:r.rssUrl,url:r.url||null,displayTitle:r.displayTitle||null,issueId:r.issueId,language:r.language,region:r.region||null,crawlIntervalHours:Number(r.crawlIntervalHours),htmlSelector:r.htmlSelector||null,active:r.active}),successMessage:"Feed updated",entityName:"feed",onSuccess:n});return e.jsxs("form",{onSubmit:p,className:"flex flex-col flex-1 overflow-hidden",children:[e.jsxs("div",{className:je,children:[l.lastCrawlError&&e.jsxs("div",{className:"flex items-start gap-2 rounded-md bg-amber-50 border border-amber-200 p-3 text-sm text-amber-800",children:[e.jsx(se,{className:"h-5 w-5 shrink-0 text-amber-500 mt-0.5"}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:"Last crawl error"}),e.jsx("p",{children:l.lastCrawlError}),l.lastCrawlErrorAt&&e.jsx("p",{className:"text-xs text-amber-600 mt-1",children:I(l.last
1CrawlErrorAt)})]})]}),e.jsx(m,{id:"feed-title",label:"Title",value:c.title,onChange:r=>t("title",r.target.value),required:!0}),e.jsx(m,{id:"feed-display-title",label:"Display Title (optional)",value:c.displayTitle,onChange:r=>t("displayTitle",r.target.value),placeholder:"Public-facing name"}),e.jsx(m,{id:"feed-rss-url",label:"RSS URL",type:"url",value:c.rssUrl,onChange:r=>t("rssUrl",r.target.value),required:!0}),e.jsx(m,{id:"feed-url",label:"Homepage URL (optional)",type:"url",value:c.url,onChange:r=>t("url",r.target.value),placeholder:"e.g. https://reuters.com"}),e.jsx(v,{id:"feed-issue",label:"Issue",placeholder:"Select issue",value:c.issueId,onChange:r=>t("issueId",r.target.value),options:B(d)}),e.jsx(v,{id:"feed-region",label:"Region",placeholder:"Select region (optional)",value:c.region,onChange:r=>t("region",r.target.value),options:q.map(r=>({value:r.value,label:r.label}))}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(m,{id:"feed-lang",label:"Language",value:c.language,onChange:r=>t("language",r.target.value)}),e.jsx(m,{id:"feed-interval",label:"Interval (hours)",type:"number",min:"1",value:c.crawlIntervalHours,onChange:r=>t("crawlIntervalHours",r.target.value)})]}),e.jsx(m,{id:"feed-selector",label:"HTML Selector (optional)",value:c.htmlSelector,onChange:r=>t("htmlSelector",r.target.value),placeholder:"e.g. article .content"}),e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:c.active,onChange:r=>t("active",r.target.checked),className:"rounded border-neutral-300 text-brand-600 focus:ring-brand-500"}),"Active"]}),e.jsx(Fe,{feedId:s}),e.jsx(Se,{feedId:s})]}),e.jsx(be,{isPending:o,isDirty:x,onCancel:n})]})}function ke({feedId:s,issues:d,onClose:n}){const{data:l,isLoading:a,error:i}=O(s||"");return e.jsx(ve,{open:!!s,onClose:n,title:l?.title||"Feed",loading:a,error:!!i,children:l&&e.jsx(Ee,{feedId:s,issues:d,onClose:n})})}function Re(s){const d=s.filter(a=>!a.parentId).sort((a,i)=>a.name.localeCompare(i.name)),n=new Map;for(const a of s)if(a.parentId){const i=n.get(a.parentId)||[];i.push(a),n.set(a.parentId,i)}const l=[];for(const a of d){l.push({value:a.id,label:a.name});const i=n.get(a.id)||[];i.sort((c,t)=>c.name.localeCompare(t.name));for(const c of i)l.push({value:c.id,label:`â ${c.name}`})}return l}function rt(){const[s,d]=h.useState(!1),[n,l]=h.useState(""),a=Z({...s?{}:{active:!0},...n?{issueId:n}:{}}),i=te(),c=Q(),t=ee(),{toast:x}=S(),{launchTask:o}=ae(),p=Y(),[r,E]=h.useState(!1),[z,k]=h.useState(null),[j,y]=h.useState(null),R=()=>{p.invalidateQueries({queryKey:["feeds"]})},K=u=>{const w=`Crawling ${a.data?.find(g=>g.id===u)?.title||"feed"}`;o({id:`crawl-feed-${u}-${Date.now()}`,label:w,executor:async()=>{const g=await H.feeds.crawl(u);return{succeeded:g.newStories,failed:g.errors}},onComplete:R})},_=()=>{const u=a.data;if(!u||u.length===0)return;const f=u.filter(g=>g.active),w=`Crawling ${f.length} feeds`;o({id:`crawl-all-${Date.now()}`,label:w,executor:async g=>{let A=0,N=0;for(const T of f){try{const $=await H.feeds.crawl(T.id);A+=$.newStories,N+=$.errors}catch{N++}g(f.indexOf(T)+1,f.length)}return{succeeded:A,failed:N}},onComplete:R})},W=async()=>{if(j){try{const u=await t.mutateAsync(j);x("success",u.message)}catch(u){x("error",u instanceof Error?u.message:"Failed to delete feed")}y(null)}};return e.jsxs(e.Fragment,{children:[e.jsx(G,{children:e.jsx("title",{children:"Feeds â Admin â Actually Relevant"})}),e.jsx(le,{title:"Feeds",description:a.data?`${a.data.length} feeds`:void 0,actions:e.jsxs(e.Fragment,{children:[e.jsx(b,{variant:s?"secondary":"ghost",onClick:()=>d(!s),children:s?"Hide inactive":"Show inactive"}),!1,e.jsx(b,{variant:"secondary",onClick:_,children:"Crawl All"}),e.jsx(b,{onClick:()=>E(!0),children:"Add Feed"})]})}),i.data&&i.data.length>0&&e.jsx("div",{className:"mb-4",children:e.jsx(v,{id:"filter-issue",label:"Issue",placeholder:"All issues",value:n,onChange:u=>l(u.target.value),options:Re(i.data)})}),a.isLoading&&e.jsx("div",{className:"flex justify-center py-12",children:e.jsx(V,{})}),a.error&&e.jsx(re,{message:"Failed to load feeds",onRetry:()=>a.refetch()}),a.data&&a.data.length===0&&e.jsx(ne,{title:"No feeds yet",description:"Add your first RSS feed."}),a.data&&a.data.length>0&&e.jsx(we,{feeds:a.data,issues:i.data||[],qualityMetrics:c.data,onEdit:k,onCrawl:K,onDelete:y}),e.jsx(Ne,{open:r,onClose:()=>E(!1),issues:i.data||[]}),e.jsx(ke,{feedId:z,issues:i.data||[],onClose:()=>k(null)}),e.jsx(ie,{open:!!j,onClose:()=>y(null),onConfirm:W,title:"Delete feed?",description:"If the feed has stories it will be deactivated. Otherwise it will be permanently removed.",variant:"danger",confirmLabel:"Delete",loading:t.isPending})]})}
1export{rt 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.