directus-extension-sql-query-panel 1.0.5 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +1 -1
- package/package.json +2 -1
package/dist/app.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{useApi as e,useStores as t,definePanel as n}from"@directus/extensions-sdk";import{ref as a,computed as o,resolveComponent as r,resolveDirective as l,openBlock as i,createElementBlock as s,createElementVNode as u,normalizeClass as c,createVNode as d,withCtx as f,createCommentVNode as v,Fragment as m,renderList as p,normalizeStyle as h,createTextVNode as b,toDisplayString as y,createBlock as g,unref as w,renderSlot as k,withModifiers as x,withDirectives as _,toRefs as S,nextTick as q,watch as j,createSlots as A}from"vue";import{useRouter as C}from"vue-router";import{useI18n as $}from"vue-i18n";var E="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function L(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var O=NaN,D="[object Symbol]",T=/^\s+|\s+$/g,N=/^[-+]0x[0-9a-f]+$/i,I=/^0b[01]+$/i,B=/^0o[0-7]+$/i,W=parseInt,M="object"==typeof E&&E&&E.Object===Object&&E,U="object"==typeof self&&self&&self.Object===Object&&self,H=M||U||Function("return this")(),R=Object.prototype.toString,F=Math.max,Q=Math.min,V=function(){return H.Date.now()};function z(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function P(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&R.call(e)==D}(e))return O;if(z(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=z(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(T,"");var n=I.test(e);return n||B.test(e)?W(e.slice(2),n?2:8):N.test(e)?O:+e}var Y=L((function(e,t,n){var a,o,r,l,i,s,u=0,c=!1,d=!1,f=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function v(t){var n=a,r=o;return a=o=void 0,u=t,l=e.apply(r,n)}function m(e){var n=e-s;return void 0===s||n>=t||n<0||d&&e-u>=r}function p(){var e=V();if(m(e))return h(e);i=setTimeout(p,function(e){var n=t-(e-s);return d?Q(n,r-(e-u)):n}(e))}function h(e){return i=void 0,f&&a?v(e):(a=o=void 0,l)}function b(){var e=V(),n=m(e);if(a=arguments,o=this,s=e,n){if(void 0===i)return function(e){return u=e,i=setTimeout(p,t),c?v(e):l}(s);if(d)return i=setTimeout(p,t),v(s)}return void 0===i&&(i=setTimeout(p,t)),l}return t=P(t)||0,z(n)&&(c=!!n.leading,r=(d="maxWait"in n)?F(P(n.maxWait)||0,t):r,f="trailing"in n?!!n.trailing:f),b.cancel=function(){void 0!==i&&clearTimeout(i),u=0,a=s=o=i=void 0},b.flush=function(){return void 0===i?l:h(V())},b}));const Z={sum:"Σ",avg:"μ",count:"#",count_unique:"#!"},G={sum:(e,t)=>e.reduce(((e,n)=>e+Number.parseInt(n[t])),0),avg:(e,t)=>Math.round(G.sum(e,t)/e.length),count:e=>e.length,count_unique:(e,t)=>new Set(e.map((e=>e[t]))).size,count_groups:(e,t)=>e.reduce(((e,n)=>{const a=n[t];return e[a]=(e[a]||0)+1,e}),{})};var J=[],K=[];function X(e,t){if(e&&"undefined"!=typeof document){var n,a=!0===t.prepend?"prepend":"append",o=!0===t.singleTag,r="string"==typeof t.container?document.querySelector(t.container):document.getElementsByTagName("head")[0];if(o){var l=J.indexOf(r);-1===l&&(l=J.push(r)-1,K[l]={}),n=K[l]&&K[l][a]?K[l][a]:K[l][a]=i()}else n=i();65279===e.charCodeAt(0)&&(e=e.substring(1)),n.styleSheet?n.styleSheet.cssText+=e:n.appendChild(document.createTextNode(e))}function i(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),t.attributes)for(var n=Object.keys(t.attributes),o=0;o<n.length;o++)e.setAttribute(n[o],t.attributes[n[o]]);var l="prepend"===a?"afterbegin":"beforeend";return r.insertAdjacentElement(l,e),e}}X("\nbody {\n --v-table-color: var(--v-input-color);\n --v-table-background-color: var(--v-input-background-color);\n}\n.fast-table[data-v-575199b6] {\n position: relative;\n height: var(--v-table-height);\n overflow-y: auto;\n}\ntable[data-v-575199b6] {\n min-width: 100%;\n min-height: 100%;\n border-collapse: collapse;\n border-spacing: 0;\n background-color: var(--v-table-background-color);\n color: var(--v-table-color);\n}\ntable thead[data-v-575199b6] {\n background-color: var(--background-normal);\n color: var(--foreground-normal);\n border-bottom: var(--border-width) solid var(--v-input-border-color);\n}\ntable thead.fixed[data-v-575199b6] {\n position: sticky;\n top: 0;\n z-index: 3;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);\n}\ntable tr.headers th[data-v-575199b6] {\n padding: 8px;\n font-weight: bold;\n min-width: 3rem;\n background-color: var(--background-normal);\n color: var(--foreground-normal);\n border-bottom: var(--border-width) solid var(--v-input-border-color);\n}\ntable tr.search th[data-v-575199b6] {\n padding: 0;\n}\ntable tr.search th .search-input.v-input[data-v-575199b6] {\n margin: 0;\n border: none;\n}\ntable th .sort-icon[data-v-575199b6] {\n opacity: 0;\n}\ntable th:hover .sort-icon[data-v-575199b6] {\n opacity: 0.5;\n}\ntable th .sort-icon.show[data-v-575199b6] {\n opacity: 1;\n}\ntable th.select[data-v-575199b6] {\n width: 2rem;\n}\ntable td[data-v-575199b6] {\n padding: 8px;\n align: middle;\n border-bottom: var(--border-width) solid var(--v-input-border-color);\n}\ntable tbody[data-v-575199b6] {\n display: contents;\n}\ntable tfoot tr[data-v-575199b6] {\n position: sticky;\n bottom: 0;\n background-color: var(--background-normal);\n box-shadow: var(--card-shadow);\n}\ntable tfoot tr td[data-v-575199b6] {\n padding: 8px;\n height: 44px;\n font-weight: bold;\n background-color: var(--background-normal);\n color: var(--foreground-normal);\n}\n",{});var ee=(e,t)=>{const n=e.__vccOpts||e;for(const[e,a]of t)n[e]=a;return n};const te={class:"fast-table"},ne={key:0,class:"search"},ae={colspan:"80%"},oe={class:"headers"},re=["onClick","align"],le={key:0},ie={key:1},se=["colspan"],ue={key:0},ce={colspan:"100%"},de={key:1},fe=["onClick"],ve={key:0},me={key:0,class:"v-text-overflow"},pe={__name:"FastTable",props:{loading:Boolean,headers:{type:Array,validator:e=>e.every((e=>e.value&&e.text)),required:!0},items:{type:Array,required:!0},sort:String,sortDesc:Boolean,fixedHeader:Boolean},emits:["update:sort","update:sortDesc","click:row"],setup(e,{emit:t}){const{t:n}=$(),S=e,q=a(""),j=o((()=>S.headers.filter((e=>e.searchable)))),A=o((()=>{const e=q.value?q.value.toLowerCase().trim():"";return e?S.items.filter((t=>j.value.some((n=>t[n.value]&&t[n.value].toLowerCase().includes(e))))):S.items})),C=o((()=>{const e=function(e,t){if(!t.some((e=>!!e.summarise)))return null;const n={};for(const a of t){if(!a.summarise)continue;const t=G[a.summarise];if(!t)throw new Error(`Summariser function for ${a.summarise} not found.`);const o=t(e,a.value);if("count_groups"===a.summarise){let e=JSON.stringify(o,null,1).replace("{\n","").replace("\n}","").replace(/[",]/g,"");n[a.value]=e}else n[a.value]=`${Z[a.summarise]} ${o}`}return n}(A.value,S.headers);return e})),E=t;return(t,a)=>{const o=r("v-icon"),$=r("v-input"),L=r("v-progress-linear"),O=r("v-card-title"),D=r("v-card"),T=l("tooltip");return i(),s("div",te,[u("table",null,[u("thead",{class:c(["table-header",{fixed:e.fixedHeader}])},[j.value.length&&e.items.length>10?(i(),s("tr",ne,[u("th",ae,[d($,{modelValue:q.value,"onUpdate:modelValue":a[0]||(a[0]=e=>q.value=e),small:"",trim:"",class:"search-input",rounded:"",placeholder:"Search"},{prepend:f((()=>[d(o,{name:"search"})])),_:1},8,["modelValue"])])])):v("v-if",!0),u("tr",oe,[(i(!0),s(m,null,p(e.headers,(n=>(i(),s("th",{style:h({minWidth:`${n.width||t.auto}ch`}),key:n.value,onClick:e=>function(e){e.sortable&&(E("update:sort",e.value),E("update:sortDesc",!S.sortDesc))}(n),align:n.align||"left"},[b(y(n.text)+" ",1),n.sortable?(i(),g(o,{key:0,name:"sort",small:"",class:c(["sort-icon",{show:e.sort===n.value}]),style:h(`transform: ${e.sortDesc?"rotateZ(0deg) rotateY(0deg)":"rotateZ(180deg) rotateY(180deg)"}; transition: .2s all ease`)},null,8,["class","style"])):v("v-if",!0)],12,re)))),128)),t.$slots["item-append"]?(i(),s("th",le,"#")):v("v-if",!0)]),e.loading?(i(),s("tr",ie,[u("td",{colspan:e.headers.length+1},[d(L,{indeterminate:""})],8,se)])):v("v-if",!0)],2),e.loading||e.items.length?(i(),s("tbody",de,[k(t.$slots,"default",{items:A.value},(()=>[(i(!0),s(m,null,p(A.value,(n=>(i(),s("tr",{onClick:e=>E("click:row",{item:n,event:e})},[(i(!0),s(m,null,p(e.headers,(e=>(i(),s("td",{key:e.value,class:c(`align-${e.align}`)},y(n[e.value]),3)))),128)),t.$slots["item-append"]?(i(),s("td",{key:0,onClick:a[1]||(a[1]=x((()=>{}),["stop"]))},[k(t.$slots,"item-append",{item:n},void 0,!0)])):v("v-if",!0)],8,fe)))),256))]),!0)])):(i(),s("tbody",ue,[u("tr",null,[u("td",ce,[d(D,{style:{padding:"2rem","--v-card-max-width":"100%"}},{default:f((()=>[d(O,null,{default:f((()=>[d(o,{name:"info",style:{"margin-right":"2rem"}}),b(" "+y(w(n)("no_items")),1)])),_:1})])),_:1})])])])),u("tfoot",null,[C.value?(i(),s("tr",ve,[(i(!0),s(m,null,p(e.headers,(e=>_((i(),s("td",{key:e.value},[C.value[e.value]?(i(),s("code",me,y(C.value[e.value]),1)):v("v-if",!0)])),[[T,e.summarise]]))),128))])):v("v-if",!0)])])])}}};var he=ee(pe,[["__scopeId","data-v-575199b6"],["__file","FastTable.vue"]]);X("\n.sql-panel-container {\n width: 100%;\n height: 100%;\n --v-table-height: 100%;\n}\n.sql-panel-container .v-text-overflow {\n user-select: text;\n white-space: pre-wrap;\n}\n.sql-panel-container .center {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n.export-csv-button {\n position: absolute;\n right: 0;\n bottom: 0;\n z-index: 2;\n opacity: 0.8;\n}\n.export-csv-button .button {\n border-radius: var(--border-radius) 0 0 0 !important;\n}\n",{});const be={key:0,class:"center"},ye={key:0},ge={__name:"panel",props:{id:String,showHeader:{type:Boolean,default:!1},columns:Array,download:{type:Boolean,default:!0},is_static:{type:Boolean,default:!1},actions:Array},setup(n){const u=C(),h=n,{id:k,showHeader:x,download:$,is_static:E}=S(h),L=a(!1),O=a(""),D=a(""),T=a(null),N=a(null),I=e(),{useInsightsStore:B}=t(),W=B(),M=a(new Set),U=o((()=>{const e={},t=[];return M.value.forEach((n=>{void 0===W.variables[n]||null===W.variables[n]?t.push(n):e[n]=W.variables[n]})),t.length?t:e}));if(E.value)q(Q);else{const e=Y(Q,1e3);j(U,(()=>{Array.isArray(U.value)?D.value=`Please specify: ${U.value.join(" & ")}`:(D.value="",N.value||(L.value=!0),e())}),{immediate:!0})}const H=o((()=>h.columns?.length>0?h.columns.map((e=>({...e,text:e.text||e.value}))):T.value)),R=a({by:null,desc:!1});let F;async function Q(){if(!Array.isArray(U.value)){L.value=!0,O.value="",T.value=null,N.value=null;try{const e={};F=e;const{data:t}=await I.get(`insights/query/${k.value}`,{params:U.value});if(F!==e)return;if(t.error&&(O.value=t.error),t.headers&&t.items){const e=t.items.length>2;T.value=t.headers.map((function(t,n){const a=t.replace(/_/g," ").replace(/(?:^|\s)\S/g,(function(e){return e.toUpperCase()}));return{text:a,value:t,width:a.length+1,sortable:e}}));const n=h.columns&&h.columns.filter((e=>e.isNumber));N.value=n?t.items.map((e=>(n.forEach((t=>{e[t.value]=""!==e[t.value]?1*e[t.value]:null})),e))):t.items}}catch(e){const t=e.response?.data?.error||e.message;t.includes("Missing query param")?(D.value=t.replace("Missing query param","Please specify"),t.split(": ")[1].split(", ").forEach((e=>M.value.add(e)))):O.value=t}L.value=!1}}function V(){if(H.value&&N.value){let e=Object.values(H.value).map((e=>e.text)).join(",");e+="\r\n",e+=function(){let e="";return N.value.forEach((t=>{for(let n in t)/[, ]/.test(t[n])?e+=`"${t[n].replace(/"/g,'\\"')}",`:e+=t[n]+",";e+="\r\n"})),e}();const t=(new Date).toISOString()+".csv"||"export.csv",n=new Blob([e],{type:"text/csv;charset=utf-8;"});if(navigator.msSaveBlob)navigator.msSaveBlob(n,t);else{const e=document.createElement("a");if(void 0!==e.download){const a=URL.createObjectURL(n);e.setAttribute("href",a),e.setAttribute("download",t),e.style.visibility="hidden",document.body.appendChild(e),e.click(),document.body.removeChild(e)}}}}function z(e,t){let n=e;for(let e in t)n=n.replace(new RegExp(`%${e}%`,"g"),t[e]);return n}function P({item:e}){const t=h.actions?.find((e=>e.row));t&&u.push(z(t.link,e))}return j(R,(({by:e,desc:t})=>{e&&(N.value=N.value.sort(((n,a)=>n[e]<a[e]?t?1:-1:n[e]>a[e]?t?-1:1:0)))}),{deep:!0}),(e,t)=>{const a=r("v-progress-circular"),o=r("v-notice"),u=r("v-icon"),h=r("v-button"),k=l("tooltip");return i(),s("div",{class:c(["sql-panel-container",{"has-header":w(x)}])},[L.value||O.value||D.value?(i(),s("div",be,[L.value?(i(),g(a,{key:0,indeterminate:""})):D.value?(i(),g(o,{key:1,type:"info",center:""},{default:f((()=>[b(y(D.value),1)])),_:1})):(i(),g(o,{key:2,type:"danger",center:""},{default:f((()=>[b(y(O.value),1)])),_:1}))])):H.value&&N.value?(i(),s(m,{key:1},[w($)?(i(),g(h,{key:0,onClick:V,icon:"",secondary:"",class:"export-csv-button"},{default:f((()=>[d(u,{name:"download-file"})])),_:1})):v("v-if",!0),d(he,{headers:H.value,items:N.value,"onClick:row":P,sort:R.value.by,"onUpdate:sort":t[0]||(t[0]=e=>R.value.by=e),sortDesc:R.value.desc,"onUpdate:sortDesc":t[1]||(t[1]=e=>R.value.desc=e),"fixed-header":""},A({_:2},[n.actions?.find((e=>!e.row))?{name:"item-append",fn:f((({item:e})=>[(i(!0),s(m,null,p(n.actions.filter((e=>!e.row)),(t=>_((i(),g(h,{outlined:"",to:z(t.link,e),icon:!t.show_label,"x-small":""},{default:f((()=>[d(u,{name:t.icon},null,8,["name"]),t.show_label?(i(),s("span",ye,y(t.label),1)):v("v-if",!0)])),_:2},1032,["to","icon"])),[[k,t.label]]))),256))])),key:"0"}:void 0]),1032,["headers","items","sort","sortDesc"])],64)):v("v-if",!0)],2)}}};const we=[],ke=[],xe=[],_e=[],Se=[n({id:"sql-query",name:"SQL Query panel",icon:"view_list",description:"Show result of a stored SQL query as a table",component:ee(ge,[["__file","panel.vue"]]),options:[{field:"sql",name:"SQL query",type:"string",meta:{note:"Supports variables in the format of {{variable_name}}. Don't quote string variables. Example: SELECT * FROM tasks WHERE list = {{list}} AND status IN ({{status}})",interface:"input-code",width:"full",options:{language:"sql"}}},{field:"columns",name:"Columns",type:"json",special:"cast-json",meta:{width:"full",interface:"list",options:{addLabel:"Add column",label:"{{name}} - {{width}}",fields:[{field:"value",name:"Column Name",type:"string",note:"As returned by query",meta:{required:!0,width:"half",interface:"input",options:{trim:!0,softLength:100}}},{field:"text",name:"Label",type:"string",note:"What to display in the column header (Default is same as name)",meta:{width:"half",interface:"input",options:{trim:!0,softLength:100}}},{field:"width",name:"Width",type:"integer",meta:{required:!0,width:"half",interface:"input",options:{min:1,max:300},note:"Width of the column in ch (character width). Default is 10."},schema:{default_value:10}},{field:"isNumber",name:"Is Numberic",type:"boolean",meta:{width:"half",interface:"boolean"}},{field:"sortable",name:"Sortable",type:"boolean",meta:{width:"half",interface:"boolean"}},{field:"searchable",name:"Searchable",type:"boolean",meta:{width:"half",interface:"boolean"}},{field:"summarise",name:"Summarise",type:"string",meta:{width:"half",interface:"select-dropdown",options:{choices:[{text:"Sum",value:"sum"},{text:"Average",value:"avg"},{text:"Count",value:"count"},{text:"Count Unique",value:"count_unique"},{text:"Count Groups",value:"count_groups"}]}}}]}}},{field:"actions",name:"Actions",type:"json",special:"cast-json",meta:{width:"full",interface:"list",options:{addLabel:"Add action",label:"{{{label}}",fields:[{field:"label",name:"Label",type:"string",meta:{required:!0,width:"half",interface:"input",options:{trim:!0,softLength:50}}},{field:"link",name:"Link",type:"string",meta:{required:!0,note:"Variables per row can be inserted as such %column_name%",width:"half",interface:"input",options:{trim:!0}}},{field:"row",name:"Activate on row click",type:"boolean",meta:{note:"If you don't want to show the action button, but want to activate the link on row click, check this box.",width:"full",interface:"boolean"}},{field:"icon",name:"Icon",type:"string",meta:{note:"Leave blank to not show an icon",width:"half",interface:"select-icon"}},{field:"show_label",name:"Show label",type:"boolean",meta:{width:"half",interface:"boolean"}}]}}},{field:"download",name:"Download button",type:"boolean",meta:{width:"half",interface:"boolean",options:{label:"Show"}},schema:{default_value:!0}},{field:"is_static",name:"Is static",type:"boolean",meta:{width:"half",interface:"boolean",options:{label:"Yes"},note:"If the result will not be affect when variables are changed, you can check this box to improve performance."},schema:{default_value:!1}},{field:"cache",name:"Cache Response",type:"integer",meta:{width:"half",interface:"input",options:{min:10,max:3600},note:"Tells the browser how long to cache results for. Default is 30 seconds."},schema:{default_value:300}}],minWidth:10,minHeight:10})],qe=[];export{ke as displays,we as interfaces,xe as layouts,_e as modules,qe as operations,Se as panels};
|
|
1
|
+
import{useApi as e,useStores as t,definePanel as a}from"@directus/extensions-sdk";import{ref as n,computed as o,resolveComponent as r,resolveDirective as l,openBlock as i,createElementBlock as s,createElementVNode as c,normalizeClass as u,createVNode as d,withCtx as f,createCommentVNode as v,Fragment as m,renderList as p,normalizeStyle as h,createTextVNode as b,toDisplayString as g,createBlock as y,unref as w,renderSlot as k,withModifiers as x,withDirectives as _,pushScopeId as q,popScopeId as S,toRefs as j,nextTick as A,watch as C,createSlots as $}from"vue";import{useRouter as E}from"vue-router";import{useI18n as L}from"vue-i18n";var O="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function T(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var D=NaN,N="[object Symbol]",I=/^\s+|\s+$/g,B=/^[-+]0x[0-9a-f]+$/i,W=/^0b[01]+$/i,M=/^0o[0-7]+$/i,U=parseInt,H="object"==typeof O&&O&&O.Object===Object&&O,R="object"==typeof self&&self&&self.Object===Object&&self,F=H||R||Function("return this")(),Q=Object.prototype.toString,V=Math.max,z=Math.min,P=function(){return F.Date.now()};function Y(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function Z(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&Q.call(e)==N}(e))return D;if(Y(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Y(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(I,"");var a=W.test(e);return a||M.test(e)?U(e.slice(2),a?2:8):B.test(e)?D:+e}var G=T((function(e,t,a){var n,o,r,l,i,s,c=0,u=!1,d=!1,f=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function v(t){var a=n,r=o;return n=o=void 0,c=t,l=e.apply(r,a)}function m(e){var a=e-s;return void 0===s||a>=t||a<0||d&&e-c>=r}function p(){var e=P();if(m(e))return h(e);i=setTimeout(p,function(e){var a=t-(e-s);return d?z(a,r-(e-c)):a}(e))}function h(e){return i=void 0,f&&n?v(e):(n=o=void 0,l)}function b(){var e=P(),a=m(e);if(n=arguments,o=this,s=e,a){if(void 0===i)return function(e){return c=e,i=setTimeout(p,t),u?v(e):l}(s);if(d)return i=setTimeout(p,t),v(s)}return void 0===i&&(i=setTimeout(p,t)),l}return t=Z(t)||0,Y(a)&&(u=!!a.leading,r=(d="maxWait"in a)?V(Z(a.maxWait)||0,t):r,f="trailing"in a?!!a.trailing:f),b.cancel=function(){void 0!==i&&clearTimeout(i),c=0,n=s=o=i=void 0},b.flush=function(){return void 0===i?l:h(P())},b}));const J={sum:"Σ",avg:"μ",count:"#",count_unique:"#!"},K={sum:(e,t)=>e.reduce(((e,a)=>e+Number.parseInt(a[t])),0),avg:(e,t)=>Math.round(K.sum(e,t)/e.length),count:e=>e.length,count_unique:(e,t)=>new Set(e.map((e=>e[t]))).size,count_groups:(e,t)=>e.reduce(((e,a)=>{const n=a[t];return e[n]=(e[n]||0)+1,e}),{})};var X=[],ee=[];function te(e,t){if(e&&"undefined"!=typeof document){var a,n=!0===t.prepend?"prepend":"append",o=!0===t.singleTag,r="string"==typeof t.container?document.querySelector(t.container):document.getElementsByTagName("head")[0];if(o){var l=X.indexOf(r);-1===l&&(l=X.push(r)-1,ee[l]={}),a=ee[l]&&ee[l][n]?ee[l][n]:ee[l][n]=i()}else a=i();65279===e.charCodeAt(0)&&(e=e.substring(1)),a.styleSheet?a.styleSheet.cssText+=e:a.appendChild(document.createTextNode(e))}function i(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),t.attributes)for(var a=Object.keys(t.attributes),o=0;o<a.length;o++)e.setAttribute(a[o],t.attributes[a[o]]);var l="prepend"===n?"afterbegin":"beforeend";return r.insertAdjacentElement(l,e),e}}te("\nbody {\n --v-table-color: var(--v-input-color);\n --v-table-background-color: var(--v-input-background-color);\n}\n.sql-query-table[data-v-fcaf817c] {\n position: relative;\n height: var(--v-table-height);\n overflow-y: auto;\n\n --sqt-head--background: var(--background-normal, var(--theme--background));\n --sqt-head--color: color: var(--foreground-normal, var(--theme--foreground));\n\n --sqt-foot--background: var(--background-normal, var(--theme--background));\n --sqt-foot--color: color: var(--foreground-normal, var(--theme--foreground));\n}\ntable[data-v-fcaf817c] {\n min-width: 100%;\n min-height: 100%;\n border-collapse: collapse;\n border-spacing: 0;\n background-color: var(--v-table-background-color);\n color: var(--v-table-color);\n}\ntable thead[data-v-fcaf817c] {\n background-color: var(--sqt-head--background);\n color: var(--sqt-head--color);\n border-bottom: var(--border-width) solid var(--v-input-border-color);\n}\ntable thead.fixed[data-v-fcaf817c] {\n position: sticky;\n top: 0;\n z-index: 3;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);\n}\ntable thead tr.headers th[data-v-fcaf817c] {\n padding: 8px;\n font-weight: bold;\n min-width: 3rem;\n background-color: var(--sqt-head--background);\n color: var(--sqt-head--color);\n border-bottom: var(--border-width) solid var(--v-input-border-color);\n}\ntable tr.search th[data-v-fcaf817c] {\n padding: 0;\n}\ntable tr.search th .search-input.v-input[data-v-fcaf817c] {\n margin: 0;\n border: none;\n}\ntable th .sort-icon[data-v-fcaf817c] {\n opacity: 0;\n}\ntable th:hover .sort-icon[data-v-fcaf817c] {\n opacity: 0.5;\n}\ntable th .sort-icon.show[data-v-fcaf817c] {\n opacity: 1;\n}\ntable th.select[data-v-fcaf817c] {\n width: 2rem;\n}\ntable td[data-v-fcaf817c] {\n padding: 8px;\n align: middle;\n border-bottom: var(--border-width) solid var(--v-input-border-color);\n}\ntable tbody[data-v-fcaf817c] {\n display: contents;\n}\ntable tfoot tr[data-v-fcaf817c] {\n position: sticky;\n bottom: 0;\n background-color: var(--sqt-foot--background);\n color: var(--sqt-foot--color);\n box-shadow: var(--card-shadow);\n}\ntable tfoot tr td[data-v-fcaf817c] {\n padding: 8px;\n height: 44px;\n font-weight: bold;\n background-color: var(--sqt-foot--background);\n color: var(--sqt-foot--color);\n}\n",{});var ae=(e,t)=>{const a=e.__vccOpts||e;for(const[e,n]of t)a[e]=n;return a};const ne=e=>(q("data-v-fcaf817c"),e=e(),S(),e),oe={class:"sql-query-table"},re={key:0,class:"search"},le={colspan:"80%"},ie={class:"headers"},se=["onClick","align"],ce={key:0},ue={key:1},de=["colspan"],fe={key:0},ve={colspan:"100%"},me={key:1},pe=["onClick"],he=ne((()=>c("tr",null,[c("td",{style:{height:"100%"}})],-1))),be={key:2},ge={key:0,class:"v-text-overflow"},ye={__name:"FastTable",props:{loading:Boolean,headers:{type:Array,validator:e=>e.every((e=>e.value&&e.text)),required:!0},items:{type:Array,required:!0},sort:String,sortDesc:Boolean,fixedHeader:Boolean},emits:["update:sort","update:sortDesc","click:row"],setup(e,{emit:t}){const{t:a}=L(),q=e,S=n(""),j=o((()=>q.headers.filter((e=>e.searchable)))),A=o((()=>{const e=S.value?S.value.toLowerCase().trim():"";return e?q.items.filter((t=>j.value.some((a=>t[a.value]&&t[a.value].toLowerCase().includes(e))))):q.items})),C=o((()=>{const e=function(e,t){if(!t.some((e=>!!e.summarise)))return null;const a={};for(const n of t){if(!n.summarise)continue;const t=K[n.summarise];if(!t)throw new Error(`Summariser function for ${n.summarise} not found.`);const o=t(e,n.value);if("count_groups"===n.summarise){let e=JSON.stringify(o,null,1).replace("{\n","").replace("\n}","").replace(/[",]/g,"");a[n.value]=e}else a[n.value]=`${J[n.summarise]} ${o}`}return a}(A.value,q.headers);return e})),$=t;return(t,n)=>{const o=r("v-icon"),E=r("v-input"),L=r("v-progress-linear"),O=r("v-card-title"),T=r("v-card"),D=l("tooltip");return i(),s("div",oe,[c("table",null,[c("thead",{class:u(["table-header",{fixed:e.fixedHeader}])},[j.value.length&&e.items.length>10?(i(),s("tr",re,[c("th",le,[d(E,{modelValue:S.value,"onUpdate:modelValue":n[0]||(n[0]=e=>S.value=e),small:"",trim:"",class:"search-input",rounded:"",placeholder:"Search"},{prepend:f((()=>[d(o,{name:"search"})])),_:1},8,["modelValue"])])])):v("v-if",!0),c("tr",ie,[(i(!0),s(m,null,p(e.headers,(a=>(i(),s("th",{style:h({minWidth:`${a.width||t.auto}ch`}),key:a.value,onClick:e=>function(e){e.sortable&&($("update:sort",e.value),$("update:sortDesc",!q.sortDesc))}(a),align:a.align||"left"},[b(g(a.text)+" ",1),a.sortable?(i(),y(o,{key:0,name:"sort",small:"",class:u(["sort-icon",{show:e.sort===a.value}]),style:h(`transform: ${e.sortDesc?"rotateZ(0deg) rotateY(0deg)":"rotateZ(180deg) rotateY(180deg)"}; transition: .2s all ease`)},null,8,["class","style"])):v("v-if",!0)],12,se)))),128)),t.$slots["item-append"]?(i(),s("th",ce,"#")):v("v-if",!0)]),e.loading?(i(),s("tr",ue,[c("td",{colspan:e.headers.length+1},[d(L,{indeterminate:""})],8,de)])):v("v-if",!0)],2),e.loading||e.items.length?(i(),s("tbody",me,[k(t.$slots,"default",{items:A.value},(()=>[(i(!0),s(m,null,p(A.value,(a=>(i(),s("tr",{onClick:e=>$("click:row",{item:a,event:e})},[(i(!0),s(m,null,p(e.headers,(e=>(i(),s("td",{key:e.value,class:u(`align-${e.align}`)},g(a[e.value]),3)))),128)),t.$slots["item-append"]?(i(),s("td",{key:0,onClick:n[1]||(n[1]=x((()=>{}),["stop"]))},[k(t.$slots,"item-append",{item:a},void 0,!0)])):v("v-if",!0)],8,pe)))),256))]),!0),v(" This is to fill up any remaining height in the table "),he])):(i(),s("tbody",fe,[c("tr",null,[c("td",ve,[d(T,{style:{padding:"2rem","--v-card-max-width":"100%",margin:"2rem auto"}},{default:f((()=>[d(O,null,{default:f((()=>[d(o,{name:"info",style:{"margin-right":"2rem"}}),b(" "+g(w(a)("no_items")),1)])),_:1})])),_:1})])])])),C.value?(i(),s("tfoot",be,[c("tr",null,[(i(!0),s(m,null,p(e.headers,(e=>_((i(),s("td",{key:e.value},[C.value[e.value]?(i(),s("code",ge,g(C.value[e.value]),1)):v("v-if",!0)])),[[D,e.summarise]]))),128))])])):v("v-if",!0)])])}}};var we=ae(ye,[["__scopeId","data-v-fcaf817c"],["__file","FastTable.vue"]]);te("\n.sql-panel-container {\n width: 100%;\n height: 100%;\n --v-table-height: 100%;\n}\n.sql-panel-container .v-text-overflow {\n user-select: text;\n white-space: pre-wrap;\n}\n.sql-panel-container .center {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n.export-csv-button {\n position: absolute;\n right: 0;\n bottom: 0;\n z-index: 2;\n opacity: 0.8;\n}\n.export-csv-button .button {\n border-radius: var(--border-radius) 0 0 0 !important;\n}\n",{});const ke={key:0,class:"center"},xe={key:0},_e={__name:"panel",props:{id:String,showHeader:{type:Boolean,default:!1},columns:Array,download:{type:Boolean,default:!0},is_static:{type:Boolean,default:!1},actions:Array},setup(a){const c=E(),h=a,{id:k,showHeader:x,download:q,is_static:S}=j(h),L=n(!1),O=n(""),T=n(""),D=n(null),N=n(null),I=e(),{useInsightsStore:B}=t(),W=B(),M=n(new Set),U=o((()=>{const e={},t=[];return M.value.forEach((a=>{void 0===W.variables[a]||null===W.variables[a]?t.push(a):e[a]=W.variables[a]})),t.length?t:e}));if(S.value)A(Q);else{const e=G(Q,1e3);C(U,(()=>{Array.isArray(U.value)?T.value=`Please specify: ${U.value.join(" & ")}`:(T.value="",N.value||(L.value=!0),e())}),{immediate:!0})}const H=o((()=>h.columns?.length>0?h.columns.map((e=>({...e,text:e.text||e.value}))):D.value)),R=n({by:null,desc:!1});let F;async function Q(){if(!Array.isArray(U.value)){L.value=!0,O.value="",D.value=null,N.value=null;try{const e={};F=e;const{data:t}=await I.get(`insights/query/${k.value}`,{params:U.value});if(F!==e)return;if(t.error&&(O.value=t.error),t.headers&&t.items){const e=t.items.length>2;D.value=t.headers.map((function(t,a){const n=t.replace(/_/g," ").replace(/(?:^|\s)\S/g,(function(e){return e.toUpperCase()}));return{text:n,value:t,width:n.length+1,sortable:e}}));const a=h.columns&&h.columns.filter((e=>e.isNumber));N.value=a?t.items.map((e=>(a.forEach((t=>{e[t.value]=""!==e[t.value]?1*e[t.value]:null})),e))):t.items}}catch(e){const t=e.response?.data?.error||e.message;t.includes("Missing query param")?(T.value=t.replace("Missing query param","Please specify"),t.split(": ")[1].split(", ").forEach((e=>M.value.add(e)))):O.value=t}L.value=!1}}function V(){if(H.value&&N.value){let e=Object.values(H.value).map((e=>e.text)).join(",");e+="\r\n",e+=function(){let e="";return N.value.forEach((t=>{for(let a in t)/[, ]/.test(t[a])?e+=`"${t[a].replace(/"/g,'\\"')}",`:e+=t[a]+",";e+="\r\n"})),e}();const t=(new Date).toISOString()+".csv"||"export.csv",a=new Blob([e],{type:"text/csv;charset=utf-8;"});if(navigator.msSaveBlob)navigator.msSaveBlob(a,t);else{const e=document.createElement("a");if(void 0!==e.download){const n=URL.createObjectURL(a);e.setAttribute("href",n),e.setAttribute("download",t),e.style.visibility="hidden",document.body.appendChild(e),e.click(),document.body.removeChild(e)}}}}function z(e,t){let a=e;for(let e in t)a=a.replace(new RegExp(`%${e}%`,"g"),t[e]);return a}function P({item:e}){const t=h.actions?.find((e=>e.row));t&&c.push(z(t.link,e))}return C(R,(({by:e,desc:t})=>{e&&(N.value=N.value.sort(((a,n)=>a[e]<n[e]?t?1:-1:a[e]>n[e]?t?-1:1:0)))}),{deep:!0}),(e,t)=>{const n=r("v-progress-circular"),o=r("v-notice"),c=r("v-icon"),h=r("v-button"),k=l("tooltip");return i(),s("div",{class:u(["sql-panel-container",{"has-header":w(x)}])},[L.value||O.value||T.value?(i(),s("div",ke,[L.value?(i(),y(n,{key:0,indeterminate:""})):T.value?(i(),y(o,{key:1,type:"info",center:""},{default:f((()=>[b(g(T.value),1)])),_:1})):(i(),y(o,{key:2,type:"danger",center:""},{default:f((()=>[b(g(O.value),1)])),_:1}))])):H.value&&N.value?(i(),s(m,{key:1},[w(q)?(i(),y(h,{key:0,onClick:V,icon:"",secondary:"",class:"export-csv-button"},{default:f((()=>[d(c,{name:"download-file"})])),_:1})):v("v-if",!0),d(we,{headers:H.value,items:N.value,"onClick:row":P,sort:R.value.by,"onUpdate:sort":t[0]||(t[0]=e=>R.value.by=e),sortDesc:R.value.desc,"onUpdate:sortDesc":t[1]||(t[1]=e=>R.value.desc=e),"fixed-header":""},$({_:2},[a.actions?.find((e=>!e.row))?{name:"item-append",fn:f((({item:e})=>[(i(!0),s(m,null,p(a.actions.filter((e=>!e.row)),(t=>_((i(),y(h,{outlined:"",to:z(t.link,e),icon:!t.show_label,"x-small":""},{default:f((()=>[d(c,{name:t.icon},null,8,["name"]),t.show_label?(i(),s("span",xe,g(t.label),1)):v("v-if",!0)])),_:2},1032,["to","icon"])),[[k,t.label]]))),256))])),key:"0"}:void 0]),1032,["headers","items","sort","sortDesc"])],64)):v("v-if",!0)],2)}}};const qe=[],Se=[],je=[],Ae=[],Ce=[a({id:"sql-query",name:"SQL Query panel",icon:"view_list",description:"Show result of a stored SQL query as a table",component:ae(_e,[["__file","panel.vue"]]),options:[{field:"sql",name:"SQL query",type:"string",meta:{note:"Supports variables in the format of {{variable_name}}. Don't quote string variables. Example: SELECT * FROM tasks WHERE list = {{list}} AND status IN ({{status}})",interface:"input-code",width:"full",options:{language:"sql"}}},{field:"columns",name:"Columns",type:"json",special:"cast-json",meta:{width:"full",interface:"list",options:{addLabel:"Add column",label:"{{name}} - {{width}}",fields:[{field:"value",name:"Column Name",type:"string",note:"As returned by query",meta:{required:!0,width:"half",interface:"input",options:{trim:!0,softLength:100}}},{field:"text",name:"Label",type:"string",note:"What to display in the column header (Default is same as name)",meta:{width:"half",interface:"input",options:{trim:!0,softLength:100}}},{field:"width",name:"Width",type:"integer",meta:{required:!0,width:"half",interface:"input",options:{min:1,max:300},note:"Width of the column in ch (character width). Default is 10."},schema:{default_value:10}},{field:"isNumber",name:"Is Numberic",type:"boolean",meta:{width:"half",interface:"boolean"}},{field:"sortable",name:"Sortable",type:"boolean",meta:{width:"half",interface:"boolean"}},{field:"searchable",name:"Searchable",type:"boolean",meta:{width:"half",interface:"boolean"}},{field:"summarise",name:"Summarise",type:"string",meta:{width:"half",interface:"select-dropdown",options:{choices:[{text:"Sum",value:"sum"},{text:"Average",value:"avg"},{text:"Count",value:"count"},{text:"Count Unique",value:"count_unique"},{text:"Count Groups",value:"count_groups"}]}}}]}}},{field:"actions",name:"Actions",type:"json",special:"cast-json",meta:{width:"full",interface:"list",options:{addLabel:"Add action",label:"{{{label}}",fields:[{field:"label",name:"Label",type:"string",meta:{required:!0,width:"half",interface:"input",options:{trim:!0,softLength:50}}},{field:"link",name:"Link",type:"string",meta:{required:!0,note:"Variables per row can be inserted as such %column_name%",width:"half",interface:"input",options:{trim:!0}}},{field:"row",name:"Activate on row click",type:"boolean",meta:{note:"If you don't want to show the action button, but want to activate the link on row click, check this box.",width:"full",interface:"boolean"}},{field:"icon",name:"Icon",type:"string",meta:{note:"Leave blank to not show an icon",width:"half",interface:"select-icon"}},{field:"show_label",name:"Show label",type:"boolean",meta:{width:"half",interface:"boolean"}}]}}},{field:"download",name:"Download button",type:"boolean",meta:{width:"half",interface:"boolean",options:{label:"Show"}},schema:{default_value:!0}},{field:"is_static",name:"Is static",type:"boolean",meta:{width:"half",interface:"boolean",options:{label:"Yes"},note:"If the result will not be affect when variables are changed, you can check this box to improve performance."},schema:{default_value:!1}},{field:"cache",name:"Cache Response",type:"integer",meta:{width:"half",interface:"input",options:{min:10,max:3600},note:"Tells the browser how long to cache results for. Default is 30 seconds."},schema:{default_value:300}}],minWidth:10,minHeight:10})],$e=[];export{Se as displays,qe as interfaces,je as layouts,Ae as modules,$e as operations,Ce as panels};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directus-extension-sql-query-panel",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Insights Panel for viewing results for dynamic sql queries",
|
|
6
6
|
"icon": "extension",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"directus-custom-bundle"
|
|
40
40
|
],
|
|
41
41
|
"scripts": {
|
|
42
|
+
"start": "vite --port 8080 --host",
|
|
42
43
|
"build": "directus-extension build",
|
|
43
44
|
"dev": "directus-extension build -w --no-minify",
|
|
44
45
|
"link": "directus-extension link",
|