fix: planner crash — make Task.tags optional, guard task.tags?.length

Backend TaskOut doesn't include tags field; TaskCard.vue read
task.tags.length causing TypeError on undefined. Making tags optional
in the Task type and using optional chaining is the correct fix since
the tags feature is unused (always empty).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vadym Samoilenko 2026-05-07 12:01:39 +01:00
parent afdb08f11a
commit 75c78635bc
31 changed files with 32 additions and 32 deletions

View file

@ -1 +1 @@
import{d as _,u as y,x as h,c as r,a as t,e as n,k as v,w as d,f as b,q as m,o as s,F as g,r as k,t as a,p as u,h as A}from"./index-CMUSrGrd.js";import{a as w}from"./admin-Do_x_iW1.js";import{_ as B,a as S}from"./CardContent.vue_vue_type_script_setup_true_lang-BbWKh528.js";import{_ as f}from"./Badge.vue_vue_type_script_setup_true_lang-Dhaxut8t.js";import{_ as V}from"./Spinner.vue_vue_type_script_setup_true_lang-DGWFD4UA.js";import{a as $}from"./utils-7WVCegLb.js";const N={class:"p-6"},C={key:0,class:"flex items-center justify-center h-20"},D={class:"w-full"},E={class:"px-4 py-3"},F={class:"text-sm font-medium text-foreground"},R={class:"px-4 py-3 text-sm text-muted-foreground"},U={class:"px-4 py-3"},j={class:"px-4 py-3"},q={class:"px-4 py-3 text-xs text-muted-foreground"},H=_({__name:"AdminView",setup(I){const x=y(),p=b(),i=m([]),l=m(!1);return h(async()=>{if(!x.isAdmin){p.push("/");return}l.value=!0;try{const c=await w.users();i.value=c.data}finally{l.value=!1}}),(c,o)=>(s(),r("div",N,[o[1]||(o[1]=t("h2",{class:"text-lg font-semibold text-foreground mb-6"},"Admin — Users",-1)),l.value?(s(),r("div",C,[n(V,{class:"text-primary"})])):(s(),v(B,{key:1},{default:d(()=>[n(S,{class:"p-0"},{default:d(()=>[t("table",D,[o[0]||(o[0]=t("thead",null,[t("tr",{class:"border-b border-border"},[t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"User"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Email"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Role"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Status"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Joined")])],-1)),t("tbody",null,[(s(!0),r(g,null,k(i.value,e=>(s(),r("tr",{key:e.id,class:"border-b border-border last:border-0 hover:bg-muted/30"},[t("td",E,[t("p",F,a(e.username),1)]),t("td",R,a(e.email),1),t("td",U,[n(f,{variant:e.role==="admin"?"default":"secondary",class:"text-xs"},{default:d(()=>[u(a(e.role),1)]),_:2},1032,["variant"])]),t("td",j,[n(f,{variant:e.is_active?"success":"outline",class:"text-xs"},{default:d(()=>[u(a(e.is_active?"Active":"Inactive"),1)]),_:2},1032,["variant"])]),t("td",q,a(A($)(e.created_at)),1)]))),128))])])]),_:1})]),_:1}))]))}});export{H as default};
import{d as _,u as y,x as h,c as r,a as t,e as n,k as v,w as d,f as b,q as m,o as s,F as g,r as k,t as a,p as u,h as A}from"./index-BsVgmrYd.js";import{a as w}from"./admin-Ccc2J89T.js";import{_ as B,a as S}from"./CardContent.vue_vue_type_script_setup_true_lang-B3rBmmXU.js";import{_ as f}from"./Badge.vue_vue_type_script_setup_true_lang-ctqZICyq.js";import{_ as V}from"./Spinner.vue_vue_type_script_setup_true_lang-BCputspr.js";import{a as $}from"./utils-7WVCegLb.js";const N={class:"p-6"},C={key:0,class:"flex items-center justify-center h-20"},D={class:"w-full"},E={class:"px-4 py-3"},F={class:"text-sm font-medium text-foreground"},R={class:"px-4 py-3 text-sm text-muted-foreground"},U={class:"px-4 py-3"},j={class:"px-4 py-3"},q={class:"px-4 py-3 text-xs text-muted-foreground"},H=_({__name:"AdminView",setup(I){const x=y(),p=b(),i=m([]),l=m(!1);return h(async()=>{if(!x.isAdmin){p.push("/");return}l.value=!0;try{const c=await w.users();i.value=c.data}finally{l.value=!1}}),(c,o)=>(s(),r("div",N,[o[1]||(o[1]=t("h2",{class:"text-lg font-semibold text-foreground mb-6"},"Admin — Users",-1)),l.value?(s(),r("div",C,[n(V,{class:"text-primary"})])):(s(),v(B,{key:1},{default:d(()=>[n(S,{class:"p-0"},{default:d(()=>[t("table",D,[o[0]||(o[0]=t("thead",null,[t("tr",{class:"border-b border-border"},[t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"User"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Email"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Role"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Status"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Joined")])],-1)),t("tbody",null,[(s(!0),r(g,null,k(i.value,e=>(s(),r("tr",{key:e.id,class:"border-b border-border last:border-0 hover:bg-muted/30"},[t("td",E,[t("p",F,a(e.username),1)]),t("td",R,a(e.email),1),t("td",U,[n(f,{variant:e.role==="admin"?"default":"secondary",class:"text-xs"},{default:d(()=>[u(a(e.role),1)]),_:2},1032,["variant"])]),t("td",j,[n(f,{variant:e.is_active?"success":"outline",class:"text-xs"},{default:d(()=>[u(a(e.is_active?"Active":"Inactive"),1)]),_:2},1032,["variant"])]),t("td",q,a(A($)(e.created_at)),1)]))),128))])])]),_:1})]),_:1}))]))}});export{H as default};

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
import{c as a}from"./utils-7WVCegLb.js";import{d as n,o,c as s,n as d,h as i,m as c}from"./index-CMUSrGrd.js";const f=n({__name:"Badge",props:{variant:{default:"default"},class:{}},setup(r){const e=r;return(t,l)=>(o(),s("span",{class:d(i(a)("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors",{"bg-primary text-primary-foreground":e.variant==="default","bg-secondary text-secondary-foreground":e.variant==="secondary","bg-destructive text-destructive-foreground":e.variant==="destructive","border border-border text-foreground":e.variant==="outline","bg-emerald-500/20 text-emerald-400":e.variant==="success","bg-amber-500/20 text-amber-400":e.variant==="warning"},e.class))},[c(t.$slots,"default")],2))}});export{f as _};
import{c as a}from"./utils-7WVCegLb.js";import{d as n,o,c as s,n as d,h as i,m as c}from"./index-BsVgmrYd.js";const f=n({__name:"Badge",props:{variant:{default:"default"},class:{}},setup(r){const e=r;return(t,l)=>(o(),s("span",{class:d(i(a)("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors",{"bg-primary text-primary-foreground":e.variant==="default","bg-secondary text-secondary-foreground":e.variant==="secondary","bg-destructive text-destructive-foreground":e.variant==="destructive","border border-border text-foreground":e.variant==="outline","bg-emerald-500/20 text-emerald-400":e.variant==="success","bg-amber-500/20 text-amber-400":e.variant==="warning"},e.class))},[c(t.$slots,"default")],2))}});export{f as _};

View file

@ -1 +1 @@
import{_ as c}from"./Spinner.vue_vue_type_script_setup_true_lang-DGWFD4UA.js";import{c as l}from"./utils-7WVCegLb.js";import{d as u,c as m,n as f,k as b,i as v,m as g,j as p,o as n}from"./index-CMUSrGrd.js";const y=["type","disabled"],z=u({__name:"Button",props:{variant:{default:"default"},size:{default:"md"},loading:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},type:{default:"button"},class:{}},emits:["click"],setup(t,{emit:s}){const e=t,a=s,r=p(()=>l("inline-flex items-center justify-center rounded-md font-medium transition-colors","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2","disabled:pointer-events-none disabled:opacity-50",{"bg-primary text-primary-foreground hover:bg-primary/90":e.variant==="default","border border-input bg-background hover:bg-accent hover:text-accent-foreground":e.variant==="outline","hover:bg-accent hover:text-accent-foreground":e.variant==="ghost","bg-destructive text-destructive-foreground hover:bg-destructive/90":e.variant==="destructive","bg-secondary text-secondary-foreground hover:bg-secondary/80":e.variant==="secondary","underline-offset-4 hover:underline text-primary":e.variant==="link","h-8 px-3 text-xs":e.size==="sm","h-10 px-4 py-2 text-sm":e.size==="md","h-11 px-8 text-base":e.size==="lg","h-9 w-9 p-0":e.size==="icon"},e.class));return(i,o)=>(n(),m("button",{class:f(r.value),type:t.type,disabled:t.disabled||t.loading,onClick:o[0]||(o[0]=d=>a("click",d))},[t.loading?(n(),b(c,{key:0,size:"sm",class:"mr-2"})):v("",!0),g(i.$slots,"default")],10,y))}});export{z as _};
import{_ as c}from"./Spinner.vue_vue_type_script_setup_true_lang-BCputspr.js";import{c as l}from"./utils-7WVCegLb.js";import{d as u,c as m,n as f,k as b,i as v,m as g,j as p,o as n}from"./index-BsVgmrYd.js";const y=["type","disabled"],z=u({__name:"Button",props:{variant:{default:"default"},size:{default:"md"},loading:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},type:{default:"button"},class:{}},emits:["click"],setup(t,{emit:s}){const e=t,a=s,r=p(()=>l("inline-flex items-center justify-center rounded-md font-medium transition-colors","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2","disabled:pointer-events-none disabled:opacity-50",{"bg-primary text-primary-foreground hover:bg-primary/90":e.variant==="default","border border-input bg-background hover:bg-accent hover:text-accent-foreground":e.variant==="outline","hover:bg-accent hover:text-accent-foreground":e.variant==="ghost","bg-destructive text-destructive-foreground hover:bg-destructive/90":e.variant==="destructive","bg-secondary text-secondary-foreground hover:bg-secondary/80":e.variant==="secondary","underline-offset-4 hover:underline text-primary":e.variant==="link","h-8 px-3 text-xs":e.size==="sm","h-10 px-4 py-2 text-sm":e.size==="md","h-11 px-8 text-base":e.size==="lg","h-9 w-9 p-0":e.size==="icon"},e.class));return(i,o)=>(n(),m("button",{class:f(r.value),type:t.type,disabled:t.disabled||t.loading,onClick:o[0]||(o[0]=d=>a("click",d))},[t.loading?(n(),b(c,{key:0,size:"sm",class:"mr-2"})):v("",!0),g(i.$slots,"default")],10,y))}});export{z as _};

View file

@ -1 +1 @@
import{c as e}from"./utils-7WVCegLb.js";import{d as o,c as n,n as t,h as c,m as l,o as p}from"./index-CMUSrGrd.js";const _=o({__name:"Card",props:{class:{}},setup(s){const a=s;return(r,d)=>(p(),n("div",{class:t(c(e)("rounded-lg border bg-card text-card-foreground shadow-sm",a.class))},[l(r.$slots,"default")],2))}}),f=o({__name:"CardContent",props:{class:{}},setup(s){const a=s;return(r,d)=>(p(),n("div",{class:t(c(e)("p-6 pt-0",a.class))},[l(r.$slots,"default")],2))}});export{_,f as a};
import{c as e}from"./utils-7WVCegLb.js";import{d as o,c as n,n as t,h as c,m as l,o as p}from"./index-BsVgmrYd.js";const _=o({__name:"Card",props:{class:{}},setup(s){const a=s;return(r,d)=>(p(),n("div",{class:t(c(e)("rounded-lg border bg-card text-card-foreground shadow-sm",a.class))},[l(r.$slots,"default")],2))}}),f=o({__name:"CardContent",props:{class:{}},setup(s){const a=s;return(r,d)=>(p(),n("div",{class:t(c(e)("p-6 pt-0",a.class))},[l(r.$slots,"default")],2))}});export{_,f as a};

View file

@ -1 +1 @@
import{c as t}from"./utils-7WVCegLb.js";import{d as n,o,c as r,n as c,h as l,m as p}from"./index-CMUSrGrd.js";const f=n({__name:"CardHeader",props:{class:{}},setup(s){const e=s;return(a,m)=>(o(),r("div",{class:c(l(t)("flex flex-col space-y-1.5 p-6",e.class))},[p(a.$slots,"default")],2))}}),_=n({__name:"CardTitle",props:{class:{}},setup(s){const e=s;return(a,m)=>(o(),r("h3",{class:c(l(t)("text-lg font-semibold leading-none tracking-tight",e.class))},[p(a.$slots,"default")],2))}});export{f as _,_ as a};
import{c as t}from"./utils-7WVCegLb.js";import{d as n,o,c as r,n as c,h as l,m as p}from"./index-BsVgmrYd.js";const f=n({__name:"CardHeader",props:{class:{}},setup(s){const e=s;return(a,m)=>(o(),r("div",{class:c(l(t)("flex flex-col space-y-1.5 p-6",e.class))},[p(a.$slots,"default")],2))}}),_=n({__name:"CardTitle",props:{class:{}},setup(s){const e=s;return(a,m)=>(o(),r("h3",{class:c(l(t)("text-lg font-semibold leading-none tracking-tight",e.class))},[p(a.$slots,"default")],2))}});export{f as _,_ as a};

View file

@ -1 +1 @@
import{u as D}from"./devops-DCMlzRTJ.js";import{_}from"./Input.vue_vue_type_script_setup_true_lang-DA-K-Rrj.js";import{_ as V}from"./Button.vue_vue_type_script_setup_true_lang-C2Q_x3IQ.js";import{d as j,q as c,o as i,c as m,h as a,a as o,p as g,t as d,i as p,e as v,w as k,k as z,K as u}from"./index-CMUSrGrd.js";const B={class:"space-y-4"},I={key:0,class:"text-xs text-muted-foreground space-y-1"},N={class:"text-foreground"},P={class:"text-foreground"},S={key:0},U={key:1,class:"text-red-400"},b={class:"grid grid-cols-2 gap-3"},A={class:"space-y-1.5"},F={class:"space-y-1.5"},O={class:"space-y-1.5"},q={class:"flex items-center gap-2"},G=j({__name:"DevopsConnectForm",setup(E){var y,x;const t=D(),n=c(((y=t.integration)==null?void 0:y.organization)??""),r=c(((x=t.integration)==null?void 0:x.project)??""),s=c(""),f=c(!1);async function w(){if(!n.value||!r.value||!s.value){u.error("All fields are required");return}f.value=!0;try{await t.saveIntegration({organization:n.value,project:r.value,pat:s.value}),s.value="",u.success("Integration saved")}catch{u.error("Failed to save integration")}finally{f.value=!1}}async function C(){if(confirm("Delete ADO integration?"))try{await t.deleteIntegration(),n.value="",r.value="",s.value="",u.success("Integration deleted")}catch{u.error("Failed to delete integration")}}return(K,e)=>(i(),m("div",B,[a(t).integration?(i(),m("div",I,[o("p",null,[e[3]||(e[3]=g(" Connected to ",-1)),o("strong",N,d(a(t).integration.organization),1),e[4]||(e[4]=g(" / ",-1)),o("strong",P,d(a(t).integration.project),1)]),a(t).integration.last_synced_at?(i(),m("p",S," Last synced: "+d(new Date(a(t).integration.last_synced_at).toLocaleString()),1)):p("",!0),a(t).integration.last_sync_error?(i(),m("p",U," Error: "+d(a(t).integration.last_sync_error),1)):p("",!0)])):p("",!0),o("div",b,[o("div",A,[e[5]||(e[5]=o("label",{class:"text-sm font-medium text-foreground"},"Organization",-1)),v(_,{modelValue:n.value,"onUpdate:modelValue":e[0]||(e[0]=l=>n.value=l),placeholder:"myorg"},null,8,["modelValue"])]),o("div",F,[e[6]||(e[6]=o("label",{class:"text-sm font-medium text-foreground"},"Project",-1)),v(_,{modelValue:r.value,"onUpdate:modelValue":e[1]||(e[1]=l=>r.value=l),placeholder:"myproject"},null,8,["modelValue"])])]),o("div",O,[e[7]||(e[7]=o("label",{class:"text-sm font-medium text-foreground"}," Personal Access Token ",-1)),v(_,{modelValue:s.value,"onUpdate:modelValue":e[2]||(e[2]=l=>s.value=l),type:"password",placeholder:"••••••••",autocomplete:"new-password"},null,8,["modelValue"])]),o("div",q,[v(V,{loading:f.value,onClick:w},{default:k(()=>[g(d(a(t).integration?"Update":"Connect"),1)]),_:1},8,["loading"]),a(t).integration?(i(),z(V,{key:0,variant:"destructive",size:"sm",onClick:C},{default:k(()=>[...e[8]||(e[8]=[g(" Disconnect ",-1)])]),_:1})):p("",!0)])]))}});export{G as _};
import{u as D}from"./devops-Dr0K2zsR.js";import{_}from"./Input.vue_vue_type_script_setup_true_lang-0Z6OrHEc.js";import{_ as V}from"./Button.vue_vue_type_script_setup_true_lang-CJHBIupl.js";import{d as j,q as c,o as i,c as m,h as a,a as o,p as g,t as d,i as p,e as v,w as k,k as z,K as u}from"./index-BsVgmrYd.js";const B={class:"space-y-4"},I={key:0,class:"text-xs text-muted-foreground space-y-1"},N={class:"text-foreground"},P={class:"text-foreground"},S={key:0},U={key:1,class:"text-red-400"},b={class:"grid grid-cols-2 gap-3"},A={class:"space-y-1.5"},F={class:"space-y-1.5"},O={class:"space-y-1.5"},q={class:"flex items-center gap-2"},G=j({__name:"DevopsConnectForm",setup(E){var y,x;const t=D(),n=c(((y=t.integration)==null?void 0:y.organization)??""),r=c(((x=t.integration)==null?void 0:x.project)??""),s=c(""),f=c(!1);async function w(){if(!n.value||!r.value||!s.value){u.error("All fields are required");return}f.value=!0;try{await t.saveIntegration({organization:n.value,project:r.value,pat:s.value}),s.value="",u.success("Integration saved")}catch{u.error("Failed to save integration")}finally{f.value=!1}}async function C(){if(confirm("Delete ADO integration?"))try{await t.deleteIntegration(),n.value="",r.value="",s.value="",u.success("Integration deleted")}catch{u.error("Failed to delete integration")}}return(K,e)=>(i(),m("div",B,[a(t).integration?(i(),m("div",I,[o("p",null,[e[3]||(e[3]=g(" Connected to ",-1)),o("strong",N,d(a(t).integration.organization),1),e[4]||(e[4]=g(" / ",-1)),o("strong",P,d(a(t).integration.project),1)]),a(t).integration.last_synced_at?(i(),m("p",S," Last synced: "+d(new Date(a(t).integration.last_synced_at).toLocaleString()),1)):p("",!0),a(t).integration.last_sync_error?(i(),m("p",U," Error: "+d(a(t).integration.last_sync_error),1)):p("",!0)])):p("",!0),o("div",b,[o("div",A,[e[5]||(e[5]=o("label",{class:"text-sm font-medium text-foreground"},"Organization",-1)),v(_,{modelValue:n.value,"onUpdate:modelValue":e[0]||(e[0]=l=>n.value=l),placeholder:"myorg"},null,8,["modelValue"])]),o("div",F,[e[6]||(e[6]=o("label",{class:"text-sm font-medium text-foreground"},"Project",-1)),v(_,{modelValue:r.value,"onUpdate:modelValue":e[1]||(e[1]=l=>r.value=l),placeholder:"myproject"},null,8,["modelValue"])])]),o("div",O,[e[7]||(e[7]=o("label",{class:"text-sm font-medium text-foreground"}," Personal Access Token ",-1)),v(_,{modelValue:s.value,"onUpdate:modelValue":e[2]||(e[2]=l=>s.value=l),type:"password",placeholder:"••••••••",autocomplete:"new-password"},null,8,["modelValue"])]),o("div",q,[v(V,{loading:f.value,onClick:w},{default:k(()=>[g(d(a(t).integration?"Update":"Connect"),1)]),_:1},8,["loading"]),a(t).integration?(i(),z(V,{key:0,variant:"destructive",size:"sm",onClick:C},{default:k(()=>[...e[8]||(e[8]=[g(" Disconnect ",-1)])]),_:1})):p("",!0)])]))}});export{G as _};

View file

@ -1 +1 @@
import{u as $}from"./devops-DCMlzRTJ.js";import{_ as f,a as _}from"./CardContent.vue_vue_type_script_setup_true_lang-BbWKh528.js";import{a as y,_ as v}from"./CardTitle.vue_vue_type_script_setup_true_lang-DKwAVa1N.js";import{_ as z}from"./Button.vue_vue_type_script_setup_true_lang-C2Q_x3IQ.js";import{_ as k}from"./Spinner.vue_vue_type_script_setup_true_lang-DGWFD4UA.js";import{_ as A}from"./DevopsConnectForm.vue_vue_type_script_setup_true_lang-C3QMf5bS.js";import{d as I,x as S,c as a,a as o,h as r,k as g,w as l,i as u,e as i,o as n,p as c,t as d,F as h,r as b,n as w,q as D,j,K as C}from"./index-CMUSrGrd.js";import"./utils-7WVCegLb.js";import"./Input.vue_vue_type_script_setup_true_lang-DA-K-Rrj.js";const V={class:"p-6 space-y-6"},B={class:"flex items-center justify-between gap-4 flex-wrap"},L={class:"flex items-center gap-2"},W={key:0,class:"flex items-center gap-2 text-sm text-muted-foreground"},F={key:1,class:"flex items-center gap-3"},O={class:"text-sm text-foreground"},E={key:0,class:"text-xs text-muted-foreground ml-2"},K={key:2,class:"flex items-center gap-3"},R={key:3,class:"text-xs text-destructive mt-2"},q={class:"flex items-center justify-between gap-3 flex-wrap"},M={class:"flex items-center rounded-lg border border-border overflow-hidden bg-muted/30"},T=["onClick"],G={key:0,class:"flex items-center justify-center py-8"},H={key:1,class:"text-center py-8 text-sm text-muted-foreground"},J={key:2,class:"space-y-1"},P={class:"text-xs font-mono text-muted-foreground w-10 shrink-0"},Q={class:"flex-1 min-w-0"},U={class:"text-sm text-foreground truncate"},X={class:"text-xs text-muted-foreground"},Y=["href"],ue=I({__name:"DevopsView",setup(Z){const e=$(),m=D("All");S(async()=>{await e.fetchIntegration(),e.integration&&await e.fetchWorkItems()});const p=j(()=>m.value==="All"?e.workItems:e.workItems.filter(x=>x.state===m.value));async function N(){try{await e.sync(),C.success("Sync complete"),await e.fetchWorkItems()}catch{C.error(e.error??"Sync failed")}}return(x,t)=>(n(),a("div",V,[o("div",B,[t[1]||(t[1]=o("h2",{class:"text-lg font-semibold text-foreground"},"Azure DevOps",-1)),o("div",L,[r(e).integration?(n(),g(z,{key:0,variant:"outline",size:"sm",loading:r(e).syncing,onClick:N},{default:l(()=>[...t[0]||(t[0]=[c(" Sync Now ",-1)])]),_:1},8,["loading"])):u("",!0)])]),i(f,null,{default:l(()=>[i(_,{class:"pt-4"},{default:l(()=>{var s;return[r(e).loading&&!r(e).integration?(n(),a("div",W,[i(k,{size:"sm"}),t[2]||(t[2]=o("span",null,"Loading...",-1))])):r(e).integration?(n(),a("div",F,[t[5]||(t[5]=o("div",{class:"h-2 w-2 rounded-full bg-[hsl(var(--success))]"},null,-1)),o("span",O,[t[3]||(t[3]=c(" Connected to ",-1)),o("strong",null,d(r(e).integration.organization),1),t[4]||(t[4]=c(" / ",-1)),o("strong",null,d(r(e).integration.project),1)]),r(e).integration.last_synced_at?(n(),a("span",E," Last synced: "+d(new Date(r(e).integration.last_synced_at).toLocaleString()),1)):u("",!0)])):(n(),a("div",K,[...t[6]||(t[6]=[o("div",{class:"h-2 w-2 rounded-full bg-muted-foreground"},null,-1),o("span",{class:"text-sm text-muted-foreground"},"Not connected",-1)])])),(s=r(e).integration)!=null&&s.last_sync_error?(n(),a("p",R," Error: "+d(r(e).integration.last_sync_error),1)):u("",!0)]}),_:1})]),_:1}),!r(e).integration&&!r(e).loading?(n(),g(f,{key:0},{default:l(()=>[i(v,null,{default:l(()=>[i(y,{class:"text-sm"},{default:l(()=>[...t[7]||(t[7]=[c("Connect Azure DevOps",-1)])]),_:1})]),_:1}),i(_,null,{default:l(()=>[i(A)]),_:1})]),_:1})):u("",!0),r(e).integration?(n(),g(f,{key:1},{default:l(()=>[i(v,{class:"pb-2"},{default:l(()=>[o("div",q,[i(y,{class:"text-sm"},{default:l(()=>[...t[8]||(t[8]=[c("Work Items",-1)])]),_:1}),o("div",M,[(n(),a(h,null,b(["All","Active","Resolved","Closed"],s=>o("button",{key:s,class:w(["px-3 py-1 text-xs font-medium transition-colors",m.value===s?"bg-primary text-primary-foreground":"text-muted-foreground hover:text-foreground hover:bg-muted/50"]),onClick:ee=>m.value=s},d(s),11,T)),64))])])]),_:1}),i(_,null,{default:l(()=>[r(e).loading?(n(),a("div",G,[i(k,{size:"md",class:"text-primary"})])):p.value.length===0?(n(),a("div",H," No work items found ")):(n(),a("div",J,[(n(!0),a(h,null,b(p.value,s=>(n(),a("div",{key:s.id,class:"flex items-center gap-3 px-3 py-2.5 rounded-lg hover:bg-muted/30 transition-colors"},[o("span",P,"#"+d(s.ado_id),1),o("div",Q,[o("p",U,d(s.title),1),o("p",X,d(s.type),1)]),o("span",{class:w(["text-xs px-2 py-0.5 rounded-full shrink-0",s.state==="Active"?"bg-blue-500/10 text-blue-400":s.state==="Resolved"?"bg-green-500/10 text-green-400":(s.state==="Closed","bg-muted text-muted-foreground")])},d(s.state),3),s.url?(n(),a("a",{key:0,href:s.url,target:"_blank",class:"text-xs text-primary hover:underline shrink-0"}," Open → ",8,Y)):u("",!0)]))),128))]))]),_:1})]),_:1})):u("",!0)]))}});export{ue as default};
import{u as $}from"./devops-Dr0K2zsR.js";import{_ as f,a as _}from"./CardContent.vue_vue_type_script_setup_true_lang-B3rBmmXU.js";import{a as y,_ as v}from"./CardTitle.vue_vue_type_script_setup_true_lang-BO3n7g7a.js";import{_ as z}from"./Button.vue_vue_type_script_setup_true_lang-CJHBIupl.js";import{_ as k}from"./Spinner.vue_vue_type_script_setup_true_lang-BCputspr.js";import{_ as A}from"./DevopsConnectForm.vue_vue_type_script_setup_true_lang-CTHVanFL.js";import{d as I,x as S,c as a,a as o,h as r,k as g,w as l,i as u,e as i,o as n,p as c,t as d,F as h,r as b,n as w,q as D,j,K as C}from"./index-BsVgmrYd.js";import"./utils-7WVCegLb.js";import"./Input.vue_vue_type_script_setup_true_lang-0Z6OrHEc.js";const V={class:"p-6 space-y-6"},B={class:"flex items-center justify-between gap-4 flex-wrap"},L={class:"flex items-center gap-2"},W={key:0,class:"flex items-center gap-2 text-sm text-muted-foreground"},F={key:1,class:"flex items-center gap-3"},O={class:"text-sm text-foreground"},E={key:0,class:"text-xs text-muted-foreground ml-2"},K={key:2,class:"flex items-center gap-3"},R={key:3,class:"text-xs text-destructive mt-2"},q={class:"flex items-center justify-between gap-3 flex-wrap"},M={class:"flex items-center rounded-lg border border-border overflow-hidden bg-muted/30"},T=["onClick"],G={key:0,class:"flex items-center justify-center py-8"},H={key:1,class:"text-center py-8 text-sm text-muted-foreground"},J={key:2,class:"space-y-1"},P={class:"text-xs font-mono text-muted-foreground w-10 shrink-0"},Q={class:"flex-1 min-w-0"},U={class:"text-sm text-foreground truncate"},X={class:"text-xs text-muted-foreground"},Y=["href"],ue=I({__name:"DevopsView",setup(Z){const e=$(),m=D("All");S(async()=>{await e.fetchIntegration(),e.integration&&await e.fetchWorkItems()});const p=j(()=>m.value==="All"?e.workItems:e.workItems.filter(x=>x.state===m.value));async function N(){try{await e.sync(),C.success("Sync complete"),await e.fetchWorkItems()}catch{C.error(e.error??"Sync failed")}}return(x,t)=>(n(),a("div",V,[o("div",B,[t[1]||(t[1]=o("h2",{class:"text-lg font-semibold text-foreground"},"Azure DevOps",-1)),o("div",L,[r(e).integration?(n(),g(z,{key:0,variant:"outline",size:"sm",loading:r(e).syncing,onClick:N},{default:l(()=>[...t[0]||(t[0]=[c(" Sync Now ",-1)])]),_:1},8,["loading"])):u("",!0)])]),i(f,null,{default:l(()=>[i(_,{class:"pt-4"},{default:l(()=>{var s;return[r(e).loading&&!r(e).integration?(n(),a("div",W,[i(k,{size:"sm"}),t[2]||(t[2]=o("span",null,"Loading...",-1))])):r(e).integration?(n(),a("div",F,[t[5]||(t[5]=o("div",{class:"h-2 w-2 rounded-full bg-[hsl(var(--success))]"},null,-1)),o("span",O,[t[3]||(t[3]=c(" Connected to ",-1)),o("strong",null,d(r(e).integration.organization),1),t[4]||(t[4]=c(" / ",-1)),o("strong",null,d(r(e).integration.project),1)]),r(e).integration.last_synced_at?(n(),a("span",E," Last synced: "+d(new Date(r(e).integration.last_synced_at).toLocaleString()),1)):u("",!0)])):(n(),a("div",K,[...t[6]||(t[6]=[o("div",{class:"h-2 w-2 rounded-full bg-muted-foreground"},null,-1),o("span",{class:"text-sm text-muted-foreground"},"Not connected",-1)])])),(s=r(e).integration)!=null&&s.last_sync_error?(n(),a("p",R," Error: "+d(r(e).integration.last_sync_error),1)):u("",!0)]}),_:1})]),_:1}),!r(e).integration&&!r(e).loading?(n(),g(f,{key:0},{default:l(()=>[i(v,null,{default:l(()=>[i(y,{class:"text-sm"},{default:l(()=>[...t[7]||(t[7]=[c("Connect Azure DevOps",-1)])]),_:1})]),_:1}),i(_,null,{default:l(()=>[i(A)]),_:1})]),_:1})):u("",!0),r(e).integration?(n(),g(f,{key:1},{default:l(()=>[i(v,{class:"pb-2"},{default:l(()=>[o("div",q,[i(y,{class:"text-sm"},{default:l(()=>[...t[8]||(t[8]=[c("Work Items",-1)])]),_:1}),o("div",M,[(n(),a(h,null,b(["All","Active","Resolved","Closed"],s=>o("button",{key:s,class:w(["px-3 py-1 text-xs font-medium transition-colors",m.value===s?"bg-primary text-primary-foreground":"text-muted-foreground hover:text-foreground hover:bg-muted/50"]),onClick:ee=>m.value=s},d(s),11,T)),64))])])]),_:1}),i(_,null,{default:l(()=>[r(e).loading?(n(),a("div",G,[i(k,{size:"md",class:"text-primary"})])):p.value.length===0?(n(),a("div",H," No work items found ")):(n(),a("div",J,[(n(!0),a(h,null,b(p.value,s=>(n(),a("div",{key:s.id,class:"flex items-center gap-3 px-3 py-2.5 rounded-lg hover:bg-muted/30 transition-colors"},[o("span",P,"#"+d(s.ado_id),1),o("div",Q,[o("p",U,d(s.title),1),o("p",X,d(s.type),1)]),o("span",{class:w(["text-xs px-2 py-0.5 rounded-full shrink-0",s.state==="Active"?"bg-blue-500/10 text-blue-400":s.state==="Resolved"?"bg-green-500/10 text-green-400":(s.state==="Closed","bg-muted text-muted-foreground")])},d(s.state),3),s.url?(n(),a("a",{key:0,href:s.url,target:"_blank",class:"text-xs text-primary hover:underline shrink-0"}," Open → ",8,Y)):u("",!0)]))),128))]))]),_:1})]),_:1})):u("",!0)]))}});export{ue as default};

View file

@ -1 +1 @@
import{d as k,x as y,G as b,k as h,H as x,e as c,T as g,w as m,o as a,c as n,a as o,m as r,t as u,i,n as w}from"./index-CMUSrGrd.js";import{_ as $}from"./Button.vue_vue_type_script_setup_true_lang-C2Q_x3IQ.js";const C={key:0,class:"fixed inset-0 z-50 flex items-center justify-center p-4"},B=["aria-label"],j={key:0,class:"flex items-center justify-between p-6 pb-4"},z={class:"text-lg font-semibold text-foreground"},E={key:0,class:"text-sm text-muted-foreground mt-1"},L={class:"px-6 pb-4"},M={key:1,class:"flex justify-end gap-2 px-6 pb-6"},V=k({__name:"Dialog",props:{open:{type:Boolean},title:{},description:{},maxWidth:{default:"max-w-lg"}},emits:["close"],setup(e,{emit:f}){const p=e,l=f;function d(t){t.key==="Escape"&&p.open&&l("close")}return y(()=>document.addEventListener("keydown",d)),b(()=>document.removeEventListener("keydown",d)),(t,s)=>(a(),h(x,{to:"body"},[c(g,{"enter-active-class":"transition-opacity duration-200","enter-from-class":"opacity-0","enter-to-class":"opacity-100","leave-active-class":"transition-opacity duration-200","leave-from-class":"opacity-100","leave-to-class":"opacity-0"},{default:m(()=>[e.open?(a(),n("div",C,[o("div",{class:"absolute inset-0 bg-black/60 backdrop-blur-sm",onClick:s[0]||(s[0]=v=>l("close"))}),o("div",{class:w(["relative w-full bg-card border border-border rounded-lg shadow-xl z-10",e.maxWidth]),role:"dialog","aria-modal":!0,"aria-label":e.title},[e.title||t.$slots.header?(a(),n("div",j,[o("div",null,[r(t.$slots,"header",{},()=>[o("h2",z,u(e.title),1),e.description?(a(),n("p",E,u(e.description),1)):i("",!0)])]),c($,{variant:"ghost",size:"icon",class:"shrink-0",onClick:s[1]||(s[1]=v=>l("close"))},{default:m(()=>[...s[2]||(s[2]=[o("svg",{class:"h-4 w-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[o("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)])]),_:1})])):i("",!0),o("div",L,[r(t.$slots,"default")]),t.$slots.footer?(a(),n("div",M,[r(t.$slots,"footer")])):i("",!0)],10,B)])):i("",!0)]),_:3})]))}});export{V as _};
import{d as k,x as y,G as b,k as h,H as x,e as c,T as g,w as m,o as a,c as n,a as o,m as r,t as u,i,n as w}from"./index-BsVgmrYd.js";import{_ as $}from"./Button.vue_vue_type_script_setup_true_lang-CJHBIupl.js";const C={key:0,class:"fixed inset-0 z-50 flex items-center justify-center p-4"},B=["aria-label"],j={key:0,class:"flex items-center justify-between p-6 pb-4"},z={class:"text-lg font-semibold text-foreground"},E={key:0,class:"text-sm text-muted-foreground mt-1"},L={class:"px-6 pb-4"},M={key:1,class:"flex justify-end gap-2 px-6 pb-6"},V=k({__name:"Dialog",props:{open:{type:Boolean},title:{},description:{},maxWidth:{default:"max-w-lg"}},emits:["close"],setup(e,{emit:f}){const p=e,l=f;function d(t){t.key==="Escape"&&p.open&&l("close")}return y(()=>document.addEventListener("keydown",d)),b(()=>document.removeEventListener("keydown",d)),(t,s)=>(a(),h(x,{to:"body"},[c(g,{"enter-active-class":"transition-opacity duration-200","enter-from-class":"opacity-0","enter-to-class":"opacity-100","leave-active-class":"transition-opacity duration-200","leave-from-class":"opacity-100","leave-to-class":"opacity-0"},{default:m(()=>[e.open?(a(),n("div",C,[o("div",{class:"absolute inset-0 bg-black/60 backdrop-blur-sm",onClick:s[0]||(s[0]=v=>l("close"))}),o("div",{class:w(["relative w-full bg-card border border-border rounded-lg shadow-xl z-10",e.maxWidth]),role:"dialog","aria-modal":!0,"aria-label":e.title},[e.title||t.$slots.header?(a(),n("div",j,[o("div",null,[r(t.$slots,"header",{},()=>[o("h2",z,u(e.title),1),e.description?(a(),n("p",E,u(e.description),1)):i("",!0)])]),c($,{variant:"ghost",size:"icon",class:"shrink-0",onClick:s[1]||(s[1]=v=>l("close"))},{default:m(()=>[...s[2]||(s[2]=[o("svg",{class:"h-4 w-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[o("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M6 18L18 6M6 6l12 12"})],-1)])]),_:1})])):i("",!0),o("div",L,[r(t.$slots,"default")]),t.$slots.footer?(a(),n("div",M,[r(t.$slots,"footer")])):i("",!0)],10,B)])):i("",!0)]),_:3})]))}});export{V as _};

View file

@ -1 +1 @@
import{c as i}from"./utils-7WVCegLb.js";import{d,c as s,n as u,h as m,o as r}from"./index-CMUSrGrd.js";const c=["id","name","type","value","placeholder","disabled","autocomplete","min","max","step"],g=d({__name:"Input",props:{modelValue:{},type:{},placeholder:{},disabled:{type:Boolean},class:{},id:{},name:{},autocomplete:{},min:{},max:{},step:{}},emits:["update:modelValue","change","blur","focus"],setup(e,{emit:n}){const a=e,o=n;return(f,t)=>(r(),s("input",{id:e.id,name:e.name,type:e.type??"text",value:e.modelValue,placeholder:e.placeholder,disabled:e.disabled,autocomplete:e.autocomplete,min:e.min,max:e.max,step:e.step,class:u(m(i)("flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm","ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium","placeholder:text-muted-foreground","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2","disabled:cursor-not-allowed disabled:opacity-50",a.class)),onInput:t[0]||(t[0]=l=>o("update:modelValue",l.target.value)),onChange:t[1]||(t[1]=l=>o("change",l.target.value)),onBlur:t[2]||(t[2]=l=>o("blur",l)),onFocus:t[3]||(t[3]=l=>o("focus",l))},null,42,c))}});export{g as _};
import{c as i}from"./utils-7WVCegLb.js";import{d,c as s,n as u,h as m,o as r}from"./index-BsVgmrYd.js";const c=["id","name","type","value","placeholder","disabled","autocomplete","min","max","step"],g=d({__name:"Input",props:{modelValue:{},type:{},placeholder:{},disabled:{type:Boolean},class:{},id:{},name:{},autocomplete:{},min:{},max:{},step:{}},emits:["update:modelValue","change","blur","focus"],setup(e,{emit:n}){const a=e,o=n;return(f,t)=>(r(),s("input",{id:e.id,name:e.name,type:e.type??"text",value:e.modelValue,placeholder:e.placeholder,disabled:e.disabled,autocomplete:e.autocomplete,min:e.min,max:e.max,step:e.step,class:u(m(i)("flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm","ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium","placeholder:text-muted-foreground","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2","disabled:cursor-not-allowed disabled:opacity-50",a.class)),onInput:t[0]||(t[0]=l=>o("update:modelValue",l.target.value)),onChange:t[1]||(t[1]=l=>o("change",l.target.value)),onBlur:t[2]||(t[2]=l=>o("blur",l)),onFocus:t[3]||(t[3]=l=>o("focus",l))},null,42,c))}});export{g as _};

View file

@ -1 +1 @@
import{a as b}from"./admin-Do_x_iW1.js";import{_ as K,a as $}from"./CardContent.vue_vue_type_script_setup_true_lang-BbWKh528.js";import{_ as p}from"./Button.vue_vue_type_script_setup_true_lang-C2Q_x3IQ.js";import{_ as V}from"./Dialog.vue_vue_type_script_setup_true_lang-eW9IuHG4.js";import{_ as N}from"./Input.vue_vue_type_script_setup_true_lang-DA-K-Rrj.js";import{_ as A}from"./Spinner.vue_vue_type_script_setup_true_lang-DGWFD4UA.js";import{d as B,x as L,c as l,a as t,e as r,w as n,q as i,o as a,p as v,F as P,r as F,t as u,h as k,k as I,i as j,K as y}from"./index-CMUSrGrd.js";import{a as h}from"./utils-7WVCegLb.js";const D={class:"p-6"},R={class:"flex items-center justify-between mb-6"},z={key:0,class:"flex items-center justify-center h-20"},M={key:1,class:"text-center text-muted-foreground py-8 text-sm"},T={key:2,class:"w-full"},U={class:"px-4 py-3 text-sm text-foreground"},q={class:"px-4 py-3 text-sm font-mono text-muted-foreground"},E={class:"px-4 py-3 text-xs text-muted-foreground"},H={class:"px-4 py-3 text-xs text-muted-foreground"},S={class:"px-4 py-3 text-right"},G={class:"space-y-4"},J={key:0,class:"rounded-md bg-emerald-500/10 border border-emerald-500/30 p-3"},O={class:"text-xs font-mono text-foreground break-all"},Q={key:1,class:"space-y-1.5"},re=B({__name:"KeysView",setup(W){const f=i([]),_=i(!1),c=i(!1),m=i(""),x=i(!1),d=i(null);L(()=>g());async function g(){_.value=!0;try{const o=await b.keys();f.value=o.data}finally{_.value=!1}}async function w(){if(m.value.trim()){x.value=!0;try{const o=await b.createKey({label:m.value});d.value=o.data.key,y.success("API key created"),await g(),m.value=""}catch{y.error("Failed to create key")}finally{x.value=!1}}}async function C(o){if(confirm(`Revoke key "${o.label}"? This cannot be undone.`))try{await b.revokeKey(o.id),y.success("Key revoked"),f.value=f.value.filter(e=>e.id!==o.id)}catch{y.error("Failed to revoke key")}}return(o,e)=>(a(),l("div",D,[t("div",R,[e[5]||(e[5]=t("h2",{class:"text-lg font-semibold text-foreground"},"API Keys",-1)),r(p,{size:"sm",onClick:e[0]||(e[0]=s=>{c.value=!0,d.value=null})},{default:n(()=>[...e[4]||(e[4]=[t("svg",{class:"h-4 w-4 mr-1.5",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),v(" New Key ",-1)])]),_:1})]),r(K,null,{default:n(()=>[r($,{class:"p-0"},{default:n(()=>[_.value?(a(),l("div",z,[r(A,{class:"text-primary"})])):f.value.length===0?(a(),l("div",M," No API keys ")):(a(),l("table",T,[e[7]||(e[7]=t("thead",null,[t("tr",{class:"border-b border-border"},[t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Label"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Prefix"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Created"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Last Used"),t("th",{class:"px-4 py-3"})])],-1)),t("tbody",null,[(a(!0),l(P,null,F(f.value,s=>(a(),l("tr",{key:s.id,class:"border-b border-border last:border-0 hover:bg-muted/30"},[t("td",U,u(s.label),1),t("td",q,u(s.prefix)+"...",1),t("td",E,u(k(h)(s.created_at)),1),t("td",H,u(s.last_used?k(h)(s.last_used):"Never"),1),t("td",S,[r(p,{variant:"ghost",size:"sm",class:"text-destructive",onClick:X=>C(s)},{default:n(()=>[...e[6]||(e[6]=[v(" Revoke ",-1)])]),_:1},8,["onClick"])])]))),128))])]))]),_:1})]),_:1}),r(V,{open:c.value,title:"Create API Key",onClose:e[3]||(e[3]=s=>c.value=!1)},{footer:n(()=>[r(p,{variant:"outline",onClick:e[2]||(e[2]=s=>c.value=!1)},{default:n(()=>[v(u(d.value?"Done":"Cancel"),1)]),_:1}),d.value?j("",!0):(a(),I(p,{key:0,loading:x.value,onClick:w},{default:n(()=>[...e[10]||(e[10]=[v(" Create ",-1)])]),_:1},8,["loading"]))]),default:n(()=>[t("div",G,[d.value?(a(),l("div",J,[e[8]||(e[8]=t("p",{class:"text-xs text-emerald-400 font-medium mb-1"},"Key created — save it now!",-1)),t("p",O,u(d.value),1)])):(a(),l("div",Q,[e[9]||(e[9]=t("label",{class:"text-sm font-medium text-foreground"},"Label",-1)),r(N,{modelValue:m.value,"onUpdate:modelValue":e[1]||(e[1]=s=>m.value=s),placeholder:"e.g. claude-collector",disabled:x.value},null,8,["modelValue","disabled"])]))])]),_:1},8,["open"])]))}});export{re as default};
import{a as b}from"./admin-Ccc2J89T.js";import{_ as K,a as $}from"./CardContent.vue_vue_type_script_setup_true_lang-B3rBmmXU.js";import{_ as p}from"./Button.vue_vue_type_script_setup_true_lang-CJHBIupl.js";import{_ as V}from"./Dialog.vue_vue_type_script_setup_true_lang-D3o8WZbf.js";import{_ as N}from"./Input.vue_vue_type_script_setup_true_lang-0Z6OrHEc.js";import{_ as A}from"./Spinner.vue_vue_type_script_setup_true_lang-BCputspr.js";import{d as B,x as L,c as l,a as t,e as r,w as n,q as i,o as a,p as v,F as P,r as F,t as u,h as k,k as I,i as j,K as y}from"./index-BsVgmrYd.js";import{a as h}from"./utils-7WVCegLb.js";const D={class:"p-6"},R={class:"flex items-center justify-between mb-6"},z={key:0,class:"flex items-center justify-center h-20"},M={key:1,class:"text-center text-muted-foreground py-8 text-sm"},T={key:2,class:"w-full"},U={class:"px-4 py-3 text-sm text-foreground"},q={class:"px-4 py-3 text-sm font-mono text-muted-foreground"},E={class:"px-4 py-3 text-xs text-muted-foreground"},H={class:"px-4 py-3 text-xs text-muted-foreground"},S={class:"px-4 py-3 text-right"},G={class:"space-y-4"},J={key:0,class:"rounded-md bg-emerald-500/10 border border-emerald-500/30 p-3"},O={class:"text-xs font-mono text-foreground break-all"},Q={key:1,class:"space-y-1.5"},re=B({__name:"KeysView",setup(W){const f=i([]),_=i(!1),c=i(!1),m=i(""),x=i(!1),d=i(null);L(()=>g());async function g(){_.value=!0;try{const o=await b.keys();f.value=o.data}finally{_.value=!1}}async function w(){if(m.value.trim()){x.value=!0;try{const o=await b.createKey({label:m.value});d.value=o.data.key,y.success("API key created"),await g(),m.value=""}catch{y.error("Failed to create key")}finally{x.value=!1}}}async function C(o){if(confirm(`Revoke key "${o.label}"? This cannot be undone.`))try{await b.revokeKey(o.id),y.success("Key revoked"),f.value=f.value.filter(e=>e.id!==o.id)}catch{y.error("Failed to revoke key")}}return(o,e)=>(a(),l("div",D,[t("div",R,[e[5]||(e[5]=t("h2",{class:"text-lg font-semibold text-foreground"},"API Keys",-1)),r(p,{size:"sm",onClick:e[0]||(e[0]=s=>{c.value=!0,d.value=null})},{default:n(()=>[...e[4]||(e[4]=[t("svg",{class:"h-4 w-4 mr-1.5",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),v(" New Key ",-1)])]),_:1})]),r(K,null,{default:n(()=>[r($,{class:"p-0"},{default:n(()=>[_.value?(a(),l("div",z,[r(A,{class:"text-primary"})])):f.value.length===0?(a(),l("div",M," No API keys ")):(a(),l("table",T,[e[7]||(e[7]=t("thead",null,[t("tr",{class:"border-b border-border"},[t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Label"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Prefix"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Created"),t("th",{class:"text-left text-xs font-medium text-muted-foreground px-4 py-3"},"Last Used"),t("th",{class:"px-4 py-3"})])],-1)),t("tbody",null,[(a(!0),l(P,null,F(f.value,s=>(a(),l("tr",{key:s.id,class:"border-b border-border last:border-0 hover:bg-muted/30"},[t("td",U,u(s.label),1),t("td",q,u(s.prefix)+"...",1),t("td",E,u(k(h)(s.created_at)),1),t("td",H,u(s.last_used?k(h)(s.last_used):"Never"),1),t("td",S,[r(p,{variant:"ghost",size:"sm",class:"text-destructive",onClick:X=>C(s)},{default:n(()=>[...e[6]||(e[6]=[v(" Revoke ",-1)])]),_:1},8,["onClick"])])]))),128))])]))]),_:1})]),_:1}),r(V,{open:c.value,title:"Create API Key",onClose:e[3]||(e[3]=s=>c.value=!1)},{footer:n(()=>[r(p,{variant:"outline",onClick:e[2]||(e[2]=s=>c.value=!1)},{default:n(()=>[v(u(d.value?"Done":"Cancel"),1)]),_:1}),d.value?j("",!0):(a(),I(p,{key:0,loading:x.value,onClick:w},{default:n(()=>[...e[10]||(e[10]=[v(" Create ",-1)])]),_:1},8,["loading"]))]),default:n(()=>[t("div",G,[d.value?(a(),l("div",J,[e[8]||(e[8]=t("p",{class:"text-xs text-emerald-400 font-medium mb-1"},"Key created — save it now!",-1)),t("p",O,u(d.value),1)])):(a(),l("div",Q,[e[9]||(e[9]=t("label",{class:"text-sm font-medium text-foreground"},"Label",-1)),r(N,{modelValue:m.value,"onUpdate:modelValue":e[1]||(e[1]=s=>m.value=s),placeholder:"e.g. claude-collector",disabled:x.value},null,8,["modelValue","disabled"])]))])]),_:1},8,["open"])]))}});export{re as default};

View file

@ -1 +1 @@
import{G as T,q as y,d as J,u as O,x as V,c as f,a as o,n as b,h as l,t as v,k as $,w as x,i as k,e as C,o as c,p as w,F as B,r as F,j as z}from"./index-CMUSrGrd.js";import{_ as A,a as D}from"./CardContent.vue_vue_type_script_setup_true_lang-BbWKh528.js";import{_ as N}from"./Button.vue_vue_type_script_setup_true_lang-C2Q_x3IQ.js";import"./utils-7WVCegLb.js";import"./Spinner.vue_vue_type_script_setup_true_lang-DGWFD4UA.js";function U(E){const e=y([]),i=y(!1),m=y(null);let s=null,r=null,u=!1;function p(){if(!u)try{s=new EventSource(E),s.onopen=()=>{i.value=!0,m.value=null},s.onmessage=n=>{try{const g=JSON.parse(n.data);e.value.push({type:"message",data:g}),e.value.length>200&&e.value.shift()}catch{e.value.push({type:"message",data:n.data})}},s.addEventListener("session_start",n=>{try{e.value.push({type:"session_start",data:JSON.parse(n.data)})}catch{e.value.push({type:"session_start",data:n.data})}e.value.length>200&&e.value.shift()}),s.addEventListener("session_end",n=>{try{e.value.push({type:"session_end",data:JSON.parse(n.data)})}catch{e.value.push({type:"session_end",data:n.data})}e.value.length>200&&e.value.shift()}),s.addEventListener("activity",n=>{try{e.value.push({type:"activity",data:JSON.parse(n.data)})}catch{e.value.push({type:"activity",data:n.data})}e.value.length>200&&e.value.shift()}),s.onerror=()=>{i.value=!1,m.value="Connection lost, reconnecting...",s==null||s.close(),s=null,u||(r=setTimeout(()=>p(),5e3))}}catch{m.value="Failed to connect to event stream",u||(r=setTimeout(()=>p(),5e3))}}function _(){u=!0,r&&clearTimeout(r),s==null||s.close(),s=null,i.value=!1}function h(){e.value=[]}return T(()=>{_()}),{events:e,connected:i,error:m,connect:p,disconnect:_,clearEvents:h}}const I={class:"p-6 h-full flex flex-col"},R={class:"flex items-center gap-3 mb-4"},q={class:"flex items-center gap-2"},G={class:"text-xs text-muted-foreground"},M={key:0,class:"mb-4 text-xs text-amber-400 bg-amber-500/10 border border-amber-500/30 rounded px-3 py-2"},P={key:0,class:"flex items-center justify-center h-full text-sm text-muted-foreground"},W={key:1,class:"overflow-y-auto h-full font-mono text-xs"},H={class:"flex-1 min-w-0"},K={class:"flex items-center gap-2 flex-wrap"},Q={key:0,class:"text-muted-foreground"},X={class:"text-muted-foreground truncate mt-0.5"},ne=J({__name:"LiveView",setup(E){const e=O(),i=e.getToken(),m=`/cc-dashboard/api/events${i?`?token=${encodeURIComponent(i)}`:""}`,{events:s,connected:r,error:u,connect:p,clearEvents:_}=U(m);V(()=>{e.isAuthenticated&&i&&p()});const h=z(()=>[...s.value].reverse().slice(0,100));function n(t){return t==="session_start"?"text-emerald-400":t==="session_end"?"text-amber-400":t==="activity"?"text-blue-400":"text-muted-foreground"}function g(t){return t==="session_start"?"▶":t==="session_end"?"■":t==="activity"?"●":"○"}function j(t){if(typeof t=="string")return t;if(t&&typeof t=="object"){const a=t;return a.message||a.summary||JSON.stringify(t)}return String(t)}function S(t){if(t&&typeof t=="object"){const a=t;return a.display_name||a.project_id||""}return""}return(t,a)=>(c(),f("div",I,[o("div",R,[a[2]||(a[2]=o("h2",{class:"text-lg font-semibold text-foreground flex-1"},"Live Feed",-1)),o("div",q,[o("div",{class:b(["h-2 w-2 rounded-full",l(r)?"bg-emerald-500 animate-pulse":"bg-red-500"])},null,2),o("span",G,v(l(r)?"Connected":"Disconnected"),1)]),l(r)?k("",!0):(c(),$(N,{key:0,variant:"outline",size:"sm",onClick:l(p)},{default:x(()=>[...a[0]||(a[0]=[w(" Reconnect ",-1)])]),_:1},8,["onClick"])),C(N,{variant:"ghost",size:"sm",onClick:l(_)},{default:x(()=>[...a[1]||(a[1]=[w(" Clear ",-1)])]),_:1},8,["onClick"])]),l(u)&&!l(r)?(c(),f("div",M,v(l(u)),1)):k("",!0),C(A,{class:"flex-1 overflow-hidden"},{default:x(()=>[C(D,{class:"p-0 h-full"},{default:x(()=>[h.value.length===0?(c(),f("div",P,[...a[3]||(a[3]=[o("div",{class:"text-center"},[o("div",{class:"text-2xl mb-2"},"📡"),o("p",null,"Waiting for events..."),o("p",{class:"text-xs mt-1"},"Activity will appear here in real-time")],-1)])])):(c(),f("div",W,[(c(!0),f(B,null,F(h.value,(d,L)=>(c(),f("div",{key:L,class:"flex items-start gap-2 px-4 py-1.5 hover:bg-muted/50 border-b border-border/30"},[o("span",{class:b([n(d.type),"shrink-0 mt-0.5"])},v(g(d.type)),3),o("div",H,[o("div",K,[o("span",{class:b([n(d.type),"font-medium"])},v(d.type),3),S(d.data)?(c(),f("span",Q,v(S(d.data)),1)):k("",!0)]),o("p",X,v(j(d.data)),1)])]))),128))]))]),_:1})]),_:1})]))}});export{ne as default};
import{G as T,q as y,d as J,u as O,x as V,c as f,a as o,n as b,h as l,t as v,k as $,w as x,i as k,e as C,o as c,p as w,F as B,r as F,j as z}from"./index-BsVgmrYd.js";import{_ as A,a as D}from"./CardContent.vue_vue_type_script_setup_true_lang-B3rBmmXU.js";import{_ as N}from"./Button.vue_vue_type_script_setup_true_lang-CJHBIupl.js";import"./utils-7WVCegLb.js";import"./Spinner.vue_vue_type_script_setup_true_lang-BCputspr.js";function U(E){const e=y([]),i=y(!1),m=y(null);let s=null,r=null,u=!1;function p(){if(!u)try{s=new EventSource(E),s.onopen=()=>{i.value=!0,m.value=null},s.onmessage=n=>{try{const g=JSON.parse(n.data);e.value.push({type:"message",data:g}),e.value.length>200&&e.value.shift()}catch{e.value.push({type:"message",data:n.data})}},s.addEventListener("session_start",n=>{try{e.value.push({type:"session_start",data:JSON.parse(n.data)})}catch{e.value.push({type:"session_start",data:n.data})}e.value.length>200&&e.value.shift()}),s.addEventListener("session_end",n=>{try{e.value.push({type:"session_end",data:JSON.parse(n.data)})}catch{e.value.push({type:"session_end",data:n.data})}e.value.length>200&&e.value.shift()}),s.addEventListener("activity",n=>{try{e.value.push({type:"activity",data:JSON.parse(n.data)})}catch{e.value.push({type:"activity",data:n.data})}e.value.length>200&&e.value.shift()}),s.onerror=()=>{i.value=!1,m.value="Connection lost, reconnecting...",s==null||s.close(),s=null,u||(r=setTimeout(()=>p(),5e3))}}catch{m.value="Failed to connect to event stream",u||(r=setTimeout(()=>p(),5e3))}}function _(){u=!0,r&&clearTimeout(r),s==null||s.close(),s=null,i.value=!1}function h(){e.value=[]}return T(()=>{_()}),{events:e,connected:i,error:m,connect:p,disconnect:_,clearEvents:h}}const I={class:"p-6 h-full flex flex-col"},R={class:"flex items-center gap-3 mb-4"},q={class:"flex items-center gap-2"},G={class:"text-xs text-muted-foreground"},M={key:0,class:"mb-4 text-xs text-amber-400 bg-amber-500/10 border border-amber-500/30 rounded px-3 py-2"},P={key:0,class:"flex items-center justify-center h-full text-sm text-muted-foreground"},W={key:1,class:"overflow-y-auto h-full font-mono text-xs"},H={class:"flex-1 min-w-0"},K={class:"flex items-center gap-2 flex-wrap"},Q={key:0,class:"text-muted-foreground"},X={class:"text-muted-foreground truncate mt-0.5"},ne=J({__name:"LiveView",setup(E){const e=O(),i=e.getToken(),m=`/cc-dashboard/api/events${i?`?token=${encodeURIComponent(i)}`:""}`,{events:s,connected:r,error:u,connect:p,clearEvents:_}=U(m);V(()=>{e.isAuthenticated&&i&&p()});const h=z(()=>[...s.value].reverse().slice(0,100));function n(t){return t==="session_start"?"text-emerald-400":t==="session_end"?"text-amber-400":t==="activity"?"text-blue-400":"text-muted-foreground"}function g(t){return t==="session_start"?"▶":t==="session_end"?"■":t==="activity"?"●":"○"}function j(t){if(typeof t=="string")return t;if(t&&typeof t=="object"){const a=t;return a.message||a.summary||JSON.stringify(t)}return String(t)}function S(t){if(t&&typeof t=="object"){const a=t;return a.display_name||a.project_id||""}return""}return(t,a)=>(c(),f("div",I,[o("div",R,[a[2]||(a[2]=o("h2",{class:"text-lg font-semibold text-foreground flex-1"},"Live Feed",-1)),o("div",q,[o("div",{class:b(["h-2 w-2 rounded-full",l(r)?"bg-emerald-500 animate-pulse":"bg-red-500"])},null,2),o("span",G,v(l(r)?"Connected":"Disconnected"),1)]),l(r)?k("",!0):(c(),$(N,{key:0,variant:"outline",size:"sm",onClick:l(p)},{default:x(()=>[...a[0]||(a[0]=[w(" Reconnect ",-1)])]),_:1},8,["onClick"])),C(N,{variant:"ghost",size:"sm",onClick:l(_)},{default:x(()=>[...a[1]||(a[1]=[w(" Clear ",-1)])]),_:1},8,["onClick"])]),l(u)&&!l(r)?(c(),f("div",M,v(l(u)),1)):k("",!0),C(A,{class:"flex-1 overflow-hidden"},{default:x(()=>[C(D,{class:"p-0 h-full"},{default:x(()=>[h.value.length===0?(c(),f("div",P,[...a[3]||(a[3]=[o("div",{class:"text-center"},[o("div",{class:"text-2xl mb-2"},"📡"),o("p",null,"Waiting for events..."),o("p",{class:"text-xs mt-1"},"Activity will appear here in real-time")],-1)])])):(c(),f("div",W,[(c(!0),f(B,null,F(h.value,(d,L)=>(c(),f("div",{key:L,class:"flex items-start gap-2 px-4 py-1.5 hover:bg-muted/50 border-b border-border/30"},[o("span",{class:b([n(d.type),"shrink-0 mt-0.5"])},v(g(d.type)),3),o("div",H,[o("div",K,[o("span",{class:b([n(d.type),"font-medium"])},v(d.type),3),S(d.data)?(c(),f("span",Q,v(S(d.data)),1)):k("",!0)]),o("p",X,v(j(d.data)),1)])]))),128))]))]),_:1})]),_:1})]))}});export{ne as default};

View file

@ -1 +1 @@
import{d as h,u as f,c as o,a as t,b as m,e as a,w as d,o as r,f as g,g as p,h as i,t as x,i as w}from"./index-CMUSrGrd.js";import{_ as y,a as b}from"./CardContent.vue_vue_type_script_setup_true_lang-BbWKh528.js";import"./utils-7WVCegLb.js";const v={class:"min-h-screen flex items-center justify-center bg-background p-4"},_={class:"w-full max-w-sm"},k={class:"space-y-4"},C={key:0,class:"rounded-md bg-destructive/10 border border-destructive/30 px-3 py-2 text-sm text-destructive"},B=["disabled"],V={key:0},S={key:1},M=h({__name:"LoginView",setup(F){const c=g(),l=p(),s=f();async function u(){try{await s.loginWithMicrosoft();const n=l.query.redirect;c.push(n??"/")}catch{}}return(n,e)=>(r(),o("div",v,[t("div",_,[e[2]||(e[2]=m('<div class="text-center mb-8"><div class="inline-flex h-12 w-12 items-center justify-center rounded-xl bg-primary mb-3"><svg class="h-7 w-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path></svg></div><h1 class="text-2xl font-bold text-foreground">CC Dashboard</h1><p class="text-sm text-muted-foreground mt-1">Corporate Planning Hub</p></div>',1)),a(y,null,{default:d(()=>[a(b,{class:"pt-6"},{default:d(()=>[t("div",k,[i(s).error?(r(),o("div",C,x(i(s).error),1)):w("",!0),t("button",{type:"button",disabled:i(s).loading,class:"w-full flex items-center justify-center gap-3 rounded-md border border-border bg-white px-4 py-2.5 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",onClick:u},[e[0]||(e[0]=t("svg",{class:"h-5 w-5 shrink-0",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[t("rect",{x:"1",y:"1",width:"9",height:"9",fill:"#F25022"}),t("rect",{x:"11",y:"1",width:"9",height:"9",fill:"#7FBA00"}),t("rect",{x:"1",y:"11",width:"9",height:"9",fill:"#00A4EF"}),t("rect",{x:"11",y:"11",width:"9",height:"9",fill:"#FFB900"})],-1)),i(s).loading?(r(),o("span",V,"Signing in…")):(r(),o("span",S,"Sign in with Microsoft"))],8,B),e[1]||(e[1]=t("p",{class:"text-center text-xs text-muted-foreground"}," Use your @oliver.agency account ",-1))])]),_:1})]),_:1})])]))}});export{M as default};
import{d as h,u as f,c as o,a as t,b as m,e as a,w as d,o as r,f as g,g as p,h as i,t as x,i as w}from"./index-BsVgmrYd.js";import{_ as y,a as b}from"./CardContent.vue_vue_type_script_setup_true_lang-B3rBmmXU.js";import"./utils-7WVCegLb.js";const v={class:"min-h-screen flex items-center justify-center bg-background p-4"},_={class:"w-full max-w-sm"},k={class:"space-y-4"},C={key:0,class:"rounded-md bg-destructive/10 border border-destructive/30 px-3 py-2 text-sm text-destructive"},B=["disabled"],V={key:0},S={key:1},M=h({__name:"LoginView",setup(F){const c=g(),l=p(),s=f();async function u(){try{await s.loginWithMicrosoft();const n=l.query.redirect;c.push(n??"/")}catch{}}return(n,e)=>(r(),o("div",v,[t("div",_,[e[2]||(e[2]=m('<div class="text-center mb-8"><div class="inline-flex h-12 w-12 items-center justify-center rounded-xl bg-primary mb-3"><svg class="h-7 w-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path></svg></div><h1 class="text-2xl font-bold text-foreground">CC Dashboard</h1><p class="text-sm text-muted-foreground mt-1">Corporate Planning Hub</p></div>',1)),a(y,null,{default:d(()=>[a(b,{class:"pt-6"},{default:d(()=>[t("div",k,[i(s).error?(r(),o("div",C,x(i(s).error),1)):w("",!0),t("button",{type:"button",disabled:i(s).loading,class:"w-full flex items-center justify-center gap-3 rounded-md border border-border bg-white px-4 py-2.5 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",onClick:u},[e[0]||(e[0]=t("svg",{class:"h-5 w-5 shrink-0",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg"},[t("rect",{x:"1",y:"1",width:"9",height:"9",fill:"#F25022"}),t("rect",{x:"11",y:"1",width:"9",height:"9",fill:"#7FBA00"}),t("rect",{x:"1",y:"11",width:"9",height:"9",fill:"#00A4EF"}),t("rect",{x:"11",y:"11",width:"9",height:"9",fill:"#FFB900"})],-1)),i(s).loading?(r(),o("span",V,"Signing in…")):(r(),o("span",S,"Sign in with Microsoft"))],8,B),e[1]||(e[1]=t("p",{class:"text-center text-xs text-muted-foreground"}," Use your @oliver.agency account ",-1))])]),_:1})]),_:1})])]))}});export{M as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
import{c as r}from"./utils-7WVCegLb.js";import{d as s,o as n,c as t,n as l,h as c,a as d,A as u}from"./index-CMUSrGrd.js";const h=s({__name:"Progress",props:{value:{},max:{default:100},class:{},color:{default:"default"}},setup(a){const e=a,o=()=>Math.min(100,Math.max(0,e.value/e.max*100));return(i,m)=>(n(),t("div",{class:l(c(r)("relative h-2 w-full overflow-hidden rounded-full bg-secondary",e.class))},[d("div",{class:l(["h-full rounded-full transition-all duration-300",{"bg-primary":a.color==="default","bg-emerald-500":a.color==="success","bg-amber-500":a.color==="warning","bg-red-500":a.color==="danger"}]),style:u({width:`${o()}%`})},null,6)],2))}});export{h as _};
import{c as r}from"./utils-7WVCegLb.js";import{d as s,o as n,c as t,n as l,h as c,a as d,A as u}from"./index-BsVgmrYd.js";const h=s({__name:"Progress",props:{value:{},max:{default:100},class:{},color:{default:"default"}},setup(a){const e=a,o=()=>Math.min(100,Math.max(0,e.value/e.max*100));return(i,m)=>(n(),t("div",{class:l(c(r)("relative h-2 w-full overflow-hidden rounded-full bg-secondary",e.class))},[d("div",{class:l(["h-full rounded-full transition-all duration-300",{"bg-primary":a.color==="default","bg-emerald-500":a.color==="success","bg-amber-500":a.color==="warning","bg-red-500":a.color==="danger"}]),style:u({width:`${o()}%`})},null,6)],2))}});export{h as _};

View file

@ -1,4 +1,4 @@
var Ce=Object.defineProperty;var ae=a=>{throw TypeError(a)};var Ee=(a,t,e)=>t in a?Ce(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var k=(a,t,e)=>Ee(a,typeof t!="symbol"?t+"":t,e),Le=(a,t,e)=>t.has(a)||ae("Cannot "+e);var ce=(a,t,e)=>t.has(a)?ae("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(a):t.set(a,e);var Z=(a,t,e)=>(Le(a,t,"access private method"),e);import{E as V,d as Be,x as qe,c as z,a as x,n as U,e as P,w as I,F as Ze,r as Pe,q as A,o as $,p as G,k as pe,t as W,h as Me,i as he,K as ue}from"./index-CMUSrGrd.js";import{a as De,_ as Qe}from"./CardContent.vue_vue_type_script_setup_true_lang-BbWKh528.js";import{_ as fe}from"./Badge.vue_vue_type_script_setup_true_lang-Dhaxut8t.js";import{_ as Ne}from"./Button.vue_vue_type_script_setup_true_lang-C2Q_x3IQ.js";import{_ as je}from"./Spinner.vue_vue_type_script_setup_true_lang-DGWFD4UA.js";import{a as Oe,i as He}from"./utils-7WVCegLb.js";import{_ as Fe}from"./_plugin-vue_export-helper-DlAUqK2U.js";const ge={list:()=>V.get("/api/reports"),get:a=>V.get(`/api/reports/${a}`),generate:a=>V.post("/api/reports/generate",a)};function J(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}let S=J();function we(a){S=a}const ye=/[&<>"']/,Ve=new RegExp(ye.source,"g"),$e=/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,Ue=new RegExp($e.source,"g"),Ge={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},de=a=>Ge[a];function m(a,t){if(t){if(ye.test(a))return a.replace(Ve,de)}else if($e.test(a))return a.replace(Ue,de);return a}const We=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;function Xe(a){return a.replace(We,(t,e)=>(e=e.toLowerCase(),e==="colon"?":":e.charAt(0)==="#"?e.charAt(1)==="x"?String.fromCharCode(parseInt(e.substring(2),16)):String.fromCharCode(+e.substring(1)):""))}const Ke=/(^|[^\[])\^/g;function d(a,t){let e=typeof a=="string"?a:a.source;t=t||"";const n={replace:(i,r)=>{let s=typeof r=="string"?r:r.source;return s=s.replace(Ke,"$1"),e=e.replace(i,s),n},getRegex:()=>new RegExp(e,t)};return n}function ke(a){try{a=encodeURI(a).replace(/%25/g,"%")}catch{return null}return a}const E={exec:()=>null};function xe(a,t){const e=a.replace(/\|/g,(r,s,l)=>{let o=!1,u=s;for(;--u>=0&&l[u]==="\\";)o=!o;return o?"|":" |"}),n=e.split(/ \|/);let i=0;if(n[0].trim()||n.shift(),n.length>0&&!n[n.length-1].trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length<t;)n.push("");for(;i<n.length;i++)n[i]=n[i].trim().replace(/\\\|/g,"|");return n}function M(a,t,e){const n=a.length;if(n===0)return"";let i=0;for(;i<n&&a.charAt(n-i-1)===t;)i++;return a.slice(0,n-i)}function Je(a,t){if(a.indexOf(t[1])===-1)return-1;let e=0;for(let n=0;n<a.length;n++)if(a[n]==="\\")n++;else if(a[n]===t[0])e++;else if(a[n]===t[1]&&(e--,e<0))return n;return-1}function me(a,t,e,n){const i=t.href,r=t.title?m(t.title):null,s=a[1].replace(/\\([\[\]])/g,"$1");if(a[0].charAt(0)!=="!"){n.state.inLink=!0;const l={type:"link",raw:e,href:i,title:r,text:s,tokens:n.inlineTokens(s)};return n.state.inLink=!1,l}return{type:"image",raw:e,href:i,title:r,text:m(s)}}function Ye(a,t){const e=a.match(/^(\s+)(?:```)/);if(e===null)return t;const n=e[1];return t.split(`
var Ce=Object.defineProperty;var ae=a=>{throw TypeError(a)};var Ee=(a,t,e)=>t in a?Ce(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var k=(a,t,e)=>Ee(a,typeof t!="symbol"?t+"":t,e),Le=(a,t,e)=>t.has(a)||ae("Cannot "+e);var ce=(a,t,e)=>t.has(a)?ae("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(a):t.set(a,e);var Z=(a,t,e)=>(Le(a,t,"access private method"),e);import{E as V,d as Be,x as qe,c as z,a as x,n as U,e as P,w as I,F as Ze,r as Pe,q as A,o as $,p as G,k as pe,t as W,h as Me,i as he,K as ue}from"./index-BsVgmrYd.js";import{a as De,_ as Qe}from"./CardContent.vue_vue_type_script_setup_true_lang-B3rBmmXU.js";import{_ as fe}from"./Badge.vue_vue_type_script_setup_true_lang-ctqZICyq.js";import{_ as Ne}from"./Button.vue_vue_type_script_setup_true_lang-CJHBIupl.js";import{_ as je}from"./Spinner.vue_vue_type_script_setup_true_lang-BCputspr.js";import{a as Oe,i as He}from"./utils-7WVCegLb.js";import{_ as Fe}from"./_plugin-vue_export-helper-DlAUqK2U.js";const ge={list:()=>V.get("/api/reports"),get:a=>V.get(`/api/reports/${a}`),generate:a=>V.post("/api/reports/generate",a)};function J(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}let S=J();function we(a){S=a}const ye=/[&<>"']/,Ve=new RegExp(ye.source,"g"),$e=/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,Ue=new RegExp($e.source,"g"),Ge={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},de=a=>Ge[a];function m(a,t){if(t){if(ye.test(a))return a.replace(Ve,de)}else if($e.test(a))return a.replace(Ue,de);return a}const We=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;function Xe(a){return a.replace(We,(t,e)=>(e=e.toLowerCase(),e==="colon"?":":e.charAt(0)==="#"?e.charAt(1)==="x"?String.fromCharCode(parseInt(e.substring(2),16)):String.fromCharCode(+e.substring(1)):""))}const Ke=/(^|[^\[])\^/g;function d(a,t){let e=typeof a=="string"?a:a.source;t=t||"";const n={replace:(i,r)=>{let s=typeof r=="string"?r:r.source;return s=s.replace(Ke,"$1"),e=e.replace(i,s),n},getRegex:()=>new RegExp(e,t)};return n}function ke(a){try{a=encodeURI(a).replace(/%25/g,"%")}catch{return null}return a}const E={exec:()=>null};function xe(a,t){const e=a.replace(/\|/g,(r,s,l)=>{let o=!1,u=s;for(;--u>=0&&l[u]==="\\";)o=!o;return o?"|":" |"}),n=e.split(/ \|/);let i=0;if(n[0].trim()||n.shift(),n.length>0&&!n[n.length-1].trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length<t;)n.push("");for(;i<n.length;i++)n[i]=n[i].trim().replace(/\\\|/g,"|");return n}function M(a,t,e){const n=a.length;if(n===0)return"";let i=0;for(;i<n&&a.charAt(n-i-1)===t;)i++;return a.slice(0,n-i)}function Je(a,t){if(a.indexOf(t[1])===-1)return-1;let e=0;for(let n=0;n<a.length;n++)if(a[n]==="\\")n++;else if(a[n]===t[0])e++;else if(a[n]===t[1]&&(e--,e<0))return n;return-1}function me(a,t,e,n){const i=t.href,r=t.title?m(t.title):null,s=a[1].replace(/\\([\[\]])/g,"$1");if(a[0].charAt(0)!=="!"){n.state.inLink=!0;const l={type:"link",raw:e,href:i,title:r,text:s,tokens:n.inlineTokens(s)};return n.state.inLink=!1,l}return{type:"image",raw:e,href:i,title:r,text:m(s)}}function Ye(a,t){const e=a.match(/^(\s+)(?:```)/);if(e===null)return t;const n=e[1];return t.split(`
`).map(i=>{const r=i.match(/^\s+/);if(r===null)return i;const[s]=r;return s.length>=n.length?i.slice(n.length):i}).join(`
`)}class Q{constructor(t){k(this,"options");k(this,"rules");k(this,"lexer");this.options=t||S}space(t){const e=this.rules.block.newline.exec(t);if(e&&e[0].length>0)return{type:"space",raw:e[0]}}code(t){const e=this.rules.block.code.exec(t);if(e){const n=e[0].replace(/^ {1,4}/gm,"");return{type:"code",raw:e[0],codeBlockStyle:"indented",text:this.options.pedantic?n:M(n,`
`)}}}fences(t){const e=this.rules.block.fences.exec(t);if(e){const n=e[0],i=Ye(n,e[3]||"");return{type:"code",raw:n,lang:e[2]?e[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):e[2],text:i}}}heading(t){const e=this.rules.block.heading.exec(t);if(e){let n=e[2].trim();if(/#$/.test(n)){const i=M(n,"#");(this.options.pedantic||!i||/ $/.test(i))&&(n=i.trim())}return{type:"heading",raw:e[0],depth:e[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(t){const e=this.rules.block.hr.exec(t);if(e)return{type:"hr",raw:e[0]}}blockquote(t){const e=this.rules.block.blockquote.exec(t);if(e){let n=e[0].replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,`

View file

@ -1 +1 @@
import{d as N,u as E,x as P,c as U,a,e as t,w as s,q as f,o as k,p as u,h as c,k as z,i as B,E as I,K as x}from"./index-CMUSrGrd.js";import{u as F}from"./devops-DCMlzRTJ.js";import{_ as w,a as V}from"./CardContent.vue_vue_type_script_setup_true_lang-BbWKh528.js";import{_ as $,a as S}from"./CardTitle.vue_vue_type_script_setup_true_lang-DKwAVa1N.js";import{_ as y}from"./Input.vue_vue_type_script_setup_true_lang-DA-K-Rrj.js";import{_}from"./Button.vue_vue_type_script_setup_true_lang-C2Q_x3IQ.js";import{_ as O}from"./DevopsConnectForm.vue_vue_type_script_setup_true_lang-C3QMf5bS.js";import{i as C}from"./utils-7WVCegLb.js";import"./Spinner.vue_vue_type_script_setup_true_lang-DGWFD4UA.js";function T(i,l){const n=`/cc-dashboard/api/export/timesheet.csv?from=${i}&to=${l}`,o=document.createElement("a");o.href=n,o.download=`timesheet-${i}-${l}.csv`,o.click()}function A(i,l){const n=`/cc-dashboard/api/export/timesheet.ics?from=${i}&to=${l}`,o=document.createElement("a");o.href=n,o.download=`timesheet-${i}-${l}.ics`,o.click()}const H={class:"p-6 space-y-6 max-w-2xl"},K={class:"space-y-1.5"},M={class:"space-y-1.5"},j={class:"flex items-center justify-between"},q={class:"flex items-center gap-3 flex-wrap"},h={class:"space-y-1.5"},G={class:"space-y-1.5"},J={class:"flex items-center gap-2"},se=N({__name:"SettingsView",setup(i){const l=E(),n=F(),o=f(""),p=f(0),g=f(!1),d=f(""),m=f("");P(()=>{l.user&&(o.value=l.user.username,p.value=l.user.daily_overhead_hours??0),n.fetchIntegration();const v=new Date;m.value=C(v);const e=new Date(v);e.setDate(v.getDate()-30),d.value=C(e)});async function D(){g.value=!0;try{await I.patch("/api/auth/me",{username:o.value,daily_overhead_hours:p.value}),await l.fetchMe(),x.success("Profile saved")}catch{x.error("Failed to save profile")}finally{g.value=!1}}async function b(){try{await n.sync(),x.success("Sync complete")}catch{x.error(n.error??"Sync failed")}}return(v,e)=>(k(),U("div",H,[e[18]||(e[18]=a("h2",{class:"text-lg font-semibold text-foreground"},"Settings",-1)),t(w,null,{default:s(()=>[t($,null,{default:s(()=>[t(S,{class:"text-sm"},{default:s(()=>[...e[6]||(e[6]=[u("Profile",-1)])]),_:1})]),_:1}),t(V,{class:"space-y-4"},{default:s(()=>[a("div",K,[e[7]||(e[7]=a("label",{class:"text-sm font-medium text-foreground"},"Username",-1)),t(y,{modelValue:o.value,"onUpdate:modelValue":e[0]||(e[0]=r=>o.value=r),placeholder:"username"},null,8,["modelValue"])]),a("div",M,[e[8]||(e[8]=a("label",{class:"text-sm font-medium text-foreground"},"Daily Overhead Hours",-1)),t(y,{modelValue:p.value,"onUpdate:modelValue":e[1]||(e[1]=r=>p.value=r),type:"number",min:"0",max:"8",step:"0.25",class:"w-32"},null,8,["modelValue"]),e[9]||(e[9]=a("p",{class:"text-xs text-muted-foreground"}," Hours per day to add for overhead / meetings ",-1))]),t(_,{loading:g.value,onClick:D},{default:s(()=>[...e[10]||(e[10]=[u("Save Profile",-1)])]),_:1},8,["loading"])]),_:1})]),_:1}),t(w,null,{default:s(()=>[t($,null,{default:s(()=>[a("div",j,[t(S,{class:"text-sm"},{default:s(()=>[...e[11]||(e[11]=[u("Azure DevOps Integration",-1)])]),_:1}),c(n).integration?(k(),z(_,{key:0,variant:"outline",size:"sm",loading:c(n).syncing,onClick:b},{default:s(()=>[...e[12]||(e[12]=[u(" Sync Now ",-1)])]),_:1},8,["loading"])):B("",!0)])]),_:1}),t(V,null,{default:s(()=>[t(O)]),_:1})]),_:1}),t(w,null,{default:s(()=>[t($,null,{default:s(()=>[t(S,{class:"text-sm"},{default:s(()=>[...e[13]||(e[13]=[u("Export",-1)])]),_:1})]),_:1}),t(V,{class:"space-y-4"},{default:s(()=>[a("div",q,[a("div",h,[e[14]||(e[14]=a("label",{class:"text-xs text-muted-foreground"},"From",-1)),t(y,{modelValue:d.value,"onUpdate:modelValue":e[2]||(e[2]=r=>d.value=r),type:"date",class:"h-8 text-xs"},null,8,["modelValue"])]),a("div",G,[e[15]||(e[15]=a("label",{class:"text-xs text-muted-foreground"},"To",-1)),t(y,{modelValue:m.value,"onUpdate:modelValue":e[3]||(e[3]=r=>m.value=r),type:"date",class:"h-8 text-xs"},null,8,["modelValue"])])]),a("div",J,[t(_,{variant:"outline",size:"sm",onClick:e[4]||(e[4]=r=>c(T)(d.value,m.value))},{default:s(()=>[...e[16]||(e[16]=[u(" Download CSV ",-1)])]),_:1}),t(_,{variant:"outline",size:"sm",onClick:e[5]||(e[5]=r=>c(A)(d.value,m.value))},{default:s(()=>[...e[17]||(e[17]=[u(" Download ICS ",-1)])]),_:1})])]),_:1})]),_:1})]))}});export{se as default};
import{d as N,u as E,x as P,c as U,a,e as t,w as s,q as f,o as k,p as u,h as c,k as z,i as B,E as I,K as x}from"./index-BsVgmrYd.js";import{u as F}from"./devops-Dr0K2zsR.js";import{_ as w,a as V}from"./CardContent.vue_vue_type_script_setup_true_lang-B3rBmmXU.js";import{_ as $,a as S}from"./CardTitle.vue_vue_type_script_setup_true_lang-BO3n7g7a.js";import{_ as y}from"./Input.vue_vue_type_script_setup_true_lang-0Z6OrHEc.js";import{_}from"./Button.vue_vue_type_script_setup_true_lang-CJHBIupl.js";import{_ as O}from"./DevopsConnectForm.vue_vue_type_script_setup_true_lang-CTHVanFL.js";import{i as C}from"./utils-7WVCegLb.js";import"./Spinner.vue_vue_type_script_setup_true_lang-BCputspr.js";function T(i,l){const n=`/cc-dashboard/api/export/timesheet.csv?from=${i}&to=${l}`,o=document.createElement("a");o.href=n,o.download=`timesheet-${i}-${l}.csv`,o.click()}function A(i,l){const n=`/cc-dashboard/api/export/timesheet.ics?from=${i}&to=${l}`,o=document.createElement("a");o.href=n,o.download=`timesheet-${i}-${l}.ics`,o.click()}const H={class:"p-6 space-y-6 max-w-2xl"},K={class:"space-y-1.5"},M={class:"space-y-1.5"},j={class:"flex items-center justify-between"},q={class:"flex items-center gap-3 flex-wrap"},h={class:"space-y-1.5"},G={class:"space-y-1.5"},J={class:"flex items-center gap-2"},se=N({__name:"SettingsView",setup(i){const l=E(),n=F(),o=f(""),p=f(0),g=f(!1),d=f(""),m=f("");P(()=>{l.user&&(o.value=l.user.username,p.value=l.user.daily_overhead_hours??0),n.fetchIntegration();const v=new Date;m.value=C(v);const e=new Date(v);e.setDate(v.getDate()-30),d.value=C(e)});async function D(){g.value=!0;try{await I.patch("/api/auth/me",{username:o.value,daily_overhead_hours:p.value}),await l.fetchMe(),x.success("Profile saved")}catch{x.error("Failed to save profile")}finally{g.value=!1}}async function b(){try{await n.sync(),x.success("Sync complete")}catch{x.error(n.error??"Sync failed")}}return(v,e)=>(k(),U("div",H,[e[18]||(e[18]=a("h2",{class:"text-lg font-semibold text-foreground"},"Settings",-1)),t(w,null,{default:s(()=>[t($,null,{default:s(()=>[t(S,{class:"text-sm"},{default:s(()=>[...e[6]||(e[6]=[u("Profile",-1)])]),_:1})]),_:1}),t(V,{class:"space-y-4"},{default:s(()=>[a("div",K,[e[7]||(e[7]=a("label",{class:"text-sm font-medium text-foreground"},"Username",-1)),t(y,{modelValue:o.value,"onUpdate:modelValue":e[0]||(e[0]=r=>o.value=r),placeholder:"username"},null,8,["modelValue"])]),a("div",M,[e[8]||(e[8]=a("label",{class:"text-sm font-medium text-foreground"},"Daily Overhead Hours",-1)),t(y,{modelValue:p.value,"onUpdate:modelValue":e[1]||(e[1]=r=>p.value=r),type:"number",min:"0",max:"8",step:"0.25",class:"w-32"},null,8,["modelValue"]),e[9]||(e[9]=a("p",{class:"text-xs text-muted-foreground"}," Hours per day to add for overhead / meetings ",-1))]),t(_,{loading:g.value,onClick:D},{default:s(()=>[...e[10]||(e[10]=[u("Save Profile",-1)])]),_:1},8,["loading"])]),_:1})]),_:1}),t(w,null,{default:s(()=>[t($,null,{default:s(()=>[a("div",j,[t(S,{class:"text-sm"},{default:s(()=>[...e[11]||(e[11]=[u("Azure DevOps Integration",-1)])]),_:1}),c(n).integration?(k(),z(_,{key:0,variant:"outline",size:"sm",loading:c(n).syncing,onClick:b},{default:s(()=>[...e[12]||(e[12]=[u(" Sync Now ",-1)])]),_:1},8,["loading"])):B("",!0)])]),_:1}),t(V,null,{default:s(()=>[t(O)]),_:1})]),_:1}),t(w,null,{default:s(()=>[t($,null,{default:s(()=>[t(S,{class:"text-sm"},{default:s(()=>[...e[13]||(e[13]=[u("Export",-1)])]),_:1})]),_:1}),t(V,{class:"space-y-4"},{default:s(()=>[a("div",q,[a("div",h,[e[14]||(e[14]=a("label",{class:"text-xs text-muted-foreground"},"From",-1)),t(y,{modelValue:d.value,"onUpdate:modelValue":e[2]||(e[2]=r=>d.value=r),type:"date",class:"h-8 text-xs"},null,8,["modelValue"])]),a("div",G,[e[15]||(e[15]=a("label",{class:"text-xs text-muted-foreground"},"To",-1)),t(y,{modelValue:m.value,"onUpdate:modelValue":e[3]||(e[3]=r=>m.value=r),type:"date",class:"h-8 text-xs"},null,8,["modelValue"])])]),a("div",J,[t(_,{variant:"outline",size:"sm",onClick:e[4]||(e[4]=r=>c(T)(d.value,m.value))},{default:s(()=>[...e[16]||(e[16]=[u(" Download CSV ",-1)])]),_:1}),t(_,{variant:"outline",size:"sm",onClick:e[5]||(e[5]=r=>c(A)(d.value,m.value))},{default:s(()=>[...e[17]||(e[17]=[u(" Download ICS ",-1)])]),_:1})])]),_:1})]),_:1})]))}});export{se as default};

View file

@ -1 +1 @@
import{d as l,o as n,c as o,n as t,a as r}from"./index-CMUSrGrd.js";const i=l({__name:"Spinner",props:{size:{},class:{}},setup(s){return(a,e)=>(n(),o("svg",{class:t(["animate-spin text-current",s.size==="sm"?"h-3 w-3":s.size==="lg"?"h-6 w-6":"h-4 w-4",a.$props.class]),xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24"},[...e[0]||(e[0]=[r("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"},null,-1),r("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"},null,-1)])],2))}});export{i as _};
import{d as l,o as n,c as o,n as t,a as r}from"./index-BsVgmrYd.js";const i=l({__name:"Spinner",props:{size:{},class:{}},setup(s){return(a,e)=>(n(),o("svg",{class:t(["animate-spin text-current",s.size==="sm"?"h-3 w-3":s.size==="lg"?"h-6 w-6":"h-4 w-4",a.$props.class]),xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24"},[...e[0]||(e[0]=[r("circle",{class:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor","stroke-width":"4"},null,-1),r("path",{class:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"},null,-1)])],2))}});export{i as _};

View file

@ -1 +1 @@
import{E as e}from"./index-CMUSrGrd.js";const i={users:()=>e.get("/api/admin/users"),keys:()=>e.get("/api/keys"),createKey:s=>e.post("/api/keys",s),revokeKey:s=>e.delete(`/api/keys/${s}`)};export{i as a};
import{E as e}from"./index-BsVgmrYd.js";const i={users:()=>e.get("/api/admin/users"),keys:()=>e.get("/api/keys"),createKey:s=>e.post("/api/keys",s),revokeKey:s=>e.delete(`/api/keys/${s}`)};export{i as a};

View file

@ -1 +1 @@
import{E as t}from"./index-CMUSrGrd.js";const e={summary:a=>t.get("/api/dashboard/summary",{params:a}),projects:a=>t.get("/api/dashboard/projects",{params:a}),timeline:a=>t.get("/api/dashboard/timeline",{params:a}),monthly:a=>t.get("/api/dashboard/monthly",{params:a}),dow:a=>t.get("/api/dashboard/dow",{params:a}),tools:a=>t.get("/api/dashboard/tools",{params:a}),activity:a=>t.get("/api/dashboard/activity",{params:a}),calendar:a=>t.get("/api/dashboard/calendar",{params:a}),project:(a,o)=>t.get("/api/dashboard/project/"+a,{params:o})};export{e as d};
import{E as t}from"./index-BsVgmrYd.js";const e={summary:a=>t.get("/api/dashboard/summary",{params:a}),projects:a=>t.get("/api/dashboard/projects",{params:a}),timeline:a=>t.get("/api/dashboard/timeline",{params:a}),monthly:a=>t.get("/api/dashboard/monthly",{params:a}),dow:a=>t.get("/api/dashboard/dow",{params:a}),tools:a=>t.get("/api/dashboard/tools",{params:a}),activity:a=>t.get("/api/dashboard/activity",{params:a}),calendar:a=>t.get("/api/dashboard/calendar",{params:a}),project:(a,o)=>t.get("/api/dashboard/project/"+a,{params:o})};export{e as d};

View file

@ -1 +1 @@
import{E as s,B as I,q as o}from"./index-CMUSrGrd.js";const i={getIntegration:()=>s.get("/api/devops/integration"),saveIntegration:e=>s.put("/api/devops/integration",e),deleteIntegration:()=>s.delete("/api/devops/integration"),sync:()=>s.post("/api/devops/sync"),workItems:e=>s.get("/api/devops/work-items",{params:e?{state:e}:void 0})},m=I("devops",()=>{const e=o(null),l=o([]),r=o(!1),n=o(!1),c=o(null);async function u(){n.value=!0;try{const t=await i.getIntegration();e.value=t.data}catch{e.value=null}finally{n.value=!1}}async function d(t){const a=await i.saveIntegration(t);e.value=a.data}async function g(){await i.deleteIntegration(),e.value=null}async function f(){var t,a;r.value=!0,c.value=null;try{await i.sync(),await u()}catch(v){const p=v;throw c.value=((a=(t=p.response)==null?void 0:t.data)==null?void 0:a.detail)??p.message??"Sync failed",v}finally{r.value=!1}}async function y(t){n.value=!0;try{const a=await i.workItems(t);l.value=a.data}catch{l.value=[]}finally{n.value=!1}}return{integration:e,workItems:l,syncing:r,loading:n,error:c,fetchIntegration:u,saveIntegration:d,deleteIntegration:g,sync:f,fetchWorkItems:y}});export{m as u};
import{E as s,B as I,q as o}from"./index-BsVgmrYd.js";const i={getIntegration:()=>s.get("/api/devops/integration"),saveIntegration:e=>s.put("/api/devops/integration",e),deleteIntegration:()=>s.delete("/api/devops/integration"),sync:()=>s.post("/api/devops/sync"),workItems:e=>s.get("/api/devops/work-items",{params:e?{state:e}:void 0})},m=I("devops",()=>{const e=o(null),l=o([]),r=o(!1),n=o(!1),c=o(null);async function u(){n.value=!0;try{const t=await i.getIntegration();e.value=t.data}catch{e.value=null}finally{n.value=!1}}async function d(t){const a=await i.saveIntegration(t);e.value=a.data}async function g(){await i.deleteIntegration(),e.value=null}async function f(){var t,a;r.value=!0,c.value=null;try{await i.sync(),await u()}catch(v){const p=v;throw c.value=((a=(t=p.response)==null?void 0:t.data)==null?void 0:a.detail)??p.message??"Sync failed",v}finally{r.value=!1}}async function y(t){n.value=!0;try{const a=await i.workItems(t);l.value=a.data}catch{l.value=[]}finally{n.value=!1}}return{integration:e,workItems:l,syncing:r,loading:n,error:c,fetchIntegration:u,saveIntegration:d,deleteIntegration:g,sync:f,fetchWorkItems:y}});export{m as u};

File diff suppressed because one or more lines are too long

View file

@ -14,7 +14,7 @@
else { document.documentElement.classList.remove('dark'); }
})();
</script>
<script type="module" crossorigin src="/cc-dashboard/static/assets/index-CMUSrGrd.js"></script>
<script type="module" crossorigin src="/cc-dashboard/static/assets/index-BsVgmrYd.js"></script>
<link rel="stylesheet" crossorigin href="/cc-dashboard/static/assets/index-DopqRgoW.css">
</head>
<body>

View file

@ -54,7 +54,7 @@ const priorityColor = (p: number) => {
<p class="text-sm font-medium text-foreground leading-tight truncate">{{ task.title }}</p>
<!-- Tags -->
<div v-if="task.tags.length" class="flex items-center gap-1 mt-1 flex-wrap">
<div v-if="task.tags?.length" class="flex items-center gap-1 mt-1 flex-wrap">
<span
v-for="tag in task.tags"
:key="tag.id"

View file

@ -33,7 +33,7 @@ export interface Task {
project_id: string | null
azure_work_item_id: string | null
completed_at: string | null
tags: TagBrief[]
tags?: TagBrief[]
}
export interface TaskBlock {