PageSourceSearch

https://gr2me.com/build/assets/Tags-BGFsKrE9.js

js gr2me.com collected 2026-10-03 01:13:27 UTC 11,496 bytes, 1 lines download raw bytes

1import{j as d,o as G,c as J,w as K,m as a,a as t,u as N,h as M,f as o,i as v,n as F,b as r,v as p,e as D,x as Q,t as c,F as V,r as _,A as W,l as A}from"./app-Ci4PRDRI.js";import{_ as X}from"./AdminLayout-B3inJRNm.js";import{u as Y}from"./useMediaLibrary-BWkuYZy_.js";import{a as E}from"./url-C3816kfx.js";/* empty css              */import"./MediaLibraryModal-DH_hg5Gm.js";import"./_plugin-vue_export-helper-DlAUqK2U.js";/* empty css                                                                       */import"./EkMenuGroup.vue_vue_type_style_index_0_lang-r46qgxkl.js";/* empty css                                                                */import"./EkToastContainer-Dd2c_SyD.js";const ee={class:"flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-6"},te={class:"flex items-center gap-3"},se=["href"],ne={key:0,class:"admin-card p-6 mb-6"},le={class:"grid grid-cols-1 md:grid-cols-2 gap-4"},ae={class:"flex items-center gap-2"},oe={class:"flex justify-end gap-3"},ie={class:"admin-card p-4 mb-6"},de={class:"flex flex-col sm:flex-row gap-3 sm:items-center"},re={class:"flex items-center gap-2 text-sm text-(--admin-text-secondary) whitespace-nowrap"},ue={class:"text-xs text-(--admin-text-muted) mt-2"},me={class:"admin-card overflow-hidden"},pe={class:"admin-table"},ce={class:"flex items-center gap-3"},ve={class:"font-medium text-(--admin-text)"},ge={class:"text-(--admin-text-muted) text-sm font-mono"},fe=["href"],xe={key:1,class:"text-(--admin-text-muted)"},be={class:"text-right"},ye={key:0,class:"flex items-center justify-end gap-2"},ke=["value"],we=["onClick","disabled"],he={key:1,class:"flex items-center justify-end gap-2"},Ce=["onClick"],Me=["onClick"],$e=["onClick","disabled"],Ue={key:1,colspan:"4"},Te=["onSubmit"],Ve={class:"grid grid-cols-1 md:grid-cols-3 gap-4 mb-4"},Se={class:"flex items-center gap-2"},je={key:0,class:"admin-empty-state"},He={__name:"Tags",props:{tags:Array,shared:Object},setup(S){const $=S,f=Y(),i=d($.tags||[]),x=d(null),y=d(null),g=d(!1),u=d({name:"",slug:"",description:"",color:"#3b82f6"}),m=d({name:"",slug:"",description:"",color:""}),q=async()=>{try{const n=await f.post("/tags",u.value);n.success&&(i.value.push(n.data),u.value={name:"",slug:"",description:"",color:"#3b82f6"},g.value=!1)}catch(n){alert("Failed to create tag: "+(n.message||"Unknown error"))}},z=n=>{x.value=n.id,m.value={name:n.name,slug:n.slug,description:n.description||"",color:n.color||"#3b82f6"}},L=()=>{x.value=null},P=async n=>{try{const e=await f.put(`/tags/${n.id}`,m.value);if(e.success){const s=i.value.findIndex(l=>l.id===n.id);s>-1&&(i.value[s]={...i.value[s],...e.data}),x.value=null}}catch(e){alert("Failed to update tag: "+(e.message||"Unknown error"))}},H=async n=>{if(confirm(`Delete tag "${n.name}"? Posts with this tag will not be deleted.`)){y.value=n.id;try{await f.delete(`/tags/${n.id}`),i.value=i.value.filter(e=>e.id!==n.id)}catch(e){alert("Failed to delete tag: "+(e.message||"Unknown error"))}finally{y.value=null}}},k=d(""),U=d("usage"),T=d(!1),w=d(null),b=d(""),h=d(!1);async function j(){try{const n=await f.get("/api/admin/tags");n?.data&&(i.value=n.data)}catch(n){console.error("Failed to refresh tags:",n)}}const I=A(()=>{let n=i.value.slice();if(k.value.trim()){const e=k.value.trim().toLowerCase();n=n.filter(s=>s.name.toLowerCase().includes(e)||(s.slug||"").includes(e))}return T.value&&(n=n.filter(e=>!e.posts_count)),U.value==="usage"?n.sort((e,s)=>(s.posts_count||0)-(e.posts_count||0)||e.name.localeCompare(s.name)):n.sort((e,s)=>e.name.localeCompare(s.name)),n}),O=A(()=>i.value.filter(n=>!n.posts_count).length);function R(n){w.value=n.id,b.value="",x.value=null}async function Z(n){const e=i.value.find(s=>String(s.id)===String(b.value));if(e&&confirm(`Merge "${n.name}" into "${e.name}"? Every post tagged "${n.name}" gets "${e.name}" instead, and "${n.name}" is deleted.`)){h.value=!0;try{await f.post(`/api/admin/tags/${n.id}/merge`,{target_id:e.id}),w.value=null,await j()}catch(s){alert("Merge failed: "+(s.message||"Unknown error"))}finally{h.value=!1}}}G(j);const C=()=>{const n=$.shared?.auth?.permissions||[];return n.includes("*")?!0:n.includes("posts.tags.create")||n.includes("posts.tags.edit")},B=()=>{const n=$.shared?.auth?.permissions||[];return n.includes("*")?!0:n.includes("posts.tags.delete")};return(n,e)=>(a(),J(X,{shared:S.shared,pageTitle:"Tags"},{default:K(()=>[t("div",ee,[e[18]||(e[18]=t("div",null,[t("h1",{class:"text-2xl font-bold text-(--admin-text)"},"Tags"),t("p",{class:"text-sm text-(--admin-text-secondary) mt-1"},"Manage post tags")],-1)),t("div",te,[t("a",{href:N(E)("/admin/posts"),class:"admin-btn admin-btn-secondary"},[...e[16]||(e[16]=[t("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M15 19l-7-7 7-7"})],-1),M(" Back to Posts ",-1)])],8,se),C()?(a(),o("button",{key:0,onClick:e[0]||(e[0]=s=>g.value=!g.value),class:"admin-btn admin-btn-primary"},[...e[17]||(e[17]=[t("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 4v16m8-8H4"})],-1),M(" New Tag ",-1)])])):v("",!0)])]),g.value?(a(),o("div",ne,[e[23]||(e[23]=t("h3",{class:"font-medium text-(--admin-text) mb-4"},"Create New Tag",-1)),t("form",{onSubmit:F(q,["prevent"]),class:"space-y-4"},[t("div",le,[t("div",null,[e[19]||(e[19]=t("label",{class:"admin-label"},"Name",-1)),r(t("input",{"onUpdate:modelValue":e[1]||(e[1]=s=>u.value.name=s),type:"text",class:"admin-input",placeholder:"Tag name",required:""},null,512),[[p,u.value.name]])]),t("div",null,[e[20]||(e[20]=t("label",{class:"admin-label"},"Color",-1)),t("div",ae,[r(t("input",{"onUpdate:modelValue":e[2]||(e[2]=s=>u.value.color=s),type:"color",class:"w-10 h-10 rounded cursor-pointer"},null,512),[[p,u.value.color]]),r(t("input",{"onUpdate:modelValue":e[3]||(e[3]=s=>u.value.color=s),type:"text",class:"admin-input flex-1",placeholder:"#3b82f6"},null,512),[[p,u.value.color]])])])]),t("div",null,[e[21]||(e[21]=t("label",{class:"admin-label"},"Description (optional)",-1)),r(t("textarea",{"onUpdate:modelValue":e[4]||(e[4]=s=>u.value.description=s),rows:"2",class:"admin-input",placeholder:"Tag description..."},null,512),[[p,u.value.description]])]),t("div",oe,[t("button",{type:"button",onClick:e[5]||(e[5]=s=>g.value=!1),class:"admin-btn admin-btn-secondary"}," Cancel "),e[22]||(e[22]=t("button",{type:"submit",class:"admin-btn admin-btn-primary"}," Create Tag ",-1))])],32)])):v("",!0),t("div",ie,[t("div",de,[r(t("input",{"onUpdate:modelValue":e[6]||(e[6]=s=>k.value=s),type:"text",class:"admin-input flex-1",placeholder:"Search tags..."},null,512),[[p,k.value]]),r(t("select",{"onUpdate:modelValue":e[7]||
1(e[7]=s=>U.value=s),class:"admin-input sm:w-44"},[...e[24]||(e[24]=[t("option",{value:"usage"},"Most used first",-1),t("option",{value:"name"},"Name A to Z",-1)])],512),[[D,U.value]]),t("label",re,[r(t("input",{"onUpdate:modelValue":e[8]||(e[8]=s=>T.value=s),type:"checkbox",class:"admin-checkbox"},null,512),[[Q,T.value]]),M(" Unused only ("+c(O.value)+") ",1)])]),t("p",ue,c(i.value.length)+" tags. Merge folds one tag into another and moves all its posts; the post count links to the filtered post list.",1)]),t("div",me,[t("table",pe,[e[31]||(e[31]=t("thead",null,[t("tr",null,[t("th",{class:"rounded-tl-2xl"},"Tag"),t("th",null,"Slug"),t("th",null,"Posts"),t("th",{class:"text-right rounded-tr-2xl"},"Actions")])],-1)),t("tbody",null,[(a(!0),o(V,null,_(I.value,s=>(a(),o("tr",{key:s.id},[x.value!==s.id?(a(),o(V,{key:0},[t("td",null,[t("div",ce,[t("span",{class:"w-4 h-4 rounded-full",style:W({backgroundColor:s.color||"#e5e7eb"})},null,4),t("span",ve,c(s.name),1)])]),t("td",null,[t("span",ge,c(s.slug),1)]),t("td",null,[s.posts_count?(a(),o("a",{key:0,href:N(E)(`/admin/posts?tag_id=${s.id}`),class:"text-(--admin-brand) hover:underline"},c(s.posts_count),9,fe)):(a(),o("span",xe,"0"))]),t("td",be,[w.value===s.id?(a(),o("div",ye,[e[26]||(e[26]=t("span",{class:"text-sm text-(--admin-text-secondary)"},"Merge into",-1)),r(t("select",{"onUpdate:modelValue":e[9]||(e[9]=l=>b.value=l),class:"admin-input admin-input-sm w-48"},[e[25]||(e[25]=t("option",{value:""},"Choose tag...",-1)),(a(!0),o(V,null,_(i.value.filter(l=>
1l.id!==s.id),l=>(a(),o("option",{key:l.id,value:l.id},c(l.name)+" ("+c(l.posts_count||0)+")",9,ke))),128))],512),[[D,b.value]]),t("button",{type:"button",onClick:l=>Z(s),disabled:!b.value||h.value,class:"admin-btn admin-btn-primary admin-btn-sm disabled:opacity-50"},c(h.value?"Merging...":"Merge"),9,we),t("button",{type:"button",onClick:e[10]||(e[10]=l=>w.value=null),class:"admin-btn admin-btn-ghost admin-btn-sm"},"Cancel")])):(a(),o("div",he,[C()?(a(),o("button",{key:0,onClick:l=>z(s),class:"admin-btn admin-btn-ghost px-3 py-1.5 text-sm text-(--admin-brand)"}," Edit ",8,Ce)):v("",!0),C()&&B()?(a(),o("button",{key:1,onClick:l=>R(s),class:"admin-btn admin-btn-ghost px-3 py-1.5 text-sm text-(--admin-text-secondary)",title:"Move all posts to another tag and delete this one"}," Merge ",8,Me)):v("",!0),B()?(a(),o("button",{key:2,onClick:l=>H(s),disabled:y.value===s.id,class:"admin-btn admin-btn-ghost px-3 py-1.5 text-sm text-(--admin-error) disabled:opacity-50"},c(y.value===s.id?"Deleting...":"Delete"),9,$e)):v("",!0)]))])],64)):(a(),o("td",Ue,[t("form",{onSubmit:F(l=>P(s),["prevent"]),class:"py-2"},[t("div",Ve,[t("div",null,[e[27]||(e[27]=t("label",{class:"admin-label text-xs"},"Name",-1)),r(t("input",{"onUpdate:modelValue":e[11]||(e[11]=l=>m.value.name=l),type:"text",class:"admin-input",required:""},null,512),[[p,m.value.name]])]),t("div",null,[e[28]||(e[28]=t("label",{class:"admin-label text-xs"},"Slug",-1)),r(t("input",{"onUpdate:modelValue":e[12]||(e[12]=l=>m.value.slug=l),type:"text",class:"admin-input"},null,512),[[p,m.value.slug]])]),t("div",null,[e[29]||(e[29]=t("label",{class:"admin-label text-xs"},"Color",-1)),t("div",Se,[r(t("input",{"onUpdate:modelValue":e[13]||(e[13]=l=>m.value.color=l),type:"color",class:"w-8 h-8 rounded cursor-pointer"},null,512),[[p,m.value.color]]),r(t("input",{"onUpdate:modelValue":e[14]||(e[14]=l=>m.value.color=l),type:"text",class:"admin-input flex-1"},null,512),[[p,m.value.color]])])])]),t("div",{class:"flex justify-end gap-2"},[t("button",{type:"button",onClick:L,class:"admin-btn admin-btn-ghost text-sm"}," Cancel "),e[30]||(e[30]=t("button",{type:"submit",class:"admin-btn admin-btn-primary text-sm"}," Save ",-1))])],40,Te)]))]))),128))])]),i.value.length===0?(a(),o("div",je,[e[33]||(e[33]=t("div",{class:"admin-empty-state-icon"},[t("svg",{fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"1.5",d:"M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"})])],-1)),e[34]||(e[34]=t("p",{class:"admin-empty-state-title"},"No tags yet",-1)),e[35]||(e[35]=t("p",{class:"admin-empty-state-text"},"Create tags to organize your posts.",-1)),C()?(a(),o("button",{key:0,onClick:e[15]||(e[15]=s=>g.value=!0),class:"admin-btn admin-btn-primary mt-6"},[...e[32]||(e[32]=[t("svg",{class:"w-4 h-4 mr-2",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[t("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 4v16m8-8H4"})],-1),M(" Create Tag ",-1)])])):v("",!0)])):v("",!0)])]),_:1},8,["shared"]))}};export{He 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.