@bygd/nc-report-ui 0.1.18 → 0.1.20

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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("@material-ui/core/Paper"),a=require("@material-ui/core/styles"),r=require("@material-ui/core/LinearProgress"),n=require("react-google-charts"),l=require("numeral"),i=require("axios"),o=require("@material-ui/core/Typography"),s=require("nunjucks"),u=require("@material-ui/core/FormControl"),d=require("@material-ui/core/Select"),c=require("@material-ui/core/MenuItem"),f=require("react-intersection-observer"),m=require("@mui/material"),p=require("@mui/icons-material/CheckBoxOutlineBlank"),h=require("@mui/icons-material/CheckBox"),y=require("@mui/material/Box"),g=require("@mui/material/InputLabel"),b=require("@mui/material/MenuItem"),v=require("@mui/material/FormControl"),E=require("@mui/material/Select"),w=require("eventemitter3"),x=require("@material-ui/core/Grid"),S=require("@material-ui/core/Box"),C=require("@material-ui/core/Container");function k(e){return e&&e.__esModule?e:{default:e}}function q(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach(function(a){if("default"!==a){var r=Object.getOwnPropertyDescriptor(e,a);Object.defineProperty(t,a,r.get?r:{enumerable:!0,get:function(){return e[a]}})}}),t.default=e,Object.freeze(t)}var M=q(e),R=k(t),I=k(r),T=k(l),A=k(i),D=k(o),O=k(s),_=k(u),F=k(d),z=k(c),Y=k(p),P=k(h),j=k(y),$=k(g),B=k(b),W=k(v),G=k(E),L=k(w),U=k(x),V=k(S),H=k(C);function K(){return K=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var a=arguments[t];for(var r in a)({}).hasOwnProperty.call(a,r)&&(e[r]=a[r])}return e},K.apply(null,arguments)}const N=a.makeStyles(e=>({root:{width:"100%","& > * + *":{marginTop:e.spacing(2)}}}));function J(e){const t=N();return M.default.createElement("div",K({className:t.root},e),M.default.createElement(I.default,null))}function Q(e,t,a="array"){const r=e.columns,n=[...t.doc.metrics,...t.doc.dimensions].reduce((e,t)=>(e[t.name]=t,e),{});return e=>{const t="array"===a?[]:{};return r.reduce((t,r)=>{const l=e[r.name],i=n[r.name];let o=l;return o="timestamp"===i.type?new Date(l):i.format?i.format&&i.prefix?{v:+l,f:i.prefix+" "+T.default(l).format(i.format)}:i.format?{v:+l,f:T.default(l).format(i.format)}:l:l,"array"===a?t.push(o):t[r.name]=o?.f||o,t},t)}}const X="https://report-api.netcapital.pro",Z=A.default.create({baseURL:X,headers:{"Content-Type":"application/json"}}),ee={},te=()=>{const e=Object.keys(ee);return e.length>0?e[0]:null},ae={setBaseUrl(e){Z.defaults.baseURL=e||X},setToken(e){e&&(Z.defaults.headers.common.Authorization=`Bearer ${e}`)},loadDashboardMeta:async({dashboardId:e})=>{const{data:t}=await Z.get(`/dashboard-meta/${e}`);return ee[e]={dashboards:t.dashboards||{},charts:t.charts||{},reports:t.reports||{},reportMetadata:t.reportMetadata||{},dateRanges:t.dateRanges||[]},ee[e]},getDashboard:async({id:e,dashboardId:t})=>{const a=t||te();if(a&&ee[a]?.dashboards?.[e])return ee[a].dashboards[e];const{data:r}=await Z.get(`/entity/dashboards/${e}`);return r},getChart:async({id:e,dashboardId:t})=>{const a=t||te();if(a&&ee[a]?.charts?.[e])return ee[a].charts[e];const{data:r}=await Z.get(`/entity/charts/${e}`);return r},getReport:async({id:e,dashboardId:t})=>{const a=t||te();if(a&&ee[a]?.reports?.[e])return ee[a].reports[e];const{data:r}=await Z.get(`/entity/reports/${e}`);return r},getProviders:async()=>{const{data:e}=await Z.get("/entity/providers");return e},getReportSchema:async({id:e,dashboardId:t,query:a={}})=>{const r=t||te();if(r&&ee[r]?.reportMetadata?.[e])return ee[r].reportMetadata[e];const{data:n}=await Z.post(`/reports/${e}/metadata`,a);return n},runReport:async({id:e,query:t={}})=>{const{data:a}=await Z.post(`/reports/${e}/run`,t);return a},runAdHocReport:async({report:e})=>{const{data:t}=await Z.post("/report-build/run",e);return t},getDateRanges:async({dashboardId:e}={})=>{const t=e||te();if(t&&ee[t]?.dateRanges)return ee[t].dateRanges;const{data:a}=await Z.get("/globals/date-ranges");return a},getReportDefinitions:async()=>{const{data:e}=await Z.get("/report-definitions");return e},getReportDefinition:async({id:e})=>{const{data:t}=await Z.get(`/report-definitions/${e}`);return t},createReportDefinition:async({reportDefinition:e})=>{const{data:t}=await Z.post("/report-definitions",e);return t},updateReportDefinition:async({id:e,reportDefinition:t})=>{const{data:a}=await Z.put(`/report-definitions/${e}`,t);return a},deleteReportDefinition:async({id:e})=>{const{data:t}=await Z.delete(`/report-definitions/${e}`);return t}},re=a.makeStyles(e=>({headerRow:{fontFamily:e.typography.fontFamily,fontSize:e.typography.fontSize},tableRow:{fontFamily:e.typography.fontFamily,fontSize:e.typography.fontSize},oddTableRow:{fontFamily:e.typography.fontFamily,fontSize:e.typography.fontSize},headerCell:{backgroundColor:"white",padding:"4px !important"}})),ne={none:"YYYY-MM-dd",day:"MMM dd",week:"MMM dd",month:"YYYY MMM",year:"YYYY"};const le={GoogleChart:function({chart:t,source:a,view:r,report:l,schema:i,dashboard:o,query:s}){const[u,d]=M.default.useState([]),c=re(),[f,m]=M.default.useState([]);e.useEffect(()=>{(async()=>{const e=await ae.getDateRanges();m(e)})()},[]);const p=e.useMemo(()=>{const e="YYYY-MM-dd",t=s?.date_range?.name,a=f.find(e=>e.name===t);if(!a)return e;return ne[a?.granularity]||e},[f,s]);return M.default.useEffect(()=>{if(!(t&&r&&a&&l&&i))return;let e=[];e.push(function(e,t){const a=[...t.doc.metrics,...t.doc.dimensions];return e.columns.reduce((e,t)=>{const r=a.find(e=>e.name===t.name)||t;return e.push(r.title||r.name),e},[])}(r,i));const n=Q(r,i);a?.forEach(t=>{const a=n(t);e.push(a)}),a?.length?d(e):d()},[t,a,r,l,i]),u?M.default.createElement("div",{style:{}},M.default.createElement(n.Chart,K({width:t?.doc.size?.width||"100%",chartType:t?.doc.chart?.type,data:u,options:(e=>{if("Table"===t?.doc.chart?.type)return{...t?.doc.chart?.options,cssClassNames:c};if("AreaChart"===t?.doc.chart?.type){const a=t?.doc.chart?.options?.hAxis||{},r={...{ticks:e.slice(1).map(e=>e[0]),format:p},...a};return{...t?.doc.chart?.options,hAxis:r,focusTarget:"category"}}return t?.doc.chart?.options})(u)},t?.doc.chart?.props))):M.default.createElement("div",null)},LabelChart:function({chart:e,source:t,view:a,report:r,schema:n}){const[l,i]=M.default.useState([]),[o,s]=M.default.useState(),[u,d]=M.default.useState();return M.default.useEffect(()=>{if(!(e&&a&&t&&r&&n))return;let l=[];const o=Q(a,n);t.forEach(e=>l.push(o(e))),i(l);const u=e?.doc?.chart?.options||{},c=u?.index||0;if(l.length>0&&s(l[0][c]),u.subText?.format){O.default.configure({autoescape:!1});const e=Q(a,n,"object")(t[0]),r=O.default.renderString(u.subText?.format,e);d(r)}},[e,t,a,r,n]),M.default.createElement("div",{style:{display:"flex",justifyContent:"center",alignContent:"center",height:"100%",flexDirection:"column"}},M.default.createElement(D.default,{variant:"h6"},o?.f||o),M.default.createElement(D.default,{variant:"caption"},u))}};function ie(e,t){return void 0!==le[e]?M.default.createElement(le[e],t):M.default.createElement(J,t)}const oe=M.createElement(Y.default,{fontSize:"small"}),se=M.createElement(P.default,{fontSize:"small"});function ue({items:t,selectedKeys:a,defaultSelectedKeys:r,onChange:n,inputValue:l,defaultInputValue:i,onInputChange:o,debounceMs:s=300,label:u,placeholder:d,loading:c,disabled:f,size:p="small",error:h,helperText:y,limitTags:g=3,disableClearable:b,id:v,textFieldProps:E}){const w=e.useMemo(()=>Array.isArray(t)?t:[],[t]),x=Array.isArray(a),[S,C]=e.useState(Array.isArray(r)?r:[]),k=x?a:S,q=e.useMemo(()=>{const e=new Map;for(const t of w)e.set(t&&t.key,t);return e},[w]),R=e.useMemo(()=>(Array.isArray(k)?k:[]).map(e=>q.get(e)).filter(Boolean),[k,q]),I="string"==typeof l,[T,A]=e.useState("string"==typeof i?i:""),D=I?l:T,O=function(t,a=300){const r=e.useRef(t),n=e.useRef(null);return r.current=t,e.useEffect(()=>()=>{n.current&&window.clearTimeout(n.current)},[]),M.useCallback((...e)=>{r.current&&(n.current&&window.clearTimeout(n.current),n.current=window.setTimeout(()=>{r.current&&r.current(...e)},a))},[a])}(e=>{o&&o(e)},s),_=R;return M.createElement(m.FormControl,{fullWidth:!0,error:h,disabled:f},M.createElement(m.Autocomplete,{openOnFocus:!0,forcePopupIcon:!0,id:v,multiple:!0,disableCloseOnSelect:!0,options:w,value:_,inputValue:D,getOptionLabel:e=>e&&"object"==typeof e?e.value??"":"",isOptionEqualToValue:(e,t)=>e&&t&&e.key===t.key,loading:c,limitTags:g,disableClearable:b,onChange:(e,t)=>{const a=Array.isArray(t)?t.map(e=>e&&e.key):[];x||C(a),n&&n(a,Array.isArray(t)?t:[])},onInputChange:(e,t,a)=>{I||A(t??""),"input"===a?O(t??""):"clear"===a&&O("")},renderOption:(e,t,{selected:a})=>M.createElement("li",K({},e,{key:t&&t.key||Math.random().toString(36)}),M.createElement(m.Checkbox,{icon:oe,checkedIcon:se,style:{marginRight:8},checked:!!a}),t&&t.value),renderTags:(e,t)=>(Array.isArray(e)?e:[]).map((e,a)=>M.createElement(m.Chip,K({},t({index:a}),{key:e&&e.key||a,label:e&&e.value||""}))),renderInput:e=>M.createElement(m.TextField,K({},e,{label:u,placeholder:d,InputProps:{...e.InputProps,endAdornment:M.createElement(M.Fragment,null,c?M.createElement(m.CircularProgress,{size:18}):null,e.InputProps.endAdornment)},size:p},E))}),y?M.createElement(m.FormHelperText,null,y):null)}const de=({filter:t,channel:a,query:r})=>{const[n,l]=e.useState([]),[i,o]=e.useState([]),[s,u]=e.useState(!1),[d,c]=e.useState("");return e.useEffect(()=>{o(r?.filter?.[t?.filter]||[])},[r]),e.useEffect(()=>{(async()=>{u(!0);const e=await async function(e,t){return t?.source?(await ae.runReport({id:t.source})).map(e=>({key:e[t.field],value:e[t.field]})):[]}(0,t);l(e),u(!1)})()},[d]),M.default.createElement("div",{style:{display:"flex"}},M.default.createElement("div",{style:{maxWidth:640,minWidth:200}},M.default.createElement(ue,{id:t?.title,label:t?.title,placeholder:"Type to search…",items:n,selectedKeys:i,onChange:(e,r)=>{o(e),a.emit("filterChanged",t,{[t.filter]:e})},onInputChange:e=>{c(e)},loading:s,debounceMs:300,helperText:i.length?`${i.length} selected`:""})))};function ce({items:e,value:t,label:a,onChange:r,sx:n={width:"100%"}}){const l=e.some(e=>e.key===t)?t:"";return M.default.createElement(j.default,{sx:n},M.default.createElement(W.default,{fullWidth:!0},M.default.createElement($.default,{id:"demo-simple-select-label"},a),M.default.createElement(G.default,{labelId:"demo-simple-select-label",id:"demo-simple-select",value:l,label:a,onChange:r,MenuProps:{style:{maxHeight:"300px"}},size:"small"},e.map(e=>{const{key:t,value:a,disabled:r}=e;return M.default.createElement(B.default,{key:t,value:t,disabled:r},a)}))))}const fe=({filter:t,channel:a,query:r})=>{const[n,l]=e.useState([]),[i,o]=e.useState("");return e.useEffect(()=>{o(r?.date_range?.name)},[r]),e.useEffect(()=>{(async()=>{const e=(await ae.getDateRanges()).filter(e=>!(t.allowedOptions.length>0)||t.allowedOptions.some(t=>t===e.name)).map(e=>({key:e.name,value:e.title}));l(e)})()},[]),M.default.createElement("div",{style:{minWidth:"200px",maxWidth:"640px"}},M.default.createElement(ce,{items:n,value:i,label:t?.title,onChange:(e,r)=>{const n=e.target.value;o(n),a.emit("filterChanged",t,{date_range:{name:n}})}}))},me=({filters:e=[],channel:t,query:a})=>M.default.createElement("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px"}},e.map(e=>"multi-select"===e.type?M.default.createElement(de,{key:e.title,channel:t,filter:e,query:a}):"date-range"===e.type?M.default.createElement(fe,{key:e.title,channel:t,filter:e,query:a}):null));var pe=e=>M.default.useRef(e||new L.default).current,he=e=>{const t=M.default.useState({}),a=M.default.useCallback((a,r)=>{let n={...t.current,...r};for(var l in t.current=n,n)"date_range"===l||n[l].length||delete n[l];e?.emit("mergedFilterChanged",{value:n})},[e]);M.default.useEffect(()=>(e?.on("filterChanged",a),()=>{e?.off("filterChanged",a)}),[e])},ye=({id:e,cache:t,dashboard:a,channel:r,...n})=>{const[l,i]=M.default.useState(),[o,s]=M.default.useState(),[u,d]=M.default.useState(),[c,m]=M.default.useState(),[p,h]=M.default.useState(ie()),[y,g]=M.default.useState(),[b,v]=M.default.useState(0),[E,w]=M.default.useState(!1),[x,S]=M.default.useState(),[C,k]=M.default.useState(!1),q=M.default.useRef({value:n?.filter}),[I,T]=M.default.useState({}),{ref:A,inView:O,entry:Y}=f.useInView({threshold:.1,delay:1e3}),P=pe(r);he(P);const j=M.default.useCallback(e=>{const t=e.target.value;v(t),g(l.doc.view[t])},[l]);M.default.useEffect(()=>{e&&(async()=>{const a=e,r=t?.[a]||await ae.getChart({id:a}),l=r.doc.source?.id,o=l?t?.[l]||await ae.getReport({id:l}):void 0,u=t?.[`schema_${l}`]||n?.schema||await ae.getReportSchema({id:l}),c=r.doc?.view?.[0];v(0),s(o),i(r),g(c),d(u),k(!0)})().catch(e=>{console.error(e.message)})},[e]),M.default.useEffect(()=>{l&&c&&(!l?.doc?.source?.id||o)&&u&&(async()=>{h(ie(l.doc.chart?.component,{view:y,source:c,chart:l,report:o,schema:u,dashboard:a,query:I}))})().catch(e=>{console.error(e.message)})},[l,c,y,o,u]);const $=e=>{const t={...o?.doc.query.filter||{},...n?.filter,...e?.value},a=t.date_range||o?.doc.query.date_range;if(delete t.date_range,k(!1),S(),w(!0),"context"===l?.doc?.source?.type)return m({filter:t}),void w(!1);const r={filter:t,date_range:a,parameters:n?.params};T(r),ae.runReport({id:o.id,query:r}).then(e=>{m(l.doc.source.reverse?e.reverse():e)}).catch(e=>{m([])}).finally(()=>{w(!1)})},B=e=>{q.current=e,O?$(e):(S(e),k(!0))};return M.default.useEffect(()=>(P?.on("mergedFilterChanged",B),()=>{P?.off("mergedFilterChanged",B)}),[P,o,l,O]),M.default.useEffect(()=>{O&&C&&$(x)},[O,C]),M.default.useEffect(()=>{k(!0)},[n.params]),M.default.createElement(R.default,{ref:A,style:{padding:"16px",paddingTop:0,flexGrow:1,borderRadius:12,display:"flex",flexDirection:"column",gap:"16px"},elevation:2},M.default.createElement(J,{style:{visibility:E?"visible":"hidden"}}),M.default.createElement("div",{style:{display:"flex"}},M.default.createElement("div",null,l&&M.default.createElement("div",{style:{display:"flex",alignItems:"center",lineHeight:0}},M.default.createElement(D.default,{noWrap:!0,variant:"caption"},n?.title||l.doc.name," "))),M.default.createElement("div",{style:{flexGrow:1}}),M.default.createElement("div",null,l?.doc?.view?.length>1&&M.default.createElement(_.default,null,M.default.createElement(F.default,{labelId:"date-range-select-label",id:"date-range-select",value:b,onChange:j,style:{fontSize:"12px"},disableUnderline:!0},l.doc.view.map((e,t)=>M.default.createElement(z.default,{key:t,value:t},e.title)))))),M.default.createElement("div",{style:{position:"relative",flexGrow:a?void 0:1,display:"flex",flexDirection:"column"}},M.default.createElement(me,{filters:l?.doc?.filters,channel:P,query:I}),p))};var ge={Chart:ye,Dashboard:function({id:t="sample_dashboard",api:a,params:r}){const[n,l]=M.default.useState(),[i]=M.default.useState(),[o,s]=M.default.useState([]),u=M.default.useRef({}),d=pe();he(d),e.useEffect(()=>{ae.setBaseUrl(a.base_url),ae.setToken(a.token)},[a]);const c=async e=>{const t=e?.doc?.rows||[],a=[];for(let e=0;e<t.length;e++){const r=t[e];r.columns?.forEach(e=>{if(e.override?.filter?.length){const t={};e.override.filter.forEach(e=>{e.hasOwnProperty("value")&&(t[e.field]=[e.value])}),e.filter=t}}),a.push(r)}s(a)};return M.default.useEffect(()=>{t&&(async()=>{ae.setBaseUrl(a.base_url),ae.setToken(a.token),await ae.loadDashboardMeta({dashboardId:t});const e=await ae.getDashboard({id:t});u.current[e?.id]=e,l(e),await c(e)})().catch(e=>console.error(e.message))},[t]),M.default.createElement(H.default,{maxWidth:!1,disableGutters:!0,style:{height:"100vh",padding:0,margin:0,overflow:"hidden"}},M.default.createElement(U.default,{container:!0,spacing:2,style:{height:"100%",width:"100%"}},o?.map((e,t)=>M.default.createElement(U.default,{key:t,container:!0,item:!0,alignItems:"stretch",spacing:2},e?.columns?.map((e,t)=>M.default.createElement(U.default,{key:t,item:!0,xs:!0,style:{display:"flex"}},M.default.createElement(V.default,{style:{flex:1,display:"flex",flexDirection:"column"}},M.default.createElement(ye,{api:a,cache:u.current,id:e.id,dashboard:n,schema:i,channel:null,title:e.title,filter:e.filter,params:r}))))))))}};exports.default=ge;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("@material-ui/core/Paper"),a=require("@material-ui/core/styles"),r=require("@material-ui/core"),n=require("react-google-charts"),l=require("numeral"),o=require("axios"),i=require("@material-ui/core/Typography"),s=require("nunjucks"),u=require("@material-ui/core/FormControl"),d=require("@material-ui/core/Select"),c=require("@material-ui/core/MenuItem"),f=require("react-intersection-observer"),m=require("@mui/material"),p=require("@mui/icons-material/CheckBoxOutlineBlank"),h=require("@mui/icons-material/CheckBox"),y=require("@mui/material/Box"),g=require("@mui/material/InputLabel"),b=require("@mui/material/MenuItem"),v=require("@mui/material/FormControl"),E=require("@mui/material/Select"),w=require("eventemitter3"),x=require("@material-ui/core/Grid"),C=require("@material-ui/core/Container");function S(e){return e&&e.__esModule?e:{default:e}}function k(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach(function(a){if("default"!==a){var r=Object.getOwnPropertyDescriptor(e,a);Object.defineProperty(t,a,r.get?r:{enumerable:!0,get:function(){return e[a]}})}}),t.default=e,Object.freeze(t)}var R=k(e),q=S(t),M=S(l),A=S(o),I=S(i),T=S(s),O=S(u),D=S(d),F=S(c),P=S(p),_=S(h),j=S(y),z=S(g),Y=S(b),$=S(v),B=S(E),U=S(w),L=S(x),W=S(C);function V(){return V=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var a=arguments[t];for(var r in a)({}).hasOwnProperty.call(a,r)&&(e[r]=a[r])}return e},V.apply(null,arguments)}const G=a.makeStyles(e=>({root:{width:"100%","& > * + *":{marginTop:e.spacing(2)}}}));function H(e){const t=G();return R.default.createElement("div",V({className:t.root},e),R.default.createElement(r.CircularProgress,{style:{color:"rgb(70, 134, 128)"},size:25}))}function K(e,t,a="array"){const r=e.columns,n=[...t.doc.metrics,...t.doc.dimensions].reduce((e,t)=>(e[t.name]=t,e),{});return e=>{const t="array"===a?[]:{};return r.reduce((t,r)=>{const l=e[r.name],o=n[r.name];let i=l;return i="timestamp"===o.type?new Date(l):o.format?o.format&&o.prefix?{v:+l,f:o.prefix+" "+M.default(l).format(o.format)}:o.format?{v:+l,f:M.default(l).format(o.format)}:l:l,"array"===a?t.push(i):t[r.name]=i?.f||i,t},t)}}const N="https://report-api.netcapital.pro",J=A.default.create({baseURL:N,headers:{"Content-Type":"application/json"}}),Q={},X=()=>{const e=Object.keys(Q);return e.length>0?e[0]:null},Z={setBaseUrl(e){J.defaults.baseURL=e||N},setToken(e){e&&(J.defaults.headers.common.Authorization=`Bearer ${e}`)},loadDashboardMeta:async({dashboardId:e})=>{const{data:t}=await J.get(`/dashboard-meta/${e}`);return Q[e]={dashboards:t.dashboards||{},charts:t.charts||{},reports:t.reports||{},reportMetadata:t.reportMetadata||{},dateRanges:t.dateRanges||[]},Q[e]},getDashboard:async({id:e,dashboardId:t})=>{const a=t||X();if(a&&Q[a]?.dashboards?.[e])return Q[a].dashboards[e];const{data:r}=await J.get(`/entity/dashboards/${e}`);return r},getChart:async({id:e,dashboardId:t})=>{const a=t||X();if(a&&Q[a]?.charts?.[e])return Q[a].charts[e];const{data:r}=await J.get(`/entity/charts/${e}`);return r},getReport:async({id:e,dashboardId:t})=>{const a=t||X();if(a&&Q[a]?.reports?.[e])return Q[a].reports[e];const{data:r}=await J.get(`/entity/reports/${e}`);return r},getProviders:async()=>{const{data:e}=await J.get("/entity/providers");return e},getReportSchema:async({id:e,dashboardId:t,query:a={}})=>{const r=t||X();if(r&&Q[r]?.reportMetadata?.[e])return Q[r].reportMetadata[e];const{data:n}=await J.post(`/reports/${e}/metadata`,a);return n},runReport:async({id:e,query:t={}})=>{const{data:a}=await J.post(`/reports/${e}/run`,t);return a},runAdHocReport:async({report:e})=>{const{data:t}=await J.post("/report-build/run",e);return t},downloadAdHocReport:async({report:e,filename:t})=>{const a=await J.post("/report-build/run?download=csv",e,{responseType:"blob"}),r=window.URL.createObjectURL(new Blob([a.data])),n=document.createElement("a");n.href=r;let l=t||"report.csv";if(!t){const e=a.headers["content-disposition"];if(e){const t=e.match(/filename="?(.+)"?/i);t&&t[1]&&(l=t[1])}}n.setAttribute("download",l),document.body.appendChild(n),n.click(),n.remove(),window.URL.revokeObjectURL(r)},getDateRanges:async({dashboardId:e}={})=>{const t=e||X();if(t&&Q[t]?.dateRanges)return Q[t].dateRanges;const{data:a}=await J.get("/globals/date-ranges");return a},getReportDefinitions:async()=>{const{data:e}=await J.get("/report-definitions");return e},getReportDefinition:async({id:e})=>{const{data:t}=await J.get(`/report-definitions/${e}`);return t},createReportDefinition:async({reportDefinition:e})=>{const{data:t}=await J.post("/report-definitions",e);return t},updateReportDefinition:async({id:e,reportDefinition:t})=>{const{data:a}=await J.put(`/report-definitions/${e}`,t);return a},deleteReportDefinition:async({id:e})=>{const{data:t}=await J.delete(`/report-definitions/${e}`);return t}},ee=a.makeStyles(e=>({headerRow:{fontFamily:e.typography.fontFamily,fontSize:e.typography.fontSize},tableRow:{fontFamily:e.typography.fontFamily,fontSize:e.typography.fontSize},oddTableRow:{fontFamily:e.typography.fontFamily,fontSize:e.typography.fontSize},headerCell:{backgroundColor:"white",padding:"4px !important"}})),te={none:"YYYY-MM-dd",day:"MMM dd",week:"MMM dd",month:"YYYY MMM",year:"YYYY"};const ae={GoogleChart:function({chart:t,source:a,view:r,report:l,schema:o,dashboard:i,query:s}){const[u,d]=R.default.useState([]),c=ee(),[f,m]=R.default.useState([]);e.useEffect(()=>{(async()=>{const e=await Z.getDateRanges();m(e)})()},[]);const p=e.useMemo(()=>{const e="YYYY-MM-dd",t=s?.date_range?.name,a=f.find(e=>e.name===t);if(!a)return e;return te[a?.granularity]||e},[f,s]);return R.default.useEffect(()=>{if(!(t&&r&&a&&l&&o))return;let e=[];e.push(function(e,t){const a=[...t.doc.metrics,...t.doc.dimensions];return e.columns.reduce((e,t)=>{const r=a.find(e=>e.name===t.name)||t;return e.push(r.title||r.name),e},[])}(r,o));const n=K(r,o);a?.forEach(t=>{const a=n(t);e.push(a)}),a?.length?d(e):d()},[t,a,r,l,o]),u?R.default.createElement("div",{style:{}},R.default.createElement(n.Chart,V({width:t?.doc.size?.width||"100%",chartType:t?.doc.chart?.type,data:u,options:(e=>{const a=["#468682","#ff686b","#6c757d","#FFD700","#073b4c"];if("Table"===t?.doc.chart?.type)return{...t?.doc.chart?.options,cssClassNames:c};if("AreaChart"===t?.doc.chart?.type){const r=t?.doc.chart?.options?.hAxis||{},n={...{ticks:e.slice(1).map(e=>e[0]),format:p},...r};return{...t?.doc.chart?.options,hAxis:n,focusTarget:"category",colors:a}}return{...t?.doc.chart?.options,colors:a}})(u)},t?.doc.chart?.props))):R.default.createElement("div",null)},LabelChart:function({chart:e,source:t,view:a,report:r,schema:n}){const[l,o]=R.default.useState([]),[i,s]=R.default.useState(),[u,d]=R.default.useState();return R.default.useEffect(()=>{if(!(e&&a&&t&&r&&n))return;let l=[];const i=K(a,n);t.forEach(e=>l.push(i(e))),o(l);const u=e?.doc?.chart?.options||{},c=u?.index||0;if(l.length>0&&s(l[0][c]),u.subText?.format){T.default.configure({autoescape:!1});const e=K(a,n,"object")(t[0]),r=T.default.renderString(u.subText?.format,e);d(r)}},[e,t,a,r,n]),R.default.createElement("div",{style:{display:"flex",justifyContent:"center",alignContent:"center",height:"100%",flexDirection:"column"}},R.default.createElement(I.default,{variant:"h6"},i?.f||i),R.default.createElement(I.default,{variant:"caption"},u))}};function re(e,t){return void 0!==ae[e]?R.default.createElement(ae[e],t):R.default.createElement(H,t)}const ne=R.createElement(P.default,{fontSize:"small"}),le=R.createElement(_.default,{fontSize:"small"});function oe({items:t,selectedKeys:a,defaultSelectedKeys:r,onChange:n,inputValue:l,defaultInputValue:o,onInputChange:i,debounceMs:s=300,label:u,placeholder:d,loading:c,disabled:f,size:p="small",error:h,helperText:y,limitTags:g=3,disableClearable:b,id:v,textFieldProps:E}){const w=e.useMemo(()=>Array.isArray(t)?t:[],[t]),x=Array.isArray(a),[C,S]=e.useState(Array.isArray(r)?r:[]),k=x?a:C,q=e.useMemo(()=>{const e=new Map;for(const t of w)e.set(t&&t.key,t);return e},[w]),M=e.useMemo(()=>(Array.isArray(k)?k:[]).map(e=>q.get(e)).filter(Boolean),[k,q]),A="string"==typeof l,[I,T]=e.useState("string"==typeof o?o:""),O=A?l:I,D=function(t,a=300){const r=e.useRef(t),n=e.useRef(null);return r.current=t,e.useEffect(()=>()=>{n.current&&window.clearTimeout(n.current)},[]),R.useCallback((...e)=>{r.current&&(n.current&&window.clearTimeout(n.current),n.current=window.setTimeout(()=>{r.current&&r.current(...e)},a))},[a])}(e=>{i&&i(e)},s),F=M;return R.createElement(m.FormControl,{fullWidth:!0,error:h,disabled:f},R.createElement(m.Autocomplete,{openOnFocus:!0,forcePopupIcon:!0,id:v,multiple:!0,disableCloseOnSelect:!0,options:w,value:F,inputValue:O,getOptionLabel:e=>e&&"object"==typeof e?e.value??"":"",isOptionEqualToValue:(e,t)=>e&&t&&e.key===t.key,loading:c,limitTags:g,disableClearable:b,onChange:(e,t)=>{const a=Array.isArray(t)?t.map(e=>e&&e.key):[];x||S(a),n&&n(a,Array.isArray(t)?t:[])},onInputChange:(e,t,a)=>{A||T(t??""),"input"===a?D(t??""):"clear"===a&&D("")},renderOption:(e,t,{selected:a})=>R.createElement("li",V({},e,{key:t&&t.key||Math.random().toString(36)}),R.createElement(m.Checkbox,{icon:ne,checkedIcon:le,style:{marginRight:8},checked:!!a}),t&&t.value),renderTags:(e,t)=>(Array.isArray(e)?e:[]).map((e,a)=>R.createElement(m.Chip,V({},t({index:a}),{key:e&&e.key||a,label:e&&e.value||""}))),renderInput:e=>R.createElement(m.TextField,V({},e,{label:u,placeholder:d,InputProps:{...e.InputProps,endAdornment:R.createElement(R.Fragment,null,c?R.createElement(m.CircularProgress,{size:18}):null,e.InputProps.endAdornment)},size:p},E))}),y?R.createElement(m.FormHelperText,null,y):null)}const ie=({filter:t,channel:a,query:r})=>{const[n,l]=e.useState([]),[o,i]=e.useState([]),[s,u]=e.useState(!1),[d,c]=e.useState("");return e.useEffect(()=>{i(r?.filter?.[t?.filter]||[])},[r]),e.useEffect(()=>{(async()=>{u(!0);const e=await async function(e,t){return t?.source?(await Z.runReport({id:t.source})).map(e=>({key:e[t.field],value:e[t.field]})):[]}(0,t);l(e),u(!1)})()},[d]),R.default.createElement("div",{style:{display:"flex"}},R.default.createElement("div",{style:{maxWidth:640,minWidth:200}},R.default.createElement(oe,{id:t?.title,label:t?.title,placeholder:"Type to search…",items:n,selectedKeys:o,onChange:(e,r)=>{i(e),a.emit("filterChanged",t,{[t.filter]:e})},onInputChange:e=>{c(e)},loading:s,debounceMs:300,helperText:o.length?`${o.length} selected`:""})))};function se({items:e,value:t,label:a,onChange:r,sx:n={width:"100%"},disabled:l=!1}){const o=e.some(e=>e.key===t)?t:"";return R.default.createElement(j.default,{sx:n},R.default.createElement($.default,{fullWidth:!0},R.default.createElement(z.default,{id:"demo-simple-select-label"},a),R.default.createElement(B.default,{labelId:"demo-simple-select-label",id:"demo-simple-select",value:o,label:a,onChange:r,disabled:l,MenuProps:{style:{maxHeight:"300px"}},size:"small"},e.map(e=>{const{key:t,value:a,disabled:r}=e;return R.default.createElement(Y.default,{key:t,value:t,disabled:r},a)}))))}const ue=({filter:t,channel:a,query:r})=>{const[n,l]=e.useState([]),[o,i]=e.useState("");return e.useEffect(()=>{i(r?.date_range?.name)},[r]),e.useEffect(()=>{(async()=>{const e=(await Z.getDateRanges()).filter(e=>!(t.allowedOptions.length>0)||t.allowedOptions.some(t=>t===e.name)).map(e=>({key:e.name,value:e.title}));l(e)})()},[]),R.default.createElement("div",{style:{minWidth:"200px",maxWidth:"640px"}},R.default.createElement(se,{items:n,value:o,label:t?.title,onChange:(e,r)=>{const n=e.target.value;i(n),a.emit("filterChanged",t,{date_range:{name:n}})}}))},de=({filters:e=[],channel:t,query:a})=>R.default.createElement("div",{style:{display:"flex",flexWrap:"wrap",gap:"8px"}},e.map(e=>"multi-select"===e.type?R.default.createElement(ie,{key:e.title,channel:t,filter:e,query:a}):"date-range"===e.type?R.default.createElement(ue,{key:e.title,channel:t,filter:e,query:a}):null));var ce=e=>R.default.useRef(e||new U.default).current,fe=e=>{const t=R.default.useState({}),a=R.default.useCallback((a,r)=>{let n={...t.current,...r};for(var l in t.current=n,n)"date_range"===l||n[l].length||delete n[l];e?.emit("mergedFilterChanged",{value:n})},[e]);R.default.useEffect(()=>(e?.on("filterChanged",a),()=>{e?.off("filterChanged",a)}),[e])},me=({id:e,cache:t,dashboard:a,channel:r,...n})=>{const[l,o]=R.default.useState(),[i,s]=R.default.useState(),[u,d]=R.default.useState(),[c,m]=R.default.useState(),[p,h]=R.default.useState(re()),[y,g]=R.default.useState(),[b,v]=R.default.useState(0),[E,w]=R.default.useState(!1),[x,C]=R.default.useState(),[S,k]=R.default.useState(!1),M=R.default.useRef({value:n?.filter}),[A,T]=R.default.useState({}),{ref:P,inView:_,entry:j}=f.useInView({threshold:.1,delay:1e3}),z=ce(r);fe(z);const Y=R.default.useCallback(e=>{const t=e.target.value;v(t),g(l.doc.view[t])},[l]);R.default.useEffect(()=>{e&&(async()=>{const a=e,r=t?.[a]||await Z.getChart({id:a}),l=r.doc.source?.id,i=l?t?.[l]||await Z.getReport({id:l}):void 0,u=t?.[`schema_${l}`]||n?.schema||await Z.getReportSchema({id:l}),c=r.doc?.view?.[0];v(0),s(i),o(r),g(c),d(u),k(!0)})().catch(e=>{console.error(e.message)})},[e]),R.default.useEffect(()=>{l&&c&&(!l?.doc?.source?.id||i)&&u&&(async()=>{h(re(l.doc.chart?.component,{view:y,source:c,chart:l,report:i,schema:u,dashboard:a,query:A}))})().catch(e=>{console.error(e.message)})},[l,c,y,i,u]);const $=e=>{const t={...i?.doc.query.filter||{},...n?.filter,...e?.value},a=t.date_range||i?.doc.query.date_range;if(delete t.date_range,k(!1),C(),w(!0),"context"===l?.doc?.source?.type)return m({filter:t}),void w(!1);const r={filter:t,date_range:a,parameters:n?.params};T(r),Z.runReport({id:i.id,query:r}).then(e=>{m(l.doc.source.reverse?e.reverse():e)}).catch(e=>{m([])}).finally(()=>{w(!1)})},B=e=>{M.current=e,_?$(e):(C(e),k(!0))};return R.default.useEffect(()=>(z?.on("mergedFilterChanged",B),()=>{z?.off("mergedFilterChanged",B)}),[z,i,l,_]),R.default.useEffect(()=>{_&&S&&$(x)},[_,S]),R.default.useEffect(()=>{k(!0)},[n.params]),R.default.createElement(q.default,{ref:P,elevation:0,style:{borderRadius:12,padding:20,border:"1px solid #e5e5e5",background:"#fff",display:"flex",flexDirection:"column",gap:"12px",height:"100%"}},l&&R.default.createElement("div",{style:{display:"flex",alignItems:"center",lineHeight:0}},R.default.createElement(I.default,{variant:"subtitle2",style:{fontWeight:600,color:"#252525"}},n?.title||l.doc.name," ")),E?R.default.createElement(H,{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100%",width:"100%"}}):R.default.createElement(R.default.Fragment,null,R.default.createElement("div",{style:{display:"flex"}},R.default.createElement("div",{style:{flexGrow:1}}),R.default.createElement("div",null,l?.doc?.view?.length>1&&R.default.createElement(O.default,null,R.default.createElement(D.default,{labelId:"date-range-select-label",id:"date-range-select",value:b,onChange:Y,style:{fontSize:"12px"},disableUnderline:!0},l.doc.view.map((e,t)=>R.default.createElement(F.default,{key:t,value:t},e.title)))))),R.default.createElement("div",{style:{position:"relative",flexGrow:a?void 0:1,display:"flex",flexDirection:"column"}},R.default.createElement(de,{filters:l?.doc?.filters,channel:z,query:A}),p)))};const pe=e.createContext(void 0),he=()=>e.useContext(pe);var ye={Chart:me,Dashboard:function({id:t="sample_dashboard",api:a,params:r}){const n=he(),l=a||n?.api||{},o=r||n?.parameters||{},[i,s]=R.default.useState(),[u]=R.default.useState(),[d,c]=R.default.useState([]),f=R.default.useRef({}),m=ce();fe(m),console.log({rows:d},{dashboard:i},{schema:u},{params:o}),e.useEffect(()=>{Z.setBaseUrl(l.base_url),Z.setToken(l.token)},[l]);const p=async e=>{const t=e?.doc?.rows||[],a=[];for(let e=0;e<t.length;e++){const r=t[e];r.columns?.forEach(e=>{if(e.override?.filter?.length){const t={};e.override.filter.forEach(e=>{e.hasOwnProperty("value")&&(t[e.field]=[e.value])}),e.filter=t}}),a.push(r)}c(a)};return R.default.useEffect(()=>{t&&(async()=>{Z.setBaseUrl(l.base_url),Z.setToken(l.token),await Z.loadDashboardMeta({dashboardId:t});const e=await Z.getDashboard({id:t});f.current[e?.id]=e,s(e),await p(e)})().catch(e=>console.error(e.message))},[t]),R.default.createElement(W.default,{maxWidth:!1,disableGutters:!0},R.default.createElement(L.default,{container:!0,spacing:3},d?.map((e,t)=>{const a=(e=>0===e?12:12/e)(e.columns.length);return R.default.createElement(R.default.Fragment,{key:t},1===t?R.default.createElement(L.default,{item:!0,xs:12},R.default.createElement(L.default,{container:!0,spacing:3},e.columns.map((e,t)=>R.default.createElement(L.default,{key:t,item:!0,xs:12,md:a},R.default.createElement(me,{api:l,cache:f.current,id:e.id,dashboard:i,schema:u,title:e.title,filter:e.filter,params:o}))))):e.columns.map((e,t)=>R.default.createElement(L.default,{key:t,item:!0,xs:12,md:a},R.default.createElement(me,{api:l,cache:f.current,id:e.id,dashboard:i,schema:u,title:e.title,filter:e.filter,params:o}))))})))},ReportingProvider:({defaultParameters:t={},defaultApi:a={},children:r})=>{const[n,l]=e.useState(t),[o,i]=e.useState(a),s={parameters:n,setParameters:l,api:o,setApi:i,setReportingContext:({parameters:e,api:t})=>{void 0!==e&&l(e),void 0!==t&&i(t)}};return R.default.createElement(pe.Provider,{value:s},r)},useReportingContext:()=>{const t=e.useContext(pe);if(void 0===t)throw new Error("useReportingContext must be used within a ReportingProvider");return t},useReportingContextOptional:he};exports.default=ye;
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
- import React__default, { useEffect, useMemo, useState, useRef } from 'react';
2
+ import React__default, { useEffect, useMemo, useState, useRef, useContext, createContext } from 'react';
3
3
  import Paper from '@material-ui/core/Paper';
4
4
  import { makeStyles } from '@material-ui/core/styles';
5
- import LinearProgress from '@material-ui/core/LinearProgress';
5
+ import { CircularProgress } from '@material-ui/core';
6
6
  import { Chart as Chart$1 } from 'react-google-charts';
7
7
  import numeral from 'numeral';
8
8
  import axios from 'axios';
@@ -12,7 +12,7 @@ import FormControl$2 from '@material-ui/core/FormControl';
12
12
  import Select$1 from '@material-ui/core/Select';
13
13
  import MenuItem$1 from '@material-ui/core/MenuItem';
14
14
  import { useInView } from 'react-intersection-observer';
15
- import { FormControl, Autocomplete, TextField, CircularProgress, Chip, Checkbox, FormHelperText } from '@mui/material';
15
+ import { FormControl, Autocomplete, TextField, CircularProgress as CircularProgress$1, Chip, Checkbox, FormHelperText } from '@mui/material';
16
16
  import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
17
17
  import CheckBoxIcon from '@mui/icons-material/CheckBox';
18
18
  import Box from '@mui/material/Box';
@@ -22,7 +22,6 @@ import FormControl$1 from '@mui/material/FormControl';
22
22
  import Select from '@mui/material/Select';
23
23
  import EventEmitter from 'eventemitter3';
24
24
  import Grid from '@material-ui/core/Grid';
25
- import Box$1 from '@material-ui/core/Box';
26
25
  import Container from '@material-ui/core/Container';
27
26
 
28
27
  function _extends() {
@@ -37,8 +36,8 @@ function _extends() {
37
36
 
38
37
  const useStyles$1 = makeStyles(theme => ({
39
38
  root: {
40
- width: '100%',
41
- '& > * + *': {
39
+ width: "100%",
40
+ "& > * + *": {
42
41
  marginTop: theme.spacing(2)
43
42
  }
44
43
  }
@@ -47,7 +46,13 @@ function LinearIndeterminate(props) {
47
46
  const classes = useStyles$1();
48
47
  return /*#__PURE__*/React__default.createElement("div", _extends({
49
48
  className: classes.root
50
- }, props), /*#__PURE__*/React__default.createElement(LinearProgress, null));
49
+ }, props), /*#__PURE__*/React__default.createElement(CircularProgress, {
50
+ style: {
51
+ color: "rgb(70, 134, 128)"
52
+ } // custom color
53
+ ,
54
+ size: 25
55
+ }));
51
56
  }
52
57
 
53
58
  function ValuePicker(view, schema, outputFormat = 'array') {
@@ -275,6 +280,43 @@ const Api = {
275
280
  } = await apiClient.post(`/report-build/run`, report);
276
281
  return data;
277
282
  },
283
+ /**
284
+ * Download ad-hoc report as CSV
285
+ * @param {Object} params - Parameters object
286
+ * @param {Object} params.report - Report definition object containing dimensions, metrics, etc.
287
+ * @param {string} [params.filename] - Optional filename for the downloaded file
288
+ * @returns {Promise} Downloads CSV file
289
+ */
290
+ downloadAdHocReport: async ({
291
+ report,
292
+ filename
293
+ }) => {
294
+ const response = await apiClient.post(`/report-build/run?download=csv`, report, {
295
+ responseType: 'blob'
296
+ });
297
+
298
+ // Create a download link and trigger download
299
+ const url = window.URL.createObjectURL(new Blob([response.data]));
300
+ const link = document.createElement('a');
301
+ link.href = url;
302
+
303
+ // Use provided filename, or extract from Content-Disposition header, or use default
304
+ let finalFilename = filename || 'report.csv';
305
+ if (!filename) {
306
+ const contentDisposition = response.headers['content-disposition'];
307
+ if (contentDisposition) {
308
+ const filenameMatch = contentDisposition.match(/filename="?(.+)"?/i);
309
+ if (filenameMatch && filenameMatch[1]) {
310
+ finalFilename = filenameMatch[1];
311
+ }
312
+ }
313
+ }
314
+ link.setAttribute('download', finalFilename);
315
+ document.body.appendChild(link);
316
+ link.click();
317
+ link.remove();
318
+ window.URL.revokeObjectURL(url);
319
+ },
278
320
  getDateRanges: async ({
279
321
  dashboardId
280
322
  } = {}) => {
@@ -384,11 +426,11 @@ const useStyles = makeStyles(theme => ({
384
426
  // },
385
427
  }));
386
428
  const dateRangeFormats = {
387
- "none": "YYYY-MM-dd",
388
- "day": "MMM dd",
389
- "week": "MMM dd",
390
- "month": "YYYY MMM",
391
- "year": "YYYY"
429
+ none: "YYYY-MM-dd",
430
+ day: "MMM dd",
431
+ week: "MMM dd",
432
+ month: "YYYY MMM",
433
+ year: "YYYY"
392
434
  };
393
435
  function GoogleChart({
394
436
  chart,
@@ -409,7 +451,7 @@ function GoogleChart({
409
451
  })();
410
452
  }, []);
411
453
  const dateRangeFormat = useMemo(() => {
412
- const defaultFormat = 'YYYY-MM-dd';
454
+ const defaultFormat = "YYYY-MM-dd";
413
455
  const name = query?.date_range?.name;
414
456
  const dateRange = dateRanges.find(f => f.name === name);
415
457
  if (!dateRange) return defaultFormat;
@@ -417,12 +459,14 @@ function GoogleChart({
417
459
  return format;
418
460
  }, [dateRanges, query]);
419
461
  const getOptions = data => {
420
- if (chart?.doc.chart?.type === 'Table') {
462
+ const customColors = ["#468682", "#ff686b", "#6c757d", "#FFD700", "#073b4c"]; // your custom colors
463
+
464
+ if (chart?.doc.chart?.type === "Table") {
421
465
  return {
422
466
  ...chart?.doc.chart?.options,
423
467
  cssClassNames: classes
424
468
  };
425
- } else if (chart?.doc.chart?.type === 'AreaChart') {
469
+ } else if (chart?.doc.chart?.type === "AreaChart") {
426
470
  const hAxisFromChart = chart?.doc.chart?.options?.hAxis || {};
427
471
  const hAxisDefaults = {
428
472
  ticks: data.slice(1).map(row => row[0]),
@@ -432,17 +476,18 @@ function GoogleChart({
432
476
  ...hAxisDefaults,
433
477
  ...hAxisFromChart
434
478
  };
435
-
436
- // console.log({GoogleChart:{chart,source,view,report,schema,query,dateRanges,dateRangeFormat,ticks:hAxis.ticks}})
437
-
438
479
  return {
439
480
  ...chart?.doc.chart?.options,
440
- ...{
441
- hAxis,
442
- focusTarget: 'category'
443
- }
481
+ hAxis,
482
+ focusTarget: "category",
483
+ colors: customColors // <-- add this line
444
484
  };
445
- } else return chart?.doc.chart?.options;
485
+ } else {
486
+ return {
487
+ ...chart?.doc.chart?.options,
488
+ colors: customColors // add for other chart types too
489
+ };
490
+ }
446
491
  };
447
492
  React__default.useEffect(() => {
448
493
  if (!chart || !view || !source || !report || !schema) return;
@@ -458,7 +503,7 @@ function GoogleChart({
458
503
  return data ? /*#__PURE__*/React__default.createElement("div", {
459
504
  style: {}
460
505
  }, /*#__PURE__*/React__default.createElement(Chart$1, _extends({
461
- width: chart?.doc.size?.width || '100%'
506
+ width: chart?.doc.size?.width || "100%"
462
507
  //height={dashboard ? (chart?.doc.size?.height || '300px') : '100%'}
463
508
  ,
464
509
  chartType: chart?.doc.chart?.type,
@@ -660,7 +705,7 @@ function CheckboxMultiAutocomplete({
660
705
  placeholder: placeholder,
661
706
  InputProps: {
662
707
  ...params.InputProps,
663
- endAdornment: /*#__PURE__*/React.createElement(React.Fragment, null, loading ? /*#__PURE__*/React.createElement(CircularProgress, {
708
+ endAdornment: /*#__PURE__*/React.createElement(React.Fragment, null, loading ? /*#__PURE__*/React.createElement(CircularProgress$1, {
664
709
  size: 18
665
710
  }) : null, params.InputProps.endAdornment)
666
711
  },
@@ -739,7 +784,8 @@ function SingleSelect({
739
784
  onChange,
740
785
  sx = {
741
786
  width: '100%'
742
- }
787
+ },
788
+ disabled = false
743
789
  }) {
744
790
  // Check if the current value exists in items, otherwise use empty string
745
791
  const validValue = items.some(itm => itm.key === value) ? value : '';
@@ -755,6 +801,7 @@ function SingleSelect({
755
801
  value: validValue,
756
802
  label: label,
757
803
  onChange: onChange,
804
+ disabled: disabled,
758
805
  MenuProps: {
759
806
  style: {
760
807
  maxHeight: '300px'
@@ -909,7 +956,7 @@ var Chart = ({
909
956
  entry
910
957
  } = useInView({
911
958
  /* Optional options */
912
- threshold: 0.10,
959
+ threshold: 0.1,
913
960
  delay: 1000
914
961
  });
915
962
  const channelUsed = useChannel(channel);
@@ -1002,7 +1049,7 @@ var Chart = ({
1002
1049
  setDirty(false);
1003
1050
  setFilter();
1004
1051
  setLoading(true);
1005
- if (chart?.doc?.source?.type === 'context') {
1052
+ if (chart?.doc?.source?.type === "context") {
1006
1053
  setSource({
1007
1054
  filter: finalFilter
1008
1055
  });
@@ -1038,9 +1085,9 @@ var Chart = ({
1038
1085
  }
1039
1086
  };
1040
1087
  React__default.useEffect(() => {
1041
- channelUsed?.on('mergedFilterChanged', onMergedFilterChanged);
1088
+ channelUsed?.on("mergedFilterChanged", onMergedFilterChanged);
1042
1089
  return () => {
1043
- channelUsed?.off('mergedFilterChanged', onMergedFilterChanged);
1090
+ channelUsed?.off("mergedFilterChanged", onMergedFilterChanged);
1044
1091
  };
1045
1092
  }, [channelUsed, report, chart, inView]);
1046
1093
  React__default.useEffect(() => {
@@ -1052,37 +1099,42 @@ var Chart = ({
1052
1099
  }, [props.params]);
1053
1100
  return /*#__PURE__*/React__default.createElement(Paper, {
1054
1101
  ref: ref,
1102
+ elevation: 0,
1055
1103
  style: {
1056
- //margin: "4px",
1057
- padding: "16px",
1058
- paddingTop: 0,
1059
- //flexGrow: dashboard ? undefined : 1, display: "flex", flexDirection: "column",
1060
- flexGrow: 1,
1061
- // gap:'16px',
1062
1104
  borderRadius: 12,
1063
- display: 'flex',
1064
- flexDirection: 'column',
1065
- gap: '16px'
1066
- },
1067
- elevation: 2
1068
- }, /*#__PURE__*/React__default.createElement(LinearIndeterminate, {
1105
+ padding: 20,
1106
+ border: "1px solid #e5e5e5",
1107
+ background: "#fff",
1108
+ display: "flex",
1109
+ flexDirection: "column",
1110
+ gap: "12px",
1111
+ height: "100%"
1112
+ }
1113
+ }, chart && /*#__PURE__*/React__default.createElement("div", {
1069
1114
  style: {
1070
- visibility: loading ? 'visible' : 'hidden'
1115
+ display: "flex",
1116
+ alignItems: "center",
1117
+ lineHeight: 0
1071
1118
  }
1072
- }), /*#__PURE__*/React__default.createElement("div", {
1119
+ }, /*#__PURE__*/React__default.createElement(Typography, {
1120
+ variant: "subtitle2",
1073
1121
  style: {
1074
- display: "flex"
1122
+ fontWeight: 600,
1123
+ color: "#252525"
1075
1124
  }
1076
- }, /*#__PURE__*/React__default.createElement("div", null, chart && /*#__PURE__*/React__default.createElement("div", {
1125
+ }, props?.title || chart.doc.name, " ")), loading ? /*#__PURE__*/React__default.createElement(LinearIndeterminate, {
1077
1126
  style: {
1078
1127
  display: "flex",
1128
+ justifyContent: "center",
1079
1129
  alignItems: "center",
1080
- lineHeight: 0
1130
+ height: "100%",
1131
+ width: "100%"
1081
1132
  }
1082
- }, /*#__PURE__*/React__default.createElement(Typography, {
1083
- noWrap: true,
1084
- variant: "caption"
1085
- }, props?.title || chart.doc.name, " "))), /*#__PURE__*/React__default.createElement("div", {
1133
+ }) : /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("div", {
1134
+ style: {
1135
+ display: "flex"
1136
+ }
1137
+ }, /*#__PURE__*/React__default.createElement("div", {
1086
1138
  style: {
1087
1139
  flexGrow: 1
1088
1140
  }
@@ -1105,15 +1157,99 @@ var Chart = ({
1105
1157
  // paddingTop: chart?.doc?.size?.vpad,
1106
1158
  // paddingBottom: chart?.doc?.size?.vpad,
1107
1159
  flexGrow: dashboard ? undefined : 1,
1108
- display: 'flex',
1109
- flexDirection: 'column'
1160
+ display: "flex",
1161
+ flexDirection: "column"
1110
1162
  // gap:'16px'
1111
1163
  }
1112
1164
  }, /*#__PURE__*/React__default.createElement(ChartFilters, {
1113
1165
  filters: chart?.doc?.filters,
1114
1166
  channel: channelUsed,
1115
1167
  query: currentQuery
1116
- }), chartType));
1168
+ }), chartType)));
1169
+ };
1170
+
1171
+ // Create the context
1172
+ const ReportingContext = /*#__PURE__*/createContext(undefined);
1173
+
1174
+ /**
1175
+ * ReportingProvider - Provides reporting configuration context to child components
1176
+ *
1177
+ * @param {Object} props
1178
+ * @param {Object} [props.defaultParameters] - Default parameters for reports (base_currency, merchants, client, etc.)
1179
+ * @param {Object} [props.defaultApi] - Default API configuration (token, base_url)
1180
+ * @param {React.ReactNode} props.children - Child components
1181
+ */
1182
+ const ReportingProvider = ({
1183
+ defaultParameters = {},
1184
+ defaultApi = {},
1185
+ children
1186
+ }) => {
1187
+ const [parameters, setParameters] = useState(defaultParameters);
1188
+ const [api, setApi] = useState(defaultApi);
1189
+ const value = {
1190
+ parameters,
1191
+ setParameters,
1192
+ api,
1193
+ setApi,
1194
+ // Convenience method to update both at once
1195
+ setReportingContext: ({
1196
+ parameters: newParams,
1197
+ api: newApi
1198
+ }) => {
1199
+ if (newParams !== undefined) {
1200
+ setParameters(newParams);
1201
+ }
1202
+ if (newApi !== undefined) {
1203
+ setApi(newApi);
1204
+ }
1205
+ }
1206
+ };
1207
+ return /*#__PURE__*/React__default.createElement(ReportingContext.Provider, {
1208
+ value: value
1209
+ }, children);
1210
+ };
1211
+
1212
+ /**
1213
+ * useReportingContext - Hook to access reporting context
1214
+ *
1215
+ * @returns {Object} Context value with parameters, api, and setter functions
1216
+ * @returns {Object} return.parameters - Current parameters object
1217
+ * @returns {Function} return.setParameters - Function to update parameters
1218
+ * @returns {Object} return.api - Current API configuration
1219
+ * @returns {Function} return.setApi - Function to update API configuration
1220
+ * @returns {Function} return.setReportingContext - Function to update both parameters and api
1221
+ *
1222
+ * @example
1223
+ * const { parameters, setParameters, api, setApi, setReportingContext } = useReportingContext();
1224
+ *
1225
+ * // Update parameters only
1226
+ * setParameters({ base_currency: 'USD', merchants: [...] });
1227
+ *
1228
+ * // Update API only
1229
+ * setApi({ token: 'new-token', base_url: 'https://api.example.com' });
1230
+ *
1231
+ * // Update both at once
1232
+ * setReportingContext({
1233
+ * parameters: { base_currency: 'EUR' },
1234
+ * api: { token: 'token', base_url: 'https://api.example.com' }
1235
+ * });
1236
+ */
1237
+ const useReportingContext = () => {
1238
+ const context = useContext(ReportingContext);
1239
+ if (context === undefined) {
1240
+ throw new Error('useReportingContext must be used within a ReportingProvider');
1241
+ }
1242
+ return context;
1243
+ };
1244
+
1245
+ /**
1246
+ * useReportingContextOptional - Hook to optionally access reporting context
1247
+ * Returns null if used outside of ReportingProvider (useful for optional fallback)
1248
+ *
1249
+ * @returns {Object|null} Context value or null if not within provider
1250
+ */
1251
+ const useReportingContextOptional = () => {
1252
+ return useContext(ReportingContext);
1117
1253
  };
1118
1254
 
1119
1255
  function Dashboard({
@@ -1121,6 +1257,11 @@ function Dashboard({
1121
1257
  api,
1122
1258
  params
1123
1259
  }) {
1260
+ const reportingContext = useReportingContextOptional();
1261
+
1262
+ // Use props if provided, otherwise fall back to context
1263
+ const finalApi = api || reportingContext?.api || {};
1264
+ const finalParams = params || reportingContext?.parameters || {};
1124
1265
  const [dashboard, setDashboard] = React__default.useState();
1125
1266
  //const [schema, setSchema] = React.useState();
1126
1267
  const [schema] = React__default.useState();
@@ -1128,15 +1269,24 @@ function Dashboard({
1128
1269
  const cache = React__default.useRef({});
1129
1270
  const channel = useChannel();
1130
1271
  useFilterManager(channel);
1272
+ console.log({
1273
+ rows
1274
+ }, {
1275
+ dashboard
1276
+ }, {
1277
+ schema
1278
+ }, {
1279
+ params: finalParams
1280
+ });
1131
1281
  useEffect(() => {
1132
- // console.log('token changed',api);
1282
+ // console.log('token changed',finalApi);
1133
1283
 
1134
- Api.setBaseUrl(api.base_url);
1135
- Api.setToken(api.token);
1136
- }, [api]);
1284
+ Api.setBaseUrl(finalApi.base_url);
1285
+ Api.setToken(finalApi.token);
1286
+ }, [finalApi]);
1137
1287
  const init = async () => {
1138
- Api.setBaseUrl(api.base_url);
1139
- Api.setToken(api.token);
1288
+ Api.setBaseUrl(finalApi.base_url);
1289
+ Api.setToken(finalApi.token);
1140
1290
  await Api.loadDashboardMeta({
1141
1291
  dashboardId: id
1142
1292
  });
@@ -1161,7 +1311,7 @@ function Dashboard({
1161
1311
  if (column.override?.filter?.length) {
1162
1312
  const filter = {};
1163
1313
  column.override.filter.forEach(item => {
1164
- if (item.hasOwnProperty('value')) filter[item.field] = [item.value];
1314
+ if (item.hasOwnProperty("value")) filter[item.field] = [item.value];
1165
1315
  // else filter[item.field] = [sourceDataRow[item.field]];
1166
1316
  });
1167
1317
  column.filter = filter;
@@ -1175,6 +1325,10 @@ function Dashboard({
1175
1325
  if (!id) return;
1176
1326
  init().catch(error => console.error(error.message));
1177
1327
  }, [id]);
1328
+ const getMd = count => {
1329
+ if (count === 0) return 12;
1330
+ return 12 / count;
1331
+ };
1178
1332
  return (
1179
1333
  /*#__PURE__*/
1180
1334
  // <Container>
@@ -1203,59 +1357,70 @@ function Dashboard({
1203
1357
  // </Container>
1204
1358
  React__default.createElement(Container, {
1205
1359
  maxWidth: false,
1206
- disableGutters: true,
1207
- style: {
1208
- // backgroundColor:'yellow',
1209
- height: '100vh',
1210
- padding: 0,
1211
- margin: 0,
1212
- overflow: 'hidden'
1213
- }
1360
+ disableGutters: true
1361
+ // style={{
1362
+ // padding: "24px",
1363
+ // background: "#f7f8fa",
1364
+ // borderRadius: "10px",
1365
+ // }}
1214
1366
  }, /*#__PURE__*/React__default.createElement(Grid, {
1215
1367
  container: true,
1216
- spacing: 2,
1217
- style: {
1218
- height: '100%',
1219
- width: '100%'
1220
- }
1221
- }, rows?.map((row, rowIndex) => /*#__PURE__*/React__default.createElement(Grid, {
1222
- key: rowIndex,
1223
- container: true,
1224
- item: true
1225
- // important: make items in this row stretch to same height
1226
- ,
1227
- alignItems: "stretch",
1228
- spacing: 2
1229
- }, row?.columns?.map((column, colIndex) => /*#__PURE__*/React__default.createElement(Grid, {
1230
- key: colIndex,
1231
- item: true,
1232
- xs: true,
1233
- style: {
1234
- display: 'flex'
1235
- }
1236
- }, /*#__PURE__*/React__default.createElement(Box$1, {
1237
- style: {
1238
- flex: 1,
1239
- display: 'flex',
1240
- flexDirection: 'column'
1241
- }
1242
- }, /*#__PURE__*/React__default.createElement(Chart, {
1243
- api: api,
1244
- cache: cache.current,
1245
- id: column.id,
1246
- dashboard: dashboard,
1247
- schema: schema,
1248
- channel: null,
1249
- title: column.title,
1250
- filter: column.filter,
1251
- params: params
1252
- }))))))))
1368
+ spacing: 3
1369
+ }, rows?.map((row, rowIndex) => {
1370
+ const count = row.columns.length;
1371
+ const md = getMd(count);
1372
+ return /*#__PURE__*/React__default.createElement(React__default.Fragment, {
1373
+ key: rowIndex
1374
+ }, rowIndex === 1 ?
1375
+ /*#__PURE__*/
1376
+ // Row 2 is special: nested grid inside a full-width container
1377
+ React__default.createElement(Grid, {
1378
+ item: true,
1379
+ xs: 12
1380
+ }, /*#__PURE__*/React__default.createElement(Grid, {
1381
+ container: true,
1382
+ spacing: 3
1383
+ }, row.columns.map((column, i) => /*#__PURE__*/React__default.createElement(Grid, {
1384
+ key: i,
1385
+ item: true,
1386
+ xs: 12,
1387
+ md: md
1388
+ }, /*#__PURE__*/React__default.createElement(Chart, {
1389
+ api: finalApi,
1390
+ cache: cache.current,
1391
+ id: column.id,
1392
+ dashboard: dashboard,
1393
+ schema: schema,
1394
+ title: column.title,
1395
+ filter: column.filter,
1396
+ params: finalParams
1397
+ }))))) :
1398
+ // All other rows behave normally
1399
+ row.columns.map((column, i) => /*#__PURE__*/React__default.createElement(Grid, {
1400
+ key: i,
1401
+ item: true,
1402
+ xs: 12,
1403
+ md: md
1404
+ }, /*#__PURE__*/React__default.createElement(Chart, {
1405
+ api: finalApi,
1406
+ cache: cache.current,
1407
+ id: column.id,
1408
+ dashboard: dashboard,
1409
+ schema: schema,
1410
+ title: column.title,
1411
+ filter: column.filter,
1412
+ params: finalParams
1413
+ }))));
1414
+ })))
1253
1415
  );
1254
1416
  }
1255
1417
 
1256
1418
  var index = {
1257
1419
  Chart,
1258
- Dashboard
1420
+ Dashboard,
1421
+ ReportingProvider,
1422
+ useReportingContext,
1423
+ useReportingContextOptional
1259
1424
  };
1260
1425
 
1261
1426
  export { index as default };