From 9570e1ccee673e3def2989b1ff134858f67252e2 Mon Sep 17 00:00:00 2001 From: MGJamJam Date: Thu, 11 Jul 2024 10:17:53 -0300 Subject: [PATCH] v1.1.0 --- CHANGELOG.md | 2 ++ dist/CHANGELOG.md | 10 ++++++++++ dist/README.md | 7 +++++++ dist/module.js | 2 +- dist/module.js.map | 2 +- dist/plugin.json | 4 ++-- package.json | 2 +- 7 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecb3196..edbd7e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Development +## 1.1.0 + ### Added - `MONTH` option to interval selection diff --git a/dist/CHANGELOG.md b/dist/CHANGELOG.md index 7593d87..edbd7e9 100644 --- a/dist/CHANGELOG.md +++ b/dist/CHANGELOG.md @@ -2,6 +2,16 @@ ## Development +## 1.1.0 + +### Added + +- `MONTH` option to interval selection + +### Changed + +- improved fetching and handling of possibly incomplete first Datapoint + ## 1.0.0 - Migrate angular-based plugin to Grafana's React-based plugin platform. diff --git a/dist/README.md b/dist/README.md index 4e26da7..7cbe264 100644 --- a/dist/README.md +++ b/dist/README.md @@ -50,6 +50,13 @@ To compare e.g. impressions per browser, we provide the `Group By` attribute to Configure the metric as described in [Time Series Graph](#time-series-graph) but uncheck the `Format as time series` option and add a `Group By` dimension. It is recommended to add a limit (e.g. 10). +## Gauges + +Configure the Gauge's `Value Options`, depending on your query. + +- For table data (`Format as time series` option **unchecked**) for the `Show` option select `All Values`. +- For time series data (`Format as time series` option **checked**) for the `Show` option select `Calculate` and choose a reducer function. + ## Support Please refer to our [Documentation](https://developer.bitmovin.com/playback/docs/integrating-bitmovin-analytics-with-grafana) and [Analytics Api Reference](https://developer.bitmovin.com/playback/reference/overview) for more information or reach out to us at [bitmovin.com](https://bitmovin.com/contact-bitmovin/). diff --git a/dist/module.js b/dist/module.js index f4752c4..bca4ae3 100644 --- a/dist/module.js +++ b/dist/module.js @@ -1,2 +1,2 @@ -define(["@grafana/data","@grafana/runtime","lodash","rxjs","react","@grafana/ui"],((e,t,n,r,a,o)=>(()=>{"use strict";var l={781:t=>{t.exports=e},531:e=>{e.exports=t},7:e=>{e.exports=o},241:e=>{e.exports=n},959:e=>{e.exports=a},269:e=>{e.exports=r}},i={};function s(e){var t=i[e];if(void 0!==t)return t.exports;var n=i[e]={exports:{}};return l[e](n,n.exports,s),n.exports}s.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return s.d(t,{a:t}),t},s.d=(e,t)=>{for(var n in t)s.o(t,n)&&!s.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},s.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),s.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var c={};return(()=>{s.r(c),s.d(c,{plugin:()=>te});var e=s(781),t=s(531),n=s(241),r=s(269);const a={license:"",orderBy:[],groupBy:[],filter:[],resultFormat:"time_series",interval:"AUTO"},o=[{value:"AUTO",label:"Auto"},{value:"MINUTE",label:"Minute"},{value:"HOUR",label:"Hour"},{value:"DAY",label:"Day"}],l=o[0];function i(e,t,r,a){if(0===e.length)return[];const o=(e=>{switch(e){case"MINUTE":return 6e4;case"HOUR":return 36e5;case"DAY":return 864e5;default:return-1}})(a);if(o<0)throw new Error(`Query interval ${a} is not a valid interval.`);const l=function(e,t,n){const r=new Date(e);switch(t){case"MINUTE":return 0===r.getSeconds()&&0===r.getMilliseconds()?e:r.setMinutes(r.getMinutes()+1,0,0);case"HOUR":return 0===r.getMinutes()&&0===r.getSeconds()&&0===r.getMilliseconds()?e:r.setHours(r.getHours()+1,0,0,0);case"DAY":const t=new Date(n).getHours(),a=new Date(n).getMinutes(),o=new Date(r.getFullYear(),r.getMonth(),r.getDate(),t,a);return o.getTime()>e?o.getTime():new Date(o).setDate(o.getDate()+1)}}(t,a,e[0][0]);let i=[0];const s=[];e[0].length>2&&(i=[...e[0].slice(1,-1),0]);for(let e=l;e<=r;e+=o){const t=[e,...i];s.push(t)}const c=(0,n.differenceWith)(s,e,((e,t)=>e[0]===t[0])),u=e.concat(c),E=(0,n.sortBy)(u,(e=>e[0]));let A=0;for(;E[A][0]({value:e,label:e}))),A=e=>u.includes(e),T=(e,t,r,a)=>{if((0,n.isEmpty)(e)&&(e=>{switch(e){case"CDN_PROVIDER":case"CUSTOM_DATA_1":case"CUSTOM_DATA_2":case"CUSTOM_DATA_3":case"CUSTOM_DATA_4":case"CUSTOM_DATA_5":case"CUSTOM_DATA_6":case"CUSTOM_DATA_7":case"CUSTOM_DATA_8":case"CUSTOM_DATA_9":case"CUSTOM_DATA_10":case"CUSTOM_DATA_11":case"CUSTOM_DATA_12":case"CUSTOM_DATA_13":case"CUSTOM_DATA_14":case"CUSTOM_DATA_15":case"CUSTOM_DATA_16":case"CUSTOM_DATA_17":case"CUSTOM_DATA_18":case"CUSTOM_DATA_19":case"CUSTOM_DATA_20":case"CUSTOM_DATA_21":case"CUSTOM_DATA_22":case"CUSTOM_DATA_23":case"CUSTOM_DATA_24":case"CUSTOM_DATA_25":case"CUSTOM_DATA_26":case"CUSTOM_DATA_27":case"CUSTOM_DATA_28":case"CUSTOM_DATA_29":case"CUSTOM_DATA_30":case"CUSTOM_USER_ID":case"ERROR_CODE":case"EXPERIMENT_NAME":case"ISP":case"PLAYER_TECH":case"PLAYER_VERSION":case"VIDEO_ID":return!0;default:return!1}})(t))return null;if("IN"===r)try{return(e=>{const t=JSON.parse(e);if(!Array.isArray(t))throw new Error;return t})(e)}catch(e){throw new Error('Couldn\'t parse IN filter, please provide data in JSON array form (e.g.: ["Firefox", "Chrome"]).')}return a?((e,t)=>{switch(t){case"IS_LINEAR":return"true"===e;case"AD_STARTUP_TIME":case"AD_WRAPPER_ADS_COUNT":case"AUDIO_BITRATE":case"CLICK_POSITION":case"CLOSE_POSITION":case"ERROR_CODE":case"MANIFEST_DOWNLOAD_TIME":case"MIN_SUGGESTED_DURATION":case"PAGE_LOAD_TIME":case"PLAYER_STARTUPTIME":case"SCREEN_HEIGHT":case"SCREEN_WIDTH":case"SKIP_POSITION":case"TIME_HOVERED":case"TIME_IN_VIEWPORT":case"TIME_PLAYED":case"TIME_UNTIL_HOVER":case"VIDEO_BITRATE":case"VIDEO_WINDOW_HEIGHT":case"VIDEO_WINDOW_WIDTH":{const t=parseInt(e,10);if(isNaN(t))throw new Error("Couldn't parse filter value, please provide data as an integer number");return t}case"CLICK_PERCENTAGE":case"CLOSE_PERCENTAGE":case"PERCENTAGE_IN_VIEWPORT":case"SKIP_PERCENTAGE":{const t=parseFloat(e);if(isNaN(t))throw new Error("Couldn't parse filter value, please provide data as a floating point number");return t}default:return e}})(e,t):((e,t)=>{switch(t){case"IS_CASTING":case"IS_LIVE":case"IS_MUTED":return"true"===e;case"AUDIO_BITRATE":case"BUFFERED":case"CLIENT_TIME":case"DOWNLOAD_SPEED":case"DRM_LOAD_TIME":case"DROPPED_FRAMES":case"DURATION":case"ERROR_CODE":case"PAGE_LOAD_TIME":case"PAGE_LOAD_TYPE":case"PAUSED":case"PLAYED":case"PLAYER_STARTUPTIME":case"SCREEN_HEIGHT":case"SCREEN_WIDTH":case"SEEKED":case"STARTUPTIME":case"VIDEO_BITRATE":case"VIDEO_DURATION":case"VIDEO_PLAYBACK_HEIGHT":case"VIDEO_PLAYBACK_WIDTH":case"VIDEO_STARTUPTIME":case"VIDEO_WINDOW_HEIGHT":case"VIDEO_WINDOW_WIDTH":case"VIDEOTIME_END":case"VIDEOTIME_START":case"VIEWTIME":{const t=parseInt(e,10);if(isNaN(t))throw new Error("Couldn't parse filter value, please provide data as an integer number");return t}case"ERROR_PERCENTAGE":case"REBUFFER_PERCENTAGE":{const t=parseFloat(e);if(isNaN(t))throw new Error("Couldn't parse filter value, please provide data as a floating point number");return t}default:return e}})(e,t)};function _(e,t,n,r,a,o,l){try{var i=e[o](l),s=i.value}catch(e){return void n(e)}i.done?t(s):Promise.resolve(s).then(r,a)}function O(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function l(e){_(o,r,a,l,i,"next",e)}function i(e){_(o,r,a,l,i,"throw",e)}l(void 0)}))}}function d(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class I extends e.DataSourceApi{getDefaultQuery(e){return a}query(t){var a=this;return O((function*(){const{range:o}=t,l=o.from.toDate(),s=o.to.toDate(),c=t.targets=(0,n.filter)(t.targets,(e=>!e.hide)),u=(0,n.filter)(c,(e=>a.isQueryComplete(e))).map((E=O((function*(t){var o;const c="time_series"===t.resultFormat&&t.interval?((e,t,n)=>{if("AUTO"!==e)return e;const r=n-t;return r<=108e5?"MINUTE":r<=5184e5?"HOUR":"DAY"})(t.interval,l.getTime(),s.getTime()):void 0;let u=t.metric;const E="percentile"===u?t.percentileValue:void 0;let _,O;t.dimension&&(A(t.dimension)?_=t.dimension:O=t.dimension);const d={filters:t.filter.map((e=>({name:e.name,operator:e.operator,value:T(e.value,e.name,e.operator,!!a.isAdAnalytics)}))),groupBy:t.groupBy,orderBy:t.orderBy,dimension:O,metric:_,start:l,end:s,licenseKey:t.license,interval:c,limit:a.parseLimit(t.limit),percentile:E},I=yield(0,r.lastValueFrom)(a.request(a.getRequestUrl(_,u),"POST",d)),D=I.data.data.result.rows,p=I.data.data.result.rowCount,S=I.data.data.result.columnLabels,C=[];d.interval&&(null===(o=d.groupBy)||void 0===o?void 0:o.length)>0?C.push(...function(t,r,a,o){if(0===t.length)return[];const l=[],s=new Map;t.forEach((e=>{var t;const n=e.slice(1,-1).toString();s.has(n)||s.set(n,[]),null===(t=s.get(n))||void 0===t||t.push(e)}));const c=[];s.forEach((e=>{c.push(i(e,r,a,o))}));const u=(0,n.zip)(...c[0])[0];return l.push({name:"Time",values:u,type:e.FieldType.time}),c.forEach((t=>{const r=t[0].slice(1,-1).join(", "),a=(0,n.zip)(...t).slice(-1);l.push({name:r,values:a[0],type:e.FieldType.number})})),l}(D,l.getTime(),s.getTime(),d.interval)):d.interval?C.push(...function(t,r,a,o,l){if(0===t.length)return[];const s=[],c=i(t,a,o,l),u=(0,n.zip)(...c);return s.push({name:"Time",values:u[0],type:e.FieldType.time}),s.push({name:r,values:u[u.length-1],type:e.FieldType.number}),s}(D,S.length>0?S[S.length-1].label:"Column 1",l.getTime(),s.getTime(),d.interval)):C.push(...function(t,r){if(0===t.length)return[];const a=[],o=(0,n.zip)(...t);let l=[];if(0===r.length)for(let e=0;ee.label)));return t[0].length>1&&o.slice(0,-1).forEach(((t,n)=>{a.push({name:l[n],values:t,type:e.FieldType.string})})),a.push({name:l[l.length-1],values:o[o.length-1],type:e.FieldType.number}),a}(D,S));let R=[];return p>=200&&(R=[{severity:"warning",text:"Your request reached the max row limit of the API. You might see incomplete data. This problem might be caused by the use of high cardinality columns in group by, too small interval, or too big of a time range."}]),(0,e.createDataFrame)({name:t.alias,fields:C,meta:{notices:R}})})),function(e){return E.apply(this,arguments)}));var E;return Promise.all(u).then((e=>({data:e})))}))()}parseLimit(e){if(null!=e)return Number.isInteger(e)?e:parseInt(e,10)}isQueryComplete(e){return!((0,n.isEmpty)(e.license)||(0,n.isEmpty)(e.dimension)||null!=e.dimension&&!A(e.dimension)&&(0,n.isEmpty)(e.metric))}getRequestUrl(e,t){let n="/analytics";return!0===this.isAdAnalytics&&(n+="/ads"),null!=e?n+"/metrics/"+e:n+"/queries/"+t}request(e,n,r){const a={"X-Api-Key":this.apiKey};null!=this.tenantOrgId&&(a["X-Tenant-Org-Id"]=this.tenantOrgId);const o={url:this.baseUrl+e,headers:a,method:n,data:r};return(0,t.getBackendSrv)().fetch(o)}testDatasource(){var e=this;return O((function*(){return(0,r.lastValueFrom)(e.request("/analytics/licenses","GET").pipe((0,r.map)((()=>({status:"success",message:"Data source successfully setup and connected."}))),(0,r.catchError)((e=>{var t,n,a,o;let l="Bitmovin: ";e.status&&(l+=e.status+" "),e.statusText?l+=e.statusText:l+="Can not connect to Bitmovin API";let i,s=(null===(t=e.data)||void 0===t?void 0:t.message)||(null===(a=e.data)||void 0===a||null===(n=a.data)||void 0===n?void 0:n.message);var c,u;return(null===(o=e.data)||void 0===o?void 0:o.requestId)&&(i="Timestamp: "+(new Date).toISOString(),i+=(null===(c=e.data)||void 0===c?void 0:c.requestId)?"\nRequestId: "+(null===(u=e.data)||void 0===u?void 0:u.requestId):""),(0,r.of)({status:"error",message:l,details:{message:s,verboseMessage:i}})}))))}))()}constructor(e){super(e),d(this,"baseUrl",void 0),d(this,"apiKey",void 0),d(this,"tenantOrgId",void 0),d(this,"isAdAnalytics",void 0),this.apiKey=e.jsonData.apiKey,this.tenantOrgId=e.jsonData.tenantOrgId,this.isAdAnalytics=e.jsonData.isAdAnalytics,this.baseUrl=e.url}}var D=s(959),p=s.n(D),S=s(7);function C(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function R(e){for(var t=1;t({value:e.licenseKey,label:e.name?e.name:e.licenseKey})},{endpoint:"/analytics/virtual-licenses",mapperFunc:e=>({value:e.id,label:e.name?e.name:e.id})},{endpoint:"/analytics/demo-licenses",mapperFunc:e=>({value:e.id,label:e.name?e.name:e.id})}];function g(e,t,n,r){return M.apply(this,arguments)}function M(){return(M=h((function*(e,n,a,o){const l={"X-Api-Key":n};null!=o&&(l["X-Tenant-Org-Id"]=o);const i={url:e,headers:l,method:"GET"},s=(yield(0,r.lastValueFrom)((0,t.getBackendSrv)().fetch(i))).data.data.result.items,c=[];for(const e of s)c.push(a(e));return c}))).apply(this,arguments)}function f(){return(f=h((function*(e,t,n){const r=[];for(const a of v){const o=yield g(t+a.endpoint,e,a.mapperFunc,n);r.push(...o)}return r}))).apply(this,arguments)}const U=["count","sum","avg","min","max","stddev","percentile","variance","median"].map((e=>({value:e,label:e}))),P=["ADVERTISER_NAME","AD_CLICKTHROUGH_URL","AD_DESCRIPTION","AD_DURATION","AD_FALLBACK_INDEX","AD_ID","AD_ID_PLAYER","AD_IMPRESSION_ID","AD_IS_PERSISTENT","AD_MODULE","AD_OFFSET","AD_PLAYBACK_HEIGHT","AD_PLAYBACK_WIDTH","AD_POSITION","AD_PRELOAD_OFFSET","AD_REPLACE_CONTENT_DURATION","AD_SCHEDULE_TIME","AD_SKIPPABLE","AD_SKIP_AFTER","AD_STARTUP_TIME","AD_SYSTEM","AD_TAG_PATH","AD_TAG_SERVER","AD_TAG_TYPE","AD_TAG_URL","AD_TITLE","AD_WRAPPER_ADS_COUNT","ANALYTICS_VERSION","APIORG_ID","APIUSER_ID","API_FRAMEWORK","AUDIO_BITRATE","AUTOPLAY","BROWSER","BROWSER_IS_BOT","BROWSER_VERSION_MAJOR","BROWSER_VERSION_MINOR","CDN_PROVIDER","CITY","CLICKED","CLICK_PERCENTAGE","CLICK_POSITION","CLICK_RATE","CLIENT_TIME","CLOSED","CLOSE_PERCENTAGE","CLOSE_POSITION","COMPLETED","COUNTRY","CREATIVE_AD_ID","CREATIVE_ID","CUSTOM_DATA_1","CUSTOM_DATA_10","CUSTOM_DATA_11","CUSTOM_DATA_12","CUSTOM_DATA_13","CUSTOM_DATA_14","CUSTOM_DATA_15","CUSTOM_DATA_16","CUSTOM_DATA_17","CUSTOM_DATA_18","CUSTOM_DATA_19","CUSTOM_DATA_2","CUSTOM_DATA_20","CUSTOM_DATA_21","CUSTOM_DATA_22","CUSTOM_DATA_23","CUSTOM_DATA_24","CUSTOM_DATA_25","CUSTOM_DATA_26","CUSTOM_DATA_27","CUSTOM_DATA_28","CUSTOM_DATA_29","CUSTOM_DATA_3","CUSTOM_DATA_30","CUSTOM_DATA_4","CUSTOM_DATA_5","CUSTOM_DATA_6","CUSTOM_DATA_7","CUSTOM_DATA_8","CUSTOM_DATA_9","CUSTOM_USER_ID","DAY","DAYPART","DEAL_ID","DEVICE_TYPE","DOMAIN","ERROR_CODE","ERROR_MESSAGE","EXPERIMENT_NAME","HOUR","IP_ADDRESS","ISP","IS_LINEAR","LANGUAGE","LICENSE_KEY","MANIFEST_DOWNLOAD_TIME","MEDIA_PATH","MEDIA_SERVER","MEDIA_URL","MIDPOINT","MINUTE","MIN_SUGGESTED_DURATION","MONTH","OPERATINGSYSTEM","OPERATINGSYSTEM_VERSION_MAJOR","OPERATINGSYSTEM_VERSION_MINOR","PAGE_LOAD_TIME","PAGE_LOAD_TYPE","PATH","PERCENTAGE_IN_VIEWPORT","PLATFORM","PLAYER","PLAYER_KEY","PLAYER_STARTUPTIME","PLAYER_TECH","PLAYER_VERSION","PLAY_PERCENTAGE","QUARTILE_1","QUARTILE_3","REGION","SCREEN_HEIGHT","SCREEN_WIDTH","SIZE","SKIPPED","SKIP_PERCENTAGE","SKIP_POSITION","STARTED","STREAM_FORMAT","SURVEY_URL","TIME","TIME_HOVERED","TIME_IN_VIEWPORT","TIME_PLAYED","TIME_TO_FIRST_AD","TIME_UNTIL_HOVER","UNIVERSAL_AD_ID_REGISTRY","UNIVERSAL_AD_ID_VALUE","USER_ID","VIDEO_BITRATE","VIDEO_ID","VIDEO_IMPRESSION_ID","VIDEO_TITLE","VIDEO_WINDOW_HEIGHT","VIDEO_WINDOW_WIDTH","YEAR"].map((e=>({value:e,label:e}))),N=["AD","ANALYTICS_VERSION","AUDIO_BITRATE","AUDIO_CODEC","AUDIO_LANGUAGE","AUTOPLAY","BROWSER","BROWSER_IS_BOT","BROWSER_VERSION_MAJOR","BROWSER_VERSION_MINOR","BUFFERED","CAST_TECH","CDN_PROVIDER","CITY","CLIENT_TIME","CONTEXT","COUNTRY","CUSTOM_DATA_1","CUSTOM_DATA_10","CUSTOM_DATA_11","CUSTOM_DATA_12","CUSTOM_DATA_13","CUSTOM_DATA_14","CUSTOM_DATA_15","CUSTOM_DATA_16","CUSTOM_DATA_17","CUSTOM_DATA_18","CUSTOM_DATA_19","CUSTOM_DATA_2","CUSTOM_DATA_20","CUSTOM_DATA_21","CUSTOM_DATA_22","CUSTOM_DATA_23","CUSTOM_DATA_24","CUSTOM_DATA_25","CUSTOM_DATA_26","CUSTOM_DATA_27","CUSTOM_DATA_28","CUSTOM_DATA_29","CUSTOM_DATA_3","CUSTOM_DATA_30","CUSTOM_DATA_4","CUSTOM_DATA_5","CUSTOM_DATA_6","CUSTOM_DATA_7","CUSTOM_DATA_8","CUSTOM_DATA_9","CUSTOM_USER_ID","DAY","DAYPART","DEVICE_CLASS","DEVICE_TYPE","DOMAIN","DOWNLOAD_SPEED","DRM_LOAD_TIME","DRM_TYPE","DROPPED_FRAMES","DURATION","ERROR_CODE","ERROR_MESSAGE","ERROR_PERCENTAGE","EXPERIMENT_NAME","FUNCTION","HOUR","ID","IMPRESSION_ID","INITIAL_TIME_TO_TARGET_LATENCY","IP_ADDRESS","ISP","IS_CASTING","IS_LIVE","IS_LOW_LATENCY","IS_MUTED","LANGUAGE","LATENCY","LICENSE_KEY","M3U8_URL","MINUTE","MONTH","MPD_URL","OPERATINGSYSTEM","OPERATINGSYSTEM_VERSION_MAJOR","OPERATINGSYSTEM_VERSION_MINOR","ORGANIZATION","PAGE_LOAD_TIME","PAGE_LOAD_TYPE","PATH","PAUSED","PLATFORM","PLAYED","PLAYER","PLAYER_STARTUPTIME","PLAYER_TECH","PLAYER_VERSION","PLAY_ATTEMPTS","PROG_URL","REBUFFER_PERCENTAGE","REGION","SCALE_FACTOR","SCREEN_HEIGHT","SCREEN_ORIENTATION","SCREEN_WIDTH","SEEKED","SIZE","STARTUPTIME","STATE","STREAM_FORMAT","SUBTITLE_ENABLED","SUBTITLE_LANGUAGE","SUPPORTED_VIDEO_CODECS","TARGET_LATENCY","TARGET_LATENCY_DELTA","TIME","TIME_TO_TARGET_LATENCY","USER_ID","VIDEOSTART_FAILED","VIDEOSTART_FAILED_REASON","VIDEOTIME_END","VIDEOTIME_START","VIDEO_BITRATE","VIDEO_CODEC","VIDEO_CODEC_TYPE","VIDEO_DURATION","VIDEO_ID","VIDEO_PLAYBACK_HEIGHT","VIDEO_PLAYBACK_WIDTH","VIDEO_SEGMENTS_DOWNLOADED","VIDEO_SEGMENTS_DOWNLOAD_SIZE","VIDEO_STARTUPTIME","VIDEO_TITLE","VIDEO_WINDOW_HEIGHT","VIDEO_WINDOW_WIDTH","VIEWTIME","YEAR"].map((e=>({value:e,label:e})));var b;function L(e){return p().createElement(S.HorizontalGroup,null,p().createElement(S.Select,{value:(0,n.isEmpty)(e.groupBy)?void 0:e.groupBy,onChange:t=>e.onChange(t.value),options:e.selectableGroupBys,width:30}),p().createElement(S.IconButton,{tooltip:"Move down",onClick:()=>e.onReorderGroupBy(1),name:"arrow-down",disabled:e.isLast}),p().createElement(S.IconButton,{tooltip:"Move up",onClick:()=>e.onReorderGroupBy(0),name:"arrow-up",disabled:e.isFirst}),p().createElement(S.IconButton,{tooltip:"Delete Group By",name:"trash-alt",onClick:e.onDelete,size:"lg",variant:"destructive"}))}!function(e){e[e.UP=0]="UP",e[e.DOWN=1]="DOWN"}(b||(b={}));const B=(e,t)=>t?(0,n.differenceWith)(P,e,((e,t)=>e.value===t)):(0,n.differenceWith)(N,e,((e,t)=>e.value===t));function V(e){const t=0===e.groupBys.length?4:0;return p().createElement(S.VerticalGroup,null,e.groupBys.map(((t,n,r)=>{return p().createElement(L,{key:n,groupBy:(a=t,o=e.isAdAnalytics,o?P.filter((e=>e.value===a)):N.filter((e=>e.value===a))),onChange:t=>((t,n)=>{const r=[...e.groupBys];r.splice(t,1,n),e.onChange(r)})(n,t),selectableGroupBys:B(r,e.isAdAnalytics),onDelete:()=>(t=>{const n=[...e.groupBys];n.splice(t,1),e.onChange(n)})(n),isFirst:0===n,isLast:n===r.length-1,onReorderGroupBy:t=>((t,n)=>{const r=[...e.groupBys],a=r[n];r.splice(n,1);const o=t===b.UP?n-1:n+1;r.splice(o,0,a),e.onChange(r)})(t,n)});var a,o})),p().createElement("div",{style:{paddingTop:t}},p().createElement(S.IconButton,{name:"plus-square",tooltip:"Add Group By",onClick:()=>(()=>{const t=B(e.groupBys,e.isAdAnalytics)[0].value;e.onChange([...e.groupBys,t])})(),size:"xl"})))}const w=[{value:"ASC",description:"Sort by ascending",icon:"sort-amount-up"},{value:"DESC",description:"Sort by descending",icon:"sort-amount-down"}];function G(e){return p().createElement(S.HorizontalGroup,{spacing:"xs"},p().createElement(S.Select,{value:(0,n.isEmpty)(e.attribute)?void 0:e.attribute,onChange:t=>e.onAttributeChange(t),options:e.selectableOrderByAttributes,width:30}),p().createElement(S.RadioButtonGroup,{options:w,value:e.sortOrder,onChange:t=>e.onSortOrderChange(t)}),p().createElement(S.IconButton,{tooltip:"Move down",onClick:()=>e.onReorderOrderBy(b.DOWN),name:"arrow-down",disabled:e.isLast}),p().createElement(S.IconButton,{tooltip:"Move up",onClick:()=>e.onReorderOrderBy(b.UP),name:"arrow-up",disabled:e.isFirst}),p().createElement(S.IconButton,{tooltip:"Delete Order By",name:"trash-alt",onClick:e.onDelete,size:"lg",variant:"destructive"}))}const F=(e,t)=>t?(0,n.differenceWith)(P,e,((e,t)=>e.value===t.name)):(0,n.differenceWith)(N,e,((e,t)=>e.value===t.name));function W(e){const t=0===e.orderBys.length?4:0;return p().createElement(S.VerticalGroup,null,e.orderBys.map(((t,n,r)=>{return p().createElement(G,{key:n,isAdAnalytics:e.isAdAnalytics,selectableOrderByAttributes:F(r,e.isAdAnalytics),attribute:(a=t.name,o=e.isAdAnalytics,o?P.filter((e=>e.value===a)):N.filter((e=>e.value===a))),onAttributeChange:t=>((t,n)=>{const r=[...e.orderBys],a={name:n.value,order:r[t].order};r.splice(t,1,a),e.onChange(r)})(n,t),sortOrder:t.order,onSortOrderChange:t=>((t,n)=>{const r=[...e.orderBys],a={name:r[t].name,order:n};r.splice(t,1,a),e.onChange(r)})(n,t),onDelete:()=>(t=>{const n=[...e.orderBys];n.splice(t,1),e.onChange(n)})(n),isFirst:0===n,isLast:n===r.length-1,onReorderOrderBy:t=>((t,n)=>{const r=t===b.UP?n-1:n+1,a=[...e.orderBys],o=a[n];a.splice(n,1),a.splice(r,0,o),e.onChange(a)})(t,n)});var a,o})),p().createElement("div",{style:{paddingTop:t}},p().createElement(S.IconButton,{name:"plus-square",tooltip:"Add Order By",onClick:()=>(()=>{const t=F(e.orderBys,e.isAdAnalytics)[0].value;e.onChange([...e.orderBys,{name:t,order:"ASC"}])})(),size:"xl"})))}const Y=["GT","GTE","LT","LTE","EQ","NE","CONTAINS","NOTCONTAINS","IN"].map((e=>({value:e,label:e})));function H(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function j(e){for(var t=1;tr(z(e.value))),[e.value]);const a=(0,D.useMemo)((()=>function(e,t){if(null!=e)return(t?P:N).find((t=>t.value===e))}(n.attribute,e.isAdAnalytics)),[n.attribute,e.isAdAnalytics]),o=(0,D.useMemo)((()=>function(e){if(null!=e)return Y.find((t=>t.value===e))}(n.operator)),[n.operator]);var l,i,s;return p().createElement(S.HorizontalGroup,{spacing:"xs"},p().createElement(S.Tooltip,{content:null!==(l=n.attributeError)&&void 0!==l?l:"",show:null!=n.attributeError,theme:"error"},p().createElement("div",null,p().createElement(S.Select,{value:a,onChange:function(e){r((t=>K(j({},t),{dirty:!0,attribute:e.value,attributeError:void 0})))},options:e.isAdAnalytics?P:N,width:k,invalid:null!=n.attributeError}))),p().createElement(S.Tooltip,{content:null!==(i=n.operatorError)&&void 0!==i?i:"",show:null!=n.operatorError,theme:"error"},p().createElement("div",null,p().createElement(S.Select,{value:o,onChange:function(e){r((t=>K(j({},t),{dirty:!0,operator:e.value,operatorError:void 0})))},options:Y,width:Q,invalid:null!=n.operatorError}))),p().createElement(S.Tooltip,{content:null!==(s=n.inputValueError)&&void 0!==s?s:"",show:null!=n.inputValueError,theme:"error"},p().createElement(S.Input,{value:n.value,onChange:e=>{return t=e.currentTarget.value,void r((e=>K(j({},e),{dirty:!0,value:t,inputValueError:void 0})));var t},invalid:null!=n.inputValueError,type:"text",width:q})),p().createElement(S.IconButton,{variant:"destructive",name:"trash-alt",size:"lg",tooltip:"Delete Filter",onClick:e.onDelete}),(t||n.dirty)&&p().createElement(S.IconButton,{variant:"primary",name:t?"plus-square":"save",size:"lg",tooltip:t?"Add new filter":"Save changes",onClick:function(){if(null!=n.attribute)if(null!=n.operator)try{T(n.value,n.attribute,n.operator,e.isAdAnalytics),e.onChange({name:n.attribute,operator:n.operator,value:n.value})}catch(e){r((t=>K(j({},t),{inputValueError:e instanceof Error?e.message:"Could not save value"})))}else r((e=>K(j({},e),{operatorError:"Filter operator has to be selected"})));else r((e=>K(j({},e),{attributeError:"Filter attribute has to be selected"})))}}),!t&&n.dirty&&p().createElement(S.IconButton,{variant:"secondary",name:"history",size:"lg",tooltip:"Revert changes",onClick:function(){r(z(e.value))}}))}const k=30,Q=15,q=30;function z(e){return{attribute:null==e?void 0:e.name,attributeError:void 0,operator:null==e?void 0:e.operator,operatorError:void 0,value:null==e?void 0:e.value,dirty:!1,inputValueError:void 0}}function X(e){const[t,n]=(0,D.useState)(!1),r=0===e.filters.length?4:0;return p().createElement(S.VerticalGroup,null,(e.filters.length>0||t)&&p().createElement(S.HorizontalGroup,{spacing:"none"},p().createElement(S.InlineLabel,{width:k,tooltip:""},"Attribute"),p().createElement(S.InlineLabel,{width:Q,tooltip:""},"Operator"),p().createElement(S.InlineLabel,{width:q,tooltip:""},"Value")),e.filters.map(((t,n)=>p().createElement(x,{isAdAnalytics:e.isAdAnalytics,value:t,onChange:t=>function(t,n){const r=[...e.filters];r.splice(t,1,n),e.onQueryFilterChange(r)}(n,t),onDelete:()=>function(t){const n=[...e.filters];n.splice(t,1),e.onQueryFilterChange(n)}(n),selectedQueryFilters:e.filters,key:n}))),p().createElement("div",{style:{paddingTop:r}},t?p().createElement(x,{isAdAnalytics:e.isAdAnalytics,value:void 0,onChange:function(t){const r=[...e.filters,t];e.onQueryFilterChange(r),n(!1)},onDelete:()=>n(!1),selectedQueryFilters:e.filters}):p().createElement(S.IconButton,{name:"plus-square",tooltip:"Add Filter",onClick:()=>n(!0),size:"xl"})))}function J(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Z(e){for(var t=1;t{""!==n.url&&null!=n.url||t(m(R({},n),{url:"https://api.bitmovin.com/v1"}))}),[]);const{jsonData:r}=n;return p().createElement(p().Fragment,null,p().createElement(S.DataSourceHttpSettings,{defaultUrl:"https://api.bitmovin.com/v1",dataSourceConfig:n,onChange:t,showAccessOptions:!0}),p().createElement(S.FieldSet,{label:"Bitmovin Analytics Details"},p().createElement(S.InlineField,{required:!0,label:"API Key",labelWidth:26},p().createElement(S.Input,{required:!0,onChange:e=>{const r=m(R({},n.jsonData),{apiKey:e.currentTarget.value});t(m(R({},n),{jsonData:r}))},value:r.apiKey||"",placeholder:"Analytics API Key",width:40})),p().createElement(S.InlineField,{label:"Tenant Org Id",labelWidth:26},p().createElement(S.Input,{onChange:e=>{const r=m(R({},n.jsonData),{tenantOrgId:e.currentTarget.value});t(m(R({},n),{jsonData:r}))},value:r.tenantOrgId||"",placeholder:"Tenant Org Id",width:40})),p().createElement(S.InlineField,{label:"Ad Analytics",tooltip:"Check if you want to query ads data",labelWidth:26},p().createElement(S.InlineSwitch,{value:r.isAdAnalytics||!1,onChange:e=>{const r=m(R({},n.jsonData),{isAdAnalytics:e.currentTarget.checked});t(m(R({},n),{jsonData:r}))}}))))})).setQueryEditor((function(e){const t=(0,n.defaults)(e.query,a),[r,i]=(0,D.useState)([]),[s,c]=(0,D.useState)("DEFAULT"),[u,T]=(0,D.useState)(""),[_,O]=(0,D.useState)("time_series"===t.resultFormat),[d,I]=(0,D.useState)(t.percentileValue),C=(0,D.useMemo)((()=>!!t.dimension&&A(t.dimension)),[t.dimension]),R=(0,D.useMemo)((()=>"percentile"===t.metric),[t.metric]);return(0,D.useEffect)((()=>{c("LOADING"),function(e,t,n){return f.apply(this,arguments)}(e.datasource.apiKey,e.datasource.baseUrl,e.datasource.tenantOrgId).then((e=>{i(e),c("SUCCESS")})).catch((e=>{c("ERROR"),T(e.status+" "+e.statusText)}))}),[e.datasource.apiKey,e.datasource.baseUrl,e.datasource.tenantOrgId]),p().createElement("div",{className:"gf-form"},p().createElement(S.FieldSet,null,p().createElement(S.InlineField,{label:"License",labelWidth:20,invalid:"ERROR"===s,error:`Error when fetching Analytics Licenses: ${u}`,disabled:"ERROR"===s,required:!0},p().createElement(S.Select,{value:t.license,onChange:n=>{e.onChange($(Z({},t),{license:n.value})),e.onRunQuery()},width:30,options:r,noOptionsMessage:"No Analytics Licenses found",isLoading:"LOADING"===s,placeholder:"LOADING"===s?"Loading Licenses":"Choose License"})),p().createElement(S.HorizontalGroup,{spacing:"xs"},!C&&p().createElement(S.InlineField,{label:"Metric",labelWidth:20,required:!0},p().createElement(S.Select,{value:t.metric,onChange:n=>(n=>{e.onChange($(Z({},t),{metric:n.value})),e.onRunQuery()})(n),width:30,options:U})),R&&p().createElement(S.Input,{value:d,onChange:e=>{let t=parseInt(e.target.value,10);t<0?t=0:t>99&&(t=99),I(t)},onBlur:()=>{e.onChange($(Z({},t),{percentileValue:d})),e.onRunQuery()},type:"number",placeholder:"value",width:10})),p().createElement(S.InlineField,{label:"Dimension",labelWidth:20,required:!0},p().createElement(S.Select,{value:t.dimension,onChange:n=>{e.onChange($(Z({},t),{dimension:n.value})),e.onRunQuery()},width:30,options:e.datasource.isAdAnalytics?P:N.concat(E)})),p().createElement(S.InlineField,{label:"Filter",labelWidth:20},p().createElement(X,{isAdAnalytics:!!e.datasource.isAdAnalytics,onQueryFilterChange:n=>{e.onChange($(Z({},t),{filter:n})),e.onRunQuery()},filters:t.filter})),p().createElement(S.InlineField,{label:"Group By",labelWidth:20},p().createElement(V,{isAdAnalytics:!!e.datasource.isAdAnalytics,onChange:n=>{e.onChange($(Z({},t),{groupBy:n})),e.onRunQuery()},groupBys:t.groupBy})),p().createElement(S.InlineField,{label:"Order By",labelWidth:20},p().createElement(W,{isAdAnalytics:!!e.datasource.isAdAnalytics,onChange:n=>{e.onChange($(Z({},t),{orderBy:n})),e.onRunQuery()},orderBys:t.orderBy})),p().createElement(S.InlineField,{label:"Limit",labelWidth:20},p().createElement(S.Input,{defaultValue:t.limit,type:"number",onBlur:n=>{const r=parseInt(n.target.value,10);e.onChange($(Z({},t),{limit:isNaN(r)?void 0:r})),e.onRunQuery()},width:30,placeholder:"No limit"})),p().createElement(S.InlineField,{label:"Format as time series",labelWidth:20},p().createElement(S.InlineSwitch,{value:_,onChange:n=>{O(n.currentTarget.checked),n.currentTarget.checked?e.onChange($(Z({},t),{interval:"AUTO",resultFormat:"time_series"})):e.onChange($(Z({},t),{interval:void 0,resultFormat:"table"})),e.onRunQuery()}})),_&&p().createElement(p().Fragment,null,p().createElement(S.InlineField,{label:"Interval",labelWidth:20},p().createElement(S.Select,{defaultValue:l,onChange:n=>(n=>{e.onChange($(Z({},t),{interval:n.value})),e.onRunQuery()})(n),width:30,options:o}))),p().createElement(S.InlineField,{label:"Alias By",labelWidth:20},p().createElement(S.Input,{defaultValue:t.alias,placeholder:"Naming pattern",onBlur:n=>{e.onChange($(Z({},t),{alias:n.target.value})),e.onRunQuery()}}))))}))})(),c})())); +define(["@grafana/data","@grafana/runtime","lodash","rxjs","moment","react","@grafana/ui"],((e,t,n,r,a,o,l)=>(()=>{"use strict";var i={781:t=>{t.exports=e},531:e=>{e.exports=t},7:e=>{e.exports=l},241:e=>{e.exports=n},468:e=>{e.exports=a},959:e=>{e.exports=o},269:e=>{e.exports=r}},s={};function c(e){var t=s[e];if(void 0!==t)return t.exports;var n=s[e]={exports:{}};return i[e](n,n.exports,c),n.exports}c.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return c.d(t,{a:t}),t},c.d=(e,t)=>{for(var n in t)c.o(t,n)&&!c.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},c.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var u={};return(()=>{c.r(u),c.d(u,{plugin:()=>ie});var e=c(781),t=c(531),n=c(241),r=c(269);const a={license:"",orderBy:[],groupBy:[],filter:[],resultFormat:"time_series",interval:"AUTO"},o=[{value:"AUTO",label:"Auto"},{value:"MINUTE",label:"Minute"},{value:"HOUR",label:"Hour"},{value:"DAY",label:"Day"},{value:"MONTH",label:"Month"}],l=o[0],i=["MINUTE","HOUR","DAY","MONTH"],s=(e,t,n)=>{if("AUTO"!==e)return e;const r=n-t;return r<=108e5?"MINUTE":r<=5184e5?"HOUR":r<=2592e6?"DAY":"MONTH"},E=e=>{switch(e){case"MINUTE":return"minute";case"HOUR":return"hour";case"DAY":return"day";case"MONTH":return"month";default:return null}};var A=c(468),T=c.n(A);function _(e,t,n){const r=new Date(e),a=new Date(t);switch(n){case"MINUTE":return a.setSeconds(0,0);case"HOUR":return a.setMinutes(0,0,0);case"DAY":return a.setHours(r.getHours(),r.getMinutes(),0,0);case"MONTH":return 1===r.getDate()?a.setDate(r.getDate()):a.setDate(0),a.setHours(r.getHours(),r.getMinutes(),0,0)}}function O(e,t,r,a){if(0===e.length)return[];const o=E(a);if(null==o)throw new Error(`Query interval ${a} is not a valid interval.`);const l=[],i=e[0].length>2?[...e[0].slice(1,-1),0]:[0];let s=T()(t);for(;s.valueOf()<=r;){const e=[s.valueOf(),...i];l.push(e),s.add(1,o),"MONTH"===a&&1!==s.date()&&s.set("date",s.daysInMonth())}const c=(0,n.differenceWith)(l,e,((e,t)=>e[0]===t[0])),u=e.concat(c);return(0,n.sortBy)(u,(e=>e[0]))}const d=["AVG_CONCURRENTVIEWERS","MAX_CONCURRENTVIEWERS","AVG-DROPPED-FRAMES"],I=d.map((e=>({value:e,label:e}))),D=e=>d.includes(e),p=(e,t,r,a)=>{if((0,n.isEmpty)(e)&&(e=>{switch(e){case"CDN_PROVIDER":case"CUSTOM_DATA_1":case"CUSTOM_DATA_2":case"CUSTOM_DATA_3":case"CUSTOM_DATA_4":case"CUSTOM_DATA_5":case"CUSTOM_DATA_6":case"CUSTOM_DATA_7":case"CUSTOM_DATA_8":case"CUSTOM_DATA_9":case"CUSTOM_DATA_10":case"CUSTOM_DATA_11":case"CUSTOM_DATA_12":case"CUSTOM_DATA_13":case"CUSTOM_DATA_14":case"CUSTOM_DATA_15":case"CUSTOM_DATA_16":case"CUSTOM_DATA_17":case"CUSTOM_DATA_18":case"CUSTOM_DATA_19":case"CUSTOM_DATA_20":case"CUSTOM_DATA_21":case"CUSTOM_DATA_22":case"CUSTOM_DATA_23":case"CUSTOM_DATA_24":case"CUSTOM_DATA_25":case"CUSTOM_DATA_26":case"CUSTOM_DATA_27":case"CUSTOM_DATA_28":case"CUSTOM_DATA_29":case"CUSTOM_DATA_30":case"CUSTOM_USER_ID":case"ERROR_CODE":case"EXPERIMENT_NAME":case"ISP":case"PLAYER_TECH":case"PLAYER_VERSION":case"VIDEO_ID":return!0;default:return!1}})(t))return null;if("IN"===r)try{return(e=>{const t=JSON.parse(e);if(!Array.isArray(t))throw new Error;return t})(e)}catch(e){throw new Error('Couldn\'t parse IN filter, please provide data in JSON array form (e.g.: ["Firefox", "Chrome"]).')}return a?((e,t)=>{switch(t){case"IS_LINEAR":return"true"===e;case"AD_STARTUP_TIME":case"AD_WRAPPER_ADS_COUNT":case"AUDIO_BITRATE":case"CLICK_POSITION":case"CLOSE_POSITION":case"ERROR_CODE":case"MANIFEST_DOWNLOAD_TIME":case"MIN_SUGGESTED_DURATION":case"PAGE_LOAD_TIME":case"PLAYER_STARTUPTIME":case"SCREEN_HEIGHT":case"SCREEN_WIDTH":case"SKIP_POSITION":case"TIME_HOVERED":case"TIME_IN_VIEWPORT":case"TIME_PLAYED":case"TIME_UNTIL_HOVER":case"VIDEO_BITRATE":case"VIDEO_WINDOW_HEIGHT":case"VIDEO_WINDOW_WIDTH":{const t=parseInt(e,10);if(isNaN(t))throw new Error("Couldn't parse filter value, please provide data as an integer number");return t}case"CLICK_PERCENTAGE":case"CLOSE_PERCENTAGE":case"PERCENTAGE_IN_VIEWPORT":case"SKIP_PERCENTAGE":{const t=parseFloat(e);if(isNaN(t))throw new Error("Couldn't parse filter value, please provide data as a floating point number");return t}default:return e}})(e,t):((e,t)=>{switch(t){case"IS_CASTING":case"IS_LIVE":case"IS_MUTED":return"true"===e;case"AUDIO_BITRATE":case"BUFFERED":case"CLIENT_TIME":case"DOWNLOAD_SPEED":case"DRM_LOAD_TIME":case"DROPPED_FRAMES":case"DURATION":case"ERROR_CODE":case"PAGE_LOAD_TIME":case"PAGE_LOAD_TYPE":case"PAUSED":case"PLAYED":case"PLAYER_STARTUPTIME":case"SCREEN_HEIGHT":case"SCREEN_WIDTH":case"SEEKED":case"STARTUPTIME":case"VIDEO_BITRATE":case"VIDEO_DURATION":case"VIDEO_PLAYBACK_HEIGHT":case"VIDEO_PLAYBACK_WIDTH":case"VIDEO_STARTUPTIME":case"VIDEO_WINDOW_HEIGHT":case"VIDEO_WINDOW_WIDTH":case"VIDEOTIME_END":case"VIDEOTIME_START":case"VIEWTIME":{const t=parseInt(e,10);if(isNaN(t))throw new Error("Couldn't parse filter value, please provide data as an integer number");return t}case"ERROR_PERCENTAGE":case"REBUFFER_PERCENTAGE":{const t=parseFloat(e);if(isNaN(t))throw new Error("Couldn't parse filter value, please provide data as a floating point number");return t}default:return e}})(e,t)};function S(e,t,n,r,a,o,l){try{var i=e[o](l),s=i.value}catch(e){return void n(e)}i.done?t(s):Promise.resolve(s).then(r,a)}function R(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function l(e){S(o,r,a,l,i,"next",e)}function i(e){S(o,r,a,l,i,"throw",e)}l(void 0)}))}}function C(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class m extends e.DataSourceApi{getDefaultQuery(e){return a}query(t){var a=this;return R((function*(){const{range:o}=t,l=a.isRelativeRangeFrom(o.raw),c=t.targets=(0,n.filter)(t.targets,(e=>!e.hide)),u=(0,n.filter)(c,(e=>a.isQueryComplete(e))).map((A=R((function*(t){var c;const u="time_series"===t.resultFormat&&t.interval?s(t.interval,o.from.valueOf(),o.to.valueOf()):void 0;let A=o.from;const T=o.to;if(l){let e=s("AUTO",A.valueOf(),T.valueOf());null!=u&&(d=u,I=e,e=i.indexOf(d)({name:e.name,operator:e.operator,value:p(e.value,e.name,e.operator,!!a.isAdAnalytics)}))),groupBy:t.groupBy,orderBy:t.orderBy,dimension:m,metric:C,start:A.toDate(),end:T.toDate(),licenseKey:t.license,interval:u,limit:a.parseLimit(t.limit),percentile:R},v=yield(0,r.lastValueFrom)(a.request(a.getRequestUrl(C,S),"POST",y)),h=v.data.data.result.rows,f=v.data.data.result.rowCount,M=v.data.data.result.columnLabels,g=[];y.interval&&(null===(c=y.groupBy)||void 0===c?void 0:c.length)>0?g.push(...function(t,r,a,o){if(0===t.length)return[];const l=[],i=new Map;t.forEach((e=>{var t;const n=e.slice(1,-1).toString();i.has(n)||i.set(n,[]),null===(t=i.get(n))||void 0===t||t.push(e)}));const s=[];i.forEach((e=>{s.push(O(e,_(e[0][0],r,o),a,o))}));const c=(0,n.zip)(...s[0])[0];return l.push({name:"Time",values:c,type:e.FieldType.time}),s.forEach((t=>{const r=t[0].slice(1,-1).join(", "),a=(0,n.zip)(...t).slice(-1);l.push({name:r,values:a[0],type:e.FieldType.number})})),l}(h,A.valueOf(),T.valueOf(),y.interval)):y.interval?g.push(...function(t,r,a,o,l){if(0===t.length)return[];const i=[],s=O(t,_(t[0][0],a,l),o,l),c=(0,n.zip)(...s);return i.push({name:"Time",values:c[0],type:e.FieldType.time}),i.push({name:r,values:c[c.length-1],type:e.FieldType.number}),i}(h,M.length>0?M[M.length-1].label:"Column 1",A.valueOf(),T.valueOf(),y.interval)):g.push(...function(t,r){if(0===t.length)return[];const a=[],o=(0,n.zip)(...t);let l=[];if(0===r.length)for(let e=0;ee.label)));return t[0].length>1&&o.slice(0,-1).forEach(((t,n)=>{a.push({name:l[n],values:t,type:e.FieldType.string})})),a.push({name:l[l.length-1],values:o[o.length-1],type:e.FieldType.number}),a}(h,M));let U=[];return f>=200&&(U=[{severity:"warning",text:"Your request reached the max row limit of the API. You might see incomplete data. This problem might be caused by the use of high cardinality columns in group by, too small interval, or too big of a time range."}]),(0,e.createDataFrame)({name:t.alias,fields:g,meta:{notices:U}})})),function(e){return A.apply(this,arguments)}));var A;return Promise.all(u).then((e=>({data:e})))}))()}isRelativeRangeFrom(e){return"string"==typeof e.from}parseLimit(e){if(null!=e)return Number.isInteger(e)?e:parseInt(e,10)}isQueryComplete(e){return!((0,n.isEmpty)(e.license)||(0,n.isEmpty)(e.dimension)||null!=e.dimension&&!D(e.dimension)&&(0,n.isEmpty)(e.metric))}getRequestUrl(e,t){let n="/analytics";return!0===this.isAdAnalytics&&(n+="/ads"),null!=e?n+"/metrics/"+e:n+"/queries/"+t}request(e,n,r){const a={"X-Api-Key":this.apiKey};null!=this.tenantOrgId&&(a["X-Tenant-Org-Id"]=this.tenantOrgId);const o={url:this.baseUrl+e,headers:a,method:n,data:r};return(0,t.getBackendSrv)().fetch(o)}testDatasource(){var e=this;return R((function*(){return(0,r.lastValueFrom)(e.request("/analytics/licenses","GET").pipe((0,r.map)((()=>({status:"success",message:"Data source successfully setup and connected."}))),(0,r.catchError)((e=>{var t,n,a,o;let l="Bitmovin: ";e.status&&(l+=e.status+" "),e.statusText?l+=e.statusText:l+="Can not connect to Bitmovin API";let i,s=(null===(t=e.data)||void 0===t?void 0:t.message)||(null===(a=e.data)||void 0===a||null===(n=a.data)||void 0===n?void 0:n.message);var c,u;return(null===(o=e.data)||void 0===o?void 0:o.requestId)&&(i="Timestamp: "+(new Date).toISOString(),i+=(null===(c=e.data)||void 0===c?void 0:c.requestId)?"\nRequestId: "+(null===(u=e.data)||void 0===u?void 0:u.requestId):""),(0,r.of)({status:"error",message:l,details:{message:s,verboseMessage:i}})}))))}))()}constructor(e){super(e),C(this,"baseUrl",void 0),C(this,"apiKey",void 0),C(this,"tenantOrgId",void 0),C(this,"isAdAnalytics",void 0),this.apiKey=e.jsonData.apiKey,this.tenantOrgId=e.jsonData.tenantOrgId,this.isAdAnalytics=e.jsonData.isAdAnalytics,this.baseUrl=e.url}}var y=c(959),v=c.n(y),h=c(7);function f(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function M(e){for(var t=1;t({value:e.licenseKey,label:e.name?e.name:e.licenseKey})},{endpoint:"/analytics/virtual-licenses",mapperFunc:e=>({value:e.id,label:e.name?e.name:e.id})},{endpoint:"/analytics/demo-licenses",mapperFunc:e=>({value:e.id,label:e.name?e.name:e.id})}];function b(e,t,n,r){return L.apply(this,arguments)}function L(){return(L=N((function*(e,n,a,o){const l={"X-Api-Key":n};null!=o&&(l["X-Tenant-Org-Id"]=o);const i={url:e,headers:l,method:"GET"},s=(yield(0,r.lastValueFrom)((0,t.getBackendSrv)().fetch(i))).data.data.result.items,c=[];for(const e of s)c.push(a(e));return c}))).apply(this,arguments)}function B(){return(B=N((function*(e,t,n){const r=[];for(const a of P){const o=yield b(t+a.endpoint,e,a.mapperFunc,n);r.push(...o)}return r}))).apply(this,arguments)}const V=["count","sum","avg","min","max","stddev","percentile","variance","median"].map((e=>({value:e,label:e}))),G=["ADVERTISER_NAME","AD_CLICKTHROUGH_URL","AD_DESCRIPTION","AD_DURATION","AD_FALLBACK_INDEX","AD_ID","AD_ID_PLAYER","AD_IMPRESSION_ID","AD_IS_PERSISTENT","AD_MODULE","AD_OFFSET","AD_PLAYBACK_HEIGHT","AD_PLAYBACK_WIDTH","AD_POSITION","AD_PRELOAD_OFFSET","AD_REPLACE_CONTENT_DURATION","AD_SCHEDULE_TIME","AD_SKIPPABLE","AD_SKIP_AFTER","AD_STARTUP_TIME","AD_SYSTEM","AD_TAG_PATH","AD_TAG_SERVER","AD_TAG_TYPE","AD_TAG_URL","AD_TITLE","AD_WRAPPER_ADS_COUNT","ANALYTICS_VERSION","APIORG_ID","APIUSER_ID","API_FRAMEWORK","AUDIO_BITRATE","AUTOPLAY","BROWSER","BROWSER_IS_BOT","BROWSER_VERSION_MAJOR","BROWSER_VERSION_MINOR","CDN_PROVIDER","CITY","CLICKED","CLICK_PERCENTAGE","CLICK_POSITION","CLICK_RATE","CLIENT_TIME","CLOSED","CLOSE_PERCENTAGE","CLOSE_POSITION","COMPLETED","COUNTRY","CREATIVE_AD_ID","CREATIVE_ID","CUSTOM_DATA_1","CUSTOM_DATA_10","CUSTOM_DATA_11","CUSTOM_DATA_12","CUSTOM_DATA_13","CUSTOM_DATA_14","CUSTOM_DATA_15","CUSTOM_DATA_16","CUSTOM_DATA_17","CUSTOM_DATA_18","CUSTOM_DATA_19","CUSTOM_DATA_2","CUSTOM_DATA_20","CUSTOM_DATA_21","CUSTOM_DATA_22","CUSTOM_DATA_23","CUSTOM_DATA_24","CUSTOM_DATA_25","CUSTOM_DATA_26","CUSTOM_DATA_27","CUSTOM_DATA_28","CUSTOM_DATA_29","CUSTOM_DATA_3","CUSTOM_DATA_30","CUSTOM_DATA_4","CUSTOM_DATA_5","CUSTOM_DATA_6","CUSTOM_DATA_7","CUSTOM_DATA_8","CUSTOM_DATA_9","CUSTOM_USER_ID","DAY","DAYPART","DEAL_ID","DEVICE_TYPE","DOMAIN","ERROR_CODE","ERROR_MESSAGE","EXPERIMENT_NAME","HOUR","IP_ADDRESS","ISP","IS_LINEAR","LANGUAGE","LICENSE_KEY","MANIFEST_DOWNLOAD_TIME","MEDIA_PATH","MEDIA_SERVER","MEDIA_URL","MIDPOINT","MINUTE","MIN_SUGGESTED_DURATION","MONTH","OPERATINGSYSTEM","OPERATINGSYSTEM_VERSION_MAJOR","OPERATINGSYSTEM_VERSION_MINOR","PAGE_LOAD_TIME","PAGE_LOAD_TYPE","PATH","PERCENTAGE_IN_VIEWPORT","PLATFORM","PLAYER","PLAYER_KEY","PLAYER_STARTUPTIME","PLAYER_TECH","PLAYER_VERSION","PLAY_PERCENTAGE","QUARTILE_1","QUARTILE_3","REGION","SCREEN_HEIGHT","SCREEN_WIDTH","SIZE","SKIPPED","SKIP_PERCENTAGE","SKIP_POSITION","STARTED","STREAM_FORMAT","SURVEY_URL","TIME","TIME_HOVERED","TIME_IN_VIEWPORT","TIME_PLAYED","TIME_TO_FIRST_AD","TIME_UNTIL_HOVER","UNIVERSAL_AD_ID_REGISTRY","UNIVERSAL_AD_ID_VALUE","USER_ID","VIDEO_BITRATE","VIDEO_ID","VIDEO_IMPRESSION_ID","VIDEO_TITLE","VIDEO_WINDOW_HEIGHT","VIDEO_WINDOW_WIDTH","YEAR"].map((e=>({value:e,label:e}))),w=["AD","ANALYTICS_VERSION","AUDIO_BITRATE","AUDIO_CODEC","AUDIO_LANGUAGE","AUTOPLAY","BROWSER","BROWSER_IS_BOT","BROWSER_VERSION_MAJOR","BROWSER_VERSION_MINOR","BUFFERED","CAST_TECH","CDN_PROVIDER","CITY","CLIENT_TIME","CONTEXT","COUNTRY","CUSTOM_DATA_1","CUSTOM_DATA_10","CUSTOM_DATA_11","CUSTOM_DATA_12","CUSTOM_DATA_13","CUSTOM_DATA_14","CUSTOM_DATA_15","CUSTOM_DATA_16","CUSTOM_DATA_17","CUSTOM_DATA_18","CUSTOM_DATA_19","CUSTOM_DATA_2","CUSTOM_DATA_20","CUSTOM_DATA_21","CUSTOM_DATA_22","CUSTOM_DATA_23","CUSTOM_DATA_24","CUSTOM_DATA_25","CUSTOM_DATA_26","CUSTOM_DATA_27","CUSTOM_DATA_28","CUSTOM_DATA_29","CUSTOM_DATA_3","CUSTOM_DATA_30","CUSTOM_DATA_4","CUSTOM_DATA_5","CUSTOM_DATA_6","CUSTOM_DATA_7","CUSTOM_DATA_8","CUSTOM_DATA_9","CUSTOM_USER_ID","DAY","DAYPART","DEVICE_CLASS","DEVICE_TYPE","DOMAIN","DOWNLOAD_SPEED","DRM_LOAD_TIME","DRM_TYPE","DROPPED_FRAMES","DURATION","ERROR_CODE","ERROR_MESSAGE","ERROR_PERCENTAGE","EXPERIMENT_NAME","FUNCTION","HOUR","ID","IMPRESSION_ID","INITIAL_TIME_TO_TARGET_LATENCY","IP_ADDRESS","ISP","IS_CASTING","IS_LIVE","IS_LOW_LATENCY","IS_MUTED","LANGUAGE","LATENCY","LICENSE_KEY","M3U8_URL","MINUTE","MONTH","MPD_URL","OPERATINGSYSTEM","OPERATINGSYSTEM_VERSION_MAJOR","OPERATINGSYSTEM_VERSION_MINOR","ORGANIZATION","PAGE_LOAD_TIME","PAGE_LOAD_TYPE","PATH","PAUSED","PLATFORM","PLAYED","PLAYER","PLAYER_STARTUPTIME","PLAYER_TECH","PLAYER_VERSION","PLAY_ATTEMPTS","PROG_URL","REBUFFER_PERCENTAGE","REGION","SCALE_FACTOR","SCREEN_HEIGHT","SCREEN_ORIENTATION","SCREEN_WIDTH","SEEKED","SIZE","STARTUPTIME","STATE","STREAM_FORMAT","SUBTITLE_ENABLED","SUBTITLE_LANGUAGE","SUPPORTED_VIDEO_CODECS","TARGET_LATENCY","TARGET_LATENCY_DELTA","TIME","TIME_TO_TARGET_LATENCY","USER_ID","VIDEOSTART_FAILED","VIDEOSTART_FAILED_REASON","VIDEOTIME_END","VIDEOTIME_START","VIDEO_BITRATE","VIDEO_CODEC","VIDEO_CODEC_TYPE","VIDEO_DURATION","VIDEO_ID","VIDEO_PLAYBACK_HEIGHT","VIDEO_PLAYBACK_WIDTH","VIDEO_SEGMENTS_DOWNLOADED","VIDEO_SEGMENTS_DOWNLOAD_SIZE","VIDEO_STARTUPTIME","VIDEO_TITLE","VIDEO_WINDOW_HEIGHT","VIDEO_WINDOW_WIDTH","VIEWTIME","YEAR"].map((e=>({value:e,label:e})));var F;function H(e){return v().createElement(h.HorizontalGroup,null,v().createElement(h.Select,{value:(0,n.isEmpty)(e.groupBy)?void 0:e.groupBy,onChange:t=>e.onChange(t.value),options:e.selectableGroupBys,width:30}),v().createElement(h.IconButton,{tooltip:"Move down",onClick:()=>e.onReorderGroupBy(1),name:"arrow-down",disabled:e.isLast}),v().createElement(h.IconButton,{tooltip:"Move up",onClick:()=>e.onReorderGroupBy(0),name:"arrow-up",disabled:e.isFirst}),v().createElement(h.IconButton,{tooltip:"Delete Group By",name:"trash-alt",onClick:e.onDelete,size:"lg",variant:"destructive"}))}!function(e){e[e.UP=0]="UP",e[e.DOWN=1]="DOWN"}(F||(F={}));const W=(e,t)=>t?(0,n.differenceWith)(G,e,((e,t)=>e.value===t)):(0,n.differenceWith)(w,e,((e,t)=>e.value===t));function Y(e){const t=0===e.groupBys.length?4:0;return v().createElement(h.VerticalGroup,null,e.groupBys.map(((t,n,r)=>{return v().createElement(H,{key:n,groupBy:(a=t,o=e.isAdAnalytics,o?G.filter((e=>e.value===a)):w.filter((e=>e.value===a))),onChange:t=>((t,n)=>{const r=[...e.groupBys];r.splice(t,1,n),e.onChange(r)})(n,t),selectableGroupBys:W(r,e.isAdAnalytics),onDelete:()=>(t=>{const n=[...e.groupBys];n.splice(t,1),e.onChange(n)})(n),isFirst:0===n,isLast:n===r.length-1,onReorderGroupBy:t=>((t,n)=>{const r=[...e.groupBys],a=r[n];r.splice(n,1);const o=t===F.UP?n-1:n+1;r.splice(o,0,a),e.onChange(r)})(t,n)});var a,o})),v().createElement("div",{style:{paddingTop:t}},v().createElement(h.IconButton,{name:"plus-square",tooltip:"Add Group By",onClick:()=>(()=>{const t=W(e.groupBys,e.isAdAnalytics)[0].value;e.onChange([...e.groupBys,t])})(),size:"xl"})))}const j=[{value:"ASC",description:"Sort by ascending",icon:"sort-amount-up"},{value:"DESC",description:"Sort by descending",icon:"sort-amount-down"}];function K(e){return v().createElement(h.HorizontalGroup,{spacing:"xs"},v().createElement(h.Select,{value:(0,n.isEmpty)(e.attribute)?void 0:e.attribute,onChange:t=>e.onAttributeChange(t),options:e.selectableOrderByAttributes,width:30}),v().createElement(h.RadioButtonGroup,{options:j,value:e.sortOrder,onChange:t=>e.onSortOrderChange(t)}),v().createElement(h.IconButton,{tooltip:"Move down",onClick:()=>e.onReorderOrderBy(F.DOWN),name:"arrow-down",disabled:e.isLast}),v().createElement(h.IconButton,{tooltip:"Move up",onClick:()=>e.onReorderOrderBy(F.UP),name:"arrow-up",disabled:e.isFirst}),v().createElement(h.IconButton,{tooltip:"Delete Order By",name:"trash-alt",onClick:e.onDelete,size:"lg",variant:"destructive"}))}const x=(e,t)=>t?(0,n.differenceWith)(G,e,((e,t)=>e.value===t.name)):(0,n.differenceWith)(w,e,((e,t)=>e.value===t.name));function k(e){const t=0===e.orderBys.length?4:0;return v().createElement(h.VerticalGroup,null,e.orderBys.map(((t,n,r)=>{return v().createElement(K,{key:n,isAdAnalytics:e.isAdAnalytics,selectableOrderByAttributes:x(r,e.isAdAnalytics),attribute:(a=t.name,o=e.isAdAnalytics,o?G.filter((e=>e.value===a)):w.filter((e=>e.value===a))),onAttributeChange:t=>((t,n)=>{const r=[...e.orderBys],a={name:n.value,order:r[t].order};r.splice(t,1,a),e.onChange(r)})(n,t),sortOrder:t.order,onSortOrderChange:t=>((t,n)=>{const r=[...e.orderBys],a={name:r[t].name,order:n};r.splice(t,1,a),e.onChange(r)})(n,t),onDelete:()=>(t=>{const n=[...e.orderBys];n.splice(t,1),e.onChange(n)})(n),isFirst:0===n,isLast:n===r.length-1,onReorderOrderBy:t=>((t,n)=>{const r=t===F.UP?n-1:n+1,a=[...e.orderBys],o=a[n];a.splice(n,1),a.splice(r,0,o),e.onChange(a)})(t,n)});var a,o})),v().createElement("div",{style:{paddingTop:t}},v().createElement(h.IconButton,{name:"plus-square",tooltip:"Add Order By",onClick:()=>(()=>{const t=x(e.orderBys,e.isAdAnalytics)[0].value;e.onChange([...e.orderBys,{name:t,order:"ASC"}])})(),size:"xl"})))}const Q=["GT","GTE","LT","LTE","EQ","NE","CONTAINS","NOTCONTAINS","IN"].map((e=>({value:e,label:e})));function q(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function z(e){for(var t=1;tr(te(e.value))),[e.value]);const a=(0,y.useMemo)((()=>function(e,t){if(null!=e)return(t?G:w).find((t=>t.value===e))}(n.attribute,e.isAdAnalytics)),[n.attribute,e.isAdAnalytics]),o=(0,y.useMemo)((()=>function(e){if(null!=e)return Q.find((t=>t.value===e))}(n.operator)),[n.operator]);var l,i,s;return v().createElement(h.HorizontalGroup,{spacing:"xs"},v().createElement(h.Tooltip,{content:null!==(l=n.attributeError)&&void 0!==l?l:"",show:null!=n.attributeError,theme:"error"},v().createElement("div",null,v().createElement(h.Select,{value:a,onChange:function(e){r((t=>X(z({},t),{dirty:!0,attribute:e.value,attributeError:void 0})))},options:e.isAdAnalytics?G:w,width:Z,invalid:null!=n.attributeError}))),v().createElement(h.Tooltip,{content:null!==(i=n.operatorError)&&void 0!==i?i:"",show:null!=n.operatorError,theme:"error"},v().createElement("div",null,v().createElement(h.Select,{value:o,onChange:function(e){r((t=>X(z({},t),{dirty:!0,operator:e.value,operatorError:void 0})))},options:Q,width:$,invalid:null!=n.operatorError}))),v().createElement(h.Tooltip,{content:null!==(s=n.inputValueError)&&void 0!==s?s:"",show:null!=n.inputValueError,theme:"error"},v().createElement(h.Input,{value:n.value,onChange:e=>{return t=e.currentTarget.value,void r((e=>X(z({},e),{dirty:!0,value:t,inputValueError:void 0})));var t},invalid:null!=n.inputValueError,type:"text",width:ee})),v().createElement(h.IconButton,{variant:"destructive",name:"trash-alt",size:"lg",tooltip:"Delete Filter",onClick:e.onDelete}),(t||n.dirty)&&v().createElement(h.IconButton,{variant:"primary",name:t?"plus-square":"save",size:"lg",tooltip:t?"Add new filter":"Save changes",onClick:function(){if(null!=n.attribute)if(null!=n.operator)try{p(n.value,n.attribute,n.operator,e.isAdAnalytics),e.onChange({name:n.attribute,operator:n.operator,value:n.value})}catch(e){r((t=>X(z({},t),{inputValueError:e instanceof Error?e.message:"Could not save value"})))}else r((e=>X(z({},e),{operatorError:"Filter operator has to be selected"})));else r((e=>X(z({},e),{attributeError:"Filter attribute has to be selected"})))}}),!t&&n.dirty&&v().createElement(h.IconButton,{variant:"secondary",name:"history",size:"lg",tooltip:"Revert changes",onClick:function(){r(te(e.value))}}))}const Z=30,$=15,ee=30;function te(e){return{attribute:null==e?void 0:e.name,attributeError:void 0,operator:null==e?void 0:e.operator,operatorError:void 0,value:null==e?void 0:e.value,dirty:!1,inputValueError:void 0}}function ne(e){const[t,n]=(0,y.useState)(!1),r=0===e.filters.length?4:0;return v().createElement(h.VerticalGroup,null,(e.filters.length>0||t)&&v().createElement(h.HorizontalGroup,{spacing:"none"},v().createElement(h.InlineLabel,{width:Z,tooltip:""},"Attribute"),v().createElement(h.InlineLabel,{width:$,tooltip:""},"Operator"),v().createElement(h.InlineLabel,{width:ee,tooltip:""},"Value")),e.filters.map(((t,n)=>v().createElement(J,{isAdAnalytics:e.isAdAnalytics,value:t,onChange:t=>function(t,n){const r=[...e.filters];r.splice(t,1,n),e.onQueryFilterChange(r)}(n,t),onDelete:()=>function(t){const n=[...e.filters];n.splice(t,1),e.onQueryFilterChange(n)}(n),selectedQueryFilters:e.filters,key:n}))),v().createElement("div",{style:{paddingTop:r}},t?v().createElement(J,{isAdAnalytics:e.isAdAnalytics,value:void 0,onChange:function(t){const r=[...e.filters,t];e.onQueryFilterChange(r),n(!1)},onDelete:()=>n(!1),selectedQueryFilters:e.filters}):v().createElement(h.IconButton,{name:"plus-square",tooltip:"Add Filter",onClick:()=>n(!0),size:"xl"})))}function re(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ae(e){for(var t=1;t{""!==n.url&&null!=n.url||t(g(M({},n),{url:"https://api.bitmovin.com/v1"}))}),[]);const{jsonData:r}=n;return v().createElement(v().Fragment,null,v().createElement(h.DataSourceHttpSettings,{defaultUrl:"https://api.bitmovin.com/v1",dataSourceConfig:n,onChange:t,showAccessOptions:!0}),v().createElement(h.FieldSet,{label:"Bitmovin Analytics Details"},v().createElement(h.InlineField,{required:!0,label:"API Key",labelWidth:26},v().createElement(h.Input,{required:!0,onChange:e=>{const r=g(M({},n.jsonData),{apiKey:e.currentTarget.value});t(g(M({},n),{jsonData:r}))},value:r.apiKey||"",placeholder:"Analytics API Key",width:40})),v().createElement(h.InlineField,{label:"Tenant Org Id",labelWidth:26},v().createElement(h.Input,{onChange:e=>{const r=g(M({},n.jsonData),{tenantOrgId:e.currentTarget.value});t(g(M({},n),{jsonData:r}))},value:r.tenantOrgId||"",placeholder:"Tenant Org Id",width:40})),v().createElement(h.InlineField,{label:"Ad Analytics",tooltip:"Check if you want to query ads data",labelWidth:26},v().createElement(h.InlineSwitch,{value:r.isAdAnalytics||!1,onChange:e=>{const r=g(M({},n.jsonData),{isAdAnalytics:e.currentTarget.checked});t(g(M({},n),{jsonData:r}))}}))))})).setQueryEditor((function(e){const t=(0,n.defaults)(e.query,a),[r,i]=(0,y.useState)([]),[s,c]=(0,y.useState)("DEFAULT"),[u,E]=(0,y.useState)(""),[A,T]=(0,y.useState)("time_series"===t.resultFormat),[_,O]=(0,y.useState)(t.percentileValue),d=(0,y.useMemo)((()=>!!t.dimension&&D(t.dimension)),[t.dimension]),p=(0,y.useMemo)((()=>"percentile"===t.metric),[t.metric]);return(0,y.useEffect)((()=>{c("LOADING"),function(e,t,n){return B.apply(this,arguments)}(e.datasource.apiKey,e.datasource.baseUrl,e.datasource.tenantOrgId).then((e=>{i(e),c("SUCCESS")})).catch((e=>{c("ERROR"),E(e.status+" "+e.statusText)}))}),[e.datasource.apiKey,e.datasource.baseUrl,e.datasource.tenantOrgId]),v().createElement("div",{className:"gf-form"},v().createElement(h.FieldSet,null,v().createElement(h.InlineField,{label:"License",labelWidth:20,invalid:"ERROR"===s,error:`Error when fetching Analytics Licenses: ${u}`,disabled:"ERROR"===s,required:!0},v().createElement(h.Select,{value:t.license,onChange:n=>{e.onChange(oe(ae({},t),{license:n.value})),e.onRunQuery()},width:30,options:r,noOptionsMessage:"No Analytics Licenses found",isLoading:"LOADING"===s,placeholder:"LOADING"===s?"Loading Licenses":"Choose License"})),v().createElement(h.HorizontalGroup,{spacing:"xs"},!d&&v().createElement(h.InlineField,{label:"Metric",labelWidth:20,required:!0},v().createElement(h.Select,{value:t.metric,onChange:n=>(n=>{e.onChange(oe(ae({},t),{metric:n.value})),e.onRunQuery()})(n),width:30,options:V})),p&&v().createElement(h.Input,{value:_,onChange:e=>{let t=parseInt(e.target.value,10);t<0?t=0:t>99&&(t=99),O(t)},onBlur:()=>{e.onChange(oe(ae({},t),{percentileValue:_})),e.onRunQuery()},type:"number",placeholder:"value",width:10})),v().createElement(h.InlineField,{label:"Dimension",labelWidth:20,required:!0},v().createElement(h.Select,{value:t.dimension,onChange:n=>{e.onChange(oe(ae({},t),{dimension:n.value})),e.onRunQuery()},width:30,options:e.datasource.isAdAnalytics?G:w.concat(I)})),v().createElement(h.InlineField,{label:"Filter",labelWidth:20},v().createElement(ne,{isAdAnalytics:!!e.datasource.isAdAnalytics,onQueryFilterChange:n=>{e.onChange(oe(ae({},t),{filter:n})),e.onRunQuery()},filters:t.filter})),v().createElement(h.InlineField,{label:"Group By",labelWidth:20},v().createElement(Y,{isAdAnalytics:!!e.datasource.isAdAnalytics,onChange:n=>{e.onChange(oe(ae({},t),{groupBy:n})),e.onRunQuery()},groupBys:t.groupBy})),v().createElement(h.InlineField,{label:"Order By",labelWidth:20},v().createElement(k,{isAdAnalytics:!!e.datasource.isAdAnalytics,onChange:n=>{e.onChange(oe(ae({},t),{orderBy:n})),e.onRunQuery()},orderBys:t.orderBy})),v().createElement(h.InlineField,{label:"Limit",labelWidth:20},v().createElement(h.Input,{defaultValue:t.limit,type:"number",onBlur:n=>{const r=parseInt(n.target.value,10);e.onChange(oe(ae({},t),{limit:isNaN(r)?void 0:r})),e.onRunQuery()},width:30,placeholder:"No limit"})),v().createElement(h.InlineField,{label:"Format as time series",labelWidth:20},v().createElement(h.InlineSwitch,{value:A,onChange:n=>{T(n.currentTarget.checked),n.currentTarget.checked?e.onChange(oe(ae({},t),{interval:"AUTO",resultFormat:"time_series"})):e.onChange(oe(ae({},t),{interval:void 0,resultFormat:"table"})),e.onRunQuery()}})),A&&v().createElement(v().Fragment,null,v().createElement(h.InlineField,{label:"Interval",labelWidth:20},v().createElement(h.Select,{defaultValue:l,value:t.interval,onChange:n=>(n=>{e.onChange(oe(ae({},t),{interval:n.value})),e.onRunQuery()})(n),width:30,options:o}))),v().createElement(h.InlineField,{label:"Alias By",labelWidth:20},v().createElement(h.Input,{defaultValue:t.alias,placeholder:"Naming pattern",onBlur:n=>{e.onChange(oe(ae({},t),{alias:n.target.value})),e.onRunQuery()}}))))}))})(),u})())); //# sourceMappingURL=module.js.map \ No newline at end of file diff --git a/dist/module.js.map b/dist/module.js.map index f9bb733..ecaac3b 100644 --- a/dist/module.js.map +++ b/dist/module.js.map @@ -1 +1 @@ -{"version":3,"file":"module.js","mappings":"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CA,YACA,qBACA,oBACA,cACA,oBACA,8BACA,mBACA,eACA,gBACA,kBACA,YACA,cACA,gBACA,cACA,aACA,WACA,uBACA,oBACA,YACA,aACA,gBACA,gBACA,WACA,UACA,iBACA,wBACA,wBACA,eACA,OACA,UACA,mBACA,iBACA,aACA,cACA,SACA,mBACA,iBACA,YACA,UACA,iBACA,cACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,gBACA,iBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,iBACA,MACA,UACA,UACA,cACA,SACA,aACA,gBACA,kBACA,OACA,aACA,MACA,YACA,WACA,cACA,yBACA,aACA,eACA,YACA,WACA,SACA,yBACA,QACA,kBACA,gCACA,gCACA,iBACA,iBACA,OACA,yBACA,WACA,SACA,aACA,qBACA,cACA,iBACA,kBACA,aACA,aACA,SACA,gBACA,eACA,OACA,UACA,kBACA,gBACA,UACA,gBACA,aACA,OACA,eACA,mBACA,cACA,mBACA,mBACA,2BACA,wBACA,UACA,gBACA,WACA,sBACA,cACA,sBACA,qBACA,QAK0G/I,KACzGgJ,IAAsB,CACrBvM,MAAOuM,EACP9L,MAAO8L,MCfEC,EA3IY,CACvB,KACA,oBACA,gBACA,cACA,iBACA,WACA,UACA,iBACA,wBACA,wBACA,WACA,YACA,eACA,OACA,cACA,UACA,UACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,gBACA,iBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,iBACA,MACA,UACA,eACA,cACA,SACA,iBACA,gBACA,WACA,iBACA,WACA,aACA,gBACA,mBACA,kBACA,WACA,OACA,KACA,gBACA,iC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","sources":["webpack://bitmovin-analytics-datasource/external amd \"@grafana/data\"","webpack://bitmovin-analytics-datasource/external amd \"@grafana/runtime\"","webpack://bitmovin-analytics-datasource/external amd \"@grafana/ui\"","webpack://bitmovin-analytics-datasource/external amd \"lodash\"","webpack://bitmovin-analytics-datasource/external amd \"react\"","webpack://bitmovin-analytics-datasource/external amd \"rxjs\"","webpack://bitmovin-analytics-datasource/webpack/bootstrap","webpack://bitmovin-analytics-datasource/webpack/runtime/compat get default export","webpack://bitmovin-analytics-datasource/webpack/runtime/define property getters","webpack://bitmovin-analytics-datasource/webpack/runtime/hasOwnProperty shorthand","webpack://bitmovin-analytics-datasource/webpack/runtime/make namespace object","webpack://bitmovin-analytics-datasource/./types/grafanaTypes.ts","webpack://bitmovin-analytics-datasource/./utils/intervalUtils.ts","webpack://bitmovin-analytics-datasource/./utils/dataUtils.ts","webpack://bitmovin-analytics-datasource/./types/metric.ts","webpack://bitmovin-analytics-datasource/./utils/filterUtils.ts","webpack://bitmovin-analytics-datasource/./datasource.ts","webpack://bitmovin-analytics-datasource/./utils/licenses.ts","webpack://bitmovin-analytics-datasource/./types/aggregationMethod.ts","webpack://bitmovin-analytics-datasource/./types/queryAdAttributes.ts","webpack://bitmovin-analytics-datasource/./types/queryAttributes.ts","webpack://bitmovin-analytics-datasource/./components/GroupByInput.tsx","webpack://bitmovin-analytics-datasource/./components/GroupByRow.tsx","webpack://bitmovin-analytics-datasource/./components/OrderByInput.tsx","webpack://bitmovin-analytics-datasource/./components/OrderByRow.tsx","webpack://bitmovin-analytics-datasource/./types/queryFilter.ts","webpack://bitmovin-analytics-datasource/./components/QueryFilterInput.tsx","webpack://bitmovin-analytics-datasource/./components/FilterRow.tsx","webpack://bitmovin-analytics-datasource/./components/QueryEditor.tsx","webpack://bitmovin-analytics-datasource/./module.ts","webpack://bitmovin-analytics-datasource/./components/ConfigEditor.tsx"],"sourcesContent":["module.exports = __WEBPACK_EXTERNAL_MODULE__781__;","module.exports = __WEBPACK_EXTERNAL_MODULE__531__;","module.exports = __WEBPACK_EXTERNAL_MODULE__7__;","module.exports = __WEBPACK_EXTERNAL_MODULE__241__;","module.exports = __WEBPACK_EXTERNAL_MODULE__959__;","module.exports = __WEBPACK_EXTERNAL_MODULE__269__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { DataSourceJsonData } from '@grafana/data';\nimport { DataQuery } from '@grafana/schema';\nimport { QueryInterval } from '../utils/intervalUtils';\nimport { QueryAttribute } from './queryAttributes';\nimport { QueryAdAttribute } from './queryAdAttributes';\nimport { Metric } from './metric';\nimport { QueryOrderBy } from './queryOrderBy';\nimport { QueryFilter } from './queryFilter';\nimport { AggregationMethod } from './aggregationMethod';\n\ntype ResultFormat = 'table' | 'time_series';\n\n/**\n * These are the options configurable via the QueryEditor\n * */\nexport interface BitmovinAnalyticsDataQuery extends DataQuery {\n license: string;\n interval?: QueryInterval | 'AUTO';\n metric?: AggregationMethod;\n dimension?: QueryAttribute | QueryAdAttribute | Metric;\n groupBy: Array;\n orderBy: QueryOrderBy[];\n limit?: number;\n filter: QueryFilter[];\n alias?: string;\n percentileValue?: number;\n resultFormat: ResultFormat;\n}\n\n/**\n * @deprecated\n * These are the options query options of the old Angular based plugin\n * */\nexport interface OldBitmovinAnalyticsDataQuery extends DataQuery {\n license: string;\n interval?: QueryInterval | 'AUTO';\n metric?: AggregationMethod;\n dimension?: QueryAttribute | QueryAdAttribute | Metric;\n groupBy: Array;\n orderBy: QueryOrderBy[];\n limit?: string;\n filter: QueryFilter[];\n alias?: string;\n percentileValue: number;\n resultFormat: ResultFormat;\n}\n\nexport const DEFAULT_QUERY: Partial = {\n license: '',\n orderBy: [],\n groupBy: [],\n filter: [],\n resultFormat: 'time_series',\n interval: 'AUTO',\n};\n\n/**\n * These are options configured for each DataSource instance\n */\nexport interface BitmovinDataSourceOptions extends DataSourceJsonData {\n apiKey: string;\n tenantOrgId?: string;\n isAdAnalytics?: boolean;\n}\n","export type QueryInterval = 'MINUTE' | 'HOUR' | 'DAY';\n\nexport type SelectableQueryInterval = QueryInterval | 'AUTO';\n\nexport const SELECTABLE_QUERY_INTERVALS: Array<{ value: SelectableQueryInterval | 'AUTO'; label: string }> = [\n { value: 'AUTO', label: 'Auto' },\n { value: 'MINUTE', label: 'Minute' },\n { value: 'HOUR', label: 'Hour' },\n { value: 'DAY', label: 'Day' },\n];\n\nexport const DEFAULT_SELECTABLE_QUERY_INTERVAL = SELECTABLE_QUERY_INTERVALS[0];\n\n/**\n * Get corresponding interval in milliseconds.\n *\n * @param {QueryInterval} interval The interval\n * @returns {number} Interval in milliseconds or -1 if unknown.\n */\nexport const intervalToMilliseconds = (interval: QueryInterval): number => {\n switch (interval) {\n case 'MINUTE':\n return 1000 * 60;\n case 'HOUR':\n return 1000 * 60 * 60;\n case 'DAY':\n return 1000 * 60 * 60 * 24;\n default:\n return -1;\n }\n};\n\n/**\n * Calculates the Query interval based on a given selected interval, start timestamp and end timestamp\n *\n * @param {SelectableQueryInterval} interval The selected interval\n * @param {number} startTimestamp The start timestamp in milliseconds\n * @param {number} endTimestamp The end timestamp in milliseconds\n * @returns {QueryInterval} calculated Interval as QueryInterval\n */\nexport const calculateQueryInterval = (\n interval: SelectableQueryInterval,\n startTimestamp: number,\n endTimestamp: number\n): QueryInterval => {\n if (interval !== 'AUTO') {\n return interval as QueryInterval;\n }\n\n const intervalInMilliseconds = endTimestamp - startTimestamp;\n const minuteIntervalLimitInMilliseconds = 3 * 60 * 60 * 1000; // MINUTE granularity for timeframes below 3h\n const hourIntervalLimitInMilliseconds = 6 * 24 * 60 * 60 * 1000; // HOUR granularity for timeframes below 6d\n\n if (intervalInMilliseconds <= minuteIntervalLimitInMilliseconds) {\n return 'MINUTE';\n } else if (intervalInMilliseconds <= hourIntervalLimitInMilliseconds) {\n return 'HOUR';\n }\n return 'DAY';\n};\n\n/**\n * Rounds up a timestamp according to the specified query interval.\n *\n * @param {number} startTimestamp The start timestamp of the query.\n * @param {QueryInterval} interval The query interval.\n * @param {number} dataTimestamp The timestamp of a data point. Needed to calculate correct Day interval timestamp.\n * @return {number} The rounded up timestamp.\n */\nexport function ceilTimestampAccordingToQueryInterval(\n startTimestamp: number,\n interval: QueryInterval,\n dataTimestamp: number\n): number {\n const startDate = new Date(startTimestamp);\n switch (interval) {\n case 'MINUTE':\n if (startDate.getSeconds() === 0 && startDate.getMilliseconds() === 0) {\n return startTimestamp;\n }\n return startDate.setMinutes(startDate.getMinutes() + 1, 0, 0);\n case 'HOUR':\n if (startDate.getMinutes() === 0 && startDate.getSeconds() === 0 && startDate.getMilliseconds() === 0) {\n return startTimestamp;\n }\n return startDate.setHours(startDate.getHours() + 1, 0, 0, 0);\n case 'DAY':\n // Take the hours and minutes value from the datapoint timestamps as the timestamps for the day interval depend on the timezone of the license\n const dataHours = new Date(dataTimestamp).getHours();\n const dataMinutes = new Date(dataTimestamp).getMinutes();\n const startDateWithCorrectTime = new Date(\n startDate.getFullYear(),\n startDate.getMonth(),\n startDate.getDate(),\n dataHours,\n dataMinutes\n );\n\n if (startDateWithCorrectTime.getTime() > startTimestamp) {\n return startDateWithCorrectTime.getTime();\n }\n return new Date(startDateWithCorrectTime).setDate(startDateWithCorrectTime.getDate() + 1);\n }\n}\n","import { differenceWith, sortBy, zip } from 'lodash';\nimport { ceilTimestampAccordingToQueryInterval, intervalToMilliseconds, QueryInterval } from './intervalUtils';\nimport { Field, FieldType } from '@grafana/data';\n\nexport type MixedDataRow = Array;\nexport type MixedDataRowList = MixedDataRow[];\n\nexport type NumberDataRow = number[];\nexport type NumberDataRowList = NumberDataRow[];\n\n/**\n * Adds padding to a given time series to fill in any missing timestamps for a given interval.\n *\n * @param {MixedDataRowList} data The time series data to be padded. Each data row must have the following structure: [timestamp: number, groupBy1?: string, ... , groupByN?: string, value: number] where each row has the same groupByValue. If the groupByValues differ from row to row, only the groupByValues of the first row are considered.\n * @param {number} startTimestamp The start timestamp in milliseconds for the padding interval.\n * @param {number} endTimestamp The end timestamp in milliseconds for the padding interval.\n * @param {String} interval The interval used for the query, e.g. MINUTE, HOUR, ... .\n * @returns {MixedDataRowList} The padded and sorted time series data.\n */\nexport function padAndSortTimeSeries(\n data: MixedDataRowList,\n startTimestamp: number,\n endTimestamp: number,\n interval: QueryInterval\n): MixedDataRowList {\n if (data.length === 0) {\n return [];\n }\n\n const intervalInMs = intervalToMilliseconds(interval);\n if (intervalInMs < 0) {\n throw new Error(`Query interval ${interval} is not a valid interval.`);\n }\n\n // ceil timestamp to pad data with accurate timestamps and to ignore incomplete first datapoints\n const ceiledTimestamp = ceilTimestampAccordingToQueryInterval(startTimestamp, interval, data[0][0] as number);\n\n let dataRows: MixedDataRow = [0];\n const zeroValueTimeSeries: MixedDataRowList = [];\n\n // Preserve groupBys in the data if present\n if (data[0].length > 2) {\n dataRows = [...data[0].slice(1, -1), 0];\n }\n\n // Create zero value time series data for the entire interval\n for (let timestamp = ceiledTimestamp; timestamp <= endTimestamp; timestamp += intervalInMs) {\n const row = [timestamp, ...dataRows];\n zeroValueTimeSeries.push(row);\n }\n\n // Find the missing time series data\n const missingTimestampRows = differenceWith(zeroValueTimeSeries, data, (first, second) => first[0] === second[0]);\n\n // Pad data with the zero value data\n const paddedData = data.concat(missingTimestampRows);\n\n // Sort data by timestamp\n const sortedData = sortBy(paddedData, (row) => row[0]);\n\n // Ignore datapoints before ceiled start timestamp to only show complete datapoints and to not overflow graph to the left\n let index = 0;\n while (sortedData[index][0] < ceiledTimestamp) {\n index++;\n }\n const trimmedData = sortedData.slice(index);\n\n return trimmedData;\n}\n\n/**\n * Transforms grouped time series data into the Data Frame format.\n *\n * @param {MixedDataRowList} dataRows The grouped time series data to be transformed. Each data row must have the following structure: [timestamp: number, groupBy1: string, groupBy2: string, ... ,groupByN: string, value: number]\n * @param {number} startTimestamp The start timestamp in milliseconds for the time series data.\n * @param {number} endTimestamp The end timestamp in milliseconds for the time series data.\n * @param {string} interval The interval used for the time series data.\n * @returns {Array>} The transformed time series data.\n */\nexport function transformGroupedTimeSeriesData(\n dataRows: MixedDataRowList,\n startTimestamp: number,\n endTimestamp: number,\n interval: QueryInterval\n): Array> {\n if (dataRows.length === 0) {\n return [];\n }\n\n const fields: Array> = [];\n\n // Group the data by the groupBy values to display multiple time series in one graph\n const groupedTimeSeriesMap = new Map();\n dataRows.forEach((row) => {\n const groupKey = row.slice(1, -1).toString();\n if (!groupedTimeSeriesMap.has(groupKey)) {\n groupedTimeSeriesMap.set(groupKey, []);\n }\n groupedTimeSeriesMap.get(groupKey)?.push(row as []);\n });\n\n // Pad grouped data as there can only be one time field for a graph with multiple time series\n const paddedTimeSeries: MixedDataRowList[] = [];\n groupedTimeSeriesMap.forEach((data) => {\n paddedTimeSeries.push(padAndSortTimeSeries(data, startTimestamp, endTimestamp, interval));\n });\n\n // Extract and save timestamps from the first group data\n const transposedFirstGroupTimeSeriesData = zip(...paddedTimeSeries[0]);\n const timestamps = transposedFirstGroupTimeSeriesData[0];\n fields.push({ name: 'Time', values: timestamps as NumberDataRow, type: FieldType.time });\n\n // Extract time series values per group\n paddedTimeSeries.forEach((data) => {\n // Field name consisting of the groupBy values of the current time series\n const name = data[0].slice(1, -1).join(', ');\n\n //extract values\n const columns = zip(...data);\n const valueColumn = columns.slice(-1);\n\n fields.push({\n name: name,\n values: valueColumn[0] as NumberDataRow,\n type: FieldType.number,\n });\n });\n\n return fields;\n}\n\n/**\n * Transforms simple time series data into the Data Frame format.\n *\n * @param {NumberDataRowList} dataRows The time series data to be transformed. Each data row must have the following structure: [timestamp: number, value: number]\n * @param {string} columnName The name for the value column in the time series data.\n * @param {number} startTimestamp The start timestamp in milliseconds for the time series data.\n * @param {number} endTimestamp The end timestamp in milliseconds for the time series data.\n * @param {string} interval The interval used for the time series data.\n * @returns {Array>} The transformed time series data.\n */\nexport function transformSimpleTimeSeries(\n dataRows: NumberDataRowList,\n columnName: string,\n startTimestamp: number,\n endTimestamp: number,\n interval: QueryInterval\n): Array> {\n if (dataRows.length === 0) {\n return [];\n }\n\n const fields: Array> = [];\n const paddedData = padAndSortTimeSeries(dataRows, startTimestamp, endTimestamp, interval);\n const columns = zip(...paddedData);\n\n fields.push({ name: 'Time', values: columns[0] as NumberDataRow, type: FieldType.time });\n fields.push({\n name: columnName,\n values: columns[columns.length - 1] as NumberDataRow,\n type: FieldType.number,\n });\n\n return fields;\n}\n\n/**\n * Transforms table data into the Data Frame format.\n *\n * @param {MixedDataRowList} dataRows The table data to be transformed. Each data row must have the following structure: [groupBy1: string, groupBy2: string, ... , groupByN: string, value: number]\n * @param {Array<{ key: string; label: string }>} columnLabels The labels for each column in the table data.\n * @returns {Array>} The transformed table data.\n */\nexport function transformTableData(\n dataRows: MixedDataRowList,\n columnLabels: Array<{ key: string; label: string }>\n): Array> {\n if (dataRows.length === 0) {\n return [];\n }\n\n const fields: Array> = [];\n const columns = zip(...dataRows);\n\n let columnNames: string[] = [];\n if (columnLabels.length === 0) {\n for (let i = 0; i < columns.length; i++) {\n columnNames.push(`Column ${i + 1}`);\n }\n } else {\n columnNames.push(...columnLabels.map((label) => label.label));\n }\n\n const containsGroupByValues = dataRows[0].length > 1;\n if (containsGroupByValues) {\n const groupByColumns = columns.slice(0, -1);\n\n groupByColumns.forEach((column, index) => {\n fields.push({\n name: columnNames[index],\n values: column as string[],\n type: FieldType.string,\n });\n });\n }\n\n // Add the last column as a number field\n fields.push({\n name: columnNames[columnNames.length - 1],\n values: columns[columns.length - 1] as NumberDataRow,\n type: FieldType.number,\n });\n\n return fields;\n}\n","import { SelectableValue } from '@grafana/data';\n\nconst METRICS = ['AVG_CONCURRENTVIEWERS', 'MAX_CONCURRENTVIEWERS', 'AVG-DROPPED-FRAMES'] as const;\n\nexport type Metric = (typeof METRICS)[number];\n\nexport const SELECTABLE_METRICS: Array> = METRICS.map((metric) => ({\n value: metric,\n label: metric,\n}));\n\nexport const isMetric = (value: string): value is Metric => {\n return METRICS.includes(value as Metric);\n};\n","import { isEmpty } from 'lodash';\n\nimport { QueryAdAttribute } from '../types/queryAdAttributes';\nimport { QueryFilterOperator, OutputQueryFilterValue } from '../types/queryFilter';\nimport { QueryAttribute } from '../types/queryAttributes';\n\nconst isNullFilter = (filterAttribute: QueryAttribute | QueryAdAttribute): boolean => {\n switch (filterAttribute) {\n case 'CDN_PROVIDER':\n case 'CUSTOM_DATA_1':\n case 'CUSTOM_DATA_2':\n case 'CUSTOM_DATA_3':\n case 'CUSTOM_DATA_4':\n case 'CUSTOM_DATA_5':\n case 'CUSTOM_DATA_6':\n case 'CUSTOM_DATA_7':\n case 'CUSTOM_DATA_8':\n case 'CUSTOM_DATA_9':\n case 'CUSTOM_DATA_10':\n case 'CUSTOM_DATA_11':\n case 'CUSTOM_DATA_12':\n case 'CUSTOM_DATA_13':\n case 'CUSTOM_DATA_14':\n case 'CUSTOM_DATA_15':\n case 'CUSTOM_DATA_16':\n case 'CUSTOM_DATA_17':\n case 'CUSTOM_DATA_18':\n case 'CUSTOM_DATA_19':\n case 'CUSTOM_DATA_20':\n case 'CUSTOM_DATA_21':\n case 'CUSTOM_DATA_22':\n case 'CUSTOM_DATA_23':\n case 'CUSTOM_DATA_24':\n case 'CUSTOM_DATA_25':\n case 'CUSTOM_DATA_26':\n case 'CUSTOM_DATA_27':\n case 'CUSTOM_DATA_28':\n case 'CUSTOM_DATA_29':\n case 'CUSTOM_DATA_30':\n case 'CUSTOM_USER_ID':\n case 'ERROR_CODE':\n case 'EXPERIMENT_NAME':\n case 'ISP':\n case 'PLAYER_TECH':\n case 'PLAYER_VERSION':\n case 'VIDEO_ID':\n return true;\n default:\n return false;\n }\n};\n\nconst parseValueForInFilter = (rawValue: string) => {\n const value: string[] = JSON.parse(rawValue);\n if (!Array.isArray(value)) {\n throw new Error();\n }\n return value;\n};\n\nconst convertFilterForAds = (rawValue: string, filterAttribute: QueryAdAttribute) => {\n switch (filterAttribute) {\n case 'IS_LINEAR':\n return rawValue === 'true';\n\n case 'AD_STARTUP_TIME':\n case 'AD_WRAPPER_ADS_COUNT':\n case 'AUDIO_BITRATE':\n case 'CLICK_POSITION':\n case 'CLOSE_POSITION':\n case 'ERROR_CODE':\n case 'MANIFEST_DOWNLOAD_TIME':\n case 'MIN_SUGGESTED_DURATION':\n case 'PAGE_LOAD_TIME':\n case 'PLAYER_STARTUPTIME':\n case 'SCREEN_HEIGHT':\n case 'SCREEN_WIDTH':\n case 'SKIP_POSITION':\n case 'TIME_HOVERED':\n case 'TIME_IN_VIEWPORT':\n case 'TIME_PLAYED':\n case 'TIME_UNTIL_HOVER':\n case 'VIDEO_BITRATE':\n case 'VIDEO_WINDOW_HEIGHT':\n case 'VIDEO_WINDOW_WIDTH': {\n const parsedValue = parseInt(rawValue, 10);\n if (isNaN(parsedValue)) {\n throw new Error(`Couldn't parse filter value, please provide data as an integer number`);\n }\n return parsedValue;\n }\n\n case 'CLICK_PERCENTAGE':\n case 'CLOSE_PERCENTAGE':\n case 'PERCENTAGE_IN_VIEWPORT':\n case 'SKIP_PERCENTAGE': {\n const parsedValue = parseFloat(rawValue);\n if (isNaN(parsedValue)) {\n throw new Error(`Couldn't parse filter value, please provide data as a floating point number`);\n }\n return parsedValue;\n }\n\n default:\n return rawValue;\n }\n};\n\nconst convertFilter = (rawValue: string, filterAttribute: QueryAttribute) => {\n switch (filterAttribute) {\n case 'IS_CASTING':\n case 'IS_LIVE':\n case 'IS_MUTED':\n return rawValue === 'true';\n\n case 'AUDIO_BITRATE':\n case 'BUFFERED':\n case 'CLIENT_TIME':\n case 'DOWNLOAD_SPEED':\n case 'DRM_LOAD_TIME':\n case 'DROPPED_FRAMES':\n case 'DURATION':\n case 'ERROR_CODE':\n case 'PAGE_LOAD_TIME':\n case 'PAGE_LOAD_TYPE':\n case 'PAUSED':\n case 'PLAYED':\n case 'PLAYER_STARTUPTIME':\n case 'SCREEN_HEIGHT':\n case 'SCREEN_WIDTH':\n case 'SEEKED':\n case 'STARTUPTIME':\n case 'VIDEO_BITRATE':\n case 'VIDEO_DURATION':\n case 'VIDEO_PLAYBACK_HEIGHT':\n case 'VIDEO_PLAYBACK_WIDTH':\n case 'VIDEO_STARTUPTIME':\n case 'VIDEO_WINDOW_HEIGHT':\n case 'VIDEO_WINDOW_WIDTH':\n case 'VIDEOTIME_END':\n case 'VIDEOTIME_START':\n case 'VIEWTIME': {\n const parsedValue = parseInt(rawValue, 10);\n if (isNaN(parsedValue)) {\n throw new Error(`Couldn't parse filter value, please provide data as an integer number`);\n }\n return parsedValue;\n }\n\n case 'ERROR_PERCENTAGE':\n case 'REBUFFER_PERCENTAGE': {\n const parsedValue = parseFloat(rawValue);\n if (isNaN(parsedValue)) {\n throw new Error(`Couldn't parse filter value, please provide data as a floating point number`);\n }\n return parsedValue;\n }\n\n default:\n return rawValue;\n }\n};\n\n/**\n * Transforms the string filter Value from the UI to the appropriate type for our API.\n *\n * @param {string} rawValue The raw string value from the Filter Input.\n * @param {QueryAttribute | QueryAdAttribute} filterAttribute The filter attribute.\n * @param {QueryFilterOperator} filterOperator The filter operator.\n * @param {boolean} isAdAnalytics If Ad Analytics are queried.\n * @returns {OutputQueryFilterValue} The correctly converted Filter Value.\n * */\nexport const convertFilterValueToProperType = (\n rawValue: string,\n filterAttribute: QueryAttribute | QueryAdAttribute,\n filterOperator: QueryFilterOperator,\n isAdAnalytics: boolean\n): OutputQueryFilterValue => {\n if (isEmpty(rawValue) && isNullFilter(filterAttribute)) {\n return null;\n }\n\n if (filterOperator === 'IN') {\n try {\n return parseValueForInFilter(rawValue);\n } catch (e) {\n throw new Error(\n 'Couldn\\'t parse IN filter, please provide data in JSON array form (e.g.: [\"Firefox\", \"Chrome\"]).'\n );\n }\n }\n\n if (isAdAnalytics) {\n return convertFilterForAds(rawValue, filterAttribute as QueryAdAttribute);\n }\n return convertFilter(rawValue, filterAttribute as QueryAttribute);\n};\n","import {\n CoreApp,\n createDataFrame,\n DataQueryRequest,\n DataQueryResponse,\n DataSourceApi,\n DataSourceInstanceSettings,\n Field,\n QueryResultMetaNotice,\n} from '@grafana/data';\nimport { getBackendSrv } from '@grafana/runtime';\nimport {filter, isEmpty} from 'lodash';\nimport { catchError, lastValueFrom, map, Observable, of } from 'rxjs';\n\nimport {\n BitmovinDataSourceOptions,\n BitmovinAnalyticsDataQuery,\n DEFAULT_QUERY,\n OldBitmovinAnalyticsDataQuery,\n} from './types/grafanaTypes';\nimport {\n MixedDataRowList,\n NumberDataRowList,\n transformGroupedTimeSeriesData,\n transformSimpleTimeSeries,\n transformTableData,\n} from './utils/dataUtils';\nimport { calculateQueryInterval, QueryInterval } from './utils/intervalUtils';\nimport { isMetric, Metric } from './types/metric';\nimport { AggregationMethod } from './types/aggregationMethod';\nimport { ProperTypedQueryFilter } from './types/queryFilter';\nimport { QueryAttribute } from './types/queryAttributes';\nimport { QueryAdAttribute } from './types/queryAdAttributes';\nimport { QueryOrderBy } from './types/queryOrderBy';\nimport { convertFilterValueToProperType } from './utils/filterUtils';\n\ntype BitmovinAnalyticsRequestQuery = {\n licenseKey: string;\n start: Date;\n end: Date;\n filters: ProperTypedQueryFilter[];\n groupBy: Array;\n orderBy: QueryOrderBy[];\n dimension?: QueryAttribute | QueryAdAttribute;\n metric?: Metric;\n interval?: QueryInterval;\n limit?: number;\n percentile?: number;\n};\n\nexport class DataSource extends DataSourceApi<\n BitmovinAnalyticsDataQuery | OldBitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions\n> {\n baseUrl: string;\n apiKey: string;\n tenantOrgId?: string;\n isAdAnalytics?: boolean;\n\n constructor(instanceSettings: DataSourceInstanceSettings) {\n super(instanceSettings);\n\n this.apiKey = instanceSettings.jsonData.apiKey;\n this.tenantOrgId = instanceSettings.jsonData.tenantOrgId;\n this.isAdAnalytics = instanceSettings.jsonData.isAdAnalytics;\n this.baseUrl = instanceSettings.url!;\n }\n\n getDefaultQuery(_: CoreApp): Partial {\n return DEFAULT_QUERY;\n }\n\n /**\n * The Bitmovin API Response follows these rules:\n * - If the interval property is provided in the request query, time series data is returned and the first value of each row is a timestamp in milliseconds.\n * - If the groupBy property array is not empty in the request query:\n * - Depending on whether the interval property is set:\n * - Interval is set: All values between the first one (timestamp) and the last one (not included) can be considered string values.\n * - Interval is not set: All values up to the last one (not included) can be considered string values\n * - The last value of each row is always be a number.\n * */\n async query(options: DataQueryRequest): Promise {\n const { range } = options;\n const from = range!.from.toDate();\n const to = range!.to.toDate();\n\n //filter disabled queries\n const enabledQueries = (options.targets = filter(options.targets, (t) => !t.hide));\n\n //filter invalid queries\n const validQueries = filter(enabledQueries, (t) => this.isQueryComplete(t))\n\n const promises = validQueries.map(async (target) => {\n const interval =\n target.resultFormat === 'time_series' && target.interval\n ? calculateQueryInterval(target.interval, from.getTime(), to.getTime())\n : undefined;\n\n let aggregationMethod: AggregationMethod | undefined = target.metric;\n const percentileValue = aggregationMethod === 'percentile' ? target.percentileValue : undefined;\n\n let metric: Metric | undefined = undefined;\n let dimension: QueryAttribute | QueryAdAttribute | undefined = undefined;\n if (target.dimension) {\n if (isMetric(target.dimension)) {\n metric = target.dimension as Metric;\n } else {\n dimension = target.dimension as QueryAttribute | QueryAdAttribute;\n }\n }\n\n const filters: ProperTypedQueryFilter[] = target.filter.map((filter) => {\n return {\n name: filter.name,\n operator: filter.operator,\n value: convertFilterValueToProperType(filter.value, filter.name, filter.operator, !!this.isAdAnalytics),\n };\n });\n\n const query: BitmovinAnalyticsRequestQuery = {\n filters: filters,\n groupBy: target.groupBy,\n orderBy: target.orderBy,\n dimension: dimension,\n metric: metric,\n start: from,\n end: to,\n licenseKey: target.license,\n interval: interval,\n limit: this.parseLimit(target.limit),\n percentile: percentileValue,\n };\n\n const response = await lastValueFrom(this.request(this.getRequestUrl(metric, aggregationMethod), 'POST', query));\n\n const dataRows: MixedDataRowList = response.data.data.result.rows;\n const dataRowCount: number = response.data.data.result.rowCount;\n const columnLabels: Array<{ key: string; label: string }> = response.data.data.result.columnLabels;\n\n const fields: Array> = [];\n\n // Determine the appropriate transformation based on query parameters\n if (query.interval && query.groupBy?.length > 0) {\n // If the query has an interval and group by columns, transform the data as grouped time series\n fields.push(...transformGroupedTimeSeriesData(dataRows, from.getTime(), to.getTime(), query.interval));\n } else {\n if (query.interval) {\n // If the query has an interval but no group by columns, transform the data as simple time series\n fields.push(\n ...transformSimpleTimeSeries(\n dataRows as NumberDataRowList,\n columnLabels.length > 0 ? columnLabels[columnLabels.length - 1].label : 'Column 1',\n from.getTime(),\n to.getTime(),\n query.interval\n )\n );\n } else {\n // If no interval is specified, transform the data as table data\n fields.push(...transformTableData(dataRows, columnLabels));\n }\n }\n\n let metaNotices: QueryResultMetaNotice[] = [];\n if (dataRowCount >= 200) {\n metaNotices = [\n {\n severity: 'warning',\n text: 'Your request reached the max row limit of the API. You might see incomplete data. This problem might be caused by the use of high cardinality columns in group by, too small interval, or too big of a time range.',\n },\n ];\n }\n\n return createDataFrame({\n name: target.alias,\n fields: fields,\n meta: { notices: metaNotices },\n });\n });\n\n return Promise.all(promises).then((data) => ({ data }));\n }\n\n /** needed because of old plugin logic where limit was saved as string and not as number */\n parseLimit(limit: number | string | undefined): undefined | number {\n if (limit == null) {\n return undefined;\n }\n\n if (Number.isInteger(limit)) {\n return limit as number;\n } else {\n return parseInt(limit as string, 10);\n }\n }\n\n /** check if needed fields are set to avoid sending queries to API that will certainly return an error*/\n isQueryComplete(query: BitmovinAnalyticsDataQuery) {\n if (isEmpty(query.license) || isEmpty(query.dimension)) {\n return false\n }\n\n if (query.dimension != null) {\n if (!isMetric(query.dimension) && isEmpty(query.metric)) {\n return false\n }\n }\n\n return true\n }\n\n getRequestUrl(metric?: Metric, aggregation?: AggregationMethod): string {\n let url = '/analytics';\n if (this.isAdAnalytics === true) {\n url += '/ads';\n }\n\n if (metric != null) {\n return url + '/metrics/' + metric;\n }\n\n return url + '/queries/' + aggregation;\n }\n\n request(url: string, method: string, payload?: any): Observable> {\n const headers: Record= { 'X-Api-Key': this.apiKey}\n if (this.tenantOrgId != null) {\n headers[\"X-Tenant-Org-Id\"] = this.tenantOrgId\n }\n const options = {\n url: this.baseUrl + url,\n headers: headers,\n method: method,\n data: payload,\n };\n\n return getBackendSrv().fetch(options);\n }\n\n async testDatasource() {\n return lastValueFrom(\n this.request('/analytics/licenses', 'GET').pipe(\n map(() => {\n return {\n status: 'success',\n message: 'Data source successfully setup and connected.',\n };\n }),\n catchError((err) => {\n let message = 'Bitmovin: ';\n if (err.status) {\n message += err.status + ' ';\n }\n if (err.statusText) {\n message += err.statusText;\n } else {\n message += 'Can not connect to Bitmovin API';\n }\n\n let errorMessage = err.data?.message || err.data?.data?.message;\n\n //additional errorDetails like requestId and timestamp if requestId is set\n let errorDetails;\n if (err.data?.requestId) {\n errorDetails = 'Timestamp: ' + new Date().toISOString();\n errorDetails += err.data?.requestId ? '\\nRequestId: ' + err.data?.requestId : '';\n }\n\n return of({\n status: 'error',\n message: message,\n details: { message: errorMessage, verboseMessage: errorDetails },\n });\n })\n )\n );\n }\n}\n","import { lastValueFrom } from 'rxjs';\nimport { getBackendSrv } from '@grafana/runtime';\nimport { SelectableValue } from '@grafana/data';\n\ntype AnalyticsLicense = {\n readonly name: string;\n readonly id: string;\n readonly licenseKey?: string;\n};\n\nconst licenseEndpoints = [\n {\n endpoint: '/analytics/licenses',\n mapperFunc: (license: AnalyticsLicense): SelectableValue => ({\n value: license.licenseKey,\n label: license.name ? license.name : license.licenseKey,\n }),\n },\n {\n endpoint: '/analytics/virtual-licenses',\n mapperFunc: (license: AnalyticsLicense): SelectableValue => ({\n value: license.id,\n label: license.name ? license.name : license.id,\n }),\n },\n {\n endpoint: '/analytics/demo-licenses',\n mapperFunc: (license: AnalyticsLicense): SelectableValue => ({\n value: license.id,\n label: license.name ? license.name : license.id,\n }),\n },\n];\n\nasync function fetchLicensesForEndpoint(\n url: string,\n apiKey: string,\n mapperFunc: (license: AnalyticsLicense) => SelectableValue,\n tenantOrgId?: string\n) {\n const headers: Record = { 'X-Api-Key': apiKey}\n if (tenantOrgId != null) {\n headers[\"X-Tenant-Org-Id\"] = tenantOrgId\n }\n const options = {\n url: url,\n headers: headers,\n method: 'GET',\n };\n\n const response = await lastValueFrom(getBackendSrv().fetch(options));\n // @ts-ignore\n const licenses = response.data.data.result.items;\n\n const selectableLicenses = [];\n for (const license of licenses) {\n selectableLicenses.push(mapperFunc(license));\n }\n\n return selectableLicenses;\n}\n\nexport async function fetchLicenses(apiKey: string, baseUrl: string, tenantOrgId?: string): Promise {\n const allLicenses: SelectableValue[] = [];\n\n for (const licenseEndpoint of licenseEndpoints) {\n const licenses = await fetchLicensesForEndpoint(\n baseUrl + licenseEndpoint.endpoint,\n apiKey,\n licenseEndpoint.mapperFunc,\n tenantOrgId\n );\n allLicenses.push(...licenses);\n }\n\n return allLicenses;\n}\n","import type { SelectableValue } from '@grafana/data';\n\nconst AGGREGATION_METHODS = [\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'stddev',\n 'percentile',\n 'variance',\n 'median',\n] as const;\n\nexport type AggregationMethod = (typeof AGGREGATION_METHODS)[number];\n\nexport const SELECTABLE_AGGREGATION_METHODS: Array> = AGGREGATION_METHODS.map(\n (aggregation) => ({\n value: aggregation,\n label: aggregation,\n })\n);\n","import { SelectableValue } from '@grafana/data';\n\nconst QUERY_AD_ATTRIBUTES = [\n 'ADVERTISER_NAME',\n 'AD_CLICKTHROUGH_URL',\n 'AD_DESCRIPTION',\n 'AD_DURATION',\n 'AD_FALLBACK_INDEX',\n 'AD_ID',\n 'AD_ID_PLAYER',\n 'AD_IMPRESSION_ID',\n 'AD_IS_PERSISTENT',\n 'AD_MODULE',\n 'AD_OFFSET',\n 'AD_PLAYBACK_HEIGHT',\n 'AD_PLAYBACK_WIDTH',\n 'AD_POSITION',\n 'AD_PRELOAD_OFFSET',\n 'AD_REPLACE_CONTENT_DURATION',\n 'AD_SCHEDULE_TIME',\n 'AD_SKIPPABLE',\n 'AD_SKIP_AFTER',\n 'AD_STARTUP_TIME',\n 'AD_SYSTEM',\n 'AD_TAG_PATH',\n 'AD_TAG_SERVER',\n 'AD_TAG_TYPE',\n 'AD_TAG_URL',\n 'AD_TITLE',\n 'AD_WRAPPER_ADS_COUNT',\n 'ANALYTICS_VERSION',\n 'APIORG_ID',\n 'APIUSER_ID',\n 'API_FRAMEWORK',\n 'AUDIO_BITRATE',\n 'AUTOPLAY',\n 'BROWSER',\n 'BROWSER_IS_BOT',\n 'BROWSER_VERSION_MAJOR',\n 'BROWSER_VERSION_MINOR',\n 'CDN_PROVIDER',\n 'CITY',\n 'CLICKED',\n 'CLICK_PERCENTAGE',\n 'CLICK_POSITION',\n 'CLICK_RATE',\n 'CLIENT_TIME',\n 'CLOSED',\n 'CLOSE_PERCENTAGE',\n 'CLOSE_POSITION',\n 'COMPLETED',\n 'COUNTRY',\n 'CREATIVE_AD_ID',\n 'CREATIVE_ID',\n 'CUSTOM_DATA_1',\n 'CUSTOM_DATA_10',\n 'CUSTOM_DATA_11',\n 'CUSTOM_DATA_12',\n 'CUSTOM_DATA_13',\n 'CUSTOM_DATA_14',\n 'CUSTOM_DATA_15',\n 'CUSTOM_DATA_16',\n 'CUSTOM_DATA_17',\n 'CUSTOM_DATA_18',\n 'CUSTOM_DATA_19',\n 'CUSTOM_DATA_2',\n 'CUSTOM_DATA_20',\n 'CUSTOM_DATA_21',\n 'CUSTOM_DATA_22',\n 'CUSTOM_DATA_23',\n 'CUSTOM_DATA_24',\n 'CUSTOM_DATA_25',\n 'CUSTOM_DATA_26',\n 'CUSTOM_DATA_27',\n 'CUSTOM_DATA_28',\n 'CUSTOM_DATA_29',\n 'CUSTOM_DATA_3',\n 'CUSTOM_DATA_30',\n 'CUSTOM_DATA_4',\n 'CUSTOM_DATA_5',\n 'CUSTOM_DATA_6',\n 'CUSTOM_DATA_7',\n 'CUSTOM_DATA_8',\n 'CUSTOM_DATA_9',\n 'CUSTOM_USER_ID',\n 'DAY',\n 'DAYPART',\n 'DEAL_ID',\n 'DEVICE_TYPE',\n 'DOMAIN',\n 'ERROR_CODE',\n 'ERROR_MESSAGE',\n 'EXPERIMENT_NAME',\n 'HOUR',\n 'IP_ADDRESS',\n 'ISP',\n 'IS_LINEAR',\n 'LANGUAGE',\n 'LICENSE_KEY',\n 'MANIFEST_DOWNLOAD_TIME',\n 'MEDIA_PATH',\n 'MEDIA_SERVER',\n 'MEDIA_URL',\n 'MIDPOINT',\n 'MINUTE',\n 'MIN_SUGGESTED_DURATION',\n 'MONTH',\n 'OPERATINGSYSTEM',\n 'OPERATINGSYSTEM_VERSION_MAJOR',\n 'OPERATINGSYSTEM_VERSION_MINOR',\n 'PAGE_LOAD_TIME',\n 'PAGE_LOAD_TYPE',\n 'PATH',\n 'PERCENTAGE_IN_VIEWPORT',\n 'PLATFORM',\n 'PLAYER',\n 'PLAYER_KEY',\n 'PLAYER_STARTUPTIME',\n 'PLAYER_TECH',\n 'PLAYER_VERSION',\n 'PLAY_PERCENTAGE',\n 'QUARTILE_1',\n 'QUARTILE_3',\n 'REGION',\n 'SCREEN_HEIGHT',\n 'SCREEN_WIDTH',\n 'SIZE',\n 'SKIPPED',\n 'SKIP_PERCENTAGE',\n 'SKIP_POSITION',\n 'STARTED',\n 'STREAM_FORMAT',\n 'SURVEY_URL',\n 'TIME',\n 'TIME_HOVERED',\n 'TIME_IN_VIEWPORT',\n 'TIME_PLAYED',\n 'TIME_TO_FIRST_AD',\n 'TIME_UNTIL_HOVER',\n 'UNIVERSAL_AD_ID_REGISTRY',\n 'UNIVERSAL_AD_ID_VALUE',\n 'USER_ID',\n 'VIDEO_BITRATE',\n 'VIDEO_ID',\n 'VIDEO_IMPRESSION_ID',\n 'VIDEO_TITLE',\n 'VIDEO_WINDOW_HEIGHT',\n 'VIDEO_WINDOW_WIDTH',\n 'YEAR',\n] as const;\n\nexport type QueryAdAttribute = (typeof QUERY_AD_ATTRIBUTES)[number];\n\nexport const SELECTABLE_QUERY_AD_ATTRIBUTES: Array> = QUERY_AD_ATTRIBUTES.map(\n (queryAdAttribute) => ({\n value: queryAdAttribute,\n label: queryAdAttribute,\n })\n);\n","import { SelectableValue } from '@grafana/data';\n\nconst QUERY_ATTRIBUTES = [\n 'AD',\n 'ANALYTICS_VERSION',\n 'AUDIO_BITRATE',\n 'AUDIO_CODEC',\n 'AUDIO_LANGUAGE',\n 'AUTOPLAY',\n 'BROWSER',\n 'BROWSER_IS_BOT',\n 'BROWSER_VERSION_MAJOR',\n 'BROWSER_VERSION_MINOR',\n 'BUFFERED',\n 'CAST_TECH',\n 'CDN_PROVIDER',\n 'CITY',\n 'CLIENT_TIME',\n 'CONTEXT',\n 'COUNTRY',\n 'CUSTOM_DATA_1',\n 'CUSTOM_DATA_10',\n 'CUSTOM_DATA_11',\n 'CUSTOM_DATA_12',\n 'CUSTOM_DATA_13',\n 'CUSTOM_DATA_14',\n 'CUSTOM_DATA_15',\n 'CUSTOM_DATA_16',\n 'CUSTOM_DATA_17',\n 'CUSTOM_DATA_18',\n 'CUSTOM_DATA_19',\n 'CUSTOM_DATA_2',\n 'CUSTOM_DATA_20',\n 'CUSTOM_DATA_21',\n 'CUSTOM_DATA_22',\n 'CUSTOM_DATA_23',\n 'CUSTOM_DATA_24',\n 'CUSTOM_DATA_25',\n 'CUSTOM_DATA_26',\n 'CUSTOM_DATA_27',\n 'CUSTOM_DATA_28',\n 'CUSTOM_DATA_29',\n 'CUSTOM_DATA_3',\n 'CUSTOM_DATA_30',\n 'CUSTOM_DATA_4',\n 'CUSTOM_DATA_5',\n 'CUSTOM_DATA_6',\n 'CUSTOM_DATA_7',\n 'CUSTOM_DATA_8',\n 'CUSTOM_DATA_9',\n 'CUSTOM_USER_ID',\n 'DAY',\n 'DAYPART',\n 'DEVICE_CLASS',\n 'DEVICE_TYPE',\n 'DOMAIN',\n 'DOWNLOAD_SPEED',\n 'DRM_LOAD_TIME',\n 'DRM_TYPE',\n 'DROPPED_FRAMES',\n 'DURATION',\n 'ERROR_CODE',\n 'ERROR_MESSAGE',\n 'ERROR_PERCENTAGE',\n 'EXPERIMENT_NAME',\n 'FUNCTION',\n 'HOUR',\n 'ID',\n 'IMPRESSION_ID',\n 'INITIAL_TIME_TO_TARGET_LATENCY',\n 'IP_ADDRESS',\n 'ISP',\n 'IS_CASTING',\n 'IS_LIVE',\n 'IS_LOW_LATENCY',\n 'IS_MUTED',\n 'LANGUAGE',\n 'LATENCY',\n 'LICENSE_KEY',\n 'M3U8_URL',\n 'MINUTE',\n 'MONTH',\n 'MPD_URL',\n 'OPERATINGSYSTEM',\n 'OPERATINGSYSTEM_VERSION_MAJOR',\n 'OPERATINGSYSTEM_VERSION_MINOR',\n 'ORGANIZATION',\n 'PAGE_LOAD_TIME',\n 'PAGE_LOAD_TYPE',\n 'PATH',\n 'PAUSED',\n 'PLATFORM',\n 'PLAYED',\n 'PLAYER',\n 'PLAYER_STARTUPTIME',\n 'PLAYER_TECH',\n 'PLAYER_VERSION',\n 'PLAY_ATTEMPTS',\n 'PROG_URL',\n 'REBUFFER_PERCENTAGE',\n 'REGION',\n 'SCALE_FACTOR',\n 'SCREEN_HEIGHT',\n 'SCREEN_ORIENTATION',\n 'SCREEN_WIDTH',\n 'SEEKED',\n 'SIZE',\n 'STARTUPTIME',\n 'STATE',\n 'STREAM_FORMAT',\n 'SUBTITLE_ENABLED',\n 'SUBTITLE_LANGUAGE',\n 'SUPPORTED_VIDEO_CODECS',\n 'TARGET_LATENCY',\n 'TARGET_LATENCY_DELTA',\n 'TIME',\n 'TIME_TO_TARGET_LATENCY',\n 'USER_ID',\n 'VIDEOSTART_FAILED',\n 'VIDEOSTART_FAILED_REASON',\n 'VIDEOTIME_END',\n 'VIDEOTIME_START',\n 'VIDEO_BITRATE',\n 'VIDEO_CODEC',\n 'VIDEO_CODEC_TYPE',\n 'VIDEO_DURATION',\n 'VIDEO_ID',\n 'VIDEO_PLAYBACK_HEIGHT',\n 'VIDEO_PLAYBACK_WIDTH',\n 'VIDEO_SEGMENTS_DOWNLOADED',\n 'VIDEO_SEGMENTS_DOWNLOAD_SIZE',\n 'VIDEO_STARTUPTIME',\n 'VIDEO_TITLE',\n 'VIDEO_WINDOW_HEIGHT',\n 'VIDEO_WINDOW_WIDTH',\n 'VIEWTIME',\n 'YEAR',\n] as const;\n\nexport type QueryAttribute = (typeof QUERY_ATTRIBUTES)[number];\n\nexport const SELECTABLE_QUERY_ATTRIBUTES: Array> = QUERY_ATTRIBUTES.map(\n (queryAttribute) => ({\n value: queryAttribute,\n label: queryAttribute,\n })\n);\n","import React from 'react';\nimport { SelectableValue } from '@grafana/data';\nimport { HorizontalGroup, IconButton, Select } from '@grafana/ui';\n\nimport { QueryAttribute } from '../types/queryAttributes';\nimport { QueryAdAttribute } from '../types/queryAdAttributes';\nimport { isEmpty } from 'lodash';\n\nexport enum REORDER_DIRECTION {\n UP,\n DOWN,\n}\n\ntype Props = {\n readonly groupBy: SelectableValue;\n readonly selectableGroupBys: Array>;\n readonly onDelete: () => void;\n readonly onChange: (newValue: QueryAdAttribute | QueryAttribute) => void;\n readonly isFirst: boolean;\n readonly isLast: boolean;\n readonly onReorderGroupBy: (direction: REORDER_DIRECTION) => void;\n};\n\nexport function GroupByInput(props: Props) {\n return (\n \n props.onChange(selectableValue.value!)}\n options={props.selectableGroupBys}\n width={30}\n />\n props.onReorderGroupBy(REORDER_DIRECTION.DOWN)}\n name=\"arrow-down\"\n disabled={props.isLast}\n />\n props.onReorderGroupBy(REORDER_DIRECTION.UP)}\n name=\"arrow-up\"\n disabled={props.isFirst}\n />\n \n \n );\n}\n","import React from 'react';\nimport { SelectableValue } from '@grafana/data';\nimport { IconButton, VerticalGroup } from '@grafana/ui';\nimport { differenceWith } from 'lodash';\n\nimport { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';\nimport { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';\nimport { GroupByInput, REORDER_DIRECTION } from './GroupByInput';\n\nconst getSelectableGroupByOptions = (\n selectedGroupBys: Array,\n isAdAnalytics: boolean\n): Array> => {\n if (isAdAnalytics) {\n return differenceWith(\n SELECTABLE_QUERY_AD_ATTRIBUTES,\n selectedGroupBys,\n (selectableValue, selectedValue) => selectableValue.value === selectedValue\n );\n } else {\n return differenceWith(\n SELECTABLE_QUERY_ATTRIBUTES,\n selectedGroupBys,\n (selectableValue, selectedValue) => selectableValue.value === selectedValue\n );\n }\n};\n\nconst mapGroupByToSelectableValue = (\n selectedGroupBy: QueryAttribute | QueryAdAttribute,\n isAdAnalytics: boolean\n): SelectableValue => {\n if (isAdAnalytics) {\n return SELECTABLE_QUERY_AD_ATTRIBUTES.filter((selectableValue) => selectableValue.value === selectedGroupBy);\n } else {\n return SELECTABLE_QUERY_ATTRIBUTES.filter((selectableValue) => selectableValue.value === selectedGroupBy);\n }\n};\n\ntype Props = {\n readonly isAdAnalytics: boolean;\n readonly onChange: (newGroupBys: Array) => void;\n readonly groupBys: Array;\n};\n\nexport function GroupByRow(props: Props) {\n const paddingTop= props.groupBys.length === 0 ? 4 : 0\n const deleteGroupByInput = (index: number) => {\n const newSelectedGroupBys = [...props.groupBys];\n newSelectedGroupBys.splice(index, 1);\n\n props.onChange(newSelectedGroupBys);\n };\n\n const onSelectedGroupByChange = (index: number, newSelectedGroupBy: QueryAttribute | QueryAdAttribute) => {\n const newSelectedGroupBys = [...props.groupBys];\n newSelectedGroupBys.splice(index, 1, newSelectedGroupBy);\n\n props.onChange(newSelectedGroupBys);\n };\n\n const reorderGroupBy = (direction: REORDER_DIRECTION, index: number) => {\n const newSelectedGroupBys = [...props.groupBys];\n const groupByToMove = newSelectedGroupBys[index];\n newSelectedGroupBys.splice(index, 1);\n\n const newIndex = direction === REORDER_DIRECTION.UP ? index - 1 : index + 1;\n newSelectedGroupBys.splice(newIndex, 0, groupByToMove);\n\n props.onChange(newSelectedGroupBys);\n };\n\n const addGroupByInput = () => {\n const newDefaultSelectedValue = getSelectableGroupByOptions(props.groupBys, props.isAdAnalytics)[0].value!;\n props.onChange([...props.groupBys, newDefaultSelectedValue]);\n };\n\n return (\n \n {props.groupBys.map((item, index, selectedGroupBysArray) => (\n onSelectedGroupByChange(index, newValue)}\n selectableGroupBys={getSelectableGroupByOptions(selectedGroupBysArray, props.isAdAnalytics)}\n onDelete={() => deleteGroupByInput(index)}\n isFirst={index === 0}\n isLast={index === selectedGroupBysArray.length - 1}\n onReorderGroupBy={(direction: REORDER_DIRECTION) => reorderGroupBy(direction, index)}\n />\n ))}\n
\n addGroupByInput()} size=\"xl\" />\n
\n
\n );\n}\n","import React from 'react';\nimport { SelectableValue } from '@grafana/data';\nimport { HorizontalGroup, IconButton, RadioButtonGroup, Select } from '@grafana/ui';\n\nimport { QueryAttribute } from '../types/queryAttributes';\nimport { QueryAdAttribute } from '../types/queryAdAttributes';\nimport { QuerySortOrder } from '../types/queryOrderBy';\nimport { REORDER_DIRECTION } from './GroupByInput';\nimport { isEmpty } from 'lodash';\n\ntype Props = {\n readonly isAdAnalytics: boolean;\n readonly attribute: SelectableValue;\n readonly selectableOrderByAttributes: Array>;\n readonly onAttributeChange: (newValue: SelectableValue) => void;\n readonly sortOrder: QuerySortOrder;\n readonly onSortOrderChange: (newValue: QuerySortOrder) => void;\n readonly onDelete: () => void;\n readonly isFirst: boolean;\n readonly isLast: boolean;\n readonly onReorderOrderBy: (direction: REORDER_DIRECTION) => void;\n};\n\nconst sortOrderOption: Array> = [\n { value: 'ASC', description: 'Sort by ascending', icon: 'sort-amount-up' },\n { value: 'DESC', description: 'Sort by descending', icon: 'sort-amount-down' },\n];\n\nexport function OrderByInput(props: Props) {\n return (\n \n props.onAttributeChange(selectableValue)}\n options={props.selectableOrderByAttributes}\n width={30}\n />\n props.onSortOrderChange(value)}\n />\n props.onReorderOrderBy(REORDER_DIRECTION.DOWN)}\n name=\"arrow-down\"\n disabled={props.isLast}\n />\n props.onReorderOrderBy(REORDER_DIRECTION.UP)}\n name=\"arrow-up\"\n disabled={props.isFirst}\n />\n \n \n );\n}\n","import React from 'react';\nimport { IconButton, VerticalGroup } from '@grafana/ui';\nimport type { SelectableValue } from '@grafana/data';\nimport { differenceWith } from 'lodash';\n\nimport { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';\nimport { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';\nimport type { QueryOrderBy, QuerySortOrder } from '../types/queryOrderBy';\nimport { OrderByInput } from './OrderByInput';\nimport { REORDER_DIRECTION } from './GroupByInput';\n\nconst getSelectableOrderByOptions = (\n selectedOrderBys: QueryOrderBy[],\n isAdAnalytics: boolean\n): Array> => {\n if (isAdAnalytics) {\n return differenceWith(\n SELECTABLE_QUERY_AD_ATTRIBUTES,\n selectedOrderBys,\n (selectableValue, selectedValue) => selectableValue.value === selectedValue.name\n );\n } else {\n return differenceWith(\n SELECTABLE_QUERY_ATTRIBUTES,\n selectedOrderBys,\n (selectableValue, selectedValue) => selectableValue.value === selectedValue.name\n );\n }\n};\n\nconst mapOrderByAttributeToSelectableValue = (\n selectedOrderBy: QueryAttribute | QueryAdAttribute,\n isAdAnalytics: boolean\n): SelectableValue => {\n if (isAdAnalytics) {\n return SELECTABLE_QUERY_AD_ATTRIBUTES.filter((selectableValue) => selectableValue.value === selectedOrderBy);\n } else {\n return SELECTABLE_QUERY_ATTRIBUTES.filter((selectableValue) => selectableValue.value === selectedOrderBy);\n }\n};\n\ntype Props = {\n readonly isAdAnalytics: boolean;\n readonly onChange: (newOrderBy: QueryOrderBy[]) => void;\n readonly orderBys: QueryOrderBy[];\n};\n\nexport function OrderByRow(props: Props) {\n const paddingTop= props.orderBys.length === 0 ? 4 : 0\n const deleteOrderByInput = (index: number) => {\n const newOrderBys = [...props.orderBys];\n newOrderBys.splice(index, 1);\n\n props.onChange(newOrderBys);\n };\n\n const onAttributesChange = (index: number, newAttribute: SelectableValue) => {\n const newOrderBys = [...props.orderBys];\n const newOrderBy: QueryOrderBy = { name: newAttribute.value!, order: newOrderBys[index].order };\n\n newOrderBys.splice(index, 1, newOrderBy);\n\n props.onChange(newOrderBys);\n };\n\n const onSortOrdersChange = (index: number, newSortOrder: QuerySortOrder) => {\n const newOrderBys = [...props.orderBys];\n const newOrderBy: QueryOrderBy = { name: newOrderBys[index].name, order: newSortOrder };\n\n newOrderBys.splice(index, 1, newOrderBy);\n\n props.onChange(newOrderBys);\n };\n const reorderOrderBy = (direction: REORDER_DIRECTION, index: number) => {\n const newIndex = direction === REORDER_DIRECTION.UP ? index - 1 : index + 1;\n\n const newOrderBys = [...props.orderBys];\n const orderByToMove = newOrderBys[index];\n newOrderBys.splice(index, 1);\n newOrderBys.splice(newIndex, 0, orderByToMove);\n\n props.onChange(newOrderBys);\n };\n\n const addOrderByInput = () => {\n const newDefaultSelectedValue = getSelectableOrderByOptions(props.orderBys, props.isAdAnalytics)[0].value!;\n props.onChange([...props.orderBys, { name: newDefaultSelectedValue, order: 'ASC' }]);\n };\n\n return (\n \n {props.orderBys.map((orderBy, index, selectedOrderBys) => (\n ) =>\n onAttributesChange(index, newValue)\n }\n sortOrder={orderBy.order}\n onSortOrderChange={(newValue: QuerySortOrder) => onSortOrdersChange(index, newValue)}\n onDelete={() => deleteOrderByInput(index)}\n isFirst={index === 0}\n isLast={index === selectedOrderBys.length - 1}\n onReorderOrderBy={(direction: REORDER_DIRECTION) => reorderOrderBy(direction, index)}\n />\n ))}\n\n
\n addOrderByInput()} size=\"xl\" />\n
\n
\n );\n}\n","import { QueryAdAttribute } from './queryAdAttributes';\nimport { QueryAttribute } from './queryAttributes';\nimport type { SelectableValue } from '@grafana/data';\n\nconst QUERY_FILTER_OPERATORS = ['GT', 'GTE', 'LT', 'LTE', 'EQ', 'NE', 'CONTAINS', 'NOTCONTAINS', 'IN'] as const;\n\nexport type QueryFilterOperator = (typeof QUERY_FILTER_OPERATORS)[number];\n\nexport const SELECTABLE_QUERY_FILTER_OPERATORS: Array> =\n QUERY_FILTER_OPERATORS.map((o) => ({ value: o, label: o }));\n\n/** This type is needed because of legacy reasons.\n * In the angular plugin the value was saved as a string in a dashboard JSON file. */\nexport type QueryFilter = {\n name: QueryAdAttribute | QueryAttribute;\n operator: QueryFilterOperator;\n value: string;\n};\n\n/** QueryFilter type with the correct value type that is accepted by the Bitmovin API */\nexport type ProperTypedQueryFilter = {\n name: QueryAdAttribute | QueryAttribute;\n operator: QueryFilterOperator;\n value: OutputQueryFilterValue;\n};\n\n/** Correct Filter value type that is accepted by the Bitmovin API */\nexport type OutputQueryFilterValue = boolean | number | string | string[] | null;\n","import React, { useEffect, useMemo, useState } from 'react';\nimport { HorizontalGroup, IconButton, Input, Select, Tooltip } from '@grafana/ui';\n\nimport { QueryFilter, QueryFilterOperator, SELECTABLE_QUERY_FILTER_OPERATORS } from '../types/queryFilter';\nimport type { SelectableValue } from '@grafana/data';\nimport { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';\nimport { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';\nimport { convertFilterValueToProperType } from 'utils/filterUtils';\n\ninterface QueryFilterInputProps {\n /** `undefined` when component is used to create new filter (no values yet) */\n value: undefined | QueryFilter;\n onChange(queryFilter: QueryFilter): void;\n onDelete(): void;\n isAdAnalytics: boolean;\n /** Selected query filters are used to filter out used values from attribute select options */\n selectedQueryFilters: QueryFilter[];\n}\n\nexport function QueryFilterInput(props: Readonly) {\n /** Flag to indicate that query filter is undefined, does not exist yet, and this component is used to create new one */\n const isCreatingNewOne = props.value == null;\n\n const [derivedQueryFilterState, setDerivedQueryFilterState] = useState(\n buildInitialDerivedQueryFilterState(props.value)\n );\n\n /** Update and override {@link derivedQueryFilterState}, when {@link QueryFilterInputProps} value is changed */\n useEffect(() => setDerivedQueryFilterState(buildInitialDerivedQueryFilterState(props.value)), [props.value]);\n\n const attributeSelectValue = useMemo(\n () => findAttributeSelectableValue(derivedQueryFilterState.attribute, props.isAdAnalytics),\n [derivedQueryFilterState.attribute, props.isAdAnalytics]\n );\n\n const operatorSelectValue = useMemo(\n () => findOperatorSelectableValue(derivedQueryFilterState.operator),\n [derivedQueryFilterState.operator]\n );\n\n function handleAttributeChange(selectedValue: SelectableValue) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n dirty: true,\n attribute: selectedValue.value,\n attributeError: undefined,\n }));\n }\n\n function handleOperatorChange(selectedValue: SelectableValue) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n dirty: true,\n operator: selectedValue.value,\n operatorError: undefined,\n }));\n }\n\n function handleInputValueChange(value: string) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n dirty: true,\n value: value,\n inputValueError: undefined,\n }));\n }\n\n function handleRevertClick() {\n setDerivedQueryFilterState(buildInitialDerivedQueryFilterState(props.value));\n }\n\n function handleSaveClick() {\n if (derivedQueryFilterState.attribute == null) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n attributeError: 'Filter attribute has to be selected',\n }));\n return;\n }\n\n if (derivedQueryFilterState.operator == null) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n operatorError: 'Filter operator has to be selected',\n }));\n return;\n }\n\n try {\n convertFilterValueToProperType(\n derivedQueryFilterState.value!,\n derivedQueryFilterState.attribute!,\n derivedQueryFilterState.operator!,\n props.isAdAnalytics\n );\n\n props.onChange({\n name: derivedQueryFilterState.attribute!,\n operator: derivedQueryFilterState.operator!,\n value: derivedQueryFilterState.value!,\n });\n } catch (e: unknown) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n inputValueError: e instanceof Error ? e.message : 'Could not save value',\n }));\n }\n }\n\n return (\n \n \n {/* this div wrapper is needed to expose `ref` for Tooltip above */}\n
\n \n
\n \n \n {/* this div wrapper is needed to expose `ref` for Tooltip above */}\n
\n \n
\n \n \n handleInputValueChange(e.currentTarget.value)}\n invalid={derivedQueryFilterState.inputValueError != null}\n type=\"text\"\n width={VALUE_COMPONENT_WIDTH}\n />\n \n\n \n {/* in \"create mode\" we want to show save icons all the time */}\n {(isCreatingNewOne || derivedQueryFilterState.dirty) && (\n \n )}\n {/* in \"create mode\" there is nothing to revert to */}\n {!isCreatingNewOne && derivedQueryFilterState.dirty && (\n \n )}\n
\n );\n}\n\nexport const ATTRIBUTE_COMPONENT_WIDTH = 30;\nexport const OPERATOR_COMPONENT_WIDTH = 15;\nexport const VALUE_COMPONENT_WIDTH = 30;\n\ntype DerivedQueryFilterState = {\n attribute: undefined | QueryFilter['name'];\n attributeError: undefined | string;\n operator: undefined | QueryFilter['operator'];\n operatorError: undefined | string;\n value: undefined | QueryFilter['value'];\n /** `true` if some values have been changed by inputs */\n dirty: boolean;\n /** `undefined` when input value is valid */\n inputValueError: undefined | string;\n};\n\nfunction buildInitialDerivedQueryFilterState(queryFilter: undefined | QueryFilter): DerivedQueryFilterState {\n return {\n attribute: queryFilter?.name,\n attributeError: undefined,\n operator: queryFilter?.operator,\n operatorError: undefined,\n value: queryFilter?.value,\n dirty: false,\n inputValueError: undefined,\n };\n}\n\nfunction findAttributeSelectableValue(\n attribute: undefined | QueryAttribute | QueryAdAttribute,\n isAdAnalytics: boolean\n): undefined | SelectableValue {\n if (attribute == null) {\n return undefined;\n }\n\n const ALL_ATTRIBUTES: Array> = isAdAnalytics\n ? SELECTABLE_QUERY_AD_ATTRIBUTES\n : SELECTABLE_QUERY_ATTRIBUTES;\n\n return ALL_ATTRIBUTES.find((s) => s.value === attribute);\n}\n\nfunction findOperatorSelectableValue(\n operator: undefined | QueryFilterOperator\n): undefined | SelectableValue {\n if (operator == null) {\n return undefined;\n }\n\n return SELECTABLE_QUERY_FILTER_OPERATORS.find((s) => s.value === operator);\n}\n","import React, { useState } from 'react';\nimport { HorizontalGroup, IconButton, InlineLabel, VerticalGroup } from '@grafana/ui';\n\nimport { QueryFilter } from '../types/queryFilter';\nimport {\n ATTRIBUTE_COMPONENT_WIDTH,\n OPERATOR_COMPONENT_WIDTH,\n QueryFilterInput,\n VALUE_COMPONENT_WIDTH,\n} from './QueryFilterInput';\n\ntype Props = {\n readonly isAdAnalytics: boolean;\n readonly onQueryFilterChange: (newFilters: QueryFilter[]) => void;\n readonly filters: QueryFilter[];\n};\n\nexport function FilterRow(props: Props) {\n const [hasNewQueryFilter, setHasNewQueryFilter] = useState(false);\n const paddingTop= props.filters.length === 0 ? 4 : 0\n\n function handleQueryFilterDelete(queryFilterIndex: number) {\n const newQueryFilters = [...props.filters];\n newQueryFilters.splice(queryFilterIndex, 1);\n props.onQueryFilterChange(newQueryFilters);\n }\n\n function handleQueryFilterChange(queryFilterIndex: number, changedQueryFilter: QueryFilter) {\n const newQueryFilters = [...props.filters];\n newQueryFilters.splice(queryFilterIndex, 1, changedQueryFilter);\n props.onQueryFilterChange(newQueryFilters);\n }\n\n function handleNewQueryFilterChange(newQueryFilter: QueryFilter) {\n const newQueryFilters = [...props.filters, newQueryFilter];\n props.onQueryFilterChange(newQueryFilters);\n setHasNewQueryFilter(false);\n }\n\n return (\n \n {(props.filters.length > 0 || hasNewQueryFilter) && (\n \n \n Attribute\n \n \n Operator\n \n \n Value\n \n \n )}\n\n {props.filters.map((queryFilter, queryFilterIdx) => (\n handleQueryFilterChange(queryFilterIdx, changedQueryFilter)}\n onDelete={() => handleQueryFilterDelete(queryFilterIdx)}\n selectedQueryFilters={props.filters}\n key={queryFilterIdx}\n />\n ))}\n\n
\n {hasNewQueryFilter ? (\n setHasNewQueryFilter(false)}\n selectedQueryFilters={props.filters}\n />\n ) : (\n setHasNewQueryFilter(true)} size=\"xl\" />\n )}\n
\n
\n );\n}\n","import React, { ChangeEvent, useEffect, useMemo, useState } from 'react';\nimport { FieldSet, HorizontalGroup, InlineField, InlineSwitch, Input, Select } from '@grafana/ui';\nimport type { QueryEditorProps, SelectableValue } from '@grafana/data';\nimport { defaults } from 'lodash';\n\nimport { DataSource } from '../datasource';\nimport {\n BitmovinDataSourceOptions,\n BitmovinAnalyticsDataQuery,\n DEFAULT_QUERY,\n OldBitmovinAnalyticsDataQuery,\n} from '../types/grafanaTypes';\nimport { fetchLicenses } from '../utils/licenses';\nimport { DEFAULT_SELECTABLE_QUERY_INTERVAL, SELECTABLE_QUERY_INTERVALS } from '../utils/intervalUtils';\nimport { SELECTABLE_AGGREGATION_METHODS } from '../types/aggregationMethod';\nimport { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';\nimport { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';\nimport { isMetric, SELECTABLE_METRICS } from '../types/metric';\nimport { GroupByRow } from './GroupByRow';\nimport { OrderByRow } from './OrderByRow';\nimport type { QueryOrderBy } from '../types/queryOrderBy';\nimport type { QueryFilter } from '../types/queryFilter';\nimport { FilterRow } from './FilterRow';\n\nenum LoadingState {\n Default = 'DEFAULT',\n Loading = 'LOADING',\n Success = 'SUCCESS',\n Error = 'ERROR',\n}\n\ntype Props = QueryEditorProps<\n DataSource,\n BitmovinAnalyticsDataQuery | OldBitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions\n>;\n\nexport function QueryEditor(props: Props) {\n const query = defaults(props.query, DEFAULT_QUERY);\n const [selectableLicenses, setSelectableLicenses] = useState([]);\n const [licenseLoadingState, setLicenseLoadingState] = useState(LoadingState.Default);\n const [licenseErrorMessage, setLicenseErrorMessage] = useState('');\n const [isTimeSeries, setIsTimeSeries] = useState(query.resultFormat === 'time_series');\n const [percentileValue, setPercentileValue] = useState(query.percentileValue);\n const isMetricSelected = useMemo(() => {\n return query.dimension ? isMetric(query.dimension) : false;\n }, [query.dimension]);\n const isPercentileSelected = useMemo(() => {\n return query.metric === 'percentile';\n }, [query.metric]);\n\n /** Fetch Licenses */\n useEffect(() => {\n setLicenseLoadingState(LoadingState.Loading);\n fetchLicenses(props.datasource.apiKey, props.datasource.baseUrl, props.datasource.tenantOrgId)\n .then((licenses) => {\n setSelectableLicenses(licenses);\n setLicenseLoadingState(LoadingState.Success);\n })\n .catch((e) => {\n setLicenseLoadingState(LoadingState.Error);\n setLicenseErrorMessage(e.status + ' ' + e.statusText);\n });\n }, [props.datasource.apiKey, props.datasource.baseUrl, props.datasource.tenantOrgId]);\n\n const handleLicenseChange = (item: SelectableValue) => {\n props.onChange({ ...query, license: item.value });\n props.onRunQuery();\n };\n\n const handleAggregationChange = (item: SelectableValue) => {\n props.onChange({ ...query, metric: item.value });\n props.onRunQuery();\n };\n\n const handleDimensionChange = (item: SelectableValue) => {\n props.onChange({ ...query, dimension: item.value });\n props.onRunQuery();\n };\n\n const handleGroupByChange = (newGroupBys: Array) => {\n props.onChange({ ...query, groupBy: newGroupBys });\n props.onRunQuery();\n };\n\n const handleOrderByChange = (newOrderBys: QueryOrderBy[]) => {\n props.onChange({ ...query, orderBy: newOrderBys });\n props.onRunQuery();\n };\n\n const handleQueryFilterChange = (newFilters: QueryFilter[]) => {\n props.onChange({ ...query, filter: newFilters });\n props.onRunQuery();\n };\n\n const handleLimitBlur = (event: ChangeEvent) => {\n const limit = parseInt(event.target.value, 10);\n props.onChange({ ...query, limit: isNaN(limit) ? undefined : limit });\n props.onRunQuery();\n };\n\n const handleFormatAsTimeSeriesChange = (event: ChangeEvent) => {\n setIsTimeSeries(event.currentTarget.checked);\n if (event.currentTarget.checked) {\n props.onChange({ ...query, interval: 'AUTO', resultFormat: 'time_series' });\n } else {\n props.onChange({ ...query, interval: undefined, resultFormat: 'table' });\n }\n props.onRunQuery();\n };\n\n const handleIntervalChange = (item: SelectableValue) => {\n props.onChange({ ...query, interval: item.value });\n props.onRunQuery();\n };\n\n const handleAliasByBlur = (event: ChangeEvent) => {\n props.onChange({ ...query, alias: event.target.value });\n props.onRunQuery();\n };\n\n const handlePercentileValueChange = (event: ChangeEvent) => {\n let percentile = parseInt(event.target.value, 10);\n if (percentile < 0) {\n percentile = 0;\n } else if (percentile > 99) {\n percentile = 99;\n }\n setPercentileValue(percentile);\n };\n\n const handlePercentileBlur = () => {\n props.onChange({ ...query, percentileValue: percentileValue });\n props.onRunQuery();\n };\n\n const renderTimeSeriesOption = () => {\n return (\n <>\n \n handleIntervalChange(item)}\n width={30}\n options={SELECTABLE_QUERY_INTERVALS}\n />\n \n \n );\n };\n\n return (\n
\n
\n \n \n \n \n {!isMetricSelected && (\n \n handleAggregationChange(item)}\n width={30}\n options={SELECTABLE_AGGREGATION_METHODS}\n />\n \n )}\n {isPercentileSelected && (\n \n )}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {isTimeSeries && renderTimeSeriesOption()}\n \n \n \n
\n
\n );\n}\n","import { DataSourcePlugin } from '@grafana/data';\nimport { DataSource } from './datasource';\nimport { ConfigEditor } from './components/ConfigEditor';\nimport { QueryEditor } from './components/QueryEditor';\nimport {\n BitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions,\n OldBitmovinAnalyticsDataQuery,\n} from './types/grafanaTypes';\n\nexport const plugin = new DataSourcePlugin<\n DataSource,\n BitmovinAnalyticsDataQuery | OldBitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions\n>(DataSource)\n .setConfigEditor(ConfigEditor)\n .setQueryEditor(QueryEditor);\n","import React, { ChangeEvent, useEffect } from 'react';\nimport { DataSourceHttpSettings, FieldSet, InlineField, InlineSwitch, Input } from '@grafana/ui';\nimport { DataSourcePluginOptionsEditorProps } from '@grafana/data';\nimport { BitmovinDataSourceOptions } from '../types/grafanaTypes';\n\ninterface Props extends DataSourcePluginOptionsEditorProps {}\n\nexport function ConfigEditor(props: Props) {\n const { onOptionsChange, options } = props;\n\n // sets the instanceSettings.url to the default bitmovin api url if it is not already set when opening the ConfigEditor\n useEffect(() => {\n if (options.url === '' || options.url == null) {\n onOptionsChange({ ...options, url: 'https://api.bitmovin.com/v1' });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const onAdAnalyticsChange = (event: ChangeEvent) => {\n const jsonData = {\n ...options.jsonData,\n isAdAnalytics: event.currentTarget.checked,\n };\n onOptionsChange({ ...options, jsonData });\n };\n\n const onAPIKeyChange = (event: ChangeEvent) => {\n const jsonData = {\n ...options.jsonData,\n apiKey: event.currentTarget.value,\n };\n onOptionsChange({ ...options, jsonData });\n };\n\n const onTenantOrgIdChange = (event: ChangeEvent) => {\n const jsonData = {\n ...options.jsonData,\n tenantOrgId: event.currentTarget.value,\n };\n onOptionsChange({ ...options, jsonData });\n };\n\n const { jsonData } = options;\n\n return (\n <>\n \n\n
\n \n \n \n \n \n \n \n \n \n
\n \n );\n}\n"],"names":["module","exports","__WEBPACK_EXTERNAL_MODULE__781__","__WEBPACK_EXTERNAL_MODULE__531__","__WEBPACK_EXTERNAL_MODULE__7__","__WEBPACK_EXTERNAL_MODULE__241__","__WEBPACK_EXTERNAL_MODULE__959__","__WEBPACK_EXTERNAL_MODULE__269__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","n","getter","__esModule","d","a","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","r","Symbol","toStringTag","value","DEFAULT_QUERY","license","orderBy","groupBy","filter","resultFormat","interval","SELECTABLE_QUERY_INTERVALS","label","DEFAULT_SELECTABLE_QUERY_INTERVAL","padAndSortTimeSeries","data","startTimestamp","endTimestamp","length","intervalInMs","intervalToMilliseconds","Error","ceiledTimestamp","dataTimestamp","startDate","Date","getSeconds","getMilliseconds","setMinutes","getMinutes","setHours","getHours","dataHours","dataMinutes","startDateWithCorrectTime","getFullYear","getMonth","getDate","getTime","setDate","ceilTimestampAccordingToQueryInterval","dataRows","zeroValueTimeSeries","slice","timestamp","row","push","missingTimestampRows","differenceWith","first","second","paddedData","concat","sortedData","sortBy","index","METRICS","SELECTABLE_METRICS","map","metric","isMetric","includes","convertFilterValueToProperType","rawValue","filterAttribute","filterOperator","isAdAnalytics","isEmpty","isNullFilter","JSON","parse","Array","isArray","parseValueForInFilter","e","parsedValue","parseInt","isNaN","parseFloat","convertFilterForAds","convertFilter","DataSource","DataSourceApi","getDefaultQuery","_","options","range","from","toDate","to","enabledQueries","targets","t","hide","promises","isQueryComplete","target","query","intervalInMilliseconds","calculateQueryInterval","aggregationMethod","percentileValue","dimension","filters","name","operator","start","end","licenseKey","limit","parseLimit","percentile","response","lastValueFrom","request","getRequestUrl","result","rows","dataRowCount","rowCount","columnLabels","fields","groupedTimeSeriesMap","Map","forEach","groupKey","toString","has","set","paddedTimeSeries","timestamps","zip","values","type","FieldType","time","join","valueColumn","number","transformGroupedTimeSeriesData","columnName","columns","transformSimpleTimeSeries","columnNames","i","column","string","transformTableData","metaNotices","severity","text","createDataFrame","alias","meta","notices","Promise","all","then","Number","isInteger","aggregation","url","this","method","payload","headers","apiKey","tenantOrgId","baseUrl","getBackendSrv","fetch","testDatasource","pipe","status","message","catchError","err","statusText","errorDetails","errorMessage","requestId","toISOString","of","details","verboseMessage","constructor","instanceSettings","super","jsonData","licenseEndpoints","endpoint","mapperFunc","id","fetchLicensesForEndpoint","licenses","items","selectableLicenses","fetchLicenses","allLicenses","licenseEndpoint","SELECTABLE_AGGREGATION_METHODS","SELECTABLE_QUERY_AD_ATTRIBUTES","queryAdAttribute","SELECTABLE_QUERY_ATTRIBUTES","queryAttribute","GroupByInput","props","HorizontalGroup","Select","onChange","selectableValue","selectableGroupBys","width","IconButton","tooltip","onClick","onReorderGroupBy","disabled","isLast","isFirst","onDelete","size","variant","REORDER_DIRECTION","getSelectableGroupByOptions","selectedGroupBys","selectedValue","GroupByRow","paddingTop","groupBys","VerticalGroup","item","selectedGroupBysArray","selectedGroupBy","newValue","newSelectedGroupBy","newSelectedGroupBys","splice","onSelectedGroupByChange","deleteGroupByInput","direction","groupByToMove","newIndex","UP","reorderGroupBy","div","style","newDefaultSelectedValue","addGroupByInput","sortOrderOption","description","icon","OrderByInput","spacing","attribute","onAttributeChange","selectableOrderByAttributes","RadioButtonGroup","sortOrder","onSortOrderChange","onReorderOrderBy","DOWN","getSelectableOrderByOptions","selectedOrderBys","OrderByRow","orderBys","selectedOrderBy","newAttribute","newOrderBys","newOrderBy","order","onAttributesChange","newSortOrder","onSortOrdersChange","deleteOrderByInput","orderByToMove","reorderOrderBy","addOrderByInput","SELECTABLE_QUERY_FILTER_OPERATORS","QueryFilterInput","isCreatingNewOne","derivedQueryFilterState","setDerivedQueryFilterState","useState","buildInitialDerivedQueryFilterState","useEffect","attributeSelectValue","useMemo","find","s","findAttributeSelectableValue","operatorSelectValue","findOperatorSelectableValue","Tooltip","content","attributeError","show","theme","prevState","dirty","ATTRIBUTE_COMPONENT_WIDTH","invalid","operatorError","OPERATOR_COMPONENT_WIDTH","inputValueError","Input","handleInputValueChange","currentTarget","VALUE_COMPONENT_WIDTH","queryFilter","FilterRow","hasNewQueryFilter","setHasNewQueryFilter","InlineLabel","queryFilterIdx","changedQueryFilter","queryFilterIndex","newQueryFilters","onQueryFilterChange","handleQueryFilterChange","handleQueryFilterDelete","selectedQueryFilters","newQueryFilter","LoadingState","plugin","DataSourcePlugin","setConfigEditor","onOptionsChange","DataSourceHttpSettings","defaultUrl","dataSourceConfig","showAccessOptions","FieldSet","InlineField","required","labelWidth","event","placeholder","InlineSwitch","checked","setQueryEditor","defaults","setSelectableLicenses","licenseLoadingState","setLicenseLoadingState","licenseErrorMessage","setLicenseErrorMessage","isTimeSeries","setIsTimeSeries","setPercentileValue","isMetricSelected","isPercentileSelected","datasource","catch","className","error","onRunQuery","noOptionsMessage","isLoading","handleAggregationChange","onBlur","newFilters","newGroupBys","defaultValue","handleIntervalChange"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"module.js","mappings":"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EAAiBD,GACnE,MAAM+B,EAAiC,GAEvC,IAAK,MAAMC,KAAmBV,EAAkB,CAC9C,MAAMK,QAAiBD,EACrBzB,EAAU+B,EAAgBT,SAC1BxB,EACAiC,EAAgBR,WAChBxB,GAEF+B,EAAYnK,QAAQ+J,EACtB,CAEA,OAAOI,CACT,KAdsBD,MAAAA,KAAAA,U,CC5DtB,MAcaG,EAde,CAC1B,QACA,MACA,MACA,MACA,MACA,SACA,aACA,WACA,UAK2GvJ,KAC1G+G,IAAiB,CAChBvK,MAAOuK,EACP9J,MAAO8J,MCsIEyC,EAvJe,CAC1B,kBACA,sBACA,iBACA,cACA,oBACA,QACA,eACA,mBACA,mBACA,YACA,YACA,qBACA,oBACA,cACA,oBACA,8BACA,mBACA,eACA,gBACA,kBACA,YACA,cACA,gBACA,cACA,aACA,WACA,uBACA,oBACA,YACA,aACA,gBACA,gBACA,WACA,UACA,iBACA,wBACA,wBACA,eACA,OACA,UACA,mBACA,iBACA,aACA,cACA,SACA,mBACA,iBACA,YACA,UACA,iBACA,cACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,gBACA,iBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,iBACA,MACA,UACA,UACA,cACA,SACA,aACA,gBACA,kBACA,OACA,aACA,MACA,YACA,WACA,cACA,yBACA,aACA,eACA,YACA,WACA,SACA,yBACA,QACA,kBACA,gCACA,gCACA,iBACA,iBACA,OACA,yBACA,WACA,SACA,aACA,qBACA,cACA,iBACA,kBACA,aACA,aACA,SACA,gBACA,eACA,OACA,UACA,kBACA,gBACA,UACA,gBACA,aACA,OACA,eACA,mBACA,cACA,mBACA,mBACA,2BACA,wBACA,UACA,gBACA,WACA,sBACA,cACA,sBACA,qBACA,QAK0GxJ,KACzGyJ,IAAsB,CACrBjN,MAAOiN,EACPxM,MAAOwM,MCfEC,EA3IY,CACvB,KACA,oBACA,gBACA,cACA,iBACA,WACA,UACA,iBACA,wBACA,wBACA,WACA,YACA,eACA,OACA,cACA,UACA,UACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,gBACA,iBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,iBACA,MACA,UACA,eACA,cACA,SACA,iBACA,gBACA,WACA,iBACA,WACA,aACA,gBACA,mBACA,kBACA,WACA,OACA,KACA,gBACA,iCACA,aACA,MACA,aACA,UACA,iBACA,WACA,WACA,UACA,cACA,WACA,SACA,QACA,UACA,kBACA,gCACA,gCACA,eACA,iBACA,iBACA,OACA,SACA,WACA,SACA,SACA,qBACA,cACA,iBACA,gBACA,WACA,sBACA,SACA,eACA,gBACA,qBACA,eACA,SACA,OACA,cACA,QACA,gBACA,mBACA,oBACA,yBACA,iBACA,uBACA,OACA,yBACA,UACA,oBACA,2BACA,gBACA,kBACA,gBACA,cACA,mBACA,iBACA,WACA,wBACA,uBACA,4BACA,+BACA,oBACA,cACA,sBACA,qBACA,WACA,QAKkG1J,KACjG2J,IAAoB,CACnBnN,MAAOmN,EACP1M,MAAO0M,M,MCzHJ,SAASC,EAAaC,GAC3B,OACE,kBAACC,EAAAA,gBAAeA,KACd,kBAACC,EAAAA,OAAMA,CACLvN,OAAOiE,EAAAA,EAAAA,SAAQoJ,EAAMjN,cAAW1B,EAAY2O,EAAMjN,QAClDoN,SAAWC,GAAoBJ,EAAMG,SAASC,EAAgBzN,OAC9DmF,QAASkI,EAAMK,mBACfC,MAAO,KAET,kBAACC,EAAAA,WAAUA,CACTC,QAAQ,YACRC,QAAS,IAAMT,EAAMU,iBAAiB,GACtClH,KAAK,aACLmH,SAAUX,EAAMY,SAElB,kBAACL,EAAAA,WAAUA,CACTC,QAAQ,UACRC,QAAS,IAAMT,EAAMU,iBAAiB,GACtClH,KAAK,WACLmH,SAAUX,EAAMa,UAElB,kBAACN,EAAAA,WAAUA,CAACC,QAAQ,kBAAkBhH,KAAK,YAAYiH,QAAST,EAAMc,SAAUC,KAAK,KAAKC,QAAQ,gBAGxG,E,SAvCYC,G,mCAAAA,IAAAA,EAAAA,CAAAA,ICCZ,MAAMC,EAA8B,CAClCC,EACAxK,IAEIA,GACKhB,EAAAA,EAAAA,gBACLgK,EACAwB,GACA,CAACf,EAAiBgB,IAAkBhB,EAAgBzN,QAAUyO,KAGzDzL,EAAAA,EAAAA,gBACLkK,EACAsB,GACA,CAACf,EAAiBgB,IAAkBhB,EAAgBzN,QAAUyO,IAsB7D,SAASC,EAAWrB,GACzB,MAAMsB,EAAsC,IAA1BtB,EAAMuB,SAAS5M,OAAe,EAAI,EA+BpD,OACE,kBAAC6M,EAAAA,cAAaA,KACXxB,EAAMuB,SAASpL,KAAI,CAACsL,EAAMtF,EAAOuF,KAChC,yBAAC3B,EAAYA,CACXlO,IAAKsK,EACLpJ,SArDR4O,EAqD6CF,EApD7C9K,EAoDmDqJ,EAAMrJ,cAlDrDA,EACKgJ,EAA+B3M,QAAQoN,GAAoBA,EAAgBzN,QAAUgP,IAErF9B,EAA4B7M,QAAQoN,GAAoBA,EAAgBzN,QAAUgP,KAgDnFxB,SAAWyB,GA7Ba,EAACzF,EAAe0F,KAC9C,MAAMC,EAAsB,IAAI9B,EAAMuB,UACtCO,EAAoBC,OAAO5F,EAAO,EAAG0F,GAErC7B,EAAMG,SAAS2B,EAAoB,EAyB8BE,CAAwB7F,EAAOyF,GAC1FvB,mBAAoBa,EAA4BQ,EAAuB1B,EAAMrJ,eAC7EmK,SAAU,IAtCS,CAAC3E,IAC1B,MAAM2F,EAAsB,IAAI9B,EAAMuB,UACtCO,EAAoBC,OAAO5F,EAAO,GAElC6D,EAAMG,SAAS2B,EAAoB,EAkCbG,CAAmB9F,GACnC0E,QAAmB,IAAV1E,EACTyE,OAAQzE,IAAUuF,EAAsB/M,OAAS,EACjD+L,iBAAmBwB,GA3BJ,EAACA,EAA8B/F,KACpD,MAAM2F,EAAsB,IAAI9B,EAAMuB,UAChCY,EAAgBL,EAAoB3F,GAC1C2F,EAAoBC,OAAO5F,EAAO,GAElC,MAAMiG,EAAWF,IAAcjB,EAAkBoB,GAAKlG,EAAQ,EAAIA,EAAQ,EAC1E2F,EAAoBC,OAAOK,EAAU,EAAGD,GAExCnC,EAAMG,SAAS2B,EAAoB,EAmBuBQ,CAAeJ,EAAW/F,KA5DpD,IAClCwF,EACAhL,C,IA6DI,kBAAC4L,MAAAA,CAAIC,MAAO,CAAElB,eACZ,kBAACf,EAAAA,WAAUA,CAAC/G,KAAK,cAAcgH,QAAQ,eAAeC,QAAS,IApB7C,MACtB,MAAMgC,EAA0BvB,EAA4BlB,EAAMuB,SAAUvB,EAAMrJ,eAAe,GAAGhE,MACpGqN,EAAMG,SAAS,IAAIH,EAAMuB,SAAUkB,GAAyB,EAkBaC,GAAmB3B,KAAK,QAIrG,CCzEA,MAAM4B,EAA0D,CAC9D,CAAEhQ,MAAO,MAAOiQ,YAAa,oBAAqBC,KAAM,kBACxD,CAAElQ,MAAO,OAAQiQ,YAAa,qBAAsBC,KAAM,qBAGrD,SAASC,EAAa9C,GAC3B,OACE,kBAACC,EAAAA,gBAAeA,CAAC8C,QAAQ,MACvB,kBAAC7C,EAAAA,OAAMA,CACLvN,OAAOiE,EAAAA,EAAAA,SAAQoJ,EAAMgD,gBAAa3R,EAAY2O,EAAMgD,UACpD7C,SAAWC,GAAoBJ,EAAMiD,kBAAkB7C,GACvDtI,QAASkI,EAAMkD,4BACf5C,MAAO,KAET,kBAAC6C,EAAAA,iBAAgBA,CACfrL,QAAS6K,EACThQ,MAAOqN,EAAMoD,UACbjD,SAAWxN,GAAUqN,EAAMqD,kBAAkB1Q,KAE/C,kBAAC4N,EAAAA,WAAUA,CACTC,QAAQ,YACRC,QAAS,IAAMT,EAAMsD,iBAAiBrC,EAAkBsC,MACxD/J,KAAK,aACLmH,SAAUX,EAAMY,SAElB,kBAACL,EAAAA,WAAUA,CACTC,QAAQ,UACRC,QAAS,IAAMT,EAAMsD,iBAAiBrC,EAAkBoB,IACxD7I,KAAK,WACLmH,SAAUX,EAAMa,UAElB,kBAACN,EAAAA,WAAUA,CAACC,QAAQ,kBAAkBhH,KAAK,YAAYiH,QAAST,EAAMc,SAAUC,KAAK,KAAKC,QAAQ,gBAGxG,CC9CA,MAAMwC,EAA8B,CAClCC,EACA9M,IAEIA,GACKhB,EAAAA,EAAAA,gBACLgK,EACA8D,GACA,CAACrD,EAAiBgB,IAAkBhB,EAAgBzN,QAAUyO,EAAc5H,QAGvE7D,EAAAA,EAAAA,gBACLkK,EACA4D,GACA,CAACrD,EAAiBgB,IAAkBhB,EAAgBzN,QAAUyO,EAAc5H,OAsB3E,SAASkK,EAAW1D,GACzB,MAAMsB,EAAuC,IAA1BtB,EAAM2D,SAAShP,OAAe,EAAI,EAyCrD,OACE,kBAAC6M,EAAAA,cAAaA,KACXxB,EAAM2D,SAASxN,KAAI,CAACrD,EAASqJ,EAAOsH,KACnC,yBAACX,EAAYA,CACXjR,IAAKsK,EACLxF,cAAeqJ,EAAMrJ,cACrBuM,4BAA6BM,EAA4BC,EAAkBzD,EAAMrJ,eACjFqM,WAjERY,EAiEwD9Q,EAAQ0G,KAhEhE7C,EAgEsEqJ,EAAMrJ,cA9DxEA,EACKgJ,EAA+B3M,QAAQoN,GAAoBA,EAAgBzN,QAAUiR,IAErF/D,EAA4B7M,QAAQoN,GAAoBA,EAAgBzN,QAAUiR,KA4DnFX,kBAAoBrB,GAzCD,EAACzF,EAAe0H,KACzC,MAAMC,EAAc,IAAI9D,EAAM2D,UACxBI,EAA2B,CAAEvK,KAAMqK,EAAalR,MAAQqR,MAAOF,EAAY3H,GAAO6H,OAExFF,EAAY/B,OAAO5F,EAAO,EAAG4H,GAE7B/D,EAAMG,SAAS2D,EAAY,EAoCnBG,CAAmB9H,EAAOyF,GAE5BwB,UAAWtQ,EAAQkR,MACnBX,kBAAoBzB,GApCD,EAACzF,EAAe+H,KACzC,MAAMJ,EAAc,IAAI9D,EAAM2D,UACxBI,EAA2B,CAAEvK,KAAMsK,EAAY3H,GAAO3C,KAAMwK,MAAOE,GAEzEJ,EAAY/B,OAAO5F,EAAO,EAAG4H,GAE7B/D,EAAMG,SAAS2D,EAAY,EA8B4BK,CAAmBhI,EAAOyF,GAC3Ed,SAAU,IArDS,CAAC3E,IAC1B,MAAM2H,EAAc,IAAI9D,EAAM2D,UAC9BG,EAAY/B,OAAO5F,EAAO,GAE1B6D,EAAMG,SAAS2D,EAAY,EAiDLM,CAAmBjI,GACnC0E,QAAmB,IAAV1E,EACTyE,OAAQzE,IAAUsH,EAAiB9O,OAAS,EAC5C2O,iBAAmBpB,GAhCJ,EAACA,EAA8B/F,KACpD,MAAMiG,EAAWF,IAAcjB,EAAkBoB,GAAKlG,EAAQ,EAAIA,EAAQ,EAEpE2H,EAAc,IAAI9D,EAAM2D,UACxBU,EAAgBP,EAAY3H,GAClC2H,EAAY/B,OAAO5F,EAAO,GAC1B2H,EAAY/B,OAAOK,EAAU,EAAGiC,GAEhCrE,EAAMG,SAAS2D,EAAY,EAwB+BQ,CAAepC,EAAW/F,KA3E3C,IAC3CyH,EACAjN,C,IA6EI,kBAAC4L,MAAAA,CAAIC,MAAO,CAAElB,eACZ,kBAACf,EAAAA,WAAUA,CAAC/G,KAAK,cAAcgH,QAAQ,eAAeC,QAAS,IA1B7C,MACtB,MAAMgC,EAA0Be,EAA4BxD,EAAM2D,SAAU3D,EAAMrJ,eAAe,GAAGhE,MACpGqN,EAAMG,SAAS,IAAIH,EAAM2D,SAAU,CAAEnK,KAAMiJ,EAAyBuB,MAAO,QAAS,EAwBXO,GAAmBxD,KAAK,QAIrG,CC9GA,MAIayD,EAJkB,CAAC,KAAM,MAAO,KAAM,MAAO,KAAM,KAAM,WAAY,cAAe,MAKxErO,KAAKrE,IAAO,CAAEa,MAAOb,EAAGsB,MAAOtB,M,izBCUjD,SAAS2S,EAAiBzE,GAE/B,MAAM0E,EAAkC,MAAf1E,EAAMrN,OAExBgS,EAAyBC,IAA8BC,EAAAA,EAAAA,UAC5DC,GAAoC9E,EAAMrN,SAI5CoS,EAAAA,EAAAA,YAAU,IAAMH,EAA2BE,GAAoC9E,EAAMrN,SAAS,CAACqN,EAAMrN,QAErG,MAAMqS,GAAuBC,EAAAA,EAAAA,UAC3B,IA6KJ,SACEjC,EACArM,GAEA,GAAiB,MAAbqM,EAQJ,OAJkFrM,EAC9EgJ,EACAE,GAEkBqF,MAAMC,GAAMA,EAAExS,QAAUqQ,GAChD,CA1LUoC,CAA6BT,EAAwB3B,UAAWhD,EAAMrJ,gBAC5E,CAACgO,EAAwB3B,UAAWhD,EAAMrJ,gBAGtC0O,GAAsBJ,EAAAA,EAAAA,UAC1B,IAuLJ,SACExL,GAEA,GAAgB,MAAZA,EAIJ,OAAO+K,EAAkCU,MAAMC,GAAMA,EAAExS,QAAU8G,GACnE,CA/LU6L,CAA4BX,EAAwBlL,WAC1D,CAACkL,EAAwBlL,W,IA2EZkL,EAgBAA,EAgBAA,EAnCf,OACE,kBAAC1E,EAAAA,gBAAeA,CAAC8C,QAAQ,MACvB,kBAACwC,EAAAA,QAAOA,CACNC,QAA+C,QAAtCb,EAAAA,EAAwBc,sBAAxBd,IAAAA,EAAAA,EAA0C,GACnDe,KAAgD,MAA1Cf,EAAwBc,eAC9BE,MAAM,SAGN,kBAACpD,MAAAA,KACC,kBAACrC,EAAAA,OAAMA,CACLvN,MAAOqS,EACP7E,SAhFV,SAA+BiB,GAC7BwD,GAA4BgB,GAAe,OACtCA,GAAAA,CACHC,OAAO,EACP7C,UAAW5B,EAAczO,MACzB8S,oBAAgBpU,KAEpB,EA0EUyG,QAASkI,EAAMrJ,cAAgBgJ,EAAiCE,EAChES,MAAOwF,EACPC,QAAmD,MAA1CpB,EAAwBc,mBAIvC,kBAACF,EAAAA,QAAOA,CACNC,QAA8C,QAArCb,EAAAA,EAAwBqB,qBAAxBrB,IAAAA,EAAAA,EAAyC,GAClDe,KAA+C,MAAzCf,EAAwBqB,cAC9BL,MAAM,SAGN,kBAACpD,MAAAA,KACC,kBAACrC,EAAAA,OAAMA,CACLvN,MAAO0S,EACPlF,SAvFV,SAA8BiB,GAC5BwD,GAA4BgB,GAAe,OACtCA,GAAAA,CACHC,OAAO,EACPpM,SAAU2H,EAAczO,MACxBqT,mBAAe3U,KAEnB,EAiFUyG,QAAS0M,EACTlE,MAAO2F,EACPF,QAAkD,MAAzCpB,EAAwBqB,kBAIvC,kBAACT,EAAAA,QAAOA,CACNC,QAAgD,QAAvCb,EAAAA,EAAwBuB,uBAAxBvB,IAAAA,EAAAA,EAA2C,GACpDe,KAAiD,MAA3Cf,EAAwBuB,gBAC9BP,MAAM,SAEN,kBAACQ,EAAAA,MAAKA,CACJxT,MAAOgS,EAAwBhS,MAC/BwN,SAAWhJ,IAAMiP,OA5FOzT,EA4FgBwE,EAAEkP,cAAc1T,WA3F9DiS,GAA4BgB,GAAe,OACtCA,GAAAA,CACHC,OAAO,EACPlT,MAAOA,EACPuT,qBAAiB7U,MALrB,IAAgCsB,CA4FsC,EAC9DoT,QAAoD,MAA3CpB,EAAwBuB,gBACjC5K,KAAK,OACLgF,MAAOgG,MAIX,kBAAC/F,EAAAA,WAAUA,CAACS,QAAQ,cAAcxH,KAAK,YAAYuH,KAAK,KAAKP,QAAQ,gBAAgBC,QAAST,EAAMc,YAElG4D,GAAoBC,EAAwBkB,QAC5C,kBAACtF,EAAAA,WAAUA,CACTS,QAAQ,UACRxH,KAAMkL,EAAmB,cAAgB,OACzC3D,KAAK,KACLP,QAASkE,EAAmB,iBAAmB,eAC/CjE,QA9FR,WACE,GAAyC,MAArCkE,EAAwB3B,UAQ5B,GAAwC,MAApC2B,EAAwBlL,SAQ5B,IACElD,EACEoO,EAAwBhS,MACxBgS,EAAwB3B,UACxB2B,EAAwBlL,SACxBuG,EAAMrJ,eAGRqJ,EAAMG,SAAS,CACb3G,KAAMmL,EAAwB3B,UAC9BvJ,SAAUkL,EAAwBlL,SAClC9G,MAAOgS,EAAwBhS,OAEnC,CAAE,MAAOwE,GACPyN,GAA4BgB,GAAe,OACtCA,GAAAA,CACHM,gBAAiB/O,aAAatC,MAAQsC,EAAE6G,QAAU,0BAEtD,MAzBE4G,GAA4BgB,GAAe,OACtCA,GAAAA,CACHI,cAAe,8CAVjBpB,GAA4BgB,GAAe,OACtCA,GAAAA,CACHH,eAAgB,yCAgCtB,KA8DMf,GAAoBC,EAAwBkB,OAC5C,kBAACtF,EAAAA,WAAUA,CAACS,QAAQ,YAAYxH,KAAK,UAAUuH,KAAK,KAAKP,QAAQ,iBAAiBC,QAvGxF,WACEmE,EAA2BE,GAAoC9E,EAAMrN,OACvE,IAyGF,CAEO,MAAMmT,EAA4B,GAC5BG,EAA2B,GAC3BK,GAAwB,GAcrC,SAASxB,GAAoCyB,GAC3C,MAAO,CACLvD,UAAWuD,aAAAA,EAAAA,EAAa/M,KACxBiM,oBAAgBpU,EAChBoI,SAAU8M,aAAAA,EAAAA,EAAa9M,SACvBuM,mBAAe3U,EACfsB,MAAO4T,aAAAA,EAAAA,EAAa5T,MACpBkT,OAAO,EACPK,qBAAiB7U,EAErB,CCzLO,SAASmV,GAAUxG,GACxB,MAAOyG,EAAmBC,IAAwB7B,EAAAA,EAAAA,WAAkB,GAC9DvD,EAAqC,IAAzBtB,EAAMzG,QAAQ5E,OAAe,EAAI,EAoBnD,OACE,kBAAC6M,EAAAA,cAAaA,MACVxB,EAAMzG,QAAQ5E,OAAS,GAAK8R,IAC5B,kBAACxG,EAAAA,gBAAeA,CAAC8C,QAAS,QACxB,kBAAC4D,EAAAA,YAAWA,CAACrG,MAAOwF,EAA2BtF,QAAQ,IAAG,aAG1D,kBAACmG,EAAAA,YAAWA,CAACrG,MAAO2F,EAA0BzF,QAAQ,IAAG,YAGzD,kBAACmG,EAAAA,YAAWA,CAACrG,MAAOgG,GAAuB9F,QAAQ,IAAG,UAMzDR,EAAMzG,QAAQpD,KAAI,CAACoQ,EAAaK,IAC/B,kBAACnC,EAAgBA,CACf9N,cAAeqJ,EAAMrJ,cACrBhE,MAAO4T,EACPpG,SAAW0G,GAhCnB,SAAiCC,EAA0BD,GACzD,MAAME,EAAkB,IAAI/G,EAAMzG,SAClCwN,EAAgBhF,OAAO+E,EAAkB,EAAGD,GAC5C7G,EAAMgH,oBAAoBD,EAC5B,CA4B0CE,CAAwBL,EAAgBC,GAC1E/F,SAAU,IAvClB,SAAiCgG,GAC/B,MAAMC,EAAkB,IAAI/G,EAAMzG,SAClCwN,EAAgBhF,OAAO+E,EAAkB,GACzC9G,EAAMgH,oBAAoBD,EAC5B,CAmCwBG,CAAwBN,GACxCO,qBAAsBnH,EAAMzG,QAC5B1H,IAAK+U,MAIT,kBAACrE,MAAAA,CAAIC,MAAO,CAAElB,eACXmF,EACC,kBAAChC,EAAgBA,CACf9N,cAAeqJ,EAAMrJ,cACrBhE,WAAOtB,EACP8O,SAtCV,SAAoCiH,GAClC,MAAML,EAAkB,IAAI/G,EAAMzG,QAAS6N,GAC3CpH,EAAMgH,oBAAoBD,GAC1BL,GAAqB,EACvB,EAmCU5F,SAAU,IAAM4F,GAAqB,GACrCS,qBAAsBnH,EAAMzG,UAG9B,kBAACgH,EAAAA,WAAUA,CAAC/G,KAAK,cAAcgH,QAAQ,aAAaC,QAAS,IAAMiG,GAAqB,GAAO3F,KAAK,QAK9G,C,s0BCzDKsG,G,6EAAAA,KAAAA,GAAAA,CAAAA,ICdE,MAAMC,GAAS,IAAIC,EAAAA,iBAIxB7P,GACC8P,iBCRI,SAAsBxH,GAC3B,MAAM,gBAAEyH,EAAe,QAAE3P,GAAYkI,GAGrC+E,EAAAA,EAAAA,YAAU,KACY,KAAhBjN,EAAQqF,KAA6B,MAAfrF,EAAQqF,KAChCsK,EAAgB,OAAK3P,GAAAA,CAASqF,IAAK,gCACrC,GAEC,IAEH,MAwBM,SAAE2B,GAAahH,EAErB,OACE,oCACE,kBAAC4P,EAAAA,uBAAsBA,CACrBC,WAAW,8BACXC,iBAAkB9P,EAClBqI,SAAUsH,EACVI,mBAAmB,IAGrB,kBAACC,EAAAA,SAAQA,CAAC1U,MAAM,8BACd,kBAAC2U,EAAAA,YAAWA,CAACC,UAAAA,EAAS5U,MAAM,UAAU6U,WAAY,IAChD,kBAAC9B,EAAAA,MAAKA,CACJ6B,UAAAA,EACA7H,SA/Bc+H,IACtB,MAAMpJ,EAAW,OACZhH,EAAQgH,UAAQ,CACnBtB,OAAQ0K,EAAM7B,cAAc1T,QAE9B8U,EAAgB,OAAK3P,GAAAA,CAASgH,a,EA2BtBnM,MAAOmM,EAAStB,QAAU,GAC1B2K,YAAY,oBACZ7H,MAAO,MAGX,kBAACyH,EAAAA,YAAWA,CAAC3U,MAAM,gBAAgB6U,WAAY,IAC7C,kBAAC9B,EAAAA,MAAKA,CACJhG,SA/BmB+H,IAC3B,MAAMpJ,EAAW,OACZhH,EAAQgH,UAAQ,CACnBrB,YAAayK,EAAM7B,cAAc1T,QAEnC8U,EAAgB,OAAK3P,GAAAA,CAASgH,a,EA2BtBnM,MAAOmM,EAASrB,aAAe,GAC/B0K,YAAY,gBACZ7H,MAAO,MAGX,kBAACyH,EAAAA,YAAWA,CAAC3U,MAAM,eAAeoN,QAAS,sCAAuCyH,WAAY,IAC5F,kBAACG,EAAAA,aAAYA,CAACzV,MAAOmM,EAASnI,gBAAiB,EAAOwJ,SAtDjC+H,IAC3B,MAAMpJ,EAAW,OACZhH,EAAQgH,UAAQ,CACnBnI,cAAeuR,EAAM7B,cAAcgC,UAErCZ,EAAgB,OAAK3P,GAAAA,CAASgH,a,MAsDlC,ID7DGwJ,gBDqBI,SAAqBtI,GAC1B,MAAMvH,GAAQ8P,EAAAA,EAAAA,UAASvI,EAAMvH,MAAO7F,IAC7B0M,EAAoBkJ,IAAyB3D,EAAAA,EAAAA,UAA4B,KACzE4D,EAAqBC,IAA0B7D,EAAAA,EAAAA,UAAQA,YACvD8D,EAAqBC,IAA0B/D,EAAAA,EAAAA,UAAS,KACxDgE,EAAcC,IAAmBjE,EAAAA,EAAAA,UAAgC,gBAAvBpM,EAAMxF,eAChDoG,EAAiB0P,IAAsBlE,EAAAA,EAAAA,UAASpM,EAAMY,iBACvD2P,GAAmB/D,EAAAA,EAAAA,UAAQ,MACxBxM,EAAMa,WAAYjD,EAASoC,EAAMa,YACvC,CAACb,EAAMa,YACJ2P,GAAuBhE,EAAAA,EAAAA,UAAQ,IACX,eAAjBxM,EAAMrC,QACZ,CAACqC,EAAMrC,SAuGV,OApGA2O,EAAAA,EAAAA,YAAU,KACR2D,EAAuB,WXSpB,SAA6BlL,EAAgBE,EAAiBD,G,OAA/C8B,EAAAA,MAAAA,KAAAA,U,CWRlBA,CAAcS,EAAMkJ,WAAW1L,OAAQwC,EAAMkJ,WAAWxL,QAASsC,EAAMkJ,WAAWzL,aAC/EV,MAAMqC,IACLoJ,EAAsBpJ,GACtBsJ,EAAuB,UAAvBA,IAEDS,OAAOhS,IACNuR,EAAuB,SACvBE,EAAuBzR,EAAE4G,OAAS,IAAM5G,EAAEgH,WAAW,GACrD,GACH,CAAC6B,EAAMkJ,WAAW1L,OAAQwC,EAAMkJ,WAAWxL,QAASsC,EAAMkJ,WAAWzL,cA0FtE,kBAAC8E,MAAAA,CAAI6G,UAAU,WACb,kBAACtB,EAAAA,SAAQA,KACP,kBAACC,EAAAA,YAAWA,CACV3U,MAAM,UACN6U,WAAY,GACZlC,QAAiC,UAAxB0C,EACTY,MAAO,2CAA2CV,IAClDhI,SAAkC,UAAxB8H,EACVT,UAAAA,GAEA,kBAAC9H,EAAAA,OAAMA,CACLvN,MAAO8F,EAAM5F,QACbsN,SApGmBsB,IAC3BzB,EAAMG,SAAS,SAAK1H,GAAAA,CAAO5F,QAAS4O,EAAK9O,SACzCqN,EAAMsJ,YAAY,EAmGVhJ,MAAO,GACPxI,QAASwH,EACTiK,iBAAiB,8BACjBC,UAAmC,YAAxBf,EACXN,YAAqC,YAAxBM,EAA+C,mBAAqB,oBAGrF,kBAACxI,EAAAA,gBAAeA,CAAC8C,QAAQ,OACrBiG,GACA,kBAACjB,EAAAA,YAAWA,CAAC3U,MAAM,SAAS6U,WAAY,GAAID,UAAAA,GAC1C,kBAAC9H,EAAAA,OAAMA,CACLvN,MAAO8F,EAAMrC,OACb+J,SAAWsB,GA5GO,CAACA,IAC/BzB,EAAMG,SAAS,SAAK1H,GAAAA,CAAOrC,OAAQqL,EAAK9O,SACxCqN,EAAMsJ,YAAY,EA0GcG,CAAwBhI,GAC5CnB,MAAO,GACPxI,QAAS4H,KAIduJ,GACC,kBAAC9C,EAAAA,MAAKA,CACJxT,MAAO0G,EACP8G,SAlEyB+H,IACnC,IAAIlO,EAAa3C,SAAS6Q,EAAM1P,OAAO7F,MAAO,IAC1CqH,EAAa,EACfA,EAAa,EACJA,EAAa,KACtBA,EAAa,IAEf+O,EAAmB/O,EAAW,EA4DpB0P,OAzDiB,KAC3B1J,EAAMG,SAAS,SAAK1H,GAAAA,CAAOY,gBAAiBA,KAC5C2G,EAAMsJ,YAAY,EAwDRhO,KAAK,SACL6M,YAAY,QACZ7H,MAAO,MAIb,kBAACyH,EAAAA,YAAWA,CAAC3U,MAAM,YAAY6U,WAAY,GAAID,UAAAA,GAC7C,kBAAC9H,EAAAA,OAAMA,CACLvN,MAAO8F,EAAMa,UACb6G,SA3HqBsB,IAC7BzB,EAAMG,SAAS,SAAK1H,GAAAA,CAAOa,UAAWmI,EAAK9O,SAC3CqN,EAAMsJ,YAAY,EA0HVhJ,MAAO,GACPxI,QACEkI,EAAMkJ,WAAWvS,cACbgJ,EACAE,EAA4B9J,OAAOG,MAI7C,kBAAC6R,EAAAA,YAAWA,CAAC3U,MAAM,SAAS6U,WAAY,IACtC,kBAACzB,GAASA,CACR7P,gBAAeqJ,EAAMkJ,WAAWvS,cAChCqQ,oBAxHuB2C,IAC/B3J,EAAMG,SAAS,SAAK1H,GAAAA,CAAOzF,OAAQ2W,KACnC3J,EAAMsJ,YAAY,EAuHV/P,QAASd,EAAMzF,UAGnB,kBAAC+U,EAAAA,YAAWA,CAAC3U,MAAM,WAAW6U,WAAY,IACxC,kBAAC5G,EAAUA,CACT1K,gBAAeqJ,EAAMkJ,WAAWvS,cAChCwJ,SAzImByJ,IAC3B5J,EAAMG,SAAS,SAAK1H,GAAAA,CAAO1F,QAAS6W,KACpC5J,EAAMsJ,YAAY,EAwIV/H,SAAU9I,EAAM1F,WAGpB,kBAACgV,EAAAA,YAAWA,CAAC3U,MAAM,WAAW6U,WAAY,IACxC,kBAACvE,EAAUA,CACT/M,gBAAeqJ,EAAMkJ,WAAWvS,cAChCwJ,SA3ImB2D,IAC3B9D,EAAMG,SAAS,SAAK1H,GAAAA,CAAO3F,QAASgR,KACpC9D,EAAMsJ,YAAY,EA0IV3F,SAAUlL,EAAM3F,WAGpB,kBAACiV,EAAAA,YAAWA,CAAC3U,MAAM,QAAQ6U,WAAY,IACrC,kBAAC9B,EAAAA,MAAKA,CAAC0D,aAAcpR,EAAMqB,MAAOwB,KAAK,SAASoO,OAtI/BxB,IACvB,MAAMpO,EAAQzC,SAAS6Q,EAAM1P,OAAO7F,MAAO,IAC3CqN,EAAMG,SAAS,SAAK1H,GAAAA,CAAOqB,MAAOxC,MAAMwC,QAASzI,EAAYyI,KAC7DkG,EAAMsJ,YAAY,EAmI6DhJ,MAAO,GAAI6H,YAAY,cAElG,kBAACJ,EAAAA,YAAWA,CAAC3U,MAAM,wBAAwB6U,WAAY,IACrD,kBAACG,EAAAA,aAAYA,CAACzV,MAAOkW,EAAc1I,SAnIH+H,IACtCY,EAAgBZ,EAAM7B,cAAcgC,SAChCH,EAAM7B,cAAcgC,QACtBrI,EAAMG,SAAS,SAAK1H,GAAAA,CAAOvF,SAAU,OAAQD,aAAc,iBAE3D+M,EAAMG,SAAS,SAAK1H,GAAAA,CAAOvF,cAAU7B,EAAW4B,aAAc,WAEhE+M,EAAMsJ,YAAY,KA8HbT,GAhGH,oCACE,kBAACd,EAAAA,YAAWA,CAAC3U,MAAM,WAAW6U,WAAY,IACxC,kBAAC/H,EAAAA,OAAMA,CACL2J,aAAcxW,EACdV,MAAO8F,EAAMvF,SACbiN,SAAWsB,GAhCQ,CAACA,IAC5BzB,EAAMG,SAAS,SAAK1H,GAAAA,CAAOvF,SAAUuO,EAAK9O,SAC1CqN,EAAMsJ,YAAY,EA8BUQ,CAAqBrI,GACzCnB,MAAO,GACPxI,QAAS3E,MA0Fb,kBAAC4U,EAAAA,YAAWA,CAAC3U,MAAM,WAAW6U,WAAY,IACxC,kBAAC9B,EAAAA,MAAKA,CAAC0D,aAAcpR,EAAMiE,MAAOyL,YAAY,iBAAiBuB,OAxH5CxB,IACzBlI,EAAMG,SAAS,SAAK1H,GAAAA,CAAOiE,MAAOwL,EAAM1P,OAAO7F,SAC/CqN,EAAMsJ,YAAY,MA2HtB,G","sources":["webpack://bitmovin-analytics-datasource/external amd \"@grafana/data\"","webpack://bitmovin-analytics-datasource/external amd \"@grafana/runtime\"","webpack://bitmovin-analytics-datasource/external amd \"@grafana/ui\"","webpack://bitmovin-analytics-datasource/external amd \"lodash\"","webpack://bitmovin-analytics-datasource/external amd \"moment\"","webpack://bitmovin-analytics-datasource/external amd \"react\"","webpack://bitmovin-analytics-datasource/external amd \"rxjs\"","webpack://bitmovin-analytics-datasource/webpack/bootstrap","webpack://bitmovin-analytics-datasource/webpack/runtime/compat get default export","webpack://bitmovin-analytics-datasource/webpack/runtime/define property getters","webpack://bitmovin-analytics-datasource/webpack/runtime/hasOwnProperty shorthand","webpack://bitmovin-analytics-datasource/webpack/runtime/make namespace object","webpack://bitmovin-analytics-datasource/./types/grafanaTypes.ts","webpack://bitmovin-analytics-datasource/./utils/intervalUtils.ts","webpack://bitmovin-analytics-datasource/./utils/dataUtils.ts","webpack://bitmovin-analytics-datasource/./types/metric.ts","webpack://bitmovin-analytics-datasource/./utils/filterUtils.ts","webpack://bitmovin-analytics-datasource/./datasource.ts","webpack://bitmovin-analytics-datasource/./utils/licenses.ts","webpack://bitmovin-analytics-datasource/./types/aggregationMethod.ts","webpack://bitmovin-analytics-datasource/./types/queryAdAttributes.ts","webpack://bitmovin-analytics-datasource/./types/queryAttributes.ts","webpack://bitmovin-analytics-datasource/./components/GroupByInput.tsx","webpack://bitmovin-analytics-datasource/./components/GroupByRow.tsx","webpack://bitmovin-analytics-datasource/./components/OrderByInput.tsx","webpack://bitmovin-analytics-datasource/./components/OrderByRow.tsx","webpack://bitmovin-analytics-datasource/./types/queryFilter.ts","webpack://bitmovin-analytics-datasource/./components/QueryFilterInput.tsx","webpack://bitmovin-analytics-datasource/./components/FilterRow.tsx","webpack://bitmovin-analytics-datasource/./components/QueryEditor.tsx","webpack://bitmovin-analytics-datasource/./module.ts","webpack://bitmovin-analytics-datasource/./components/ConfigEditor.tsx"],"sourcesContent":["module.exports = __WEBPACK_EXTERNAL_MODULE__781__;","module.exports = __WEBPACK_EXTERNAL_MODULE__531__;","module.exports = __WEBPACK_EXTERNAL_MODULE__7__;","module.exports = __WEBPACK_EXTERNAL_MODULE__241__;","module.exports = __WEBPACK_EXTERNAL_MODULE__468__;","module.exports = __WEBPACK_EXTERNAL_MODULE__959__;","module.exports = __WEBPACK_EXTERNAL_MODULE__269__;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import { DataSourceJsonData } from '@grafana/data';\nimport { DataQuery } from '@grafana/schema';\nimport { QueryInterval } from '../utils/intervalUtils';\nimport { QueryAttribute } from './queryAttributes';\nimport { QueryAdAttribute } from './queryAdAttributes';\nimport { Metric } from './metric';\nimport { QueryOrderBy } from './queryOrderBy';\nimport { QueryFilter } from './queryFilter';\nimport { AggregationMethod } from './aggregationMethod';\n\ntype ResultFormat = 'table' | 'time_series';\n\n/**\n * These are the options configurable via the QueryEditor\n * */\nexport interface BitmovinAnalyticsDataQuery extends DataQuery {\n license: string;\n interval?: QueryInterval | 'AUTO';\n metric?: AggregationMethod;\n dimension?: QueryAttribute | QueryAdAttribute | Metric;\n groupBy: Array;\n orderBy: QueryOrderBy[];\n limit?: number;\n filter: QueryFilter[];\n alias?: string;\n percentileValue?: number;\n resultFormat: ResultFormat;\n}\n\n/**\n * @deprecated\n * These are the options query options of the old Angular based plugin\n * */\nexport interface OldBitmovinAnalyticsDataQuery extends DataQuery {\n license: string;\n interval?: QueryInterval | 'AUTO';\n metric?: AggregationMethod;\n dimension?: QueryAttribute | QueryAdAttribute | Metric;\n groupBy: Array;\n orderBy: QueryOrderBy[];\n limit?: string;\n filter: QueryFilter[];\n alias?: string;\n percentileValue: number;\n resultFormat: ResultFormat;\n}\n\nexport const DEFAULT_QUERY: Partial = {\n license: '',\n orderBy: [],\n groupBy: [],\n filter: [],\n resultFormat: 'time_series',\n interval: 'AUTO',\n};\n\n/**\n * These are options configured for each DataSource instance\n */\nexport interface BitmovinDataSourceOptions extends DataSourceJsonData {\n apiKey: string;\n tenantOrgId?: string;\n isAdAnalytics?: boolean;\n}\n","// eslint-disable-next-line no-restricted-imports\nimport type { DurationInputArg2 } from 'moment';\n\nexport type QueryInterval = 'MINUTE' | 'HOUR' | 'DAY' | 'MONTH';\n\nexport type SelectableQueryInterval = QueryInterval | 'AUTO';\n\nexport const SELECTABLE_QUERY_INTERVALS: Array<{ value: SelectableQueryInterval | 'AUTO'; label: string }> = [\n { value: 'AUTO', label: 'Auto' },\n { value: 'MINUTE', label: 'Minute' },\n { value: 'HOUR', label: 'Hour' },\n { value: 'DAY', label: 'Day' },\n { value: 'MONTH', label: 'Month' },\n];\n\nexport const DEFAULT_SELECTABLE_QUERY_INTERVAL = SELECTABLE_QUERY_INTERVALS[0];\n\n/** Intervals ordered ascending by duration */\nconst intervalOrder = ['MINUTE', 'HOUR', 'DAY', 'MONTH'];\n\n/**\n * Return the smaller interval of two provided intervals\n *\n * @param {QueryInterval} interval1 The first interval\n * @param {QueryInterval} interval2 The second interval\n * */\nexport const getSmallerInterval = (interval1: QueryInterval, interval2: QueryInterval) => {\n // Get the indices of the intervals\n const index1 = intervalOrder.indexOf(interval1);\n const index2 = intervalOrder.indexOf(interval2);\n\n // Return the smaller interval\n return index1 < index2 ? interval1 : interval2;\n};\n\n/**\n * Calculates the Query interval based on a given selected interval, start timestamp and end timestamp\n *\n * @param {SelectableQueryInterval} interval The selected interval\n * @param {number} startTimestamp The start timestamp in milliseconds\n * @param {number} endTimestamp The end timestamp in milliseconds\n * @returns {QueryInterval} calculated Interval as QueryInterval\n */\nexport const calculateQueryInterval = (\n interval: SelectableQueryInterval,\n startTimestamp: number,\n endTimestamp: number\n): QueryInterval => {\n if (interval !== 'AUTO') {\n return interval as QueryInterval;\n }\n\n const intervalInMilliseconds = endTimestamp - startTimestamp;\n const minuteIntervalLimitInMilliseconds = 3 * 60 * 60 * 1000; // MINUTE granularity for timeframes below 3h\n const hourIntervalLimitInMilliseconds = 6 * 24 * 60 * 60 * 1000; // HOUR granularity for timeframes below 6d\n const dayIntervalLimitInMilliseconds = 30 * 24 * 60 * 60 * 1000; // DAY granularity for timeframes below 30d\n\n if (intervalInMilliseconds <= minuteIntervalLimitInMilliseconds) {\n return 'MINUTE';\n } else if (intervalInMilliseconds <= hourIntervalLimitInMilliseconds) {\n return 'HOUR';\n } else if (intervalInMilliseconds <= dayIntervalLimitInMilliseconds) {\n return 'DAY';\n }\n return 'MONTH';\n};\n\n/**\n * Get corresponding moment interval in milliseconds.\n *\n * @param {QueryInterval} interval The interval\n * @returns {DurationInputArg2 | null} Interval as moment time unit\n */\nexport const getMomentTimeUnitForQueryInterval = (interval: QueryInterval): DurationInputArg2 | null => {\n switch (interval) {\n case 'MINUTE':\n return 'minute';\n case 'HOUR':\n return 'hour';\n case 'DAY':\n return 'day';\n case 'MONTH':\n return 'month';\n default:\n return null;\n }\n};\n","import { differenceWith, sortBy, zip } from 'lodash';\nimport { getMomentTimeUnitForQueryInterval, QueryInterval } from './intervalUtils';\nimport { Field, FieldType } from '@grafana/data';\n// eslint-disable-next-line no-restricted-imports\nimport moment from 'moment';\nimport type { DurationInputArg2 } from 'moment/moment';\n\nexport type MixedDataRow = Array;\nexport type MixedDataRowList = MixedDataRow[];\n\nexport type NumberDataRow = number[];\nexport type NumberDataRowList = NumberDataRow[];\n\n/**\n * Calculates the start timestamp for a time series based on a given interval,\n * the start timestamp of the interval and a reference data point timestamp.\n *\n * @param {number} dataTimestamp - The timestamp of a reference data point, from which to take the correct min, hour and date (in milliseconds).\n * @param {number} intervalStartTimestamp - The start timestamp of the interval (in milliseconds).\n * @param {QueryInterval} interval - The interval used for the query, e.g. MINUTE, HOUR, ... .\n * @returns {number} - The calculated start timestamp for the time series (in milliseconds).\n */\nexport function calculateTimeSeriesStartTimestamp(\n dataTimestamp: number,\n intervalStartTimestamp: number,\n interval: QueryInterval\n): number {\n const referenceDataDate = new Date(dataTimestamp);\n const intervalStartDate = new Date(intervalStartTimestamp);\n\n switch (interval) {\n case 'MINUTE':\n return intervalStartDate.setSeconds(0, 0);\n case 'HOUR':\n return intervalStartDate.setMinutes(0, 0, 0);\n case 'DAY':\n return intervalStartDate.setHours(referenceDataDate.getHours(), referenceDataDate.getMinutes(), 0, 0);\n case 'MONTH':\n referenceDataDate.getDate() === 1\n ? intervalStartDate.setDate(referenceDataDate.getDate())\n : intervalStartDate.setDate(0); // sets the date to the last day of the previous month\n return intervalStartDate.setHours(referenceDataDate.getHours(), referenceDataDate.getMinutes(), 0, 0);\n }\n}\n\n/**\n * Adds padding to a given time series to fill in any missing timestamps for a given interval.\n *\n * @param {MixedDataRowList} data The time series data to be padded. Each data row must have the following structure: [timestamp: number, groupBy1?: string, ... , groupByN?: string, value: number] where each row has the same groupByValue. If the groupByValues differ from row to row, only the groupByValues of the first row are considered.\n * @param {number} startTimestamp The start timestamp in milliseconds for the padding interval.\n * @param {number} endTimestamp The end timestamp in milliseconds for the padding interval.\n * @param {QueryInterval} interval The interval used for the query, e.g. MINUTE, HOUR, ... .\n * @returns {MixedDataRowList} The padded and sorted time series data.\n */\nexport function padAndSortTimeSeries(\n data: MixedDataRowList,\n startTimestamp: number,\n endTimestamp: number,\n interval: QueryInterval\n): MixedDataRowList {\n if (data.length === 0) {\n return [];\n }\n\n const momentInterval = getMomentTimeUnitForQueryInterval(interval);\n if (momentInterval == null) {\n throw new Error(`Query interval ${interval} is not a valid interval.`);\n }\n\n const zeroValueTimeSeries: MixedDataRowList = [];\n // Create zero value data for padding and preserve groupBys in the data if present\n const zeroValueDataRow = data[0].length > 2 ? [...data[0].slice(1, -1), 0] : [0];\n\n let momentStartTimestamp = moment(startTimestamp);\n\n // Create zero value time series data for the entire interval\n while (momentStartTimestamp.valueOf() <= endTimestamp) {\n const row = [momentStartTimestamp.valueOf(), ...zeroValueDataRow];\n zeroValueTimeSeries.push(row);\n\n // Move the timestamp forward by one interval unit\n momentStartTimestamp.add(1, momentInterval as DurationInputArg2);\n\n // Handle the special case for monthly intervals with last day of the month data timestamps\n // This code ensures that intervals starting at the end of a month correctly transition to the\n // last day of the next month. E.g. adding one month to 30th April with moment results in 30th May,\n // but the last day of the month, i.e., 31st May is the correct value.\n if (interval === 'MONTH' && momentStartTimestamp.date() !== 1) {\n momentStartTimestamp.set('date', momentStartTimestamp.daysInMonth());\n }\n }\n\n // Find the missing time series data\n const missingTimestampRows = differenceWith(zeroValueTimeSeries, data, (first, second) => first[0] === second[0]);\n\n // Pad data with the zero value data\n const paddedData = data.concat(missingTimestampRows);\n\n // Sort data by timestamp\n const sortedData = sortBy(paddedData, (row) => row[0]);\n\n return sortedData;\n}\n\n/**\n * Transforms grouped time series data into the Data Frame format.\n *\n * @param {MixedDataRowList} dataRows The grouped time series data to be transformed. Each data row must have the following structure: [timestamp: number, groupBy1: string, groupBy2: string, ... ,groupByN: string, value: number]\n * @param {number} startTimestamp The start timestamp in milliseconds for the time series data.\n * @param {number} endTimestamp The end timestamp in milliseconds for the time series data.\n * @param {QueryInterval} interval The interval used for the time series data.\n * @returns {Array>} The transformed time series data.\n */\nexport function transformGroupedTimeSeriesData(\n dataRows: MixedDataRowList,\n startTimestamp: number,\n endTimestamp: number,\n interval: QueryInterval\n): Array> {\n if (dataRows.length === 0) {\n return [];\n }\n\n const fields: Array> = [];\n\n // Group the data by the groupBy values to display multiple time series in one graph\n const groupedTimeSeriesMap = new Map();\n dataRows.forEach((row) => {\n const groupKey = row.slice(1, -1).toString();\n if (!groupedTimeSeriesMap.has(groupKey)) {\n groupedTimeSeriesMap.set(groupKey, []);\n }\n groupedTimeSeriesMap.get(groupKey)?.push(row as []);\n });\n\n // Pad grouped data as there can only be one time field for a graph with multiple time series\n const paddedTimeSeries: MixedDataRowList[] = [];\n groupedTimeSeriesMap.forEach((data) => {\n paddedTimeSeries.push(\n padAndSortTimeSeries(\n data,\n calculateTimeSeriesStartTimestamp(data[0][0] as number, startTimestamp, interval),\n endTimestamp,\n interval\n )\n );\n });\n\n // Extract and save timestamps from the first group data\n const transposedFirstGroupTimeSeriesData = zip(...paddedTimeSeries[0]);\n const timestamps = transposedFirstGroupTimeSeriesData[0];\n fields.push({ name: 'Time', values: timestamps as NumberDataRow, type: FieldType.time });\n\n // Extract time series values per group\n paddedTimeSeries.forEach((data) => {\n // Field name consisting of the groupBy values of the current time series\n const name = data[0].slice(1, -1).join(', ');\n\n //extract values\n const columns = zip(...data);\n const valueColumn = columns.slice(-1);\n\n fields.push({\n name: name,\n values: valueColumn[0] as NumberDataRow,\n type: FieldType.number,\n });\n });\n\n return fields;\n}\n\n/**\n * Transforms simple time series data into the Data Frame format.\n *\n * @param {NumberDataRowList} dataRows The time series data to be transformed. Each data row must have the following structure: [timestamp: number, value: number]\n * @param {string} columnName The name for the value column in the time series data.\n * @param {number} startTimestamp The start timestamp in milliseconds for the time series data.\n * @param {number} endTimestamp The end timestamp in milliseconds for the time series data.\n * @param {QueryInterval} interval The interval used for the time series data.\n * @returns {Array>} The transformed time series data.\n */\nexport function transformSimpleTimeSeries(\n dataRows: NumberDataRowList,\n columnName: string,\n startTimestamp: number,\n endTimestamp: number,\n interval: QueryInterval\n): Array> {\n if (dataRows.length === 0) {\n return [];\n }\n\n const fields: Array> = [];\n const paddedData = padAndSortTimeSeries(\n dataRows,\n calculateTimeSeriesStartTimestamp(dataRows[0][0], startTimestamp, interval),\n endTimestamp,\n interval\n );\n const columns = zip(...paddedData);\n\n fields.push({ name: 'Time', values: columns[0] as NumberDataRow, type: FieldType.time });\n fields.push({\n name: columnName,\n values: columns[columns.length - 1] as NumberDataRow,\n type: FieldType.number,\n });\n\n return fields;\n}\n\n/**\n * Transforms table data into the Data Frame format.\n *\n * @param {MixedDataRowList} dataRows The table data to be transformed. Each data row must have the following structure: [groupBy1: string, groupBy2: string, ... , groupByN: string, value: number]\n * @param {Array<{ key: string; label: string }>} columnLabels The labels for each column in the table data.\n * @returns {Array>} The transformed table data.\n */\nexport function transformTableData(\n dataRows: MixedDataRowList,\n columnLabels: Array<{ key: string; label: string }>\n): Array> {\n if (dataRows.length === 0) {\n return [];\n }\n\n const fields: Array> = [];\n const columns = zip(...dataRows);\n\n let columnNames: string[] = [];\n if (columnLabels.length === 0) {\n for (let i = 0; i < columns.length; i++) {\n columnNames.push(`Column ${i + 1}`);\n }\n } else {\n columnNames.push(...columnLabels.map((label) => label.label));\n }\n\n const containsGroupByValues = dataRows[0].length > 1;\n if (containsGroupByValues) {\n const groupByColumns = columns.slice(0, -1);\n\n groupByColumns.forEach((column, index) => {\n fields.push({\n name: columnNames[index],\n values: column as string[],\n type: FieldType.string,\n });\n });\n }\n\n // Add the last column as a number field\n fields.push({\n name: columnNames[columnNames.length - 1],\n values: columns[columns.length - 1] as NumberDataRow,\n type: FieldType.number,\n });\n\n return fields;\n}\n","import { SelectableValue } from '@grafana/data';\n\nconst METRICS = ['AVG_CONCURRENTVIEWERS', 'MAX_CONCURRENTVIEWERS', 'AVG-DROPPED-FRAMES'] as const;\n\nexport type Metric = (typeof METRICS)[number];\n\nexport const SELECTABLE_METRICS: Array> = METRICS.map((metric) => ({\n value: metric,\n label: metric,\n}));\n\nexport const isMetric = (value: string): value is Metric => {\n return METRICS.includes(value as Metric);\n};\n","import { isEmpty } from 'lodash';\n\nimport { QueryAdAttribute } from '../types/queryAdAttributes';\nimport { QueryFilterOperator, OutputQueryFilterValue } from '../types/queryFilter';\nimport { QueryAttribute } from '../types/queryAttributes';\n\nconst isNullFilter = (filterAttribute: QueryAttribute | QueryAdAttribute): boolean => {\n switch (filterAttribute) {\n case 'CDN_PROVIDER':\n case 'CUSTOM_DATA_1':\n case 'CUSTOM_DATA_2':\n case 'CUSTOM_DATA_3':\n case 'CUSTOM_DATA_4':\n case 'CUSTOM_DATA_5':\n case 'CUSTOM_DATA_6':\n case 'CUSTOM_DATA_7':\n case 'CUSTOM_DATA_8':\n case 'CUSTOM_DATA_9':\n case 'CUSTOM_DATA_10':\n case 'CUSTOM_DATA_11':\n case 'CUSTOM_DATA_12':\n case 'CUSTOM_DATA_13':\n case 'CUSTOM_DATA_14':\n case 'CUSTOM_DATA_15':\n case 'CUSTOM_DATA_16':\n case 'CUSTOM_DATA_17':\n case 'CUSTOM_DATA_18':\n case 'CUSTOM_DATA_19':\n case 'CUSTOM_DATA_20':\n case 'CUSTOM_DATA_21':\n case 'CUSTOM_DATA_22':\n case 'CUSTOM_DATA_23':\n case 'CUSTOM_DATA_24':\n case 'CUSTOM_DATA_25':\n case 'CUSTOM_DATA_26':\n case 'CUSTOM_DATA_27':\n case 'CUSTOM_DATA_28':\n case 'CUSTOM_DATA_29':\n case 'CUSTOM_DATA_30':\n case 'CUSTOM_USER_ID':\n case 'ERROR_CODE':\n case 'EXPERIMENT_NAME':\n case 'ISP':\n case 'PLAYER_TECH':\n case 'PLAYER_VERSION':\n case 'VIDEO_ID':\n return true;\n default:\n return false;\n }\n};\n\nconst parseValueForInFilter = (rawValue: string) => {\n const value: string[] = JSON.parse(rawValue);\n if (!Array.isArray(value)) {\n throw new Error();\n }\n return value;\n};\n\nconst convertFilterForAds = (rawValue: string, filterAttribute: QueryAdAttribute) => {\n switch (filterAttribute) {\n case 'IS_LINEAR':\n return rawValue === 'true';\n\n case 'AD_STARTUP_TIME':\n case 'AD_WRAPPER_ADS_COUNT':\n case 'AUDIO_BITRATE':\n case 'CLICK_POSITION':\n case 'CLOSE_POSITION':\n case 'ERROR_CODE':\n case 'MANIFEST_DOWNLOAD_TIME':\n case 'MIN_SUGGESTED_DURATION':\n case 'PAGE_LOAD_TIME':\n case 'PLAYER_STARTUPTIME':\n case 'SCREEN_HEIGHT':\n case 'SCREEN_WIDTH':\n case 'SKIP_POSITION':\n case 'TIME_HOVERED':\n case 'TIME_IN_VIEWPORT':\n case 'TIME_PLAYED':\n case 'TIME_UNTIL_HOVER':\n case 'VIDEO_BITRATE':\n case 'VIDEO_WINDOW_HEIGHT':\n case 'VIDEO_WINDOW_WIDTH': {\n const parsedValue = parseInt(rawValue, 10);\n if (isNaN(parsedValue)) {\n throw new Error(`Couldn't parse filter value, please provide data as an integer number`);\n }\n return parsedValue;\n }\n\n case 'CLICK_PERCENTAGE':\n case 'CLOSE_PERCENTAGE':\n case 'PERCENTAGE_IN_VIEWPORT':\n case 'SKIP_PERCENTAGE': {\n const parsedValue = parseFloat(rawValue);\n if (isNaN(parsedValue)) {\n throw new Error(`Couldn't parse filter value, please provide data as a floating point number`);\n }\n return parsedValue;\n }\n\n default:\n return rawValue;\n }\n};\n\nconst convertFilter = (rawValue: string, filterAttribute: QueryAttribute) => {\n switch (filterAttribute) {\n case 'IS_CASTING':\n case 'IS_LIVE':\n case 'IS_MUTED':\n return rawValue === 'true';\n\n case 'AUDIO_BITRATE':\n case 'BUFFERED':\n case 'CLIENT_TIME':\n case 'DOWNLOAD_SPEED':\n case 'DRM_LOAD_TIME':\n case 'DROPPED_FRAMES':\n case 'DURATION':\n case 'ERROR_CODE':\n case 'PAGE_LOAD_TIME':\n case 'PAGE_LOAD_TYPE':\n case 'PAUSED':\n case 'PLAYED':\n case 'PLAYER_STARTUPTIME':\n case 'SCREEN_HEIGHT':\n case 'SCREEN_WIDTH':\n case 'SEEKED':\n case 'STARTUPTIME':\n case 'VIDEO_BITRATE':\n case 'VIDEO_DURATION':\n case 'VIDEO_PLAYBACK_HEIGHT':\n case 'VIDEO_PLAYBACK_WIDTH':\n case 'VIDEO_STARTUPTIME':\n case 'VIDEO_WINDOW_HEIGHT':\n case 'VIDEO_WINDOW_WIDTH':\n case 'VIDEOTIME_END':\n case 'VIDEOTIME_START':\n case 'VIEWTIME': {\n const parsedValue = parseInt(rawValue, 10);\n if (isNaN(parsedValue)) {\n throw new Error(`Couldn't parse filter value, please provide data as an integer number`);\n }\n return parsedValue;\n }\n\n case 'ERROR_PERCENTAGE':\n case 'REBUFFER_PERCENTAGE': {\n const parsedValue = parseFloat(rawValue);\n if (isNaN(parsedValue)) {\n throw new Error(`Couldn't parse filter value, please provide data as a floating point number`);\n }\n return parsedValue;\n }\n\n default:\n return rawValue;\n }\n};\n\n/**\n * Transforms the string filter Value from the UI to the appropriate type for our API.\n *\n * @param {string} rawValue The raw string value from the Filter Input.\n * @param {QueryAttribute | QueryAdAttribute} filterAttribute The filter attribute.\n * @param {QueryFilterOperator} filterOperator The filter operator.\n * @param {boolean} isAdAnalytics If Ad Analytics are queried.\n * @returns {OutputQueryFilterValue} The correctly converted Filter Value.\n * */\nexport const convertFilterValueToProperType = (\n rawValue: string,\n filterAttribute: QueryAttribute | QueryAdAttribute,\n filterOperator: QueryFilterOperator,\n isAdAnalytics: boolean\n): OutputQueryFilterValue => {\n if (isEmpty(rawValue) && isNullFilter(filterAttribute)) {\n return null;\n }\n\n if (filterOperator === 'IN') {\n try {\n return parseValueForInFilter(rawValue);\n } catch (e) {\n throw new Error(\n 'Couldn\\'t parse IN filter, please provide data in JSON array form (e.g.: [\"Firefox\", \"Chrome\"]).'\n );\n }\n }\n\n if (isAdAnalytics) {\n return convertFilterForAds(rawValue, filterAttribute as QueryAdAttribute);\n }\n return convertFilter(rawValue, filterAttribute as QueryAttribute);\n};\n","import {\n CoreApp,\n createDataFrame,\n DataQueryRequest,\n DataQueryResponse,\n DataSourceApi,\n DataSourceInstanceSettings,\n Field,\n QueryResultMetaNotice,\n RawTimeRange,\n} from '@grafana/data';\nimport { getBackendSrv } from '@grafana/runtime';\nimport { filter, isEmpty } from 'lodash';\nimport { catchError, lastValueFrom, map, Observable, of } from 'rxjs';\n\nimport {\n BitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions,\n DEFAULT_QUERY,\n OldBitmovinAnalyticsDataQuery,\n} from './types/grafanaTypes';\nimport {\n MixedDataRowList,\n NumberDataRowList,\n transformGroupedTimeSeriesData,\n transformSimpleTimeSeries,\n transformTableData,\n} from './utils/dataUtils';\nimport {\n calculateQueryInterval,\n getMomentTimeUnitForQueryInterval,\n getSmallerInterval,\n QueryInterval,\n} from './utils/intervalUtils';\nimport { isMetric, Metric } from './types/metric';\nimport { AggregationMethod } from './types/aggregationMethod';\nimport { ProperTypedQueryFilter } from './types/queryFilter';\nimport { QueryAttribute } from './types/queryAttributes';\nimport { QueryAdAttribute } from './types/queryAdAttributes';\nimport { QueryOrderBy } from './types/queryOrderBy';\nimport { convertFilterValueToProperType } from './utils/filterUtils';\n\ntype BitmovinAnalyticsRequestQuery = {\n licenseKey: string;\n start: Date;\n end: Date;\n filters: ProperTypedQueryFilter[];\n groupBy: Array;\n orderBy: QueryOrderBy[];\n dimension?: QueryAttribute | QueryAdAttribute;\n metric?: Metric;\n interval?: QueryInterval;\n limit?: number;\n percentile?: number;\n};\n\nexport class DataSource extends DataSourceApi<\n BitmovinAnalyticsDataQuery | OldBitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions\n> {\n baseUrl: string;\n apiKey: string;\n tenantOrgId?: string;\n isAdAnalytics?: boolean;\n\n constructor(instanceSettings: DataSourceInstanceSettings) {\n super(instanceSettings);\n\n this.apiKey = instanceSettings.jsonData.apiKey;\n this.tenantOrgId = instanceSettings.jsonData.tenantOrgId;\n this.isAdAnalytics = instanceSettings.jsonData.isAdAnalytics;\n this.baseUrl = instanceSettings.url!;\n }\n\n getDefaultQuery(_: CoreApp): Partial {\n return DEFAULT_QUERY;\n }\n\n /**\n * The Bitmovin API Response follows these rules:\n * - If the interval property is provided in the request query, time series data is returned and the first value of each row is a timestamp in milliseconds.\n * - If the groupBy property array is not empty in the request query:\n * - Depending on whether the interval property is set:\n * - Interval is set: All values between the first one (timestamp) and the last one (not included) can be considered string values.\n * - Interval is not set: All values up to the last one (not included) can be considered string values\n * - The last value of each row is always be a number.\n * */\n async query(options: DataQueryRequest): Promise {\n const { range } = options;\n const isRelativeRangeFrom = this.isRelativeRangeFrom(range.raw);\n\n //filter disabled queries\n const enabledQueries = (options.targets = filter(options.targets, (t) => !t.hide));\n\n //filter invalid queries\n const validQueries = filter(enabledQueries, (t) => this.isQueryComplete(t));\n\n const promises = validQueries.map(async (target) => {\n const interval =\n target.resultFormat === 'time_series' && target.interval\n ? calculateQueryInterval(target.interval, range!.from.valueOf(), range!.to.valueOf())\n : undefined;\n\n let queryFrom = range!.from;\n const queryTo = range!.to;\n\n // floor the query start time to improve cache hitting\n if (isRelativeRangeFrom) {\n let flooringInterval = calculateQueryInterval('AUTO', queryFrom.valueOf(), queryTo.valueOf());\n if (interval != null) {\n // to allow higher granularity if interval is selected by user\n flooringInterval = getSmallerInterval(interval, flooringInterval);\n }\n const momentTimeUnit = getMomentTimeUnitForQueryInterval(flooringInterval);\n if (momentTimeUnit != null) {\n // range from is a moment and startOf is mutating moment object so this has a side effect to also change the\n // grafana selected timeframe value which will adapt the grafana graph as well\n queryFrom = range!.from.startOf(momentTimeUnit);\n }\n }\n\n let aggregationMethod: AggregationMethod | undefined = target.metric;\n const percentileValue = aggregationMethod === 'percentile' ? target.percentileValue : undefined;\n\n let metric: Metric | undefined = undefined;\n let dimension: QueryAttribute | QueryAdAttribute | undefined = undefined;\n if (target.dimension) {\n if (isMetric(target.dimension)) {\n metric = target.dimension as Metric;\n } else {\n dimension = target.dimension as QueryAttribute | QueryAdAttribute;\n }\n }\n\n const filters: ProperTypedQueryFilter[] = target.filter.map((filter) => {\n return {\n name: filter.name,\n operator: filter.operator,\n value: convertFilterValueToProperType(filter.value, filter.name, filter.operator, !!this.isAdAnalytics),\n };\n });\n\n const query: BitmovinAnalyticsRequestQuery = {\n filters: filters,\n groupBy: target.groupBy,\n orderBy: target.orderBy,\n dimension: dimension,\n metric: metric,\n start: queryFrom.toDate(),\n end: queryTo.toDate(),\n licenseKey: target.license,\n interval: interval,\n limit: this.parseLimit(target.limit),\n percentile: percentileValue,\n };\n\n const response = await lastValueFrom(this.request(this.getRequestUrl(metric, aggregationMethod), 'POST', query));\n\n const dataRows: MixedDataRowList = response.data.data.result.rows;\n const dataRowCount: number = response.data.data.result.rowCount;\n const columnLabels: Array<{ key: string; label: string }> = response.data.data.result.columnLabels;\n\n const fields: Array> = [];\n\n // Determine the appropriate transformation based on query parameters\n if (query.interval && query.groupBy?.length > 0) {\n // If the query has an interval and group by columns, transform the data as grouped time series\n fields.push(\n ...transformGroupedTimeSeriesData(dataRows, queryFrom.valueOf(), queryTo.valueOf(), query.interval)\n );\n } else {\n if (query.interval) {\n // If the query has an interval but no group by columns, transform the data as simple time series\n fields.push(\n ...transformSimpleTimeSeries(\n dataRows as NumberDataRowList,\n columnLabels.length > 0 ? columnLabels[columnLabels.length - 1].label : 'Column 1',\n queryFrom.valueOf(),\n queryTo.valueOf(),\n query.interval\n )\n );\n } else {\n // If no interval is specified, transform the data as table data\n fields.push(...transformTableData(dataRows, columnLabels));\n }\n }\n\n let metaNotices: QueryResultMetaNotice[] = [];\n if (dataRowCount >= 200) {\n metaNotices = [\n {\n severity: 'warning',\n text: 'Your request reached the max row limit of the API. You might see incomplete data. This problem might be caused by the use of high cardinality columns in group by, too small interval, or too big of a time range.',\n },\n ];\n }\n\n return createDataFrame({\n name: target.alias,\n fields: fields,\n meta: { notices: metaNotices },\n });\n });\n\n return Promise.all(promises).then((data) => ({ data }));\n }\n\n /** Checks if the selected grafana Timerange From is relative or absolute */\n private isRelativeRangeFrom(range: RawTimeRange) {\n return typeof range.from === 'string';\n }\n\n /** needed because of old plugin logic where limit was saved as string and not as number */\n parseLimit(limit: number | string | undefined): undefined | number {\n if (limit == null) {\n return undefined;\n }\n\n if (Number.isInteger(limit)) {\n return limit as number;\n } else {\n return parseInt(limit as string, 10);\n }\n }\n\n /** check if needed fields are set to avoid sending queries to API that will certainly return an error*/\n isQueryComplete(query: BitmovinAnalyticsDataQuery) {\n if (isEmpty(query.license) || isEmpty(query.dimension)) {\n return false;\n }\n\n if (query.dimension != null) {\n if (!isMetric(query.dimension) && isEmpty(query.metric)) {\n return false;\n }\n }\n\n return true;\n }\n\n getRequestUrl(metric?: Metric, aggregation?: AggregationMethod): string {\n let url = '/analytics';\n if (this.isAdAnalytics === true) {\n url += '/ads';\n }\n\n if (metric != null) {\n return url + '/metrics/' + metric;\n }\n\n return url + '/queries/' + aggregation;\n }\n\n request(url: string, method: string, payload?: any): Observable> {\n const headers: Record = { 'X-Api-Key': this.apiKey };\n if (this.tenantOrgId != null) {\n headers['X-Tenant-Org-Id'] = this.tenantOrgId;\n }\n const options = {\n url: this.baseUrl + url,\n headers: headers,\n method: method,\n data: payload,\n };\n\n return getBackendSrv().fetch(options);\n }\n\n async testDatasource() {\n return lastValueFrom(\n this.request('/analytics/licenses', 'GET').pipe(\n map(() => {\n return {\n status: 'success',\n message: 'Data source successfully setup and connected.',\n };\n }),\n catchError((err) => {\n let message = 'Bitmovin: ';\n if (err.status) {\n message += err.status + ' ';\n }\n if (err.statusText) {\n message += err.statusText;\n } else {\n message += 'Can not connect to Bitmovin API';\n }\n\n let errorMessage = err.data?.message || err.data?.data?.message;\n\n //additional errorDetails like requestId and timestamp if requestId is set\n let errorDetails;\n if (err.data?.requestId) {\n errorDetails = 'Timestamp: ' + new Date().toISOString();\n errorDetails += err.data?.requestId ? '\\nRequestId: ' + err.data?.requestId : '';\n }\n\n return of({\n status: 'error',\n message: message,\n details: { message: errorMessage, verboseMessage: errorDetails },\n });\n })\n )\n );\n }\n}\n","import { lastValueFrom } from 'rxjs';\nimport { getBackendSrv } from '@grafana/runtime';\nimport { SelectableValue } from '@grafana/data';\n\ntype AnalyticsLicense = {\n readonly name: string;\n readonly id: string;\n readonly licenseKey?: string;\n};\n\nconst licenseEndpoints = [\n {\n endpoint: '/analytics/licenses',\n mapperFunc: (license: AnalyticsLicense): SelectableValue => ({\n value: license.licenseKey,\n label: license.name ? license.name : license.licenseKey,\n }),\n },\n {\n endpoint: '/analytics/virtual-licenses',\n mapperFunc: (license: AnalyticsLicense): SelectableValue => ({\n value: license.id,\n label: license.name ? license.name : license.id,\n }),\n },\n {\n endpoint: '/analytics/demo-licenses',\n mapperFunc: (license: AnalyticsLicense): SelectableValue => ({\n value: license.id,\n label: license.name ? license.name : license.id,\n }),\n },\n];\n\nasync function fetchLicensesForEndpoint(\n url: string,\n apiKey: string,\n mapperFunc: (license: AnalyticsLicense) => SelectableValue,\n tenantOrgId?: string\n) {\n const headers: Record = { 'X-Api-Key': apiKey}\n if (tenantOrgId != null) {\n headers[\"X-Tenant-Org-Id\"] = tenantOrgId\n }\n const options = {\n url: url,\n headers: headers,\n method: 'GET',\n };\n\n const response = await lastValueFrom(getBackendSrv().fetch(options));\n // @ts-ignore\n const licenses = response.data.data.result.items;\n\n const selectableLicenses = [];\n for (const license of licenses) {\n selectableLicenses.push(mapperFunc(license));\n }\n\n return selectableLicenses;\n}\n\nexport async function fetchLicenses(apiKey: string, baseUrl: string, tenantOrgId?: string): Promise {\n const allLicenses: SelectableValue[] = [];\n\n for (const licenseEndpoint of licenseEndpoints) {\n const licenses = await fetchLicensesForEndpoint(\n baseUrl + licenseEndpoint.endpoint,\n apiKey,\n licenseEndpoint.mapperFunc,\n tenantOrgId\n );\n allLicenses.push(...licenses);\n }\n\n return allLicenses;\n}\n","import type { SelectableValue } from '@grafana/data';\n\nconst AGGREGATION_METHODS = [\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'stddev',\n 'percentile',\n 'variance',\n 'median',\n] as const;\n\nexport type AggregationMethod = (typeof AGGREGATION_METHODS)[number];\n\nexport const SELECTABLE_AGGREGATION_METHODS: Array> = AGGREGATION_METHODS.map(\n (aggregation) => ({\n value: aggregation,\n label: aggregation,\n })\n);\n","import { SelectableValue } from '@grafana/data';\n\nconst QUERY_AD_ATTRIBUTES = [\n 'ADVERTISER_NAME',\n 'AD_CLICKTHROUGH_URL',\n 'AD_DESCRIPTION',\n 'AD_DURATION',\n 'AD_FALLBACK_INDEX',\n 'AD_ID',\n 'AD_ID_PLAYER',\n 'AD_IMPRESSION_ID',\n 'AD_IS_PERSISTENT',\n 'AD_MODULE',\n 'AD_OFFSET',\n 'AD_PLAYBACK_HEIGHT',\n 'AD_PLAYBACK_WIDTH',\n 'AD_POSITION',\n 'AD_PRELOAD_OFFSET',\n 'AD_REPLACE_CONTENT_DURATION',\n 'AD_SCHEDULE_TIME',\n 'AD_SKIPPABLE',\n 'AD_SKIP_AFTER',\n 'AD_STARTUP_TIME',\n 'AD_SYSTEM',\n 'AD_TAG_PATH',\n 'AD_TAG_SERVER',\n 'AD_TAG_TYPE',\n 'AD_TAG_URL',\n 'AD_TITLE',\n 'AD_WRAPPER_ADS_COUNT',\n 'ANALYTICS_VERSION',\n 'APIORG_ID',\n 'APIUSER_ID',\n 'API_FRAMEWORK',\n 'AUDIO_BITRATE',\n 'AUTOPLAY',\n 'BROWSER',\n 'BROWSER_IS_BOT',\n 'BROWSER_VERSION_MAJOR',\n 'BROWSER_VERSION_MINOR',\n 'CDN_PROVIDER',\n 'CITY',\n 'CLICKED',\n 'CLICK_PERCENTAGE',\n 'CLICK_POSITION',\n 'CLICK_RATE',\n 'CLIENT_TIME',\n 'CLOSED',\n 'CLOSE_PERCENTAGE',\n 'CLOSE_POSITION',\n 'COMPLETED',\n 'COUNTRY',\n 'CREATIVE_AD_ID',\n 'CREATIVE_ID',\n 'CUSTOM_DATA_1',\n 'CUSTOM_DATA_10',\n 'CUSTOM_DATA_11',\n 'CUSTOM_DATA_12',\n 'CUSTOM_DATA_13',\n 'CUSTOM_DATA_14',\n 'CUSTOM_DATA_15',\n 'CUSTOM_DATA_16',\n 'CUSTOM_DATA_17',\n 'CUSTOM_DATA_18',\n 'CUSTOM_DATA_19',\n 'CUSTOM_DATA_2',\n 'CUSTOM_DATA_20',\n 'CUSTOM_DATA_21',\n 'CUSTOM_DATA_22',\n 'CUSTOM_DATA_23',\n 'CUSTOM_DATA_24',\n 'CUSTOM_DATA_25',\n 'CUSTOM_DATA_26',\n 'CUSTOM_DATA_27',\n 'CUSTOM_DATA_28',\n 'CUSTOM_DATA_29',\n 'CUSTOM_DATA_3',\n 'CUSTOM_DATA_30',\n 'CUSTOM_DATA_4',\n 'CUSTOM_DATA_5',\n 'CUSTOM_DATA_6',\n 'CUSTOM_DATA_7',\n 'CUSTOM_DATA_8',\n 'CUSTOM_DATA_9',\n 'CUSTOM_USER_ID',\n 'DAY',\n 'DAYPART',\n 'DEAL_ID',\n 'DEVICE_TYPE',\n 'DOMAIN',\n 'ERROR_CODE',\n 'ERROR_MESSAGE',\n 'EXPERIMENT_NAME',\n 'HOUR',\n 'IP_ADDRESS',\n 'ISP',\n 'IS_LINEAR',\n 'LANGUAGE',\n 'LICENSE_KEY',\n 'MANIFEST_DOWNLOAD_TIME',\n 'MEDIA_PATH',\n 'MEDIA_SERVER',\n 'MEDIA_URL',\n 'MIDPOINT',\n 'MINUTE',\n 'MIN_SUGGESTED_DURATION',\n 'MONTH',\n 'OPERATINGSYSTEM',\n 'OPERATINGSYSTEM_VERSION_MAJOR',\n 'OPERATINGSYSTEM_VERSION_MINOR',\n 'PAGE_LOAD_TIME',\n 'PAGE_LOAD_TYPE',\n 'PATH',\n 'PERCENTAGE_IN_VIEWPORT',\n 'PLATFORM',\n 'PLAYER',\n 'PLAYER_KEY',\n 'PLAYER_STARTUPTIME',\n 'PLAYER_TECH',\n 'PLAYER_VERSION',\n 'PLAY_PERCENTAGE',\n 'QUARTILE_1',\n 'QUARTILE_3',\n 'REGION',\n 'SCREEN_HEIGHT',\n 'SCREEN_WIDTH',\n 'SIZE',\n 'SKIPPED',\n 'SKIP_PERCENTAGE',\n 'SKIP_POSITION',\n 'STARTED',\n 'STREAM_FORMAT',\n 'SURVEY_URL',\n 'TIME',\n 'TIME_HOVERED',\n 'TIME_IN_VIEWPORT',\n 'TIME_PLAYED',\n 'TIME_TO_FIRST_AD',\n 'TIME_UNTIL_HOVER',\n 'UNIVERSAL_AD_ID_REGISTRY',\n 'UNIVERSAL_AD_ID_VALUE',\n 'USER_ID',\n 'VIDEO_BITRATE',\n 'VIDEO_ID',\n 'VIDEO_IMPRESSION_ID',\n 'VIDEO_TITLE',\n 'VIDEO_WINDOW_HEIGHT',\n 'VIDEO_WINDOW_WIDTH',\n 'YEAR',\n] as const;\n\nexport type QueryAdAttribute = (typeof QUERY_AD_ATTRIBUTES)[number];\n\nexport const SELECTABLE_QUERY_AD_ATTRIBUTES: Array> = QUERY_AD_ATTRIBUTES.map(\n (queryAdAttribute) => ({\n value: queryAdAttribute,\n label: queryAdAttribute,\n })\n);\n","import { SelectableValue } from '@grafana/data';\n\nconst QUERY_ATTRIBUTES = [\n 'AD',\n 'ANALYTICS_VERSION',\n 'AUDIO_BITRATE',\n 'AUDIO_CODEC',\n 'AUDIO_LANGUAGE',\n 'AUTOPLAY',\n 'BROWSER',\n 'BROWSER_IS_BOT',\n 'BROWSER_VERSION_MAJOR',\n 'BROWSER_VERSION_MINOR',\n 'BUFFERED',\n 'CAST_TECH',\n 'CDN_PROVIDER',\n 'CITY',\n 'CLIENT_TIME',\n 'CONTEXT',\n 'COUNTRY',\n 'CUSTOM_DATA_1',\n 'CUSTOM_DATA_10',\n 'CUSTOM_DATA_11',\n 'CUSTOM_DATA_12',\n 'CUSTOM_DATA_13',\n 'CUSTOM_DATA_14',\n 'CUSTOM_DATA_15',\n 'CUSTOM_DATA_16',\n 'CUSTOM_DATA_17',\n 'CUSTOM_DATA_18',\n 'CUSTOM_DATA_19',\n 'CUSTOM_DATA_2',\n 'CUSTOM_DATA_20',\n 'CUSTOM_DATA_21',\n 'CUSTOM_DATA_22',\n 'CUSTOM_DATA_23',\n 'CUSTOM_DATA_24',\n 'CUSTOM_DATA_25',\n 'CUSTOM_DATA_26',\n 'CUSTOM_DATA_27',\n 'CUSTOM_DATA_28',\n 'CUSTOM_DATA_29',\n 'CUSTOM_DATA_3',\n 'CUSTOM_DATA_30',\n 'CUSTOM_DATA_4',\n 'CUSTOM_DATA_5',\n 'CUSTOM_DATA_6',\n 'CUSTOM_DATA_7',\n 'CUSTOM_DATA_8',\n 'CUSTOM_DATA_9',\n 'CUSTOM_USER_ID',\n 'DAY',\n 'DAYPART',\n 'DEVICE_CLASS',\n 'DEVICE_TYPE',\n 'DOMAIN',\n 'DOWNLOAD_SPEED',\n 'DRM_LOAD_TIME',\n 'DRM_TYPE',\n 'DROPPED_FRAMES',\n 'DURATION',\n 'ERROR_CODE',\n 'ERROR_MESSAGE',\n 'ERROR_PERCENTAGE',\n 'EXPERIMENT_NAME',\n 'FUNCTION',\n 'HOUR',\n 'ID',\n 'IMPRESSION_ID',\n 'INITIAL_TIME_TO_TARGET_LATENCY',\n 'IP_ADDRESS',\n 'ISP',\n 'IS_CASTING',\n 'IS_LIVE',\n 'IS_LOW_LATENCY',\n 'IS_MUTED',\n 'LANGUAGE',\n 'LATENCY',\n 'LICENSE_KEY',\n 'M3U8_URL',\n 'MINUTE',\n 'MONTH',\n 'MPD_URL',\n 'OPERATINGSYSTEM',\n 'OPERATINGSYSTEM_VERSION_MAJOR',\n 'OPERATINGSYSTEM_VERSION_MINOR',\n 'ORGANIZATION',\n 'PAGE_LOAD_TIME',\n 'PAGE_LOAD_TYPE',\n 'PATH',\n 'PAUSED',\n 'PLATFORM',\n 'PLAYED',\n 'PLAYER',\n 'PLAYER_STARTUPTIME',\n 'PLAYER_TECH',\n 'PLAYER_VERSION',\n 'PLAY_ATTEMPTS',\n 'PROG_URL',\n 'REBUFFER_PERCENTAGE',\n 'REGION',\n 'SCALE_FACTOR',\n 'SCREEN_HEIGHT',\n 'SCREEN_ORIENTATION',\n 'SCREEN_WIDTH',\n 'SEEKED',\n 'SIZE',\n 'STARTUPTIME',\n 'STATE',\n 'STREAM_FORMAT',\n 'SUBTITLE_ENABLED',\n 'SUBTITLE_LANGUAGE',\n 'SUPPORTED_VIDEO_CODECS',\n 'TARGET_LATENCY',\n 'TARGET_LATENCY_DELTA',\n 'TIME',\n 'TIME_TO_TARGET_LATENCY',\n 'USER_ID',\n 'VIDEOSTART_FAILED',\n 'VIDEOSTART_FAILED_REASON',\n 'VIDEOTIME_END',\n 'VIDEOTIME_START',\n 'VIDEO_BITRATE',\n 'VIDEO_CODEC',\n 'VIDEO_CODEC_TYPE',\n 'VIDEO_DURATION',\n 'VIDEO_ID',\n 'VIDEO_PLAYBACK_HEIGHT',\n 'VIDEO_PLAYBACK_WIDTH',\n 'VIDEO_SEGMENTS_DOWNLOADED',\n 'VIDEO_SEGMENTS_DOWNLOAD_SIZE',\n 'VIDEO_STARTUPTIME',\n 'VIDEO_TITLE',\n 'VIDEO_WINDOW_HEIGHT',\n 'VIDEO_WINDOW_WIDTH',\n 'VIEWTIME',\n 'YEAR',\n] as const;\n\nexport type QueryAttribute = (typeof QUERY_ATTRIBUTES)[number];\n\nexport const SELECTABLE_QUERY_ATTRIBUTES: Array> = QUERY_ATTRIBUTES.map(\n (queryAttribute) => ({\n value: queryAttribute,\n label: queryAttribute,\n })\n);\n","import React from 'react';\nimport { SelectableValue } from '@grafana/data';\nimport { HorizontalGroup, IconButton, Select } from '@grafana/ui';\n\nimport { QueryAttribute } from '../types/queryAttributes';\nimport { QueryAdAttribute } from '../types/queryAdAttributes';\nimport { isEmpty } from 'lodash';\n\nexport enum REORDER_DIRECTION {\n UP,\n DOWN,\n}\n\ntype Props = {\n readonly groupBy: SelectableValue;\n readonly selectableGroupBys: Array>;\n readonly onDelete: () => void;\n readonly onChange: (newValue: QueryAdAttribute | QueryAttribute) => void;\n readonly isFirst: boolean;\n readonly isLast: boolean;\n readonly onReorderGroupBy: (direction: REORDER_DIRECTION) => void;\n};\n\nexport function GroupByInput(props: Props) {\n return (\n \n props.onChange(selectableValue.value!)}\n options={props.selectableGroupBys}\n width={30}\n />\n props.onReorderGroupBy(REORDER_DIRECTION.DOWN)}\n name=\"arrow-down\"\n disabled={props.isLast}\n />\n props.onReorderGroupBy(REORDER_DIRECTION.UP)}\n name=\"arrow-up\"\n disabled={props.isFirst}\n />\n \n \n );\n}\n","import React from 'react';\nimport { SelectableValue } from '@grafana/data';\nimport { IconButton, VerticalGroup } from '@grafana/ui';\nimport { differenceWith } from 'lodash';\n\nimport { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';\nimport { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';\nimport { GroupByInput, REORDER_DIRECTION } from './GroupByInput';\n\nconst getSelectableGroupByOptions = (\n selectedGroupBys: Array,\n isAdAnalytics: boolean\n): Array> => {\n if (isAdAnalytics) {\n return differenceWith(\n SELECTABLE_QUERY_AD_ATTRIBUTES,\n selectedGroupBys,\n (selectableValue, selectedValue) => selectableValue.value === selectedValue\n );\n } else {\n return differenceWith(\n SELECTABLE_QUERY_ATTRIBUTES,\n selectedGroupBys,\n (selectableValue, selectedValue) => selectableValue.value === selectedValue\n );\n }\n};\n\nconst mapGroupByToSelectableValue = (\n selectedGroupBy: QueryAttribute | QueryAdAttribute,\n isAdAnalytics: boolean\n): SelectableValue => {\n if (isAdAnalytics) {\n return SELECTABLE_QUERY_AD_ATTRIBUTES.filter((selectableValue) => selectableValue.value === selectedGroupBy);\n } else {\n return SELECTABLE_QUERY_ATTRIBUTES.filter((selectableValue) => selectableValue.value === selectedGroupBy);\n }\n};\n\ntype Props = {\n readonly isAdAnalytics: boolean;\n readonly onChange: (newGroupBys: Array) => void;\n readonly groupBys: Array;\n};\n\nexport function GroupByRow(props: Props) {\n const paddingTop= props.groupBys.length === 0 ? 4 : 0\n const deleteGroupByInput = (index: number) => {\n const newSelectedGroupBys = [...props.groupBys];\n newSelectedGroupBys.splice(index, 1);\n\n props.onChange(newSelectedGroupBys);\n };\n\n const onSelectedGroupByChange = (index: number, newSelectedGroupBy: QueryAttribute | QueryAdAttribute) => {\n const newSelectedGroupBys = [...props.groupBys];\n newSelectedGroupBys.splice(index, 1, newSelectedGroupBy);\n\n props.onChange(newSelectedGroupBys);\n };\n\n const reorderGroupBy = (direction: REORDER_DIRECTION, index: number) => {\n const newSelectedGroupBys = [...props.groupBys];\n const groupByToMove = newSelectedGroupBys[index];\n newSelectedGroupBys.splice(index, 1);\n\n const newIndex = direction === REORDER_DIRECTION.UP ? index - 1 : index + 1;\n newSelectedGroupBys.splice(newIndex, 0, groupByToMove);\n\n props.onChange(newSelectedGroupBys);\n };\n\n const addGroupByInput = () => {\n const newDefaultSelectedValue = getSelectableGroupByOptions(props.groupBys, props.isAdAnalytics)[0].value!;\n props.onChange([...props.groupBys, newDefaultSelectedValue]);\n };\n\n return (\n \n {props.groupBys.map((item, index, selectedGroupBysArray) => (\n onSelectedGroupByChange(index, newValue)}\n selectableGroupBys={getSelectableGroupByOptions(selectedGroupBysArray, props.isAdAnalytics)}\n onDelete={() => deleteGroupByInput(index)}\n isFirst={index === 0}\n isLast={index === selectedGroupBysArray.length - 1}\n onReorderGroupBy={(direction: REORDER_DIRECTION) => reorderGroupBy(direction, index)}\n />\n ))}\n
\n addGroupByInput()} size=\"xl\" />\n
\n
\n );\n}\n","import React from 'react';\nimport { SelectableValue } from '@grafana/data';\nimport { HorizontalGroup, IconButton, RadioButtonGroup, Select } from '@grafana/ui';\n\nimport { QueryAttribute } from '../types/queryAttributes';\nimport { QueryAdAttribute } from '../types/queryAdAttributes';\nimport { QuerySortOrder } from '../types/queryOrderBy';\nimport { REORDER_DIRECTION } from './GroupByInput';\nimport { isEmpty } from 'lodash';\n\ntype Props = {\n readonly isAdAnalytics: boolean;\n readonly attribute: SelectableValue;\n readonly selectableOrderByAttributes: Array>;\n readonly onAttributeChange: (newValue: SelectableValue) => void;\n readonly sortOrder: QuerySortOrder;\n readonly onSortOrderChange: (newValue: QuerySortOrder) => void;\n readonly onDelete: () => void;\n readonly isFirst: boolean;\n readonly isLast: boolean;\n readonly onReorderOrderBy: (direction: REORDER_DIRECTION) => void;\n};\n\nconst sortOrderOption: Array> = [\n { value: 'ASC', description: 'Sort by ascending', icon: 'sort-amount-up' },\n { value: 'DESC', description: 'Sort by descending', icon: 'sort-amount-down' },\n];\n\nexport function OrderByInput(props: Props) {\n return (\n \n props.onAttributeChange(selectableValue)}\n options={props.selectableOrderByAttributes}\n width={30}\n />\n props.onSortOrderChange(value)}\n />\n props.onReorderOrderBy(REORDER_DIRECTION.DOWN)}\n name=\"arrow-down\"\n disabled={props.isLast}\n />\n props.onReorderOrderBy(REORDER_DIRECTION.UP)}\n name=\"arrow-up\"\n disabled={props.isFirst}\n />\n \n \n );\n}\n","import React from 'react';\nimport { IconButton, VerticalGroup } from '@grafana/ui';\nimport type { SelectableValue } from '@grafana/data';\nimport { differenceWith } from 'lodash';\n\nimport { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';\nimport { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';\nimport type { QueryOrderBy, QuerySortOrder } from '../types/queryOrderBy';\nimport { OrderByInput } from './OrderByInput';\nimport { REORDER_DIRECTION } from './GroupByInput';\n\nconst getSelectableOrderByOptions = (\n selectedOrderBys: QueryOrderBy[],\n isAdAnalytics: boolean\n): Array> => {\n if (isAdAnalytics) {\n return differenceWith(\n SELECTABLE_QUERY_AD_ATTRIBUTES,\n selectedOrderBys,\n (selectableValue, selectedValue) => selectableValue.value === selectedValue.name\n );\n } else {\n return differenceWith(\n SELECTABLE_QUERY_ATTRIBUTES,\n selectedOrderBys,\n (selectableValue, selectedValue) => selectableValue.value === selectedValue.name\n );\n }\n};\n\nconst mapOrderByAttributeToSelectableValue = (\n selectedOrderBy: QueryAttribute | QueryAdAttribute,\n isAdAnalytics: boolean\n): SelectableValue => {\n if (isAdAnalytics) {\n return SELECTABLE_QUERY_AD_ATTRIBUTES.filter((selectableValue) => selectableValue.value === selectedOrderBy);\n } else {\n return SELECTABLE_QUERY_ATTRIBUTES.filter((selectableValue) => selectableValue.value === selectedOrderBy);\n }\n};\n\ntype Props = {\n readonly isAdAnalytics: boolean;\n readonly onChange: (newOrderBy: QueryOrderBy[]) => void;\n readonly orderBys: QueryOrderBy[];\n};\n\nexport function OrderByRow(props: Props) {\n const paddingTop= props.orderBys.length === 0 ? 4 : 0\n const deleteOrderByInput = (index: number) => {\n const newOrderBys = [...props.orderBys];\n newOrderBys.splice(index, 1);\n\n props.onChange(newOrderBys);\n };\n\n const onAttributesChange = (index: number, newAttribute: SelectableValue) => {\n const newOrderBys = [...props.orderBys];\n const newOrderBy: QueryOrderBy = { name: newAttribute.value!, order: newOrderBys[index].order };\n\n newOrderBys.splice(index, 1, newOrderBy);\n\n props.onChange(newOrderBys);\n };\n\n const onSortOrdersChange = (index: number, newSortOrder: QuerySortOrder) => {\n const newOrderBys = [...props.orderBys];\n const newOrderBy: QueryOrderBy = { name: newOrderBys[index].name, order: newSortOrder };\n\n newOrderBys.splice(index, 1, newOrderBy);\n\n props.onChange(newOrderBys);\n };\n const reorderOrderBy = (direction: REORDER_DIRECTION, index: number) => {\n const newIndex = direction === REORDER_DIRECTION.UP ? index - 1 : index + 1;\n\n const newOrderBys = [...props.orderBys];\n const orderByToMove = newOrderBys[index];\n newOrderBys.splice(index, 1);\n newOrderBys.splice(newIndex, 0, orderByToMove);\n\n props.onChange(newOrderBys);\n };\n\n const addOrderByInput = () => {\n const newDefaultSelectedValue = getSelectableOrderByOptions(props.orderBys, props.isAdAnalytics)[0].value!;\n props.onChange([...props.orderBys, { name: newDefaultSelectedValue, order: 'ASC' }]);\n };\n\n return (\n \n {props.orderBys.map((orderBy, index, selectedOrderBys) => (\n ) =>\n onAttributesChange(index, newValue)\n }\n sortOrder={orderBy.order}\n onSortOrderChange={(newValue: QuerySortOrder) => onSortOrdersChange(index, newValue)}\n onDelete={() => deleteOrderByInput(index)}\n isFirst={index === 0}\n isLast={index === selectedOrderBys.length - 1}\n onReorderOrderBy={(direction: REORDER_DIRECTION) => reorderOrderBy(direction, index)}\n />\n ))}\n\n
\n addOrderByInput()} size=\"xl\" />\n
\n
\n );\n}\n","import { QueryAdAttribute } from './queryAdAttributes';\nimport { QueryAttribute } from './queryAttributes';\nimport type { SelectableValue } from '@grafana/data';\n\nconst QUERY_FILTER_OPERATORS = ['GT', 'GTE', 'LT', 'LTE', 'EQ', 'NE', 'CONTAINS', 'NOTCONTAINS', 'IN'] as const;\n\nexport type QueryFilterOperator = (typeof QUERY_FILTER_OPERATORS)[number];\n\nexport const SELECTABLE_QUERY_FILTER_OPERATORS: Array> =\n QUERY_FILTER_OPERATORS.map((o) => ({ value: o, label: o }));\n\n/** This type is needed because of legacy reasons.\n * In the angular plugin the value was saved as a string in a dashboard JSON file. */\nexport type QueryFilter = {\n name: QueryAdAttribute | QueryAttribute;\n operator: QueryFilterOperator;\n value: string;\n};\n\n/** QueryFilter type with the correct value type that is accepted by the Bitmovin API */\nexport type ProperTypedQueryFilter = {\n name: QueryAdAttribute | QueryAttribute;\n operator: QueryFilterOperator;\n value: OutputQueryFilterValue;\n};\n\n/** Correct Filter value type that is accepted by the Bitmovin API */\nexport type OutputQueryFilterValue = boolean | number | string | string[] | null;\n","import React, { useEffect, useMemo, useState } from 'react';\nimport { HorizontalGroup, IconButton, Input, Select, Tooltip } from '@grafana/ui';\n\nimport { QueryFilter, QueryFilterOperator, SELECTABLE_QUERY_FILTER_OPERATORS } from '../types/queryFilter';\nimport type { SelectableValue } from '@grafana/data';\nimport { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';\nimport { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';\nimport { convertFilterValueToProperType } from 'utils/filterUtils';\n\ninterface QueryFilterInputProps {\n /** `undefined` when component is used to create new filter (no values yet) */\n value: undefined | QueryFilter;\n onChange(queryFilter: QueryFilter): void;\n onDelete(): void;\n isAdAnalytics: boolean;\n /** Selected query filters are used to filter out used values from attribute select options */\n selectedQueryFilters: QueryFilter[];\n}\n\nexport function QueryFilterInput(props: Readonly) {\n /** Flag to indicate that query filter is undefined, does not exist yet, and this component is used to create new one */\n const isCreatingNewOne = props.value == null;\n\n const [derivedQueryFilterState, setDerivedQueryFilterState] = useState(\n buildInitialDerivedQueryFilterState(props.value)\n );\n\n /** Update and override {@link derivedQueryFilterState}, when {@link QueryFilterInputProps} value is changed */\n useEffect(() => setDerivedQueryFilterState(buildInitialDerivedQueryFilterState(props.value)), [props.value]);\n\n const attributeSelectValue = useMemo(\n () => findAttributeSelectableValue(derivedQueryFilterState.attribute, props.isAdAnalytics),\n [derivedQueryFilterState.attribute, props.isAdAnalytics]\n );\n\n const operatorSelectValue = useMemo(\n () => findOperatorSelectableValue(derivedQueryFilterState.operator),\n [derivedQueryFilterState.operator]\n );\n\n function handleAttributeChange(selectedValue: SelectableValue) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n dirty: true,\n attribute: selectedValue.value,\n attributeError: undefined,\n }));\n }\n\n function handleOperatorChange(selectedValue: SelectableValue) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n dirty: true,\n operator: selectedValue.value,\n operatorError: undefined,\n }));\n }\n\n function handleInputValueChange(value: string) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n dirty: true,\n value: value,\n inputValueError: undefined,\n }));\n }\n\n function handleRevertClick() {\n setDerivedQueryFilterState(buildInitialDerivedQueryFilterState(props.value));\n }\n\n function handleSaveClick() {\n if (derivedQueryFilterState.attribute == null) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n attributeError: 'Filter attribute has to be selected',\n }));\n return;\n }\n\n if (derivedQueryFilterState.operator == null) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n operatorError: 'Filter operator has to be selected',\n }));\n return;\n }\n\n try {\n convertFilterValueToProperType(\n derivedQueryFilterState.value!,\n derivedQueryFilterState.attribute!,\n derivedQueryFilterState.operator!,\n props.isAdAnalytics\n );\n\n props.onChange({\n name: derivedQueryFilterState.attribute!,\n operator: derivedQueryFilterState.operator!,\n value: derivedQueryFilterState.value!,\n });\n } catch (e: unknown) {\n setDerivedQueryFilterState((prevState) => ({\n ...prevState,\n inputValueError: e instanceof Error ? e.message : 'Could not save value',\n }));\n }\n }\n\n return (\n \n \n {/* this div wrapper is needed to expose `ref` for Tooltip above */}\n
\n \n
\n \n \n {/* this div wrapper is needed to expose `ref` for Tooltip above */}\n
\n \n
\n \n \n handleInputValueChange(e.currentTarget.value)}\n invalid={derivedQueryFilterState.inputValueError != null}\n type=\"text\"\n width={VALUE_COMPONENT_WIDTH}\n />\n \n\n \n {/* in \"create mode\" we want to show save icons all the time */}\n {(isCreatingNewOne || derivedQueryFilterState.dirty) && (\n \n )}\n {/* in \"create mode\" there is nothing to revert to */}\n {!isCreatingNewOne && derivedQueryFilterState.dirty && (\n \n )}\n
\n );\n}\n\nexport const ATTRIBUTE_COMPONENT_WIDTH = 30;\nexport const OPERATOR_COMPONENT_WIDTH = 15;\nexport const VALUE_COMPONENT_WIDTH = 30;\n\ntype DerivedQueryFilterState = {\n attribute: undefined | QueryFilter['name'];\n attributeError: undefined | string;\n operator: undefined | QueryFilter['operator'];\n operatorError: undefined | string;\n value: undefined | QueryFilter['value'];\n /** `true` if some values have been changed by inputs */\n dirty: boolean;\n /** `undefined` when input value is valid */\n inputValueError: undefined | string;\n};\n\nfunction buildInitialDerivedQueryFilterState(queryFilter: undefined | QueryFilter): DerivedQueryFilterState {\n return {\n attribute: queryFilter?.name,\n attributeError: undefined,\n operator: queryFilter?.operator,\n operatorError: undefined,\n value: queryFilter?.value,\n dirty: false,\n inputValueError: undefined,\n };\n}\n\nfunction findAttributeSelectableValue(\n attribute: undefined | QueryAttribute | QueryAdAttribute,\n isAdAnalytics: boolean\n): undefined | SelectableValue {\n if (attribute == null) {\n return undefined;\n }\n\n const ALL_ATTRIBUTES: Array> = isAdAnalytics\n ? SELECTABLE_QUERY_AD_ATTRIBUTES\n : SELECTABLE_QUERY_ATTRIBUTES;\n\n return ALL_ATTRIBUTES.find((s) => s.value === attribute);\n}\n\nfunction findOperatorSelectableValue(\n operator: undefined | QueryFilterOperator\n): undefined | SelectableValue {\n if (operator == null) {\n return undefined;\n }\n\n return SELECTABLE_QUERY_FILTER_OPERATORS.find((s) => s.value === operator);\n}\n","import React, { useState } from 'react';\nimport { HorizontalGroup, IconButton, InlineLabel, VerticalGroup } from '@grafana/ui';\n\nimport { QueryFilter } from '../types/queryFilter';\nimport {\n ATTRIBUTE_COMPONENT_WIDTH,\n OPERATOR_COMPONENT_WIDTH,\n QueryFilterInput,\n VALUE_COMPONENT_WIDTH,\n} from './QueryFilterInput';\n\ntype Props = {\n readonly isAdAnalytics: boolean;\n readonly onQueryFilterChange: (newFilters: QueryFilter[]) => void;\n readonly filters: QueryFilter[];\n};\n\nexport function FilterRow(props: Props) {\n const [hasNewQueryFilter, setHasNewQueryFilter] = useState(false);\n const paddingTop= props.filters.length === 0 ? 4 : 0\n\n function handleQueryFilterDelete(queryFilterIndex: number) {\n const newQueryFilters = [...props.filters];\n newQueryFilters.splice(queryFilterIndex, 1);\n props.onQueryFilterChange(newQueryFilters);\n }\n\n function handleQueryFilterChange(queryFilterIndex: number, changedQueryFilter: QueryFilter) {\n const newQueryFilters = [...props.filters];\n newQueryFilters.splice(queryFilterIndex, 1, changedQueryFilter);\n props.onQueryFilterChange(newQueryFilters);\n }\n\n function handleNewQueryFilterChange(newQueryFilter: QueryFilter) {\n const newQueryFilters = [...props.filters, newQueryFilter];\n props.onQueryFilterChange(newQueryFilters);\n setHasNewQueryFilter(false);\n }\n\n return (\n \n {(props.filters.length > 0 || hasNewQueryFilter) && (\n \n \n Attribute\n \n \n Operator\n \n \n Value\n \n \n )}\n\n {props.filters.map((queryFilter, queryFilterIdx) => (\n handleQueryFilterChange(queryFilterIdx, changedQueryFilter)}\n onDelete={() => handleQueryFilterDelete(queryFilterIdx)}\n selectedQueryFilters={props.filters}\n key={queryFilterIdx}\n />\n ))}\n\n
\n {hasNewQueryFilter ? (\n setHasNewQueryFilter(false)}\n selectedQueryFilters={props.filters}\n />\n ) : (\n setHasNewQueryFilter(true)} size=\"xl\" />\n )}\n
\n
\n );\n}\n","import React, { ChangeEvent, useEffect, useMemo, useState } from 'react';\nimport { FieldSet, HorizontalGroup, InlineField, InlineSwitch, Input, Select } from '@grafana/ui';\nimport type { QueryEditorProps, SelectableValue } from '@grafana/data';\nimport { defaults } from 'lodash';\n\nimport { DataSource } from '../datasource';\nimport {\n BitmovinDataSourceOptions,\n BitmovinAnalyticsDataQuery,\n DEFAULT_QUERY,\n OldBitmovinAnalyticsDataQuery,\n} from '../types/grafanaTypes';\nimport { fetchLicenses } from '../utils/licenses';\nimport { DEFAULT_SELECTABLE_QUERY_INTERVAL, SELECTABLE_QUERY_INTERVALS } from '../utils/intervalUtils';\nimport { SELECTABLE_AGGREGATION_METHODS } from '../types/aggregationMethod';\nimport { QueryAdAttribute, SELECTABLE_QUERY_AD_ATTRIBUTES } from '../types/queryAdAttributes';\nimport { QueryAttribute, SELECTABLE_QUERY_ATTRIBUTES } from '../types/queryAttributes';\nimport { isMetric, SELECTABLE_METRICS } from '../types/metric';\nimport { GroupByRow } from './GroupByRow';\nimport { OrderByRow } from './OrderByRow';\nimport type { QueryOrderBy } from '../types/queryOrderBy';\nimport type { QueryFilter } from '../types/queryFilter';\nimport { FilterRow } from './FilterRow';\n\nenum LoadingState {\n Default = 'DEFAULT',\n Loading = 'LOADING',\n Success = 'SUCCESS',\n Error = 'ERROR',\n}\n\ntype Props = QueryEditorProps<\n DataSource,\n BitmovinAnalyticsDataQuery | OldBitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions\n>;\n\nexport function QueryEditor(props: Props) {\n const query = defaults(props.query, DEFAULT_QUERY);\n const [selectableLicenses, setSelectableLicenses] = useState([]);\n const [licenseLoadingState, setLicenseLoadingState] = useState(LoadingState.Default);\n const [licenseErrorMessage, setLicenseErrorMessage] = useState('');\n const [isTimeSeries, setIsTimeSeries] = useState(query.resultFormat === 'time_series');\n const [percentileValue, setPercentileValue] = useState(query.percentileValue);\n const isMetricSelected = useMemo(() => {\n return query.dimension ? isMetric(query.dimension) : false;\n }, [query.dimension]);\n const isPercentileSelected = useMemo(() => {\n return query.metric === 'percentile';\n }, [query.metric]);\n\n /** Fetch Licenses */\n useEffect(() => {\n setLicenseLoadingState(LoadingState.Loading);\n fetchLicenses(props.datasource.apiKey, props.datasource.baseUrl, props.datasource.tenantOrgId)\n .then((licenses) => {\n setSelectableLicenses(licenses);\n setLicenseLoadingState(LoadingState.Success);\n })\n .catch((e) => {\n setLicenseLoadingState(LoadingState.Error);\n setLicenseErrorMessage(e.status + ' ' + e.statusText);\n });\n }, [props.datasource.apiKey, props.datasource.baseUrl, props.datasource.tenantOrgId]);\n\n const handleLicenseChange = (item: SelectableValue) => {\n props.onChange({ ...query, license: item.value });\n props.onRunQuery();\n };\n\n const handleAggregationChange = (item: SelectableValue) => {\n props.onChange({ ...query, metric: item.value });\n props.onRunQuery();\n };\n\n const handleDimensionChange = (item: SelectableValue) => {\n props.onChange({ ...query, dimension: item.value });\n props.onRunQuery();\n };\n\n const handleGroupByChange = (newGroupBys: Array) => {\n props.onChange({ ...query, groupBy: newGroupBys });\n props.onRunQuery();\n };\n\n const handleOrderByChange = (newOrderBys: QueryOrderBy[]) => {\n props.onChange({ ...query, orderBy: newOrderBys });\n props.onRunQuery();\n };\n\n const handleQueryFilterChange = (newFilters: QueryFilter[]) => {\n props.onChange({ ...query, filter: newFilters });\n props.onRunQuery();\n };\n\n const handleLimitBlur = (event: ChangeEvent) => {\n const limit = parseInt(event.target.value, 10);\n props.onChange({ ...query, limit: isNaN(limit) ? undefined : limit });\n props.onRunQuery();\n };\n\n const handleFormatAsTimeSeriesChange = (event: ChangeEvent) => {\n setIsTimeSeries(event.currentTarget.checked);\n if (event.currentTarget.checked) {\n props.onChange({ ...query, interval: 'AUTO', resultFormat: 'time_series' });\n } else {\n props.onChange({ ...query, interval: undefined, resultFormat: 'table' });\n }\n props.onRunQuery();\n };\n\n const handleIntervalChange = (item: SelectableValue) => {\n props.onChange({ ...query, interval: item.value });\n props.onRunQuery();\n };\n\n const handleAliasByBlur = (event: ChangeEvent) => {\n props.onChange({ ...query, alias: event.target.value });\n props.onRunQuery();\n };\n\n const handlePercentileValueChange = (event: ChangeEvent) => {\n let percentile = parseInt(event.target.value, 10);\n if (percentile < 0) {\n percentile = 0;\n } else if (percentile > 99) {\n percentile = 99;\n }\n setPercentileValue(percentile);\n };\n\n const handlePercentileBlur = () => {\n props.onChange({ ...query, percentileValue: percentileValue });\n props.onRunQuery();\n };\n\n const renderTimeSeriesOption = () => {\n return (\n <>\n \n handleIntervalChange(item)}\n width={30}\n options={SELECTABLE_QUERY_INTERVALS}\n />\n \n \n );\n };\n\n return (\n
\n
\n \n \n \n \n {!isMetricSelected && (\n \n handleAggregationChange(item)}\n width={30}\n options={SELECTABLE_AGGREGATION_METHODS}\n />\n \n )}\n {isPercentileSelected && (\n \n )}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {isTimeSeries && renderTimeSeriesOption()}\n \n \n \n
\n
\n );\n}\n","import { DataSourcePlugin } from '@grafana/data';\nimport { DataSource } from './datasource';\nimport { ConfigEditor } from './components/ConfigEditor';\nimport { QueryEditor } from './components/QueryEditor';\nimport {\n BitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions,\n OldBitmovinAnalyticsDataQuery,\n} from './types/grafanaTypes';\n\nexport const plugin = new DataSourcePlugin<\n DataSource,\n BitmovinAnalyticsDataQuery | OldBitmovinAnalyticsDataQuery,\n BitmovinDataSourceOptions\n>(DataSource)\n .setConfigEditor(ConfigEditor)\n .setQueryEditor(QueryEditor);\n","import React, { ChangeEvent, useEffect } from 'react';\nimport { DataSourceHttpSettings, FieldSet, InlineField, InlineSwitch, Input } from '@grafana/ui';\nimport { DataSourcePluginOptionsEditorProps } from '@grafana/data';\nimport { BitmovinDataSourceOptions } from '../types/grafanaTypes';\n\ninterface Props extends DataSourcePluginOptionsEditorProps {}\n\nexport function ConfigEditor(props: Props) {\n const { onOptionsChange, options } = props;\n\n // sets the instanceSettings.url to the default bitmovin api url if it is not already set when opening the ConfigEditor\n useEffect(() => {\n if (options.url === '' || options.url == null) {\n onOptionsChange({ ...options, url: 'https://api.bitmovin.com/v1' });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const onAdAnalyticsChange = (event: ChangeEvent) => {\n const jsonData = {\n ...options.jsonData,\n isAdAnalytics: event.currentTarget.checked,\n };\n onOptionsChange({ ...options, jsonData });\n };\n\n const onAPIKeyChange = (event: ChangeEvent) => {\n const jsonData = {\n ...options.jsonData,\n apiKey: event.currentTarget.value,\n };\n onOptionsChange({ ...options, jsonData });\n };\n\n const onTenantOrgIdChange = (event: ChangeEvent) => {\n const jsonData = {\n ...options.jsonData,\n tenantOrgId: event.currentTarget.value,\n };\n onOptionsChange({ ...options, jsonData });\n };\n\n const { jsonData } = options;\n\n return (\n <>\n \n\n
\n \n \n \n \n \n \n \n \n \n
\n \n );\n}\n"],"names":["module","exports","__WEBPACK_EXTERNAL_MODULE__781__","__WEBPACK_EXTERNAL_MODULE__531__","__WEBPACK_EXTERNAL_MODULE__7__","__WEBPACK_EXTERNAL_MODULE__241__","__WEBPACK_EXTERNAL_MODULE__468__","__WEBPACK_EXTERNAL_MODULE__959__","__WEBPACK_EXTERNAL_MODULE__269__","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","n","getter","__esModule","d","a","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","r","Symbol","toStringTag","value","DEFAULT_QUERY","license","orderBy","groupBy","filter","resultFormat","interval","SELECTABLE_QUERY_INTERVALS","label","DEFAULT_SELECTABLE_QUERY_INTERVAL","intervalOrder","calculateQueryInterval","startTimestamp","endTimestamp","intervalInMilliseconds","getMomentTimeUnitForQueryInterval","calculateTimeSeriesStartTimestamp","dataTimestamp","intervalStartTimestamp","referenceDataDate","Date","intervalStartDate","setSeconds","setMinutes","setHours","getHours","getMinutes","getDate","setDate","padAndSortTimeSeries","data","length","momentInterval","Error","zeroValueTimeSeries","zeroValueDataRow","slice","momentStartTimestamp","moment","valueOf","row","push","add","date","set","daysInMonth","missingTimestampRows","differenceWith","first","second","paddedData","concat","sortBy","METRICS","SELECTABLE_METRICS","map","metric","isMetric","includes","convertFilterValueToProperType","rawValue","filterAttribute","filterOperator","isAdAnalytics","isEmpty","isNullFilter","JSON","parse","Array","isArray","parseValueForInFilter","e","parsedValue","parseInt","isNaN","parseFloat","convertFilterForAds","convertFilter","DataSource","DataSourceApi","getDefaultQuery","_","options","range","isRelativeRangeFrom","raw","enabledQueries","targets","t","hide","promises","isQueryComplete","target","query","from","to","queryFrom","queryTo","flooringInterval","interval1","interval2","indexOf","momentTimeUnit","startOf","aggregationMethod","percentileValue","dimension","filters","name","operator","start","toDate","end","licenseKey","limit","parseLimit","percentile","response","lastValueFrom","request","getRequestUrl","dataRows","result","rows","dataRowCount","rowCount","columnLabels","fields","groupedTimeSeriesMap","Map","forEach","groupKey","toString","has","paddedTimeSeries","timestamps","zip","values","type","FieldType","time","join","valueColumn","number","transformGroupedTimeSeriesData","columnName","columns","transformSimpleTimeSeries","columnNames","i","column","index","string","transformTableData","metaNotices","severity","text","createDataFrame","alias","meta","notices","Promise","all","then","Number","isInteger","aggregation","url","this","method","payload","headers","apiKey","tenantOrgId","baseUrl","getBackendSrv","fetch","testDatasource","pipe","status","message","catchError","err","statusText","errorDetails","errorMessage","requestId","toISOString","of","details","verboseMessage","constructor","instanceSettings","super","jsonData","licenseEndpoints","endpoint","mapperFunc","id","fetchLicensesForEndpoint","licenses","items","selectableLicenses","fetchLicenses","allLicenses","licenseEndpoint","SELECTABLE_AGGREGATION_METHODS","SELECTABLE_QUERY_AD_ATTRIBUTES","queryAdAttribute","SELECTABLE_QUERY_ATTRIBUTES","queryAttribute","GroupByInput","props","HorizontalGroup","Select","onChange","selectableValue","selectableGroupBys","width","IconButton","tooltip","onClick","onReorderGroupBy","disabled","isLast","isFirst","onDelete","size","variant","REORDER_DIRECTION","getSelectableGroupByOptions","selectedGroupBys","selectedValue","GroupByRow","paddingTop","groupBys","VerticalGroup","item","selectedGroupBysArray","selectedGroupBy","newValue","newSelectedGroupBy","newSelectedGroupBys","splice","onSelectedGroupByChange","deleteGroupByInput","direction","groupByToMove","newIndex","UP","reorderGroupBy","div","style","newDefaultSelectedValue","addGroupByInput","sortOrderOption","description","icon","OrderByInput","spacing","attribute","onAttributeChange","selectableOrderByAttributes","RadioButtonGroup","sortOrder","onSortOrderChange","onReorderOrderBy","DOWN","getSelectableOrderByOptions","selectedOrderBys","OrderByRow","orderBys","selectedOrderBy","newAttribute","newOrderBys","newOrderBy","order","onAttributesChange","newSortOrder","onSortOrdersChange","deleteOrderByInput","orderByToMove","reorderOrderBy","addOrderByInput","SELECTABLE_QUERY_FILTER_OPERATORS","QueryFilterInput","isCreatingNewOne","derivedQueryFilterState","setDerivedQueryFilterState","useState","buildInitialDerivedQueryFilterState","useEffect","attributeSelectValue","useMemo","find","s","findAttributeSelectableValue","operatorSelectValue","findOperatorSelectableValue","Tooltip","content","attributeError","show","theme","prevState","dirty","ATTRIBUTE_COMPONENT_WIDTH","invalid","operatorError","OPERATOR_COMPONENT_WIDTH","inputValueError","Input","handleInputValueChange","currentTarget","VALUE_COMPONENT_WIDTH","queryFilter","FilterRow","hasNewQueryFilter","setHasNewQueryFilter","InlineLabel","queryFilterIdx","changedQueryFilter","queryFilterIndex","newQueryFilters","onQueryFilterChange","handleQueryFilterChange","handleQueryFilterDelete","selectedQueryFilters","newQueryFilter","LoadingState","plugin","DataSourcePlugin","setConfigEditor","onOptionsChange","DataSourceHttpSettings","defaultUrl","dataSourceConfig","showAccessOptions","FieldSet","InlineField","required","labelWidth","event","placeholder","InlineSwitch","checked","setQueryEditor","defaults","setSelectableLicenses","licenseLoadingState","setLicenseLoadingState","licenseErrorMessage","setLicenseErrorMessage","isTimeSeries","setIsTimeSeries","setPercentileValue","isMetricSelected","isPercentileSelected","datasource","catch","className","error","onRunQuery","noOptionsMessage","isLoading","handleAggregationChange","onBlur","newFilters","newGroupBys","defaultValue","handleIntervalChange"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/plugin.json b/dist/plugin.json index 5c8da6a..920252d 100644 --- a/dist/plugin.json +++ b/dist/plugin.json @@ -20,8 +20,8 @@ {"name": "Apache License", "url": "https://github.com/bitmovin/analytics-grafana-datasource/blob/main/LICENSE"} ], "screenshots": [], - "version": "1.0.0", - "updated": "2024-07-05" + "version": "1.1.0", + "updated": "2024-07-11" }, "dependencies": { "grafanaDependency": ">=10.1.0", diff --git a/package.json b/package.json index d02b06f..776cf24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bitmovin-analytics", - "version": "1.0.0", + "version": "1.1.0", "description": "Data source plugin which allows you to query analytics data from the bitmovin api", "scripts": { "build": "webpack -c ./.config/webpack/webpack.config.ts --env production",