diff --git a/CHANGELOG.md b/CHANGELOG.md index a7de05c..d734943 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Development +## 1.3.0 + ### Added - SSAI attributes diff --git a/dist/CHANGELOG.md b/dist/CHANGELOG.md index e7de8b9..d734943 100644 --- a/dist/CHANGELOG.md +++ b/dist/CHANGELOG.md @@ -2,6 +2,12 @@ ## Development +## 1.3.0 + +### Added + +- SSAI attributes + ## 1.2.0 ### Fix @@ -11,6 +17,7 @@ ### Added - Default Percentile Value when percentile metric is selected +- e2e testing with Playwright ## 1.1.1 diff --git a/dist/module.js b/dist/module.js index 3c02b98..9217ae5 100644 --- a/dist/module.js +++ b/dist/module.js @@ -1,2 +1,2 @@ -define(["@grafana/data","@grafana/runtime","lodash","moment","rxjs","react","@grafana/ui"],((e,t,r,n,a,o,i)=>(()=>{"use strict";var l={781:t=>{t.exports=e},531:e=>{e.exports=t},7:e=>{e.exports=i},241:e=>{e.exports=r},468:e=>{e.exports=n},959:e=>{e.exports=o},269:e=>{e.exports=a}},s={};function u(e){var t=s[e];if(void 0!==t)return t.exports;var r=s[e]={exports:{}};return l[e](r,r.exports,u),r.exports}u.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return u.d(t,{a:t}),t},u.d=(e,t)=>{for(var r in t)u.o(t,r)&&!u.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},u.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),u.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var c={};u.r(c),u.d(c,{plugin:()=>Oe});var E=u(781),d=u(531),A=u(241),T=u(468),_=u.n(T),O=u(269);const I={license:"",orderBy:[],groupBy:[],filter:[],resultFormat:"time_series",interval:"AUTO"},D=[{value:"AUTO",label:"Auto"},{value:"MINUTE",label:"Minute"},{value:"HOUR",label:"Hour"},{value:"DAY",label:"Day"},{value:"MONTH",label:"Month"}],p=D[0],y=["MINUTE","HOUR","DAY","MONTH"],S=(e,t,r)=>{if("AUTO"!==e)return e;const n=r-t;return n<=108e5?"MINUTE":n<=5184e5?"HOUR":n<=2592e6?"DAY":"MONTH"},m=e=>{switch(e){case"MINUTE":return"minute";case"HOUR":return"hour";case"DAY":return"day";case"MONTH":return"month";default:return null}};function C(e,t,r){const n=new Date(e),a=new Date(t);switch(r){case"MINUTE":return a.setSeconds(0,0);case"HOUR":return a.setMinutes(0,0,0);case"DAY":return a.setHours(n.getHours(),n.getMinutes(),0,0);case"MONTH":return 1===n.getDate()?a.setDate(n.getDate()):a.setDate(0),a.setHours(n.getHours(),n.getMinutes(),0,0)}}function R(e,t,r,n){if(0===e.length)return[];const a=m(n);if(null==a)throw new Error(`Query interval ${n} is not a valid interval.`);const o=[],i=e[0].length>2?[...e[0].slice(1,-1),0]:[0];let l=_()(t);for(;l.valueOf()<=r;){const e=[l.valueOf(),...i];o.push(e),l.add(1,a),"MONTH"===n&&1!==l.date()&&l.set("date",l.daysInMonth())}const s=(0,A.differenceWith)(o,e,((e,t)=>e[0]===t[0])),u=e.concat(s);return(0,A.sortBy)(u,(e=>e[0]))}const f=["AVG_CONCURRENTVIEWERS","MAX_CONCURRENTVIEWERS","AVG-DROPPED-FRAMES"],v=f.map((e=>({value:e,label:e}))),h=e=>f.includes(e),g=(e,t,r,n)=>{if((0,A.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 n?((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 M(e,t,r,n,a,o,i){try{var l=e[o](i),s=l.value}catch(e){return void r(e)}l.done?t(s):Promise.resolve(s).then(n,a)}function b(e){return function(){var t=this,r=arguments;return new Promise((function(n,a){var o=e.apply(t,r);function i(e){M(o,n,a,i,l,"next",e)}function l(e){M(o,n,a,i,l,"throw",e)}i(void 0)}))}}function U(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}class N extends E.DataSourceApi{getDefaultQuery(e){return I}query(e){var t=this;return b((function*(){const{range:r}=e,n=t.isRelativeRangeFrom(r.raw);let a;const o=e.targets=(0,A.filter)(e.targets,(e=>!e.hide)),i=(0,A.filter)(o,(e=>t.isQueryComplete(e))).map((l=b((function*(e){var o;const i="time_series"===e.resultFormat&&e.interval?S(e.interval,r.from.valueOf(),r.to.valueOf()):void 0;let l=_()(r.from.valueOf());const s=r.to;if(n){let e=S("AUTO",l.valueOf(),s.valueOf());null!=i&&(u=i,c=e,e=y.indexOf(u)({name:e.name,operator:e.operator,value:g(e.value,e.name,e.operator,!!t.isAdAnalytics)}))),groupBy:e.groupBy,orderBy:e.orderBy,dimension:D,metric:I,start:l.toDate(),end:s.toDate(),licenseKey:e.license,interval:i,limit:t.parseLimit(e.limit),percentile:T},f=yield(0,O.lastValueFrom)(t.request(t.getRequestUrl(I,d),"POST",p)),v=f.data.data.result.rows,M=f.data.data.result.rowCount,b=f.data.data.result.columnLabels,U=[];p.interval&&(null===(o=p.groupBy)||void 0===o?void 0:o.length)>0?U.push(...function(e,t,r,n){if(0===e.length)return[];const a=[],o=new Map;e.forEach((e=>{var t;const r=e.slice(1,-1).toString();o.has(r)||o.set(r,[]),null===(t=o.get(r))||void 0===t||t.push(e)}));const i=[];o.forEach((e=>{i.push(R(e,C(e[0][0],t,n),r,n))}));const l=(0,A.zip)(...i[0])[0];return a.push({name:"Time",values:l,type:E.FieldType.time}),i.forEach((e=>{const t=e[0].slice(1,-1).join(", "),r=(0,A.zip)(...e).slice(-1);a.push({name:t,values:r[0],type:E.FieldType.number})})),a}(v,l.valueOf(),s.valueOf(),p.interval)):p.interval?U.push(...function(e,t,r,n,a){if(0===e.length)return[];const o=[],i=R(e,C(e[0][0],r,a),n,a),l=(0,A.zip)(...i);return o.push({name:"Time",values:l[0],type:E.FieldType.time}),o.push({name:t,values:l[l.length-1],type:E.FieldType.number}),o}(v,b.length>0?b[b.length-1].label:"Column 1",l.valueOf(),s.valueOf(),p.interval)):U.push(...function(e,t){if(0===e.length)return[];const r=[],n=(0,A.zip)(...e);let a=[];if(0===t.length)for(let e=0;ee.label)));return e[0].length>1&&n.slice(0,-1).forEach(((e,t)=>{r.push({name:a[t],values:e,type:E.FieldType.string})})),r.push({name:a[a.length-1],values:n[n.length-1],type:E.FieldType.number}),r}(v,b));let N=[];return M>=200&&(N=[{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:e.alias,fields:U,meta:{notices:N}})})),function(e){return l.apply(this,arguments)}));var l;return null!=a&&r.from.startOf(a),Promise.all(i).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,A.isEmpty)(e.license)||(0,A.isEmpty)(e.dimension)||null!=e.dimension&&!h(e.dimension)&&(0,A.isEmpty)(e.metric))}getRequestUrl(e,t){let r="/analytics";return!0===this.isAdAnalytics&&(r+="/ads"),null!=e?r+"/metrics/"+e:r+"/queries/"+t}request(e,t,r){const n={"X-Api-Key":this.apiKey,"X-Api-Client":"analytics-grafana-datasource"};null!=this.tenantOrgId&&(n["X-Tenant-Org-Id"]=this.tenantOrgId);const a={url:this.baseUrl+e,headers:n,method:t,data:r};return(0,d.getBackendSrv)().fetch(a)}testDatasource(){var e=this;return b((function*(){return(0,O.lastValueFrom)(e.request("/analytics/licenses","GET").pipe((0,O.map)((()=>({status:"success",message:"Data source successfully setup and connected."}))),(0,O.catchError)((e=>{var t,r,n,a;let o="Bitmovin: ";e.status&&(o+=e.status+" "),e.statusText?o+=e.statusText:o+="Can not connect to Bitmovin API";let i,l=(null===(t=e.data)||void 0===t?void 0:t.message)||(null===(n=e.data)||void 0===n||null===(r=n.data)||void 0===r?void 0:r.message);var s,u;return(null===(a=e.data)||void 0===a?void 0:a.requestId)&&(i="Timestamp: "+(new Date).toISOString(),i+=(null===(s=e.data)||void 0===s?void 0:s.requestId)?"\nRequestId: "+(null===(u=e.data)||void 0===u?void 0:u.requestId):""),(0,O.of)({status:"error",message:o,details:{message:l,verboseMessage:i}})}))))}))()}constructor(e){super(e),U(this,"baseUrl",void 0),U(this,"apiKey",void 0),U(this,"tenantOrgId",void 0),U(this,"isAdAnalytics",void 0),this.apiKey=e.jsonData.apiKey,this.tenantOrgId=e.jsonData.tenantOrgId,this.isAdAnalytics=e.jsonData.isAdAnalytics,this.baseUrl=e.url}}var P=u(959),L=u.n(P),B=u(7);function V(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function w(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 W(e,t,r,n){return Y.apply(this,arguments)}function Y(){return(Y=q((function*(e,t,r,n){const a={"X-Api-Key":t,"X-Api-Client":"analytics-grafana-datasource"};null!=n&&(a["X-Tenant-Org-Id"]=n);const o={url:e,headers:a,method:"GET"},i=(yield(0,O.lastValueFrom)((0,d.getBackendSrv)().fetch(o))).data.data.result.items,l=[];for(const e of i)l.push(r(e));return l}))).apply(this,arguments)}function j(){return(j=q((function*(e,t,r){const n=[];for(const a of H){const o=yield W(t+a.endpoint,e,a.mapperFunc,r);n.push(...o)}return n}))).apply(this,arguments)}const K=["count","sum","avg","min","max","stddev","percentile","variance","median"].map((e=>({value:e,label:e}))),x=["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}))),$=["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 k;function Q(e){return L().createElement(B.HorizontalGroup,null,L().createElement(B.Select,{id:`query-editor-${e.queryEditorId}_group-by-select`,value:(0,A.isEmpty)(e.groupBy)?void 0:e.groupBy,onChange:t=>e.onChange(t.value),options:e.selectableGroupBys,width:30}),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_group-by-move-down-button`,tooltip:"Move down",onClick:()=>e.onReorderGroupBy(1),name:"arrow-down",disabled:e.isLast}),L().createElement(B.IconButton,{tooltip:"Move up",onClick:()=>e.onReorderGroupBy(0),name:"arrow-up",disabled:e.isFirst}),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_delete-group-by-button`,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"}(k||(k={}));const z=(e,t)=>t?(0,A.differenceWith)(x,e,((e,t)=>e.value===t)):(0,A.differenceWith)($,e,((e,t)=>e.value===t));function X(e){const t=0===e.groupBys.length?4:0;return L().createElement(B.VerticalGroup,null,e.groupBys.map(((t,r,n)=>{return L().createElement(Q,{key:r,groupBy:(a=t,o=e.isAdAnalytics,o?x.filter((e=>e.value===a)):$.filter((e=>e.value===a))),onChange:t=>((t,r)=>{const n=[...e.groupBys];n.splice(t,1,r),e.onChange(n)})(r,t),selectableGroupBys:z(n,e.isAdAnalytics),onDelete:()=>(t=>{const r=[...e.groupBys];r.splice(t,1),e.onChange(r)})(r),isFirst:0===r,isLast:r===n.length-1,onReorderGroupBy:t=>((t,r)=>{const n=[...e.groupBys],a=n[r];n.splice(r,1);const o=t===k.UP?r-1:r+1;n.splice(o,0,a),e.onChange(n)})(t,r),queryEditorId:e.queryEditorId});var a,o})),L().createElement("div",{style:{paddingTop:t}},L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_add-group-by-button`,name:"plus-square",tooltip:"Add Group By",onClick:()=>(()=>{const t=z(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 Z(e){return L().createElement(B.HorizontalGroup,{spacing:"xs"},L().createElement(B.Select,{id:`query-editor-${e.queryEditorId}_order-by-select`,value:(0,A.isEmpty)(e.attribute)?void 0:e.attribute,onChange:t=>e.onAttributeChange(t),options:e.selectableOrderByAttributes,width:30}),L().createElement(B.RadioButtonGroup,{id:`query-editor-${e.queryEditorId}_order-by-button-group`,options:J,value:e.sortOrder,onChange:t=>e.onSortOrderChange(t)}),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_order-by-move-down-button`,tooltip:"Move down",onClick:()=>e.onReorderOrderBy(k.DOWN),name:"arrow-down",disabled:e.isLast}),L().createElement(B.IconButton,{tooltip:"Move up",onClick:()=>e.onReorderOrderBy(k.UP),name:"arrow-up",disabled:e.isFirst}),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_order-by-delete-button`,tooltip:"Delete Order By",name:"trash-alt",onClick:e.onDelete,size:"lg",variant:"destructive"}))}const ee=(e,t)=>t?(0,A.differenceWith)(x,e,((e,t)=>e.value===t.name)):(0,A.differenceWith)($,e,((e,t)=>e.value===t.name));function te(e){const t=0===e.orderBys.length?4:0;return L().createElement(B.VerticalGroup,null,e.orderBys.map(((t,r,n)=>{return L().createElement(Z,{key:r,isAdAnalytics:e.isAdAnalytics,selectableOrderByAttributes:ee(n,e.isAdAnalytics),attribute:(a=t.name,o=e.isAdAnalytics,o?x.filter((e=>e.value===a)):$.filter((e=>e.value===a))),onAttributeChange:t=>((t,r)=>{const n=[...e.orderBys],a={name:r.value,order:n[t].order};n.splice(t,1,a),e.onChange(n)})(r,t),sortOrder:t.order,onSortOrderChange:t=>((t,r)=>{const n=[...e.orderBys],a={name:n[t].name,order:r};n.splice(t,1,a),e.onChange(n)})(r,t),onDelete:()=>(t=>{const r=[...e.orderBys];r.splice(t,1),e.onChange(r)})(r),isFirst:0===r,isLast:r===n.length-1,onReorderOrderBy:t=>((t,r)=>{const n=t===k.UP?r-1:r+1,a=[...e.orderBys],o=a[r];a.splice(r,1),a.splice(n,0,o),e.onChange(a)})(t,r),queryEditorId:e.queryEditorId});var a,o})),L().createElement("div",{style:{paddingTop:t}},L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_add-order-by-button`,name:"plus-square",tooltip:"Add Order By",onClick:()=>(()=>{const t=ee(e.orderBys,e.isAdAnalytics)[0].value;e.onChange([...e.orderBys,{name:t,order:"ASC"}])})(),size:"xl"})))}const re=["GT","GTE","LT","LTE","EQ","NE","CONTAINS","NOTCONTAINS","IN"].map((e=>({value:e,label:e})));function ne(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function ae(e){for(var t=1;tn(ce(e.value))),[e.value]);const a=(0,P.useMemo)((()=>function(e,t){if(null!=e)return(t?x:$).find((t=>t.value===e))}(r.attribute,e.isAdAnalytics)),[r.attribute,e.isAdAnalytics]),o=(0,P.useMemo)((()=>function(e){if(null!=e)return re.find((t=>t.value===e))}(r.operator)),[r.operator]);var i,l,s;return L().createElement(B.HorizontalGroup,{spacing:"xs"},L().createElement(B.Tooltip,{content:null!==(i=r.attributeError)&&void 0!==i?i:"",show:null!=r.attributeError,theme:"error"},L().createElement("div",null,L().createElement(B.Select,{id:`query-editor-${e.queryEditorId}_filter-attribute-select`,value:a,onChange:function(e){n((t=>oe(ae({},t),{dirty:!0,attribute:e.value,attributeError:void 0})))},options:e.isAdAnalytics?x:$,width:le,invalid:null!=r.attributeError}))),L().createElement(B.Tooltip,{content:null!==(l=r.operatorError)&&void 0!==l?l:"",show:null!=r.operatorError,theme:"error"},L().createElement("div",null,L().createElement(B.Select,{id:`query-editor-${e.queryEditorId}_filter-operator-select`,value:o,onChange:function(e){n((t=>oe(ae({},t),{dirty:!0,operator:e.value,operatorError:void 0})))},options:re,width:se,invalid:null!=r.operatorError}))),L().createElement(B.Tooltip,{content:null!==(s=r.inputValueError)&&void 0!==s?s:"",show:null!=r.inputValueError,theme:"error"},L().createElement(B.Input,{"data-testid":`query-editor-${e.queryEditorId}_filter-value-input`,value:r.value,onChange:e=>{return t=e.currentTarget.value,void n((e=>oe(ae({},e),{dirty:!0,value:t,inputValueError:void 0})));var t},invalid:null!=r.inputValueError,type:"text",width:ue})),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_filter-delete-button`,variant:"destructive",name:"trash-alt",size:"lg",tooltip:"Delete Filter",onClick:e.onDelete}),(t||r.dirty)&&L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_filter-save-button`,variant:"primary",name:t?"plus-square":"save",size:"lg",tooltip:t?"Add new filter":"Save changes",onClick:function(){if(null!=r.attribute)if(null!=r.operator)try{g(r.value,r.attribute,r.operator,e.isAdAnalytics),e.onChange({name:r.attribute,operator:r.operator,value:r.value})}catch(e){n((t=>oe(ae({},t),{inputValueError:e instanceof Error?e.message:"Could not save value"})))}else n((e=>oe(ae({},e),{operatorError:"Filter operator has to be selected"})));else n((e=>oe(ae({},e),{attributeError:"Filter attribute has to be selected"})))}}),!t&&r.dirty&&L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_filter-revert-changes-button`,variant:"secondary",name:"history",size:"lg",tooltip:"Revert changes",onClick:function(){n(ce(e.value))}}))}const le=30,se=15,ue=30;function ce(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 Ee(e){const[t,r]=(0,P.useState)(!1),n=0===e.filters.length?4:0;return L().createElement(B.VerticalGroup,null,(e.filters.length>0||t)&&L().createElement(B.HorizontalGroup,{spacing:"none"},L().createElement(B.InlineLabel,{width:le,tooltip:""},"Attribute"),L().createElement(B.InlineLabel,{width:se,tooltip:""},"Operator"),L().createElement(B.InlineLabel,{width:ue,tooltip:""},"Value")),e.filters.map(((t,r)=>L().createElement(ie,{isAdAnalytics:e.isAdAnalytics,value:t,onChange:t=>function(t,r){const n=[...e.filters];n.splice(t,1,r),e.onQueryFilterChange(n)}(r,t),onDelete:()=>function(t){const r=[...e.filters];r.splice(t,1),e.onQueryFilterChange(r)}(r),selectedQueryFilters:e.filters,key:r,queryEditorId:e.queryEditorId}))),L().createElement("div",{style:{paddingTop:n}},t?L().createElement(ie,{isAdAnalytics:e.isAdAnalytics,value:void 0,onChange:function(t){const n=[...e.filters,t];e.onQueryFilterChange(n),r(!1)},onDelete:()=>r(!1),selectedQueryFilters:e.filters,queryEditorId:e.queryEditorId}):L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_add-new-filter-button`,name:"plus-square",tooltip:"Add Filter",onClick:()=>r(!0),size:"xl"})))}function de(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function Ae(e){for(var t=1;t{""!==r.url&&null!=r.url||t(G(w({},r),{url:"https://api.bitmovin.com/v1"}))}),[]);const{jsonData:n}=r;return L().createElement(L().Fragment,null,L().createElement(B.DataSourceHttpSettings,{defaultUrl:"https://api.bitmovin.com/v1",dataSourceConfig:r,onChange:t,showAccessOptions:!0}),L().createElement(B.FieldSet,{label:"Bitmovin Analytics Details"},L().createElement(B.InlineField,{required:!0,label:"API Key",labelWidth:26},L().createElement(B.Input,{required:!0,onChange:e=>{const n=G(w({},r.jsonData),{apiKey:e.currentTarget.value});t(G(w({},r),{jsonData:n}))},value:n.apiKey||"",placeholder:"Analytics API Key",width:40,"data-testid":`config-editor-${e.options.name}_api-key-input`})),L().createElement(B.InlineField,{label:"Tenant Org Id",labelWidth:26},L().createElement(B.Input,{onChange:e=>{const n=G(w({},r.jsonData),{tenantOrgId:e.currentTarget.value});t(G(w({},r),{jsonData:n}))},value:n.tenantOrgId||"",placeholder:"Tenant Org Id",width:40,"data-testid":`config-editor-${e.options.name}_tenant-org-id-input`})),L().createElement(B.InlineField,{label:"Ad Analytics",tooltip:"Check if you want to query ads data",labelWidth:26},L().createElement(B.InlineSwitch,{value:n.isAdAnalytics||!1,onChange:e=>{const n=G(w({},r.jsonData),{isAdAnalytics:e.currentTarget.checked});t(G(w({},r),{jsonData:n}))}}))))})).setQueryEditor((function(e){const t=(0,A.defaults)(e.query,I),[r,n]=(0,P.useState)([]),[a,o]=(0,P.useState)("DEFAULT"),[i,l]=(0,P.useState)(""),[s,u]=(0,P.useState)("time_series"===t.resultFormat),[c,E]=(0,P.useState)(t.percentileValue),d=(0,P.useMemo)((()=>!!t.dimension&&h(t.dimension)),[t.dimension]),T=(0,P.useMemo)((()=>"percentile"===t.metric),[t.metric]);return(0,P.useEffect)((()=>{o("LOADING"),function(e,t,r){return j.apply(this,arguments)}(e.datasource.apiKey,e.datasource.baseUrl,e.datasource.tenantOrgId).then((e=>{n(e),o("SUCCESS")})).catch((e=>{o("ERROR"),l(e.status+" "+e.statusText)}))}),[e.datasource.apiKey,e.datasource.baseUrl,e.datasource.tenantOrgId]),L().createElement("div",{className:"gf-form"},L().createElement(B.FieldSet,null,L().createElement(B.InlineField,{label:"License",labelWidth:20,invalid:"ERROR"===a,error:`Error when fetching Analytics Licenses: ${i}`,disabled:"ERROR"===a,required:!0},L().createElement(B.Select,{id:`query-editor-${e.query.refId}_license-select`,value:t.license,onChange:r=>{e.onChange(Te(Ae({},t),{license:r.value})),e.onRunQuery()},width:30,options:r,noOptionsMessage:"No Analytics Licenses found",isLoading:"LOADING"===a,placeholder:"LOADING"===a?"Loading Licenses":"Choose License"})),L().createElement(B.HorizontalGroup,{spacing:"xs"},!d&&L().createElement(B.InlineField,{label:"Metric",labelWidth:20,required:!0},L().createElement(B.Select,{value:t.metric,onChange:r=>(r=>{let n;"percentile"===r.value&&null==c?(E(95),n=95):E(void 0),e.onChange(Te(Ae({},t),{metric:r.value,percentileValue:n})),e.onRunQuery()})(r),width:30,options:K,id:`query-editor-${e.query.refId}_aggregation-method-select`})),T&&L().createElement(B.Input,{"data-testid":`query-editor-${e.query.refId}_percentile-value-input`,value:c,onChange:e=>{let t=parseInt(e.target.value,10);t<0?t=0:t>99&&(t=99),E(t)},onBlur:()=>{e.onChange(Te(Ae({},t),{percentileValue:c})),e.onRunQuery()},type:"number",placeholder:"value",width:10})),L().createElement(B.InlineField,{label:"Dimension",labelWidth:20,required:!0},L().createElement(B.Select,{value:t.dimension,onChange:r=>{e.onChange(Te(Ae({},t),{dimension:r.value})),e.onRunQuery()},width:30,options:e.datasource.isAdAnalytics?x:$.concat(v),id:`query-editor-${e.query.refId}_dimension-select`})),L().createElement(B.InlineField,{label:"Filter",labelWidth:20},L().createElement(Ee,{isAdAnalytics:!!e.datasource.isAdAnalytics,onQueryFilterChange:r=>{e.onChange(Te(Ae({},t),{filter:r})),e.onRunQuery()},filters:t.filter,queryEditorId:e.query.refId})),L().createElement(B.InlineField,{label:"Group By",labelWidth:20},L().createElement(X,{isAdAnalytics:!!e.datasource.isAdAnalytics,onChange:r=>{e.onChange(Te(Ae({},t),{groupBy:r})),e.onRunQuery()},groupBys:t.groupBy,queryEditorId:e.query.refId})),L().createElement(B.InlineField,{label:"Order By",labelWidth:20},L().createElement(te,{isAdAnalytics:!!e.datasource.isAdAnalytics,onChange:r=>{e.onChange(Te(Ae({},t),{orderBy:r})),e.onRunQuery()},orderBys:t.orderBy,queryEditorId:e.query.refId})),L().createElement(B.InlineField,{label:"Limit",labelWidth:20},L().createElement(B.Input,{"data-testid":`query-editor-${e.query.refId}_limit-input`,defaultValue:t.limit,type:"number",onBlur:r=>{const n=parseInt(r.target.value,10);e.onChange(Te(Ae({},t),{limit:isNaN(n)?void 0:n})),e.onRunQuery()},width:30,placeholder:"No limit"})),L().createElement(B.InlineField,{label:"Format as time series",labelWidth:20},L().createElement(B.InlineSwitch,{"data-testid":`query-editor-${e.query.refId}_format-as-time-series-switch`,value:s,onChange:r=>{u(r.currentTarget.checked),r.currentTarget.checked?e.onChange(Te(Ae({},t),{interval:"AUTO",resultFormat:"time_series"})):e.onChange(Te(Ae({},t),{interval:void 0,resultFormat:"table"})),e.onRunQuery()}})),s&&L().createElement(L().Fragment,null,L().createElement(B.InlineField,{label:"Interval",labelWidth:20},L().createElement(B.Select,{id:`query-editor-${e.query.refId}_interval-select`,defaultValue:p,value:t.interval,onChange:r=>(r=>{e.onChange(Te(Ae({},t),{interval:r.value})),e.onRunQuery()})(r),width:30,options:D}))),L().createElement(B.InlineField,{label:"Alias By",labelWidth:20},L().createElement(B.Input,{"data-testid":`query-editor-${e.query.refId}_alias-by-input`,defaultValue:t.alias,placeholder:"Naming pattern",onBlur:r=>{e.onChange(Te(Ae({},t),{alias:r.target.value})),e.onRunQuery()}}))))}));return c})())); +define(["@grafana/data","@grafana/runtime","lodash","moment","rxjs","react","@grafana/ui"],((e,t,r,n,a,o,i)=>(()=>{"use strict";var l={781:t=>{t.exports=e},531:e=>{e.exports=t},7:e=>{e.exports=i},241:e=>{e.exports=r},468:e=>{e.exports=n},959:e=>{e.exports=o},269:e=>{e.exports=a}},s={};function u(e){var t=s[e];if(void 0!==t)return t.exports;var r=s[e]={exports:{}};return l[e](r,r.exports,u),r.exports}u.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return u.d(t,{a:t}),t},u.d=(e,t)=>{for(var r in t)u.o(t,r)&&!u.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},u.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),u.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var c={};u.r(c),u.d(c,{plugin:()=>Oe});var E=u(781),A=u(531),d=u(241),_=u(468),T=u.n(_),O=u(269);const I={license:"",orderBy:[],groupBy:[],filter:[],resultFormat:"time_series",interval:"AUTO"},D=[{value:"AUTO",label:"Auto"},{value:"MINUTE",label:"Minute"},{value:"HOUR",label:"Hour"},{value:"DAY",label:"Day"},{value:"MONTH",label:"Month"}],p=D[0],S=["MINUTE","HOUR","DAY","MONTH"],y=(e,t,r)=>{if("AUTO"!==e)return e;const n=r-t;return n<=108e5?"MINUTE":n<=5184e5?"HOUR":n<=2592e6?"DAY":"MONTH"},R=e=>{switch(e){case"MINUTE":return"minute";case"HOUR":return"hour";case"DAY":return"day";case"MONTH":return"month";default:return null}};function C(e,t,r){const n=new Date(e),a=new Date(t);switch(r){case"MINUTE":return a.setSeconds(0,0);case"HOUR":return a.setMinutes(0,0,0);case"DAY":return a.setHours(n.getHours(),n.getMinutes(),0,0);case"MONTH":return 1===n.getDate()?a.setDate(n.getDate()):a.setDate(0),a.setHours(n.getHours(),n.getMinutes(),0,0)}}function m(e,t,r,n){if(0===e.length)return[];const a=R(n);if(null==a)throw new Error(`Query interval ${n} is not a valid interval.`);const o=[],i=e[0].length>2?[...e[0].slice(1,-1),0]:[0];let l=T()(t);for(;l.valueOf()<=r;){const e=[l.valueOf(),...i];o.push(e),l.add(1,a),"MONTH"===n&&1!==l.date()&&l.set("date",l.daysInMonth())}const s=(0,d.differenceWith)(o,e,((e,t)=>e[0]===t[0])),u=e.concat(s);return(0,d.sortBy)(u,(e=>e[0]))}const f=["AVG_CONCURRENTVIEWERS","MAX_CONCURRENTVIEWERS","AVG-DROPPED-FRAMES"],v=f.map((e=>({value:e,label:e}))),h=e=>f.includes(e),g=(e,t,r,n)=>{if((0,d.isEmpty)(e)&&(e=>{switch(e){case"AD_TYPE":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 n?((e,t)=>{switch(t){case"IS_LINEAR":return"true"===e;case"AD_INDEX":case"AD_TYPE":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"AD_INDEX":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 M(e,t,r,n,a,o,i){try{var l=e[o](i),s=l.value}catch(e){return void r(e)}l.done?t(s):Promise.resolve(s).then(n,a)}function N(e){return function(){var t=this,r=arguments;return new Promise((function(n,a){var o=e.apply(t,r);function i(e){M(o,n,a,i,l,"next",e)}function l(e){M(o,n,a,i,l,"throw",e)}i(void 0)}))}}function U(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}class b extends E.DataSourceApi{getDefaultQuery(e){return I}query(e){var t=this;return N((function*(){const{range:r}=e,n=t.isRelativeRangeFrom(r.raw);let a;const o=e.targets=(0,d.filter)(e.targets,(e=>!e.hide)),i=(0,d.filter)(o,(e=>t.isQueryComplete(e))).map((l=N((function*(e){var o;const i="time_series"===e.resultFormat&&e.interval?y(e.interval,r.from.valueOf(),r.to.valueOf()):void 0;let l=T()(r.from.valueOf());const s=r.to;if(n){let e=y("AUTO",l.valueOf(),s.valueOf());null!=i&&(u=i,c=e,e=S.indexOf(u)({name:e.name,operator:e.operator,value:g(e.value,e.name,e.operator,!!t.isAdAnalytics)}))),groupBy:e.groupBy,orderBy:e.orderBy,dimension:D,metric:I,start:l.toDate(),end:s.toDate(),licenseKey:e.license,interval:i,limit:t.parseLimit(e.limit),percentile:_},f=yield(0,O.lastValueFrom)(t.request(t.getRequestUrl(I,A),"POST",p)),v=f.data.data.result.rows,M=f.data.data.result.rowCount,N=f.data.data.result.columnLabels,U=[];p.interval&&(null===(o=p.groupBy)||void 0===o?void 0:o.length)>0?U.push(...function(e,t,r,n){if(0===e.length)return[];const a=[],o=new Map;e.forEach((e=>{var t;const r=e.slice(1,-1).toString();o.has(r)||o.set(r,[]),null===(t=o.get(r))||void 0===t||t.push(e)}));const i=[];o.forEach((e=>{i.push(m(e,C(e[0][0],t,n),r,n))}));const l=(0,d.zip)(...i[0])[0];return a.push({name:"Time",values:l,type:E.FieldType.time}),i.forEach((e=>{const t=e[0].slice(1,-1).join(", "),r=(0,d.zip)(...e).slice(-1);a.push({name:t,values:r[0],type:E.FieldType.number})})),a}(v,l.valueOf(),s.valueOf(),p.interval)):p.interval?U.push(...function(e,t,r,n,a){if(0===e.length)return[];const o=[],i=m(e,C(e[0][0],r,a),n,a),l=(0,d.zip)(...i);return o.push({name:"Time",values:l[0],type:E.FieldType.time}),o.push({name:t,values:l[l.length-1],type:E.FieldType.number}),o}(v,N.length>0?N[N.length-1].label:"Column 1",l.valueOf(),s.valueOf(),p.interval)):U.push(...function(e,t){if(0===e.length)return[];const r=[],n=(0,d.zip)(...e);let a=[];if(0===t.length)for(let e=0;ee.label)));return e[0].length>1&&n.slice(0,-1).forEach(((e,t)=>{r.push({name:a[t],values:e,type:E.FieldType.string})})),r.push({name:a[a.length-1],values:n[n.length-1],type:E.FieldType.number}),r}(v,N));let b=[];return M>=200&&(b=[{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:e.alias,fields:U,meta:{notices:b}})})),function(e){return l.apply(this,arguments)}));var l;return null!=a&&r.from.startOf(a),Promise.all(i).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,d.isEmpty)(e.license)||(0,d.isEmpty)(e.dimension)||null!=e.dimension&&!h(e.dimension)&&(0,d.isEmpty)(e.metric))}getRequestUrl(e,t){let r="/analytics";return!0===this.isAdAnalytics&&(r+="/ads"),null!=e?r+"/metrics/"+e:r+"/queries/"+t}request(e,t,r){const n={"X-Api-Key":this.apiKey,"X-Api-Client":"analytics-grafana-datasource"};null!=this.tenantOrgId&&(n["X-Tenant-Org-Id"]=this.tenantOrgId);const a={url:this.baseUrl+e,headers:n,method:t,data:r};return(0,A.getBackendSrv)().fetch(a)}testDatasource(){var e=this;return N((function*(){return(0,O.lastValueFrom)(e.request("/analytics/licenses","GET").pipe((0,O.map)((()=>({status:"success",message:"Data source successfully setup and connected."}))),(0,O.catchError)((e=>{var t,r,n,a;let o="Bitmovin: ";e.status&&(o+=e.status+" "),e.statusText?o+=e.statusText:o+="Can not connect to Bitmovin API";let i,l=(null===(t=e.data)||void 0===t?void 0:t.message)||(null===(n=e.data)||void 0===n||null===(r=n.data)||void 0===r?void 0:r.message);var s,u;return(null===(a=e.data)||void 0===a?void 0:a.requestId)&&(i="Timestamp: "+(new Date).toISOString(),i+=(null===(s=e.data)||void 0===s?void 0:s.requestId)?"\nRequestId: "+(null===(u=e.data)||void 0===u?void 0:u.requestId):""),(0,O.of)({status:"error",message:o,details:{message:l,verboseMessage:i}})}))))}))()}constructor(e){super(e),U(this,"baseUrl",void 0),U(this,"apiKey",void 0),U(this,"tenantOrgId",void 0),U(this,"isAdAnalytics",void 0),this.apiKey=e.jsonData.apiKey,this.tenantOrgId=e.jsonData.tenantOrgId,this.isAdAnalytics=e.jsonData.isAdAnalytics,this.baseUrl=e.url}}var P=u(959),L=u.n(P),B=u(7);function V(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function w(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 H(e,t,r,n){return W.apply(this,arguments)}function W(){return(W=q((function*(e,t,r,n){const a={"X-Api-Key":t,"X-Api-Client":"analytics-grafana-datasource"};null!=n&&(a["X-Tenant-Org-Id"]=n);const o={url:e,headers:a,method:"GET"},i=(yield(0,O.lastValueFrom)((0,A.getBackendSrv)().fetch(o))).data.data.result.items,l=[];for(const e of i)l.push(r(e));return l}))).apply(this,arguments)}function j(){return(j=q((function*(e,t,r){const n=[];for(const a of Y){const o=yield H(t+a.endpoint,e,a.mapperFunc,r);n.push(...o)}return n}))).apply(this,arguments)}const K=["count","sum","avg","min","max","stddev","percentile","variance","median"].map((e=>({value:e,label:e}))),x=["ADVERTISER_NAME","AD_ABANDONMENT_RATE","AD_CLICKTHROUGH_URL","AD_DESCRIPTION","AD_DURATION","AD_FALLBACK_INDEX","AD_ID","AD_ID_PLAYER","AD_IMPRESSION_ID","AD_INDEX","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_TYPE","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","COMPLETED_FAILED_BEACON_URL","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","MIDPOINT_FAILED_BEACON_URL","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","QUARTILE1_FAILED_BEACON_URL","QUARTILE_3","QUARTILE3_FAILED_BEACON_URL","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}))),$=["AD","AD_ID","AD_INDEX","AD_POSITION","AD_SYSTEM","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 k;function Q(e){return L().createElement(B.HorizontalGroup,null,L().createElement(B.Select,{id:`query-editor-${e.queryEditorId}_group-by-select`,value:(0,d.isEmpty)(e.groupBy)?void 0:e.groupBy,onChange:t=>e.onChange(t.value),options:e.selectableGroupBys,width:30}),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_group-by-move-down-button`,tooltip:"Move down",onClick:()=>e.onReorderGroupBy(1),name:"arrow-down",disabled:e.isLast}),L().createElement(B.IconButton,{tooltip:"Move up",onClick:()=>e.onReorderGroupBy(0),name:"arrow-up",disabled:e.isFirst}),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_delete-group-by-button`,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"}(k||(k={}));const z=(e,t)=>t?(0,d.differenceWith)(x,e,((e,t)=>e.value===t)):(0,d.differenceWith)($,e,((e,t)=>e.value===t));function X(e){const t=0===e.groupBys.length?4:0;return L().createElement(B.VerticalGroup,null,e.groupBys.map(((t,r,n)=>{return L().createElement(Q,{key:r,groupBy:(a=t,o=e.isAdAnalytics,o?x.filter((e=>e.value===a)):$.filter((e=>e.value===a))),onChange:t=>((t,r)=>{const n=[...e.groupBys];n.splice(t,1,r),e.onChange(n)})(r,t),selectableGroupBys:z(n,e.isAdAnalytics),onDelete:()=>(t=>{const r=[...e.groupBys];r.splice(t,1),e.onChange(r)})(r),isFirst:0===r,isLast:r===n.length-1,onReorderGroupBy:t=>((t,r)=>{const n=[...e.groupBys],a=n[r];n.splice(r,1);const o=t===k.UP?r-1:r+1;n.splice(o,0,a),e.onChange(n)})(t,r),queryEditorId:e.queryEditorId});var a,o})),L().createElement("div",{style:{paddingTop:t}},L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_add-group-by-button`,name:"plus-square",tooltip:"Add Group By",onClick:()=>(()=>{const t=z(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 Z(e){return L().createElement(B.HorizontalGroup,{spacing:"xs"},L().createElement(B.Select,{id:`query-editor-${e.queryEditorId}_order-by-select`,value:(0,d.isEmpty)(e.attribute)?void 0:e.attribute,onChange:t=>e.onAttributeChange(t),options:e.selectableOrderByAttributes,width:30}),L().createElement(B.RadioButtonGroup,{id:`query-editor-${e.queryEditorId}_order-by-button-group`,options:J,value:e.sortOrder,onChange:t=>e.onSortOrderChange(t)}),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_order-by-move-down-button`,tooltip:"Move down",onClick:()=>e.onReorderOrderBy(k.DOWN),name:"arrow-down",disabled:e.isLast}),L().createElement(B.IconButton,{tooltip:"Move up",onClick:()=>e.onReorderOrderBy(k.UP),name:"arrow-up",disabled:e.isFirst}),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_order-by-delete-button`,tooltip:"Delete Order By",name:"trash-alt",onClick:e.onDelete,size:"lg",variant:"destructive"}))}const ee=(e,t)=>t?(0,d.differenceWith)(x,e,((e,t)=>e.value===t.name)):(0,d.differenceWith)($,e,((e,t)=>e.value===t.name));function te(e){const t=0===e.orderBys.length?4:0;return L().createElement(B.VerticalGroup,null,e.orderBys.map(((t,r,n)=>{return L().createElement(Z,{key:r,isAdAnalytics:e.isAdAnalytics,selectableOrderByAttributes:ee(n,e.isAdAnalytics),attribute:(a=t.name,o=e.isAdAnalytics,o?x.filter((e=>e.value===a)):$.filter((e=>e.value===a))),onAttributeChange:t=>((t,r)=>{const n=[...e.orderBys],a={name:r.value,order:n[t].order};n.splice(t,1,a),e.onChange(n)})(r,t),sortOrder:t.order,onSortOrderChange:t=>((t,r)=>{const n=[...e.orderBys],a={name:n[t].name,order:r};n.splice(t,1,a),e.onChange(n)})(r,t),onDelete:()=>(t=>{const r=[...e.orderBys];r.splice(t,1),e.onChange(r)})(r),isFirst:0===r,isLast:r===n.length-1,onReorderOrderBy:t=>((t,r)=>{const n=t===k.UP?r-1:r+1,a=[...e.orderBys],o=a[r];a.splice(r,1),a.splice(n,0,o),e.onChange(a)})(t,r),queryEditorId:e.queryEditorId});var a,o})),L().createElement("div",{style:{paddingTop:t}},L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_add-order-by-button`,name:"plus-square",tooltip:"Add Order By",onClick:()=>(()=>{const t=ee(e.orderBys,e.isAdAnalytics)[0].value;e.onChange([...e.orderBys,{name:t,order:"ASC"}])})(),size:"xl"})))}const re=["GT","GTE","LT","LTE","EQ","NE","CONTAINS","NOTCONTAINS","IN"].map((e=>({value:e,label:e})));function ne(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function ae(e){for(var t=1;tn(ce(e.value))),[e.value]);const a=(0,P.useMemo)((()=>function(e,t){if(null!=e)return(t?x:$).find((t=>t.value===e))}(r.attribute,e.isAdAnalytics)),[r.attribute,e.isAdAnalytics]),o=(0,P.useMemo)((()=>function(e){if(null!=e)return re.find((t=>t.value===e))}(r.operator)),[r.operator]);var i,l,s;return L().createElement(B.HorizontalGroup,{spacing:"xs"},L().createElement(B.Tooltip,{content:null!==(i=r.attributeError)&&void 0!==i?i:"",show:null!=r.attributeError,theme:"error"},L().createElement("div",null,L().createElement(B.Select,{id:`query-editor-${e.queryEditorId}_filter-attribute-select`,value:a,onChange:function(e){n((t=>oe(ae({},t),{dirty:!0,attribute:e.value,attributeError:void 0})))},options:e.isAdAnalytics?x:$,width:le,invalid:null!=r.attributeError}))),L().createElement(B.Tooltip,{content:null!==(l=r.operatorError)&&void 0!==l?l:"",show:null!=r.operatorError,theme:"error"},L().createElement("div",null,L().createElement(B.Select,{id:`query-editor-${e.queryEditorId}_filter-operator-select`,value:o,onChange:function(e){n((t=>oe(ae({},t),{dirty:!0,operator:e.value,operatorError:void 0})))},options:re,width:se,invalid:null!=r.operatorError}))),L().createElement(B.Tooltip,{content:null!==(s=r.inputValueError)&&void 0!==s?s:"",show:null!=r.inputValueError,theme:"error"},L().createElement(B.Input,{"data-testid":`query-editor-${e.queryEditorId}_filter-value-input`,value:r.value,onChange:e=>{return t=e.currentTarget.value,void n((e=>oe(ae({},e),{dirty:!0,value:t,inputValueError:void 0})));var t},invalid:null!=r.inputValueError,type:"text",width:ue})),L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_filter-delete-button`,variant:"destructive",name:"trash-alt",size:"lg",tooltip:"Delete Filter",onClick:e.onDelete}),(t||r.dirty)&&L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_filter-save-button`,variant:"primary",name:t?"plus-square":"save",size:"lg",tooltip:t?"Add new filter":"Save changes",onClick:function(){if(null!=r.attribute)if(null!=r.operator)try{g(r.value,r.attribute,r.operator,e.isAdAnalytics),e.onChange({name:r.attribute,operator:r.operator,value:r.value})}catch(e){n((t=>oe(ae({},t),{inputValueError:e instanceof Error?e.message:"Could not save value"})))}else n((e=>oe(ae({},e),{operatorError:"Filter operator has to be selected"})));else n((e=>oe(ae({},e),{attributeError:"Filter attribute has to be selected"})))}}),!t&&r.dirty&&L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_filter-revert-changes-button`,variant:"secondary",name:"history",size:"lg",tooltip:"Revert changes",onClick:function(){n(ce(e.value))}}))}const le=30,se=15,ue=30;function ce(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 Ee(e){const[t,r]=(0,P.useState)(!1),n=0===e.filters.length?4:0;return L().createElement(B.VerticalGroup,null,(e.filters.length>0||t)&&L().createElement(B.HorizontalGroup,{spacing:"none"},L().createElement(B.InlineLabel,{width:le,tooltip:""},"Attribute"),L().createElement(B.InlineLabel,{width:se,tooltip:""},"Operator"),L().createElement(B.InlineLabel,{width:ue,tooltip:""},"Value")),e.filters.map(((t,r)=>L().createElement(ie,{isAdAnalytics:e.isAdAnalytics,value:t,onChange:t=>function(t,r){const n=[...e.filters];n.splice(t,1,r),e.onQueryFilterChange(n)}(r,t),onDelete:()=>function(t){const r=[...e.filters];r.splice(t,1),e.onQueryFilterChange(r)}(r),selectedQueryFilters:e.filters,key:r,queryEditorId:e.queryEditorId}))),L().createElement("div",{style:{paddingTop:n}},t?L().createElement(ie,{isAdAnalytics:e.isAdAnalytics,value:void 0,onChange:function(t){const n=[...e.filters,t];e.onQueryFilterChange(n),r(!1)},onDelete:()=>r(!1),selectedQueryFilters:e.filters,queryEditorId:e.queryEditorId}):L().createElement(B.IconButton,{"data-testid":`query-editor-${e.queryEditorId}_add-new-filter-button`,name:"plus-square",tooltip:"Add Filter",onClick:()=>r(!0),size:"xl"})))}function Ae(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function de(e){for(var t=1;t{""!==r.url&&null!=r.url||t(G(w({},r),{url:"https://api.bitmovin.com/v1"}))}),[]);const{jsonData:n}=r;return L().createElement(L().Fragment,null,L().createElement(B.DataSourceHttpSettings,{defaultUrl:"https://api.bitmovin.com/v1",dataSourceConfig:r,onChange:t,showAccessOptions:!0}),L().createElement(B.FieldSet,{label:"Bitmovin Analytics Details"},L().createElement(B.InlineField,{required:!0,label:"API Key",labelWidth:26},L().createElement(B.Input,{required:!0,onChange:e=>{const n=G(w({},r.jsonData),{apiKey:e.currentTarget.value});t(G(w({},r),{jsonData:n}))},value:n.apiKey||"",placeholder:"Analytics API Key",width:40,"data-testid":`config-editor-${e.options.name}_api-key-input`})),L().createElement(B.InlineField,{label:"Tenant Org Id",labelWidth:26},L().createElement(B.Input,{onChange:e=>{const n=G(w({},r.jsonData),{tenantOrgId:e.currentTarget.value});t(G(w({},r),{jsonData:n}))},value:n.tenantOrgId||"",placeholder:"Tenant Org Id",width:40,"data-testid":`config-editor-${e.options.name}_tenant-org-id-input`})),L().createElement(B.InlineField,{label:"Ad Analytics",tooltip:"Check if you want to query ads data",labelWidth:26},L().createElement(B.InlineSwitch,{value:n.isAdAnalytics||!1,onChange:e=>{const n=G(w({},r.jsonData),{isAdAnalytics:e.currentTarget.checked});t(G(w({},r),{jsonData:n}))}}))))})).setQueryEditor((function(e){const t=(0,d.defaults)(e.query,I),[r,n]=(0,P.useState)([]),[a,o]=(0,P.useState)("DEFAULT"),[i,l]=(0,P.useState)(""),[s,u]=(0,P.useState)("time_series"===t.resultFormat),[c,E]=(0,P.useState)(t.percentileValue),A=(0,P.useMemo)((()=>!!t.dimension&&h(t.dimension)),[t.dimension]),_=(0,P.useMemo)((()=>"percentile"===t.metric),[t.metric]);return(0,P.useEffect)((()=>{o("LOADING"),function(e,t,r){return j.apply(this,arguments)}(e.datasource.apiKey,e.datasource.baseUrl,e.datasource.tenantOrgId).then((e=>{n(e),o("SUCCESS")})).catch((e=>{o("ERROR"),l(e.status+" "+e.statusText)}))}),[e.datasource.apiKey,e.datasource.baseUrl,e.datasource.tenantOrgId]),L().createElement("div",{className:"gf-form"},L().createElement(B.FieldSet,null,L().createElement(B.InlineField,{label:"License",labelWidth:20,invalid:"ERROR"===a,error:`Error when fetching Analytics Licenses: ${i}`,disabled:"ERROR"===a,required:!0},L().createElement(B.Select,{id:`query-editor-${e.query.refId}_license-select`,value:t.license,onChange:r=>{e.onChange(_e(de({},t),{license:r.value})),e.onRunQuery()},width:30,options:r,noOptionsMessage:"No Analytics Licenses found",isLoading:"LOADING"===a,placeholder:"LOADING"===a?"Loading Licenses":"Choose License"})),L().createElement(B.HorizontalGroup,{spacing:"xs"},!A&&L().createElement(B.InlineField,{label:"Metric",labelWidth:20,required:!0},L().createElement(B.Select,{value:t.metric,onChange:r=>(r=>{let n;"percentile"===r.value&&null==c?(E(95),n=95):E(void 0),e.onChange(_e(de({},t),{metric:r.value,percentileValue:n})),e.onRunQuery()})(r),width:30,options:K,id:`query-editor-${e.query.refId}_aggregation-method-select`})),_&&L().createElement(B.Input,{"data-testid":`query-editor-${e.query.refId}_percentile-value-input`,value:c,onChange:e=>{let t=parseInt(e.target.value,10);t<0?t=0:t>99&&(t=99),E(t)},onBlur:()=>{e.onChange(_e(de({},t),{percentileValue:c})),e.onRunQuery()},type:"number",placeholder:"value",width:10})),L().createElement(B.InlineField,{label:"Dimension",labelWidth:20,required:!0},L().createElement(B.Select,{value:t.dimension,onChange:r=>{e.onChange(_e(de({},t),{dimension:r.value})),e.onRunQuery()},width:30,options:e.datasource.isAdAnalytics?x:$.concat(v),id:`query-editor-${e.query.refId}_dimension-select`})),L().createElement(B.InlineField,{label:"Filter",labelWidth:20},L().createElement(Ee,{isAdAnalytics:!!e.datasource.isAdAnalytics,onQueryFilterChange:r=>{e.onChange(_e(de({},t),{filter:r})),e.onRunQuery()},filters:t.filter,queryEditorId:e.query.refId})),L().createElement(B.InlineField,{label:"Group By",labelWidth:20},L().createElement(X,{isAdAnalytics:!!e.datasource.isAdAnalytics,onChange:r=>{e.onChange(_e(de({},t),{groupBy:r})),e.onRunQuery()},groupBys:t.groupBy,queryEditorId:e.query.refId})),L().createElement(B.InlineField,{label:"Order By",labelWidth:20},L().createElement(te,{isAdAnalytics:!!e.datasource.isAdAnalytics,onChange:r=>{e.onChange(_e(de({},t),{orderBy:r})),e.onRunQuery()},orderBys:t.orderBy,queryEditorId:e.query.refId})),L().createElement(B.InlineField,{label:"Limit",labelWidth:20},L().createElement(B.Input,{"data-testid":`query-editor-${e.query.refId}_limit-input`,defaultValue:t.limit,type:"number",onBlur:r=>{const n=parseInt(r.target.value,10);e.onChange(_e(de({},t),{limit:isNaN(n)?void 0:n})),e.onRunQuery()},width:30,placeholder:"No limit"})),L().createElement(B.InlineField,{label:"Format as time series",labelWidth:20},L().createElement(B.InlineSwitch,{"data-testid":`query-editor-${e.query.refId}_format-as-time-series-switch`,value:s,onChange:r=>{u(r.currentTarget.checked),r.currentTarget.checked?e.onChange(_e(de({},t),{interval:"AUTO",resultFormat:"time_series"})):e.onChange(_e(de({},t),{interval:void 0,resultFormat:"table"})),e.onRunQuery()}})),s&&L().createElement(L().Fragment,null,L().createElement(B.InlineField,{label:"Interval",labelWidth:20},L().createElement(B.Select,{id:`query-editor-${e.query.refId}_interval-select`,defaultValue:p,value:t.interval,onChange:r=>(r=>{e.onChange(_e(de({},t),{interval:r.value})),e.onRunQuery()})(r),width:30,options:D}))),L().createElement(B.InlineField,{label:"Alias By",labelWidth:20},L().createElement(B.Input,{"data-testid":`query-editor-${e.query.refId}_alias-by-input`,defaultValue:t.alias,placeholder:"Naming pattern",onBlur:r=>{e.onChange(_e(de({},t),{alias:r.target.value})),e.onRunQuery()}}))))}));return c})())); //# sourceMappingURL=module.js.map \ No newline at end of file diff --git a/dist/module.js.map b/dist/module.js.map index dde2ebe..0ede746 100644 --- a/dist/module.js.map +++ b/dist/module.js.map @@ -1 +1 @@ -{"version":3,"file":"module.js","mappings":"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,IAGrC,OAAOyM,CACT,KA1BeH,MAAAA,KAAAA,U,UA4BOI,I,OAAAA,EAAf,aAA6B/B,EAAgBE,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,MCxHJ,SAASC,EAAaC,GAC3B,OACE,kBAACC,EAAAA,gBAAeA,KACd,kBAACC,EAAAA,OAAMA,CACLhB,GAAI,gBAAgBc,EAAMG,gCAC1BxN,OAAOiE,EAAAA,EAAAA,SAAQoJ,EAAMjN,cAAW1B,EAAY2O,EAAMjN,QAClDqN,SAAWC,GAAoBL,EAAMI,SAASC,EAAgB1N,OAC9DmF,QAASkI,EAAMM,mBACfC,MAAO,KAET,kBAACC,EAAAA,WAAUA,CACTC,cAAa,gBAAgBT,EAAMG,0CACnCO,QAAQ,YACRC,QAAS,IAAMX,EAAMY,iBAAi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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 \"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';\n// eslint-disable-next-line no-restricted-imports\nimport moment from 'moment';\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 let momentTimeUnit = undefined;\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 // create new moment object to not mutate the original grafana object with startOf() to not change\n // the grafana graph at this point as this would change the timeframe for all the following queries\n let queryFrom = moment(range!.from.valueOf());\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 momentTimeUnit = getMomentTimeUnitForQueryInterval(flooringInterval);\n if (momentTimeUnit != null) {\n queryFrom.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 // round down grafana start time to adjust the grafana graph and show first data point\n if (momentTimeUnit != null) {\n range.from.startOf(momentTimeUnit);\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 = {\n 'X-Api-Key': this.apiKey,\n 'X-Api-Client': 'analytics-grafana-datasource',\n };\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, 'X-Api-Client': 'analytics-grafana-datasource' };\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 readonly queryEditorId: string;\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 readonly queryEditorId: string;\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 queryEditorId={props.queryEditorId}\n />\n ))}\n
\n addGroupByInput()}\n size=\"xl\"\n />\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 readonly queryEditorId: string;\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 readonly queryEditorId: string;\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 queryEditorId={props.queryEditorId}\n />\n ))}\n\n
\n addOrderByInput()}\n size=\"xl\"\n />\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\n onChange(queryFilter: QueryFilter): void;\n\n onDelete(): void;\n\n isAdAnalytics: boolean;\n /** Selected query filters are used to filter out used values from attribute select options */\n selectedQueryFilters: QueryFilter[];\n queryEditorId: string;\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 readonly queryEditorId: string;\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 queryEditorId={props.queryEditorId}\n />\n ))}\n\n
\n {hasNewQueryFilter ? (\n setHasNewQueryFilter(false)}\n selectedQueryFilters={props.filters}\n queryEditorId={props.queryEditorId}\n />\n ) : (\n setHasNewQueryFilter(true)}\n size=\"xl\"\n />\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 // set a default value when percentile is selected and delete percentileValue when percentile is deselected\n // to not pollute the dashboard.json file\n let percentile = undefined;\n if (item.value === 'percentile' && percentileValue == null) {\n setPercentileValue(95);\n percentile = 95;\n } else {\n setPercentileValue(undefined);\n }\n\n props.onChange({ ...query, metric: item.value, percentileValue: percentile });\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 id={`query-editor-${props.query.refId}_aggregation-method-select`}\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","momentTimeUnit","enabledQueries","targets","t","hide","promises","isQueryComplete","target","query","from","to","queryFrom","queryTo","flooringInterval","interval1","interval2","indexOf","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","queryEditorId","onChange","selectableValue","selectableGroupBys","width","IconButton","data-testid","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","refId","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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AMzM,KAAWuM,EACpBE,EAAmBjK,KAAK4J,EAAWpM,IAGrC,OAAOyM,CACT,KA1BeH,MAAAA,KAAAA,U,UA4BOI,I,OAAAA,EAAf,aAA6B/B,EAAgBE,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,MC6IEyC,EA9Je,CAC1B,kBACA,sBACA,sBACA,iBACA,cACA,oBACA,QACA,eACA,mBACA,WACA,mBACA,YACA,YACA,qBACA,oBACA,cACA,oBACA,8BACA,mBACA,eACA,gBACA,kBACA,YACA,cACA,gBACA,cACA,aACA,WACA,UACA,uBACA,oBACA,YACA,aACA,gBACA,gBACA,WACA,UACA,iBACA,wBACA,wBACA,eACA,OACA,UACA,mBACA,iBACA,aACA,cACA,SACA,mBACA,iBACA,YACA,8BACA,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,6BACA,SACA,yBACA,QACA,kBACA,gCACA,gCACA,iBACA,iBACA,OACA,yBACA,WACA,SACA,aACA,qBACA,cACA,iBACA,kBACA,aACA,8BACA,aACA,8BACA,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,MClBEC,EA/IY,CACvB,KACA,QACA,WACA,cACA,YACA,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,MC5HJ,SAASC,EAAaC,GAC3B,OACE,kBAACC,EAAAA,gBAAeA,KACd,kBAACC,EAAAA,OAAMA,CACLhB,GAAI,gBAAgBc,EAAMG,gCAC1BxN,OAAOiE,EAAAA,EAAAA,SAAQoJ,EAAMjN,cAAW1B,EAAY2O,EAAMjN,QAClDqN,SAAWC,GAAoBL,EAAMI,SAASC,EAAgB1N,OAC9DmF,QAASkI,EAAMM,m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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 \"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 'AD_TYPE':\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_INDEX':\n case 'AD_TYPE':\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 'AD_INDEX':\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';\n// eslint-disable-next-line no-restricted-imports\nimport moment from 'moment';\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 let momentTimeUnit = undefined;\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 // create new moment object to not mutate the original grafana object with startOf() to not change\n // the grafana graph at this point as this would change the timeframe for all the following queries\n let queryFrom = moment(range!.from.valueOf());\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 momentTimeUnit = getMomentTimeUnitForQueryInterval(flooringInterval);\n if (momentTimeUnit != null) {\n queryFrom.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 // round down grafana start time to adjust the grafana graph and show first data point\n if (momentTimeUnit != null) {\n range.from.startOf(momentTimeUnit);\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 = {\n 'X-Api-Key': this.apiKey,\n 'X-Api-Client': 'analytics-grafana-datasource',\n };\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, 'X-Api-Client': 'analytics-grafana-datasource' };\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_ABANDONMENT_RATE',\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_INDEX',\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_TYPE',\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 'COMPLETED_FAILED_BEACON_URL',\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 'MIDPOINT_FAILED_BEACON_URL',\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 'QUARTILE1_FAILED_BEACON_URL',\n 'QUARTILE_3',\n 'QUARTILE3_FAILED_BEACON_URL',\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 'AD_ID',\n 'AD_INDEX',\n 'AD_POSITION',\n 'AD_SYSTEM',\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 readonly queryEditorId: string;\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 readonly queryEditorId: string;\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 queryEditorId={props.queryEditorId}\n />\n ))}\n
\n addGroupByInput()}\n size=\"xl\"\n />\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 readonly queryEditorId: string;\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 readonly queryEditorId: string;\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 queryEditorId={props.queryEditorId}\n />\n ))}\n\n
\n addOrderByInput()}\n size=\"xl\"\n />\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\n onChange(queryFilter: QueryFilter): void;\n\n onDelete(): void;\n\n isAdAnalytics: boolean;\n /** Selected query filters are used to filter out used values from attribute select options */\n selectedQueryFilters: QueryFilter[];\n queryEditorId: string;\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 readonly queryEditorId: string;\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 queryEditorId={props.queryEditorId}\n />\n ))}\n\n
\n {hasNewQueryFilter ? (\n setHasNewQueryFilter(false)}\n selectedQueryFilters={props.filters}\n queryEditorId={props.queryEditorId}\n />\n ) : (\n setHasNewQueryFilter(true)}\n size=\"xl\"\n />\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 // set a default value when percentile is selected and delete percentileValue when percentile is deselected\n // to not pollute the dashboard.json file\n let percentile = undefined;\n if (item.value === 'percentile' && percentileValue == null) {\n setPercentileValue(95);\n percentile = 95;\n } else {\n setPercentileValue(undefined);\n }\n\n props.onChange({ ...query, metric: item.value, percentileValue: percentile });\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 id={`query-editor-${props.query.refId}_aggregation-method-select`}\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","momentTimeUnit","enabledQueries","targets","t","hide","promises","isQueryComplete","target","query","from","to","queryFrom","queryTo","flooringInterval","interval1","interval2","indexOf","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","queryEditorId","onChange","selectableValue","selectableGroupBys","width","IconButton","data-testid","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","refId","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 739b698..20e11b2 100644 --- a/dist/plugin.json +++ b/dist/plugin.json @@ -26,8 +26,8 @@ } ], "screenshots": [], - "version": "1.2.0", - "updated": "2024-09-04" + "version": "1.3.0", + "updated": "2024-10-02" }, "dependencies": { "grafanaDependency": ">=10.1.0", diff --git a/package.json b/package.json index f88372a..b75a380 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bitmovin-analytics", - "version": "1.2.0", + "version": "1.3.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",