1import{q as ae,bE as se,r,b as ne,z as ie,b5 as v,b6 as d,b7 as l,b9 as s,b8 as o,bd as b,a6 as h,bx as x,bw as g,bc as k,ac as u,bN as re,A as W,bb as de,aL as ue,ba as A,bA as ce,bB as be,b1 as I,bG as $,c1 as B,bO as z,N as i,aZ as y}from"./index-CqTW0gwL.js";import{Q as P}from"./QTooltip-Bz8A02FK.js";import{Q as V}from"./QTd-D5YMrnCH.js";import{Q as R}from"./QBadge-CKyhOArA.js";import{Q as q,a as m}from"./QItem-Bw3I2yZn.js";import{Q as me}from"./QList-BIXPUMZF.js";import{Q as fe}from"./QMenu-C-0zhI_p.js";import{Q as pe}from"./QTable-D4kQbvZw.js";import{Q as ve}from"./QSelect-DsDrwj5i.js";import{Q as he,F as ge}from"./FormValidationSummary-BEfbttYj.js";import{Q as ke}from"./QPage-D-M_E9XA.js";import{C as D}from"./ClosePopup-DlNqzSYr.js";import{c as ye}from"./copy-to-clipboard-Dvkf0R0k.js";import{_ as we}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./position-engine-DctTkrBz.js";import"./selection-B-35Dxh9.js";import"./QMarkupTable-DUBLwfXu.js";import"./QLinearProgress-BZebGzyV.js";import"./QChip-Bt5HE8Pr.js";import"./QItemLabel-CfKeiCWi.js";import"./format-DyQxkAtJ.js";const We={class:"q-pa-md"},De={class:"page-header q-mb-lg"},_e={class:"text-h4 q-mt-none q-mb-sm"},Ce={class:"row items-center q-gutter-md"},xe={class:"col"},Ve={class:"text-body2"},Qe={class:"row q-col-gutter-md items-center"},Ue={class:"col-12 col-md-auto q-ml-auto"},qe={class:"text-h6 q-mb-md"},Ee={class:"text-weight-bold"},Se={class:"text-caption te-text-secondary"},Fe={key:1,class:"text-caption te-text-secondary"},Ne={key:1,class:"text-caption te-text-secondary"},Ae={class:"full-width text-center q-pa-lg"},Re={class:"text-h6"},Le={class:"text-body1"},G="https://us-central1-tradersedge-e708d.cloudfunctions.net/tradingViewWebhook",Me=ae({__name:"DiscordWebhooksPage",setup(Te){const f=se(),Q=r(!1),E=r(!1),S=r(!1),F=r(null),p=r([]),_=r(!1),C=r(null),U=r(!1),w=r(null),n=r({name:"",webhookUrl:"",symbols:[],isDefault:!1,enabled:!0}),L=r(!1),O=ne(()=>{const a=[];return n.value.name||a.push("Channel Name"),(!n.value.webhookUrl||!n.value.webhookUrl.startsWith("https://discord.com/api/webhooks/"))&&a.push("Discord Webhook URL"),a}),Y=a=>{L.value=!0;const e=a?.$el;e&&typeof e.scrollIntoView=="function"&&e.scrollIntoView({behavior:"smooth",block:"center"})},Z=["MNQ","MES","NQ","ES","RTY","YM","CL","GC"],j=[{name:"name",label:"Channel",field:"name",align:"left",sortable:!0},{name:"symbols",label:"Symbols",field:"symbols",align:"left"},{name:"default",label:"Default",field:"isDefault",align:"center"},{name:"status",label:"Status",field:"enabled",align:"center",sortable:!0},{name:"actions",label:"Actions",field:"actions",align:"center"}],H=async()=>{await ye(G),i.create({type:"positive",message:"Webhook URL copied to clipboard",position:"top"})},N=async()=>{Q.value=!0;try{const e=await y(f,"getDiscordWebhooks")();p.value=e.data}catch(a){console.error("Error loading webhooks:",a),i.create({type:"negative",message:"Failed to load webhooks",position:"top"})}finally{Q.value=!1}},M=()=>{C.value=null,n.value={name:"",webhookUrl:"",symbols:[],isDefault:p.value.length===0,enabled:!0},_.value=!0},J=a=>{C.value=a,n.value={name:a.name,webhookUrl:a.webhookUrl,symbols:[...a.symbols],isDefault:a.isDefault,enabled:a.enabled},_.value=!0},K=(a,e)=>{e(a.toUpperCase(),"add-unique")},T=async()=>{if(!(!n.value.name||!n.value.webhookUrl)){E.value=!0;try{C.value?(await y(f,"updateDiscordWebhook")({id:C.value.id,...n.value}),i.create({type:"positive",message:"Webhook updated successfully",position:"top"})):(await y(f,"createDiscordWebhook")(n.value),i.create({type:"positive",message:"Webhook created successfully",position:"top"})),_.value=!1,await N()}catch(a){console.error("Error saving webhook:",a);const e=a instanceof Error?a.message:"Failed to save webhook";i.create({type:"negative",message:e,position:"top"})}finally{E.value=!1}}},X=async a=>{try{await y(f,"updateDiscordWebhook")({id:a.id,enabled:!a.enabled}),a.enabled=!a.enabled,i.create({type:"positive",message:`Webhook ${a.enabled?"enabled":"disabled"} successfully`,position:"top"})}catch(e){console.error("Error updating webhook:",e),i.create({type:"negative",message:"Failed to update webhook",position:"top"})}},ee=async a=>{try{await y(f,"updateDiscordWebhook")({id:a.id,isDefault:!0}),p.value.forEach(t=>{t.isDefault=t.id===a.id}),i.create({type:"positive",message:`${a.name} is now the default webhook`,position:"top"})}catch(e){console.error("Error setting default webhook:",e),i.create({type:"negative",message:"Failed to set default webhook",position:"top"})}},oe=async a=>{F.value=a.id;try{const c=(await y(f,"testDiscordWebhook")({webhookUrl:a.webhookUrl})).data;i.create({type:"positive",message:c.message,position:"top"})}catch(e){console.error("Error testing webhook:",e);const t=e instanceof Error?e.message:"Failed to send test message";i.create({type:"negative",message:t,position:"top"})}finally{F.value=null}},te=a=>{w.value=a,U.value=!0},le=async()=>
1{if(w.value){S.value=!0;try{await y(f,"deleteDiscordWebhook")({id:w.value.id}),p.value=p.value.filter(e=>e.id!==w.value.id),i.create({type:"positive",message:"Webhook deleted successfully",position:"top"}),U.value=!1,w.value=null}catch(a){console.error("Error deleting webhook:",a),i.create({type:"negative",message:"Failed to delete webhook",position:"top"})}finally{S.value=!1}}};return ie(()=>{N()}),(a,e)=>(d(),v(ke,{class:"discord-webhooks-page"},{default:l(()=>[s("div",We,[s("div",De,[s("h4",_e,[o(h,{name:"webhook",color:"primary",size:"md",class:"q-mr-sm"}),e[8]||(e[8]=b(" Discord Webhooks ",-1))]),e[9]||(e[9]=s("p",{class:"text-subtitle1 te-text-secondary"}," Configure Discord webhooks for TradingView alerts ",-1))]),o(x,{class:"te-card q-mb-md"},{default:l(()=>[o(g,null,{default:l(()=>[s("div",Ce,[o(h,{name:"info",color:"primary",size:"sm"}),s("div",xe,[s("div",Ve,[e[11]||(e[11]=s("strong",null,"TradingView Webhook URL:",-1)),s("code",{class:"q-ml-sm"},k(G)),o(u,{flat:"",dense:"",round:"",icon:"content_copy",size:"sm",onClick:H},{default:l(()=>[o(P,null,{default:l(()=>[...e[10]||(e[10]=[b("Copy URL",-1)])]),_:1})]),_:1})]),e[12]||(e[12]=s("div",{class:"text-caption te-text-secondary q-mt-xs"}," Use this URL in your TradingView alert webhook settings. Alerts will be routed to Discord based on the symbol in the message. ",-1))])])]),_:1})]),_:1}),o(x,{class:"te-card q-mb-md"},{default:l(()=>[o(g,null,{default:l(()=>[s("div",Qe,[s("div",Ue,[o(u,{outline:"",color:"primary",label:"Refresh",icon:"refresh",class:"q-mr-sm",onClick:N,loading:Q.value},null,8,["loading"]),o(u,{color:"primary",label:"Add Webhook",icon:"add",onClick:M})])])]),_:1})]),_:1}),o(x,{class:"te-card"},{default:l(()=>[o(g,null,{default:l(()=>[s("div",qe," Configured Webhooks ("+k(p.value.length)+") ",1),o(pe,{rows:p.value,columns:j,"row-key":"id",loading:Q.value,flat:""},{"body-cell-name":l(t=>[o(V,{props:t},{default:l(()=>[s("div",Ee,k(t.row.name),1),s("div",Se,k(t.row.webhookUrl.substring(0,50))+"... ",1)]),_:2},1032,["props"])]),"body-cell-symbols":l(t=>[o(V,{props:t},{default:l(()=>[t.row.symbols.length>0?(d(!0),A(ce,{key:0},be(t.row.symbols,c=>(d(),v(R,{key:c,color:"primary",label:c,class:"q-mr-xs"},null,8,["label"]))),128)):(d(),A("span",Fe," No specific symbols "))]),_:2},1032,["props"])]),"body-cell-default":l(t=>[o(V,{props:t},{default:l(()=>[t.row.isDefault?(d(),v(R,{key:0,color:"orange",label:"Default"})):(d(),A("span",Ne,"-"))]),_:2},1032,["props"])]),"body-cell-status":l(t=>[o(V,{props:t},{default:l(()=>[o(R,{color:t.row.enabled?"positive":"grey-6",label:t.row.enabled?"Enabled":"Disabled"},null,8,["color","label"])]),_:2},1032,["props"])]),"body-cell-actions":l(t=>[o(V,{props:t},{default:l(()=>[o(u,{flat:"",dense:"",round:"",icon:"send",color:"primary",onClick:c=>oe(t.row),loading:F.value===t.row.id},{default:l(()=>[o(P,null,{default:l(()=>[...e[13]||(e[13]=[b("Send Test Message",-1)])]),_:1})]),_:1},8,["onClick","loading"]),o(u,{flat:"",dense:"",round:"",icon:"more_vert",onClick:e[0]||(e[0]=re(()=>{},["stop"]))},{default:l(()=>[o(fe,null,{default:l(()=>[o(me,{dense:""},{default:l(()=>[W((d(),v(q,{clickable:"",onClick:c=>J(t.row)},{default:l(()=>[o(m,{avatar:""},{default:l(()=>[o(h,{name:"edit",color:"primary"})]),_:1}),o(m,null,{default:l(()=>[...e[14]||(e[14]=[b("Edit",-1)])]),_:1})]),_:1},8,["onClick"])),[[D]]),W((d(),v(q,{clickable:"",onClick:c=>X(t.row)},{default:l(()=>[o(m,{avatar:""},{default:l(()=>[o(h,{name:t.row.enabled?"block":"check_circle",color:t.row.enabled?"warning":"positive"},null,8,["name","color"])]),_:2},1024),o(m,null,{default:l(()=>[b(k(t.row.enabled?"Disable":"Enable"),1)]),_:2},1024)]),_:2},1032,["onClick"])),[[D]]),t.row.isDefault?de("",!0):W((d(),v(q,{key:0,clickable:"",onClick:c=>ee(t.row)},{default:l(()=>[o(m,{avatar:""},{default:l(()=>[o(h,{name:"star",color:"orange"})]),_:1}),o(m,null,{default:l(()=>[...e[15]||(e[15]=[b("Set as Default",-1)])]),_:1})]),_:1},8,["onClick"])),[[D]]),o(ue),W((d(),v(q,{clickable:"",onClick:c=>te(t.row)},{default:l(()=>[o(m,{avatar:""},{default:l(()=>[o(h,{name:"delete",color:"negative"})]),_:1}),o(m,{class:"text-negative"},{default:l(()=>[...e[16]||(e[16]=[b("Delete",-1)])]),_:1})]),_:1},8,["onClick"])),[[D]])]),_:2},1024)]),_:2},1024)]),_:2},1024)]),_:2},1032,["props"])]),"no-data":l(()=>[s("div",Ae,[o(h,{name:"webhook",size:"48px",color:"grey-5"}),e[17]||(e[17]=s("div",{class:"text-body1 q-mt-md"},"No webhooks configured",-1)),e[18]||(e[18]=s("div",{class:"text-caption te-text-secondary q-mb-md"}," Add a Discord webhook to start receiving TradingView alerts ",-1)),o(u,{color:"primary",label:"Add First Webhook",icon:"add",onClick:M})])]),_:1},8,["rows","loading"])]),_:1})]),_:1})]),o(I,{modelValue:_.value,"onUpdate:modelValue":e[6]||(e[6]=t=>_.value=t),persistent:""},{default:l(()=>[o(x,{class:"te-card",style:{"min-width":"500px","max-width":"600px"}},{default:l(()=>[o(g,null,{default:l(()=>[s("div",Re,k(C.value?"Edit":"Add")+" Discord Webhook",1)]),_:1}),o(g,{class:"q-pt-none"},{default:l(()=>[o(he,{greedy:"",class:"q-gutter-md",onSubmit:T,onValidationError:Y},{default:l(()=>[o($,{modelValue:n.value.name,"onUpdate:modelValue":e[1]||(e[1]=t=>n.value.name=t),label:"Channel Name *",hint:"e.g., MNQ-alerts, MES-alerts, general-alerts",outlined:"",dense:"",rules:[t=>!!t||"Name is required"]},null,8,["modelValue","rules"]),o($,{modelValue:n.value.webhookUrl,"onUpdate:modelValue":e[2]||(e[2]=t=>n.value.webhookUrl=t),label:"Discord Webhook URL *",hint:"Right-click channel > Edit Channel > Integrations > Webhooks",outlined:"",dense:"",type:"url",rules:[t=>!!t||"Webhook URL is required",t=>t.startsWith("https://discord.com/api/webhooks/")||"Must be a valid Discord webhook URL"]},null,8,["modelValue","rules"]),o(ve,{modelValue:n.value.symbols,"onUpdate:modelValue":e[3]||(e[3]=t=>n.value.symbols=t),label:"Route Symbols",hint:"Alerts containing these symbols will route to this channel",outlined:"",dense:"",multiple:"","use-chips":"","use-input":"","new-value-mode":"add-unique",options:Z,onNewValue:K},null,8,["modelValue"]),o(B,{modelValue:n.value.isDefault,"onUpdate:modelValue":e[4]||(e[4]=t=>n.value.isDefault=t),label:"Default webhook (receives alerts that don't match other channels)"},null,8,["modelValue"]),o(B,{modelValue:n.value.enabled,"onUpdate:modelValue":e[5]||(e[5]=t=>n.value.enabled=t),label:"Enabled"},null,8,["modelValue"]),o(ge,{fields:O.value,show:L.value},null,8,["fields","show"])]),_:1})]),_:1}),o(z,{align:"right"},{default:l(()=>[W(o(u,{flat:"",label:"Cancel"},null,512),[[D]]),o(u,{label:"Save",color:"primary",onClick:T,loading:E.value},null,8,["loading"])]),_:1})]),_:1})]),_:1},8,["modelValue"]),o(I,{modelValue:U.value,"onUpdate:modelValue":e[7]||
1(e[7]=t=>U.value=t)},{default:l(()=>[o(x,{class:"te-card",style:{"min-width":"400px"}},{default:l(()=>[o(g,null,{default:l(()=>[...e[19]||(e[19]=[s("div",{class:"text-h6"},"Delete Webhook",-1)])]),_:1}),o(g,null,{default:l(()=>[s("p",Le,[e[20]||(e[20]=b(" Are you sure you want to delete ",-1)),s("strong",null,k(w.value?.name),1),e[21]||(e[21]=b("? ",-1))]),e[22]||(e[22]=s("p",{class:"text-body2 te-text-secondary"}," Alerts that were routed to this channel will fall back to the default webhook. ",-1))]),_:1}),o(z,{align:"right"},{default:l(()=>[W(o(u,{flat:"",label:"Cancel"},null,512),[[D]]),o(u,{label:"Delete",color:"negative",onClick:le,loading:S.value},null,8,["loading"])]),_:1})]),_:1})]),_:1},8,["modelValue"])]),_:1}))}}),io=we(Me,[["__scopeId","data-v-327207b5"]]);export{io 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.