diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js
index c18d456..be066de 100644
--- a/build/webpack.base.conf.js
+++ b/build/webpack.base.conf.js
@@ -9,9 +9,12 @@ function resolve(dir) {
module.exports = {
target: 'node',
context: resolve('src'),
- entry: './module.ts',
+ entry: {
+ './module': './module.ts',
+ './panel/graph_panel/module': './panel/graph_panel/graph_ctrl.ts'
+ },
output: {
- filename: 'module.js',
+ filename: '[name].js',
path: resolve('dist'),
libraryTarget: 'amd'
},
@@ -31,7 +34,8 @@ module.exports = {
new CopyWebpackPlugin([
{ from: 'plugin.json' },
{ from: 'img/*' },
- { from: 'partials/*' }
+ { from: 'panel/graph_panel/plugin.json', to: 'panel/graph_panel/plugin.json' },
+ { from: 'panel/graph_panel/partials/*' }
])
],
resolve: {
diff --git a/src/module.ts b/src/module.ts
index fbe999c..8aa0747 100644
--- a/src/module.ts
+++ b/src/module.ts
@@ -1,647 +1 @@
-import './series_overrides_ctrl';
-
-import template from './template';
-
-import { GraphRenderer } from './graph_renderer';
-import { GraphLegend } from './graph_legend';
-import { DataProcessor } from './data_processor';
-import { MetricExpanded } from './models/metric';
-import { DatasourceRequest } from './models/datasource';
-import { AnalyticUnitId, AnalyticUnit } from './models/analytic_unit';
-import { AnalyticService } from './services/analytic_service';
-import { AnalyticController } from './controllers/analytic_controller';
-import { PanelInfo } from './models/info';
-
-import { axesEditorComponent } from './axes_editor';
-
-import { MetricsPanelCtrl } from 'grafana/app/plugins/sdk';
-import { appEvents } from 'grafana/app/core/core'
-import { BackendSrv } from 'grafana/app/core/services/backend_srv';
-
-
-import _ from 'lodash';
-
-const BACKEND_VARIABLE_NAME = 'HASTIC_SERVER_URL';
-
-
-class GraphCtrl extends MetricsPanelCtrl {
- static template = template;
-
- analyticService: AnalyticService;
- hiddenSeries: any = {};
- seriesList: any = [];
- dataList: any = [];
- // annotations: any = [];
-
- private _datasourceRequest: DatasourceRequest;
- private _datasources: any;
-
- private _panelPath: any;
- private _renderError: boolean = false;
-
- // annotationsPromise: any;
- dataWarning: any;
- colors: any = [];
- subTabIndex: number;
- processor: DataProcessor;
-
- analyticsController: AnalyticController;
-
- _graphRenderer: GraphRenderer;
- _graphLegend: GraphLegend;
-
- _panelInfo: PanelInfo;
-
- private _analyticUnitTypes: any;
-
- panelDefaults = {
- // datasource name, null = default datasource
- datasource: null,
- // sets client side (flot) or native graphite png renderer (png)
- renderer: 'flot',
- yaxes: [
- {
- label: null,
- show: true,
- logBase: 1,
- min: null,
- max: null,
- format: 'short',
- },
- {
- label: null,
- show: true,
- logBase: 1,
- min: null,
- max: null,
- format: 'short',
- },
- ],
- xaxis: {
- show: true,
- mode: 'time',
- name: null,
- values: [],
- buckets: null,
- },
- // show/hide lines
- lines: true,
- // fill factor
- fill: 1,
- // line width in pixels
- linewidth: 1,
- // show/hide dashed line
- dashes: false,
- // length of a dash
- dashLength: 10,
- // length of space between two dashes
- spaceLength: 10,
- // show hide points
- points: false,
- // point radius in pixels
- pointradius: 5,
- // show hide bars
- bars: false,
- // enable/disable stacking
- stack: false,
- // stack percentage mode
- percentage: false,
- // legend options
- legend: {
- show: true, // disable/enable legend
- values: false, // disable/enable legend values
- min: false,
- max: false,
- current: false,
- total: false,
- avg: false,
- },
- // how null points should be handled
- nullPointMode: 'null',
- // staircase line mode
- steppedLine: false,
- // tooltip options
- tooltip: {
- value_type: 'individual',
- shared: true,
- sort: 0,
- },
- // time overrides
- timeFrom: null,
- timeShift: null,
- // metric queries
- targets: [{}],
- // series color overrides
- aliasColors: {},
- // other style overrides
- seriesOverrides: [],
- thresholds: []
- };
-
- /** @ngInject */
- constructor(
- $scope, $injector, $http,
- private annotationsSrv,
- private keybindingSrv,
- private backendSrv: BackendSrv,
- private popoverSrv,
- private contextSrv
-) {
- super($scope, $injector);
-
- _.defaults(this.panel, this.panelDefaults);
- _.defaults(this.panel.tooltip, this.panelDefaults.tooltip);
- _.defaults(this.panel.legend, this.panelDefaults.legend);
- _.defaults(this.panel.xaxis, this.panelDefaults.xaxis);
-
- this.processor = new DataProcessor(this.panel);
-
- this.analyticService = new AnalyticService(this.backendURL, $http);
-
- this.runBackendConnectivityCheck();
-
- this.analyticsController = new AnalyticController(this.panel, this.analyticService, this.events);
-
- this.bindDKey();
-
- this.events.on('render', this.onRender.bind(this));
- this.events.on('data-received', this.onDataReceived.bind(this));
- this.events.on('data-error', this.onDataError.bind(this));
- this.events.on('data-snapshot-load', this.onDataSnapshotLoad.bind(this));
- this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
- this.events.on('init-panel-actions', this.onInitPanelActions.bind(this));
-
- this.events.on('analytic-unit-status-change', async (analyticUnit: AnalyticUnit) => {
- if(analyticUnit === undefined) {
- throw new Error('analyticUnit is undefined');
- }
- if(analyticUnit.status === '404') {
- await this.analyticsController.removeAnalyticUnit(analyticUnit.id, true);
- }
- if(analyticUnit.status === 'READY') {
- await this.analyticsController.fetchSegments(analyticUnit, +this.range.from, +this.range.to);
- }
- this.render(this.seriesList);
- this.$scope.$digest();
- });
-
- this._datasources = {};
-
- appEvents.on('ds-request-response', data => {
- let requestConfig = data.config;
-
- this._datasourceRequest = {
- url: requestConfig.url,
- method: requestConfig.method,
- data: requestConfig.data,
- params: requestConfig.params,
- type: undefined
- };
- });
-
- this.analyticsController.fetchAnalyticUnitsStatuses();
-
- }
-
- bindDKey() {
- this.keybindingSrv.bind('d', this.onDKey.bind(this));
- }
-
- editPanel() {
- super.editPanel();
- this.bindDKey();
- }
-
- get backendURL(): string {
- if(this.templateSrv.index[BACKEND_VARIABLE_NAME] === undefined) {
- return undefined;
- }
- let val = this.templateSrv.index[BACKEND_VARIABLE_NAME].current.value;
- val = val.replace(/\/+$/, "");
- return val;
- }
-
- async updateAnalyticUnitTypes() {
- const analyticUnitTypes = await this.analyticService.getAnalyticUnitTypes();
- this._analyticUnitTypes = analyticUnitTypes;
- }
-
- get analyticUnitTypes() {
- return this._analyticUnitTypes;
- }
-
- get analyticUnitDetectorTypes() {
- return _.keys(this._analyticUnitTypes);
- }
-
- async runBackendConnectivityCheck() {
- if(this.backendURL === '' || this.backendURL === undefined) {
- appEvents.emit(
- 'alert-warning',
- [
- `Dashboard variable $${BACKEND_VARIABLE_NAME} is missing`,
- `Please set $${BACKEND_VARIABLE_NAME}`
- ]
- );
- return;
- }
-
- let connected = await this.analyticService.isBackendOk();
- if(connected) {
- this.updateAnalyticUnitTypes();
- appEvents.emit(
- 'alert-success',
- [
- 'Connected to Hastic server',
- `Hastic server: "${this.backendURL}"`
- ]
- );
- }
- }
-
- link(scope, elem, attrs, ctrl) {
- var $graphElem = $(elem[0]).find('#graphPanel');
- var $legendElem = $(elem[0]).find('#graphLegend');
- this._graphRenderer = new GraphRenderer(
- $graphElem, this.timeSrv, this.popoverSrv, this.contextSrv,this.$scope
- );
- this._graphLegend = new GraphLegend($legendElem, this.popoverSrv, this.$scope);
- }
-
- onInitEditMode() {
- this._updatePanelInfo();
- this.analyticsController.updateServerInfo();
-
- const partialPath = this.panelPath + 'partials';
- this.addEditorTab('Analytics', `${partialPath}/tab_analytics.html`, 2);
- this.addEditorTab('Webhooks', `${partialPath}/tab_webhooks.html`, 3);
- this.addEditorTab('Axes', axesEditorComponent, 4);
- this.addEditorTab('Legend', `${partialPath}/tab_legend.html`, 5);
- this.addEditorTab('Display', `${partialPath}/tab_display.html`, 6);
- this.addEditorTab('Hastic info', `${partialPath}/tab_info.html`, 7);
-
- this.subTabIndex = 0;
- }
-
- onInitPanelActions(actions) {
- actions.push({ text: 'Export CSV', click: 'ctrl.exportCsv()' });
- actions.push({ text: 'Toggle legend', click: 'ctrl.toggleLegend()' });
- }
-
- issueQueries(datasource) {
- // this.annotationsPromise = this.annotationsSrv.getAnnotations({
- // dashboard: this.dashboard,
- // panel: this.panel,
- // range: this.range,
- // });
- return super.issueQueries(datasource);
- }
-
- zoomOut(evt) {
- this.publishAppEvent('zoom-out', 2);
- }
-
- onDataSnapshotLoad(snapshotData) {
- // this.annotationsPromise = this.annotationsSrv.getAnnotations({
- // dashboard: this.dashboard,
- // panel: this.panel,
- // range: this.range,
- // });
- this.onDataReceived(snapshotData);
- }
-
- onDataError(err) {
- this.seriesList = [];
- // this.annotations = [];
- this.render([]);
- }
-
- async onDataReceived(dataList) {
-
- this.dataList = dataList;
- this.seriesList = this.processor.getSeriesList({
- dataList: dataList,
- range: this.range,
- });
-
- this.dataWarning = null;
- const hasSomePoint = this.seriesList.some(s => s.datapoints.length > 0);
-
- if (!hasSomePoint) {
- this.dataWarning = {
- title: 'No data points',
- tip: 'No datapoints returned from data query',
- };
- } else {
- for (let series of this.seriesList) {
- if (series.isOutsideRange) {
- this.dataWarning = {
- title: 'Data points outside time range',
- tip: 'Can be caused by timezone mismatch or missing time filter in query',
- };
- break;
- }
- }
- }
-
- var loadTasks = [
- // this.annotationsPromise,
- this.analyticsController.fetchAnalyticUnitsSegments(+this.range.from, +this.range.to)
- ];
-
- var results = await Promise.all(loadTasks);
- this.loading = false;
- // this.annotations = results[0].annotations;
- this.render(this.seriesList);
-
- }
-
- onRender(data) {
- if (!this.seriesList) {
- return;
- }
-
- for (let series of this.seriesList) {
- if (series.prediction) {
- var overrideItem = _.find(
- this.panel.seriesOverrides,
- el => el.alias === series.alias
- )
- if (overrideItem !== undefined) {
- this.addSeriesOverride({
- alias: series.alias,
- linewidth: 0,
- legend: false,
- // if pointradius === 0 -> point still shows, that's why pointradius === -1
- pointradius: -1,
- fill: 3
- });
- }
- }
- series.applySeriesOverrides(this.panel.seriesOverrides);
-
- if (series.unit) {
- this.panel.yaxes[series.yaxis - 1].format = series.unit;
- }
- }
-
- if(!this.analyticsController.graphLocked) {
- this._graphRenderer.render(data);
- this._graphLegend.render();
- this._graphRenderer.renderPanel();
- }
- }
-
- changeSeriesColor(series, color) {
- series.color = color;
- this.panel.aliasColors[series.alias] = series.color;
- this.render();
- }
-
- toggleSeries(serie, event) {
- if (event.ctrlKey || event.metaKey || event.shiftKey) {
- if (this.hiddenSeries[serie.alias]) {
- delete this.hiddenSeries[serie.alias];
- } else {
- this.hiddenSeries[serie.alias] = true;
- }
- } else {
- this.toggleSeriesExclusiveMode(serie);
- }
- this.render();
- }
-
- toggleSeriesExclusiveMode(serie) {
- var hidden = this.hiddenSeries;
-
- if (hidden[serie.alias]) {
- delete hidden[serie.alias];
- }
-
- // check if every other series is hidden
- var alreadyExclusive = _.every(this.seriesList, value => {
- if (value.alias === serie.alias) {
- return true;
- }
-
- return hidden[value.alias];
- });
-
- if (alreadyExclusive) {
- // remove all hidden series
- _.each(this.seriesList, value => {
- delete this.hiddenSeries[value.alias];
- });
- } else {
- // hide all but this serie
- _.each(this.seriesList, value => {
- if (value.alias === serie.alias) {
- return;
- }
-
- this.hiddenSeries[value.alias] = true;
- });
- }
- }
-
- toggleAxis(info) {
- var override: any = _.find(this.panel.seriesOverrides, { alias: info.alias });
- if (!override) {
- override = { alias: info.alias };
- this.panel.seriesOverrides.push(override);
- }
- info.yaxis = override.yaxis = info.yaxis === 2 ? 1 : 2;
- this.render();
- }
-
- addSeriesOverride(override) {
- this.panel.seriesOverrides.push(override || {});
- }
-
- removeSeriesOverride(override) {
- this.panel.seriesOverrides = _.without(this.panel.seriesOverrides, override);
- this.render();
- }
-
- toggleLegend() {
- this.panel.legend.show = !this.panel.legend.show;
- this.refresh();
- }
-
- legendValuesOptionChanged() {
- var legend = this.panel.legend;
- legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
- this.render();
- }
-
- exportCsv() {
- var scope = this.$scope.$new(true);
- scope.seriesList = this.seriesList;
- this.publishAppEvent('show-modal', {
- templateHtml: '',
- scope,
- modalClass: 'modal--narrow',
- });
- }
-
- // getAnnotationsByTag(tag) {
- // var res = [];
- // for (var annotation of this.annotations) {
- // if (annotation.tags.indexOf(tag) >= 0) {
- // res.push(annotation);
- // }
- // }
- // return res;
- // }
-
- // get annotationTags() {
- // var res = [];
- // for (var annotation of this.annotations) {
- // for (var tag of annotation.tags) {
- // if (res.indexOf(tag) < 0) {
- // res.push(tag);
- // }
- // }
- // }
- // return res;
- // }
-
- get panelPath() {
- if (this._panelPath === undefined) {
- this._panelPath = 'public/plugins/' + this.pluginId + '/';
- }
- return this._panelPath;
- }
-
- createNew() {
- this.analyticsController.createNew();
- }
-
- async saveNew() {
- try {
- const panelId = this.panel.id;
- const panelUrl = window.location.origin + window.location.pathname + `?panelId=${panelId}`;
-
- const datasource = await this._getDatasourceRequest();
-
- await this.analyticsController.saveNew(
- new MetricExpanded(this.panel.datasource, this.panel.targets),
- datasource,
- panelUrl
- );
- } catch(e) {
- appEvents.emit(
- 'alert-error',
- [
- 'Error while saving analytic unit',
- e.message
- ]
- );
- }
- this.$scope.$digest();
- this.render(this.seriesList);
- }
-
- onAnalyticUnitAlertChange(analyticUnit: AnalyticUnit) {
- this.analyticsController.toggleAnalyticUnitAlert(analyticUnit);
- }
-
- onAnalyticUnitNameChange(analyticUnit: AnalyticUnit) {
- this.analyticsController.fetchAnalyticUnitName(analyticUnit);
- }
-
- onColorChange(id: AnalyticUnitId, value: string) {
- if(id === undefined) {
- throw new Error('id is undefined');
- }
- this.analyticsController.onAnalyticUnitColorChange(id, value);
- this.render();
- }
-
- async onRemove(id: AnalyticUnitId) {
- if(id === undefined) {
- throw new Error('id is undefined');
- }
- await this.analyticsController.removeAnalyticUnit(id);
- this.render();
- }
-
- onCancelLabeling(id: AnalyticUnitId) {
- this.$scope.$root.appEvent('confirm-modal', {
- title: 'Clear labeling',
- text2: 'Your changes will be lost.',
- yesText: 'Clear',
- icon: 'fa-warning',
- altActionText: 'Save',
- onAltAction: () => {
- this.onToggleLabelingMode(id);
- },
- onConfirm: () => {
- this.analyticsController.undoLabeling();
- this.render();
- },
- });
- }
-
- async onToggleLabelingMode(id: AnalyticUnitId) {
- this.refresh();
- const datasource = await this._getDatasourceRequest();
- const metric = new MetricExpanded(this.panel.datasource, this.panel.targets);
- await this.analyticsController.toggleUnitTypeLabelingMode(id, metric, datasource);
- this.$scope.$digest();
- this.render();
- }
-
- onDKey() {
- if(!this.analyticsController.labelingMode) {
- return;
- }
- this.analyticsController.toggleDeleteMode();
- this.refresh();
- }
-
- onToggleVisibility(id: AnalyticUnitId) {
- this.analyticsController.toggleVisibility(id);
- this.render();
- }
-
- private async _updatePanelInfo() {
- const datasource = await this._getDatasourceByName(this.panel.datasource);
-
- this._panelInfo = {
- grafanaVersion: this.contextSrv.version,
- grafanaUrl: window.location.host,
- datasourceType: datasource.type,
- hasticServerUrl: this.backendURL
- };
- }
-
- private async _getDatasourceRequest() {
- if(this._datasourceRequest.type === undefined) {
- const datasource = await this._getDatasourceByName(this.panel.datasource);
- this._datasourceRequest.type = datasource.type;
- }
- return this._datasourceRequest;
- }
-
- private async _getDatasourceByName(name: string) {
- if(name === null) {
- throw new Error('Trying to get datasource with NULL name');
- }
- if(this._datasources[name] === undefined) {
- const datasource = await this.backendSrv.get(`/api/datasources/name/${name}`);
- return datasource;
- } else {
- return this._datasources[name];
- }
- }
-
- get panelInfo() {
- return this._panelInfo;
- }
-
- get renderError(): boolean { return this._renderError; }
- set renderError(value: boolean) { this._renderError = value; }
-}
-
-export { GraphCtrl, GraphCtrl as PanelCtrl };
+export { };
diff --git a/src/axes_editor.ts b/src/panel/graph_panel/axes_editor.ts
similarity index 100%
rename from src/axes_editor.ts
rename to src/panel/graph_panel/axes_editor.ts
diff --git a/src/colors.ts b/src/panel/graph_panel/colors.ts
similarity index 100%
rename from src/colors.ts
rename to src/panel/graph_panel/colors.ts
diff --git a/src/controllers/analytic_controller.ts b/src/panel/graph_panel/controllers/analytic_controller.ts
similarity index 100%
rename from src/controllers/analytic_controller.ts
rename to src/panel/graph_panel/controllers/analytic_controller.ts
diff --git a/src/data_processor.ts b/src/panel/graph_panel/data_processor.ts
similarity index 100%
rename from src/data_processor.ts
rename to src/panel/graph_panel/data_processor.ts
diff --git a/src/panel/graph_panel/graph_ctrl.ts b/src/panel/graph_panel/graph_ctrl.ts
new file mode 100644
index 0000000..f7a08cf
--- /dev/null
+++ b/src/panel/graph_panel/graph_ctrl.ts
@@ -0,0 +1,647 @@
+import './series_overrides_ctrl';
+
+import template from './template';
+
+import { GraphRenderer } from './graph_renderer';
+import { GraphLegend } from './graph_legend';
+import { DataProcessor } from './data_processor';
+import { MetricExpanded } from './models/metric';
+import { DatasourceRequest } from './models/datasource';
+import { AnalyticUnitId, AnalyticUnit } from './models/analytic_unit';
+import { AnalyticService } from './services/analytic_service';
+import { AnalyticController } from './controllers/analytic_controller';
+import { PanelInfo } from './models/info';
+
+import { axesEditorComponent } from './axes_editor';
+
+import { MetricsPanelCtrl } from 'grafana/app/plugins/sdk';
+import { appEvents } from 'grafana/app/core/core'
+import { BackendSrv } from 'grafana/app/core/services/backend_srv';
+
+
+import _ from 'lodash';
+
+const BACKEND_VARIABLE_NAME = 'HASTIC_SERVER_URL';
+
+
+class GraphCtrl extends MetricsPanelCtrl {
+ static template = template;
+
+ analyticService: AnalyticService;
+ hiddenSeries: any = {};
+ seriesList: any = [];
+ dataList: any = [];
+ // annotations: any = [];
+
+ private _datasourceRequest: DatasourceRequest;
+ private _datasources: any;
+
+ private _panelPath: any;
+ private _renderError: boolean = false;
+
+ // annotationsPromise: any;
+ dataWarning: any;
+ colors: any = [];
+ subTabIndex: number;
+ processor: DataProcessor;
+
+ analyticsController: AnalyticController;
+
+ _graphRenderer: GraphRenderer;
+ _graphLegend: GraphLegend;
+
+ _panelInfo: PanelInfo;
+
+ private _analyticUnitTypes: any;
+
+ panelDefaults = {
+ // datasource name, null = default datasource
+ datasource: null,
+ // sets client side (flot) or native graphite png renderer (png)
+ renderer: 'flot',
+ yaxes: [
+ {
+ label: null,
+ show: true,
+ logBase: 1,
+ min: null,
+ max: null,
+ format: 'short',
+ },
+ {
+ label: null,
+ show: true,
+ logBase: 1,
+ min: null,
+ max: null,
+ format: 'short',
+ },
+ ],
+ xaxis: {
+ show: true,
+ mode: 'time',
+ name: null,
+ values: [],
+ buckets: null,
+ },
+ // show/hide lines
+ lines: true,
+ // fill factor
+ fill: 1,
+ // line width in pixels
+ linewidth: 1,
+ // show/hide dashed line
+ dashes: false,
+ // length of a dash
+ dashLength: 10,
+ // length of space between two dashes
+ spaceLength: 10,
+ // show hide points
+ points: false,
+ // point radius in pixels
+ pointradius: 5,
+ // show hide bars
+ bars: false,
+ // enable/disable stacking
+ stack: false,
+ // stack percentage mode
+ percentage: false,
+ // legend options
+ legend: {
+ show: true, // disable/enable legend
+ values: false, // disable/enable legend values
+ min: false,
+ max: false,
+ current: false,
+ total: false,
+ avg: false,
+ },
+ // how null points should be handled
+ nullPointMode: 'null',
+ // staircase line mode
+ steppedLine: false,
+ // tooltip options
+ tooltip: {
+ value_type: 'individual',
+ shared: true,
+ sort: 0,
+ },
+ // time overrides
+ timeFrom: null,
+ timeShift: null,
+ // metric queries
+ targets: [{}],
+ // series color overrides
+ aliasColors: {},
+ // other style overrides
+ seriesOverrides: [],
+ thresholds: []
+ };
+
+ /** @ngInject */
+ constructor(
+ $scope, $injector, $http,
+ private annotationsSrv,
+ private keybindingSrv,
+ private backendSrv: BackendSrv,
+ private popoverSrv,
+ private contextSrv
+) {
+ super($scope, $injector);
+
+ _.defaults(this.panel, this.panelDefaults);
+ _.defaults(this.panel.tooltip, this.panelDefaults.tooltip);
+ _.defaults(this.panel.legend, this.panelDefaults.legend);
+ _.defaults(this.panel.xaxis, this.panelDefaults.xaxis);
+
+ this.processor = new DataProcessor(this.panel);
+
+ this.analyticService = new AnalyticService(this.backendURL, $http);
+
+ this.runBackendConnectivityCheck();
+
+ this.analyticsController = new AnalyticController(this.panel, this.analyticService, this.events);
+
+ this.bindDKey();
+
+ this.events.on('render', this.onRender.bind(this));
+ this.events.on('data-received', this.onDataReceived.bind(this));
+ this.events.on('data-error', this.onDataError.bind(this));
+ this.events.on('data-snapshot-load', this.onDataSnapshotLoad.bind(this));
+ this.events.on('init-edit-mode', this.onInitEditMode.bind(this));
+ this.events.on('init-panel-actions', this.onInitPanelActions.bind(this));
+
+ this.events.on('analytic-unit-status-change', async (analyticUnit: AnalyticUnit) => {
+ if(analyticUnit === undefined) {
+ throw new Error('analyticUnit is undefined');
+ }
+ if(analyticUnit.status === '404') {
+ await this.analyticsController.removeAnalyticUnit(analyticUnit.id, true);
+ }
+ if(analyticUnit.status === 'READY') {
+ await this.analyticsController.fetchSegments(analyticUnit, +this.range.from, +this.range.to);
+ }
+ this.render(this.seriesList);
+ this.$scope.$digest();
+ });
+
+ this._datasources = {};
+
+ appEvents.on('ds-request-response', data => {
+ let requestConfig = data.config;
+
+ this._datasourceRequest = {
+ url: requestConfig.url,
+ method: requestConfig.method,
+ data: requestConfig.data,
+ params: requestConfig.params,
+ type: undefined
+ };
+ });
+
+ this.analyticsController.fetchAnalyticUnitsStatuses();
+
+ }
+
+ bindDKey() {
+ this.keybindingSrv.bind('d', this.onDKey.bind(this));
+ }
+
+ editPanel() {
+ super.editPanel();
+ this.bindDKey();
+ }
+
+ get backendURL(): string {
+ if(this.templateSrv.index[BACKEND_VARIABLE_NAME] === undefined) {
+ return undefined;
+ }
+ let val = this.templateSrv.index[BACKEND_VARIABLE_NAME].current.value;
+ val = val.replace(/\/+$/, "");
+ return val;
+ }
+
+ async updateAnalyticUnitTypes() {
+ const analyticUnitTypes = await this.analyticService.getAnalyticUnitTypes();
+ this._analyticUnitTypes = analyticUnitTypes;
+ }
+
+ get analyticUnitTypes() {
+ return this._analyticUnitTypes;
+ }
+
+ get analyticUnitDetectorTypes() {
+ return _.keys(this._analyticUnitTypes);
+ }
+
+ async runBackendConnectivityCheck() {
+ if(this.backendURL === '' || this.backendURL === undefined) {
+ appEvents.emit(
+ 'alert-warning',
+ [
+ `Dashboard variable $${BACKEND_VARIABLE_NAME} is missing`,
+ `Please set $${BACKEND_VARIABLE_NAME}`
+ ]
+ );
+ return;
+ }
+
+ let connected = await this.analyticService.isBackendOk();
+ if(connected) {
+ this.updateAnalyticUnitTypes();
+ appEvents.emit(
+ 'alert-success',
+ [
+ 'Connected to Hastic server',
+ `Hastic server: "${this.backendURL}"`
+ ]
+ );
+ }
+ }
+
+ link(scope, elem, attrs, ctrl) {
+ var $graphElem = $(elem[0]).find('#graphPanel');
+ var $legendElem = $(elem[0]).find('#graphLegend');
+ this._graphRenderer = new GraphRenderer(
+ $graphElem, this.timeSrv, this.popoverSrv, this.contextSrv,this.$scope
+ );
+ this._graphLegend = new GraphLegend($legendElem, this.popoverSrv, this.$scope);
+ }
+
+ onInitEditMode() {
+ this._updatePanelInfo();
+ this.analyticsController.updateServerInfo();
+
+ const partialPath = this.panelPath + 'partials/graph_panel';
+ this.addEditorTab('Analytics', `${partialPath}/tab_analytics.html`, 2);
+ this.addEditorTab('Webhooks', `${partialPath}/tab_webhooks.html`, 3);
+ this.addEditorTab('Axes', axesEditorComponent, 4);
+ this.addEditorTab('Legend', `${partialPath}/tab_legend.html`, 5);
+ this.addEditorTab('Display', `${partialPath}/tab_display.html`, 6);
+ this.addEditorTab('Hastic info', `${partialPath}/tab_info.html`, 7);
+
+ this.subTabIndex = 0;
+ }
+
+ onInitPanelActions(actions) {
+ actions.push({ text: 'Export CSV', click: 'ctrl.exportCsv()' });
+ actions.push({ text: 'Toggle legend', click: 'ctrl.toggleLegend()' });
+ }
+
+ issueQueries(datasource) {
+ // this.annotationsPromise = this.annotationsSrv.getAnnotations({
+ // dashboard: this.dashboard,
+ // panel: this.panel,
+ // range: this.range,
+ // });
+ return super.issueQueries(datasource);
+ }
+
+ zoomOut(evt) {
+ this.publishAppEvent('zoom-out', 2);
+ }
+
+ onDataSnapshotLoad(snapshotData) {
+ // this.annotationsPromise = this.annotationsSrv.getAnnotations({
+ // dashboard: this.dashboard,
+ // panel: this.panel,
+ // range: this.range,
+ // });
+ this.onDataReceived(snapshotData);
+ }
+
+ onDataError(err) {
+ this.seriesList = [];
+ // this.annotations = [];
+ this.render([]);
+ }
+
+ async onDataReceived(dataList) {
+
+ this.dataList = dataList;
+ this.seriesList = this.processor.getSeriesList({
+ dataList: dataList,
+ range: this.range,
+ });
+
+ this.dataWarning = null;
+ const hasSomePoint = this.seriesList.some(s => s.datapoints.length > 0);
+
+ if (!hasSomePoint) {
+ this.dataWarning = {
+ title: 'No data points',
+ tip: 'No datapoints returned from data query',
+ };
+ } else {
+ for (let series of this.seriesList) {
+ if (series.isOutsideRange) {
+ this.dataWarning = {
+ title: 'Data points outside time range',
+ tip: 'Can be caused by timezone mismatch or missing time filter in query',
+ };
+ break;
+ }
+ }
+ }
+
+ var loadTasks = [
+ // this.annotationsPromise,
+ this.analyticsController.fetchAnalyticUnitsSegments(+this.range.from, +this.range.to)
+ ];
+
+ var results = await Promise.all(loadTasks);
+ this.loading = false;
+ // this.annotations = results[0].annotations;
+ this.render(this.seriesList);
+
+ }
+
+ onRender(data) {
+ if (!this.seriesList) {
+ return;
+ }
+
+ for (let series of this.seriesList) {
+ if (series.prediction) {
+ var overrideItem = _.find(
+ this.panel.seriesOverrides,
+ el => el.alias === series.alias
+ )
+ if (overrideItem !== undefined) {
+ this.addSeriesOverride({
+ alias: series.alias,
+ linewidth: 0,
+ legend: false,
+ // if pointradius === 0 -> point still shows, that's why pointradius === -1
+ pointradius: -1,
+ fill: 3
+ });
+ }
+ }
+ series.applySeriesOverrides(this.panel.seriesOverrides);
+
+ if (series.unit) {
+ this.panel.yaxes[series.yaxis - 1].format = series.unit;
+ }
+ }
+
+ if(!this.analyticsController.graphLocked) {
+ this._graphRenderer.render(data);
+ this._graphLegend.render();
+ this._graphRenderer.renderPanel();
+ }
+ }
+
+ changeSeriesColor(series, color) {
+ series.color = color;
+ this.panel.aliasColors[series.alias] = series.color;
+ this.render();
+ }
+
+ toggleSeries(serie, event) {
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
+ if (this.hiddenSeries[serie.alias]) {
+ delete this.hiddenSeries[serie.alias];
+ } else {
+ this.hiddenSeries[serie.alias] = true;
+ }
+ } else {
+ this.toggleSeriesExclusiveMode(serie);
+ }
+ this.render();
+ }
+
+ toggleSeriesExclusiveMode(serie) {
+ var hidden = this.hiddenSeries;
+
+ if (hidden[serie.alias]) {
+ delete hidden[serie.alias];
+ }
+
+ // check if every other series is hidden
+ var alreadyExclusive = _.every(this.seriesList, value => {
+ if (value.alias === serie.alias) {
+ return true;
+ }
+
+ return hidden[value.alias];
+ });
+
+ if (alreadyExclusive) {
+ // remove all hidden series
+ _.each(this.seriesList, value => {
+ delete this.hiddenSeries[value.alias];
+ });
+ } else {
+ // hide all but this serie
+ _.each(this.seriesList, value => {
+ if (value.alias === serie.alias) {
+ return;
+ }
+
+ this.hiddenSeries[value.alias] = true;
+ });
+ }
+ }
+
+ toggleAxis(info) {
+ var override: any = _.find(this.panel.seriesOverrides, { alias: info.alias });
+ if (!override) {
+ override = { alias: info.alias };
+ this.panel.seriesOverrides.push(override);
+ }
+ info.yaxis = override.yaxis = info.yaxis === 2 ? 1 : 2;
+ this.render();
+ }
+
+ addSeriesOverride(override) {
+ this.panel.seriesOverrides.push(override || {});
+ }
+
+ removeSeriesOverride(override) {
+ this.panel.seriesOverrides = _.without(this.panel.seriesOverrides, override);
+ this.render();
+ }
+
+ toggleLegend() {
+ this.panel.legend.show = !this.panel.legend.show;
+ this.refresh();
+ }
+
+ legendValuesOptionChanged() {
+ var legend = this.panel.legend;
+ legend.values = legend.min || legend.max || legend.avg || legend.current || legend.total;
+ this.render();
+ }
+
+ exportCsv() {
+ var scope = this.$scope.$new(true);
+ scope.seriesList = this.seriesList;
+ this.publishAppEvent('show-modal', {
+ templateHtml: '',
+ scope,
+ modalClass: 'modal--narrow',
+ });
+ }
+
+ // getAnnotationsByTag(tag) {
+ // var res = [];
+ // for (var annotation of this.annotations) {
+ // if (annotation.tags.indexOf(tag) >= 0) {
+ // res.push(annotation);
+ // }
+ // }
+ // return res;
+ // }
+
+ // get annotationTags() {
+ // var res = [];
+ // for (var annotation of this.annotations) {
+ // for (var tag of annotation.tags) {
+ // if (res.indexOf(tag) < 0) {
+ // res.push(tag);
+ // }
+ // }
+ // }
+ // return res;
+ // }
+
+ get panelPath() {
+ if (this._panelPath === undefined) {
+ this._panelPath = 'public/plugins/' + this.pluginId + '/';
+ }
+ return this._panelPath;
+ }
+
+ createNew() {
+ this.analyticsController.createNew();
+ }
+
+ async saveNew() {
+ try {
+ const panelId = this.panel.id;
+ const panelUrl = window.location.origin + window.location.pathname + `?panelId=${panelId}`;
+
+ const datasource = await this._getDatasourceRequest();
+
+ await this.analyticsController.saveNew(
+ new MetricExpanded(this.panel.datasource, this.panel.targets),
+ datasource,
+ panelUrl
+ );
+ } catch(e) {
+ appEvents.emit(
+ 'alert-error',
+ [
+ 'Error while saving analytic unit',
+ e.message
+ ]
+ );
+ }
+ this.$scope.$digest();
+ this.render(this.seriesList);
+ }
+
+ onAnalyticUnitAlertChange(analyticUnit: AnalyticUnit) {
+ this.analyticsController.toggleAnalyticUnitAlert(analyticUnit);
+ }
+
+ onAnalyticUnitNameChange(analyticUnit: AnalyticUnit) {
+ this.analyticsController.fetchAnalyticUnitName(analyticUnit);
+ }
+
+ onColorChange(id: AnalyticUnitId, value: string) {
+ if(id === undefined) {
+ throw new Error('id is undefined');
+ }
+ this.analyticsController.onAnalyticUnitColorChange(id, value);
+ this.render();
+ }
+
+ async onRemove(id: AnalyticUnitId) {
+ if(id === undefined) {
+ throw new Error('id is undefined');
+ }
+ await this.analyticsController.removeAnalyticUnit(id);
+ this.render();
+ }
+
+ onCancelLabeling(id: AnalyticUnitId) {
+ this.$scope.$root.appEvent('confirm-modal', {
+ title: 'Clear labeling',
+ text2: 'Your changes will be lost.',
+ yesText: 'Clear',
+ icon: 'fa-warning',
+ altActionText: 'Save',
+ onAltAction: () => {
+ this.onToggleLabelingMode(id);
+ },
+ onConfirm: () => {
+ this.analyticsController.undoLabeling();
+ this.render();
+ },
+ });
+ }
+
+ async onToggleLabelingMode(id: AnalyticUnitId) {
+ this.refresh();
+ const datasource = await this._getDatasourceRequest();
+ const metric = new MetricExpanded(this.panel.datasource, this.panel.targets);
+ await this.analyticsController.toggleUnitTypeLabelingMode(id, metric, datasource);
+ this.$scope.$digest();
+ this.render();
+ }
+
+ onDKey() {
+ if(!this.analyticsController.labelingMode) {
+ return;
+ }
+ this.analyticsController.toggleDeleteMode();
+ this.refresh();
+ }
+
+ onToggleVisibility(id: AnalyticUnitId) {
+ this.analyticsController.toggleVisibility(id);
+ this.render();
+ }
+
+ private async _updatePanelInfo() {
+ const datasource = await this._getDatasourceByName(this.panel.datasource);
+
+ this._panelInfo = {
+ grafanaVersion: this.contextSrv.version,
+ grafanaUrl: window.location.host,
+ datasourceType: datasource.type,
+ hasticServerUrl: this.backendURL
+ };
+ }
+
+ private async _getDatasourceRequest() {
+ if(this._datasourceRequest.type === undefined) {
+ const datasource = await this._getDatasourceByName(this.panel.datasource);
+ this._datasourceRequest.type = datasource.type;
+ }
+ return this._datasourceRequest;
+ }
+
+ private async _getDatasourceByName(name: string) {
+ if(name === null) {
+ throw new Error('Trying to get datasource with NULL name');
+ }
+ if(this._datasources[name] === undefined) {
+ const datasource = await this.backendSrv.get(`/api/datasources/name/${name}`);
+ return datasource;
+ } else {
+ return this._datasources[name];
+ }
+ }
+
+ get panelInfo() {
+ return this._panelInfo;
+ }
+
+ get renderError(): boolean { return this._renderError; }
+ set renderError(value: boolean) { this._renderError = value; }
+}
+
+export { GraphCtrl, GraphCtrl as PanelCtrl };
diff --git a/src/graph_legend.ts b/src/panel/graph_panel/graph_legend.ts
similarity index 100%
rename from src/graph_legend.ts
rename to src/panel/graph_panel/graph_legend.ts
diff --git a/src/graph_renderer.ts b/src/panel/graph_panel/graph_renderer.ts
similarity index 99%
rename from src/graph_renderer.ts
rename to src/panel/graph_panel/graph_renderer.ts
index 7688d20..2ea3b10 100644
--- a/src/graph_renderer.ts
+++ b/src/panel/graph_panel/graph_renderer.ts
@@ -10,7 +10,7 @@ import {
REGION_DELETE_COLOR_DARK
} from './controllers/analytic_controller';
-import { GraphCtrl } from './module';
+import { GraphCtrl } from './graph_ctrl';
import 'jquery';
import './vendor/flot/jquery.flot.js';
diff --git a/src/graph_tooltip.ts b/src/panel/graph_panel/graph_tooltip.ts
similarity index 99%
rename from src/graph_tooltip.ts
rename to src/panel/graph_panel/graph_tooltip.ts
index 96441b1..ae5028e 100644
--- a/src/graph_tooltip.ts
+++ b/src/panel/graph_panel/graph_tooltip.ts
@@ -1,4 +1,4 @@
-import { AnalyticSegmentsSearcher } from 'models/analytic_unit';
+import { AnalyticSegmentsSearcher } from './models/analytic_unit';
export class GraphTooltip {
diff --git a/src/histogram.ts b/src/panel/graph_panel/histogram.ts
similarity index 100%
rename from src/histogram.ts
rename to src/panel/graph_panel/histogram.ts
diff --git a/src/models/analytic_unit.ts b/src/panel/graph_panel/models/analytic_unit.ts
similarity index 100%
rename from src/models/analytic_unit.ts
rename to src/panel/graph_panel/models/analytic_unit.ts
diff --git a/src/models/datasource.ts b/src/panel/graph_panel/models/datasource.ts
similarity index 100%
rename from src/models/datasource.ts
rename to src/panel/graph_panel/models/datasource.ts
diff --git a/src/models/info.ts b/src/panel/graph_panel/models/info.ts
similarity index 100%
rename from src/models/info.ts
rename to src/panel/graph_panel/models/info.ts
diff --git a/src/models/metric.ts b/src/panel/graph_panel/models/metric.ts
similarity index 100%
rename from src/models/metric.ts
rename to src/panel/graph_panel/models/metric.ts
diff --git a/src/models/segment.ts b/src/panel/graph_panel/models/segment.ts
similarity index 100%
rename from src/models/segment.ts
rename to src/panel/graph_panel/models/segment.ts
diff --git a/src/models/segment_array.ts b/src/panel/graph_panel/models/segment_array.ts
similarity index 100%
rename from src/models/segment_array.ts
rename to src/panel/graph_panel/models/segment_array.ts
diff --git a/src/models/segment_set.ts b/src/panel/graph_panel/models/segment_set.ts
similarity index 100%
rename from src/models/segment_set.ts
rename to src/panel/graph_panel/models/segment_set.ts
diff --git a/src/models/threshold.ts b/src/panel/graph_panel/models/threshold.ts
similarity index 100%
rename from src/models/threshold.ts
rename to src/panel/graph_panel/models/threshold.ts
diff --git a/src/partials/axes_editor.html b/src/panel/graph_panel/partials/axes_editor.html
similarity index 100%
rename from src/partials/axes_editor.html
rename to src/panel/graph_panel/partials/axes_editor.html
diff --git a/src/partials/tab_analytics.html b/src/panel/graph_panel/partials/tab_analytics.html
similarity index 100%
rename from src/partials/tab_analytics.html
rename to src/panel/graph_panel/partials/tab_analytics.html
diff --git a/src/partials/tab_display.html b/src/panel/graph_panel/partials/tab_display.html
similarity index 100%
rename from src/partials/tab_display.html
rename to src/panel/graph_panel/partials/tab_display.html
diff --git a/src/partials/tab_info.html b/src/panel/graph_panel/partials/tab_info.html
similarity index 100%
rename from src/partials/tab_info.html
rename to src/panel/graph_panel/partials/tab_info.html
diff --git a/src/partials/tab_legend.html b/src/panel/graph_panel/partials/tab_legend.html
similarity index 100%
rename from src/partials/tab_legend.html
rename to src/panel/graph_panel/partials/tab_legend.html
diff --git a/src/partials/tab_webhooks.html b/src/panel/graph_panel/partials/tab_webhooks.html
similarity index 100%
rename from src/partials/tab_webhooks.html
rename to src/panel/graph_panel/partials/tab_webhooks.html
diff --git a/src/panel/graph_panel/plugin.json b/src/panel/graph_panel/plugin.json
new file mode 100644
index 0000000..ef0e63b
--- /dev/null
+++ b/src/panel/graph_panel/plugin.json
@@ -0,0 +1,11 @@
+{
+ "type": "panel",
+ "name": "Hastic Graph",
+ "id": "hastic-graph-panel",
+ "info": {
+ "logos": {
+ "small": "../hastic-app/img/icn-graph-panel.png",
+ "large": "../hastic-app/img/icn-graph-panel.png"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/series_overrides_ctrl.ts b/src/panel/graph_panel/series_overrides_ctrl.ts
similarity index 100%
rename from src/series_overrides_ctrl.ts
rename to src/panel/graph_panel/series_overrides_ctrl.ts
diff --git a/src/services/analytic_service.ts b/src/panel/graph_panel/services/analytic_service.ts
similarity index 100%
rename from src/services/analytic_service.ts
rename to src/panel/graph_panel/services/analytic_service.ts
diff --git a/src/template.ts b/src/panel/graph_panel/template.ts
similarity index 100%
rename from src/template.ts
rename to src/panel/graph_panel/template.ts
diff --git a/src/vendor/flot/jquery.flot.crosshair.js b/src/panel/graph_panel/vendor/flot/jquery.flot.crosshair.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.crosshair.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.crosshair.js
diff --git a/src/vendor/flot/jquery.flot.dashes.js b/src/panel/graph_panel/vendor/flot/jquery.flot.dashes.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.dashes.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.dashes.js
diff --git a/src/vendor/flot/jquery.flot.events.js b/src/panel/graph_panel/vendor/flot/jquery.flot.events.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.events.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.events.js
diff --git a/src/vendor/flot/jquery.flot.fillbelow.js b/src/panel/graph_panel/vendor/flot/jquery.flot.fillbelow.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.fillbelow.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.fillbelow.js
diff --git a/src/vendor/flot/jquery.flot.fillbetween.js b/src/panel/graph_panel/vendor/flot/jquery.flot.fillbetween.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.fillbetween.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.fillbetween.js
diff --git a/src/vendor/flot/jquery.flot.js b/src/panel/graph_panel/vendor/flot/jquery.flot.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.js
diff --git a/src/vendor/flot/jquery.flot.selection.js b/src/panel/graph_panel/vendor/flot/jquery.flot.selection.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.selection.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.selection.js
diff --git a/src/vendor/flot/jquery.flot.stack.js b/src/panel/graph_panel/vendor/flot/jquery.flot.stack.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.stack.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.stack.js
diff --git a/src/vendor/flot/jquery.flot.stackpercent.js b/src/panel/graph_panel/vendor/flot/jquery.flot.stackpercent.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.stackpercent.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.stackpercent.js
diff --git a/src/vendor/flot/jquery.flot.time.js b/src/panel/graph_panel/vendor/flot/jquery.flot.time.js
similarity index 100%
rename from src/vendor/flot/jquery.flot.time.js
rename to src/panel/graph_panel/vendor/flot/jquery.flot.time.js
diff --git a/src/vendor/grafana/colors.ts b/src/panel/graph_panel/vendor/grafana/colors.ts
similarity index 100%
rename from src/vendor/grafana/colors.ts
rename to src/panel/graph_panel/vendor/grafana/colors.ts
diff --git a/src/vendor/grafana/event.ts b/src/panel/graph_panel/vendor/grafana/event.ts
similarity index 100%
rename from src/vendor/grafana/event.ts
rename to src/panel/graph_panel/vendor/grafana/event.ts
diff --git a/src/vendor/grafana/event_manager.ts b/src/panel/graph_panel/vendor/grafana/event_manager.ts
similarity index 100%
rename from src/vendor/grafana/event_manager.ts
rename to src/panel/graph_panel/vendor/grafana/event_manager.ts
diff --git a/src/vendor/grafana/ticks.ts b/src/panel/graph_panel/vendor/grafana/ticks.ts
similarity index 100%
rename from src/vendor/grafana/ticks.ts
rename to src/panel/graph_panel/vendor/grafana/ticks.ts
diff --git a/src/vendor/grafana/time_series2.ts b/src/panel/graph_panel/vendor/grafana/time_series2.ts
similarity index 100%
rename from src/vendor/grafana/time_series2.ts
rename to src/panel/graph_panel/vendor/grafana/time_series2.ts
diff --git a/src/plugin.json b/src/plugin.json
index 394bca9..605852d 100644
--- a/src/plugin.json
+++ b/src/plugin.json
@@ -1,12 +1,12 @@
{
- "type": "panel",
- "name": "Hastic Graph",
- "id": "hastic-graph-panel",
+ "type": "app",
+ "name": "Hastic",
+ "id": "hastic-app",
"info": {
"author": {
- "name": "Hastic.Core Team",
- "url": "https://github.com/hastic/hastic-grafana-graph-panel"
+ "name": "CorpGlory Inc.",
+ "url": "https://github.com/hastic/hastic-grafana-app"
},
"logos": {
"small": "img/icn-graph-panel.png",
@@ -14,9 +14,11 @@
},
"version": "0.2.7"
},
-
+ "includes": [
+ {"type": "panel", "name": "Hastic Graph Panel"}
+ ],
"dependencies": {
- "grafanaVersion": "5.1.x"
+ "grafanaVersion": "5.4.x"
}
}
diff --git a/tests/analytic_controller.jest.ts b/tests/analytic_controller.jest.ts
index 07b7d64..c345acd 100644
--- a/tests/analytic_controller.jest.ts
+++ b/tests/analytic_controller.jest.ts
@@ -1,6 +1,6 @@
-import { ANALYTIC_UNIT_COLORS } from '../src/colors';
-import { MetricExpanded } from '../src/models/metric';
-import { DatasourceRequest } from '../src/models/datasource';
+import { ANALYTIC_UNIT_COLORS } from '../src/panel/graph_panel/colors';
+import { MetricExpanded } from '../src/panel/graph_panel/models/metric';
+import { DatasourceRequest } from '../src/panel/graph_panel/models/datasource';
import { analyticController } from './setup_tests';
diff --git a/tests/setup_tests.ts b/tests/setup_tests.ts
index 02fb8fc..0d55b96 100644
--- a/tests/setup_tests.ts
+++ b/tests/setup_tests.ts
@@ -1,8 +1,8 @@
-import { AnalyticController } from '../src/controllers/analytic_controller';
-import { AnalyticUnit, AnalyticUnitId } from '../src/models/analytic_unit';
-import { AnalyticService } from '../src/services/analytic_service';
-import { MetricExpanded } from '../src/models/metric';
-import { DatasourceRequest } from '../src/models/datasource';
+import { AnalyticController } from '../src/panel/graph_panel/controllers/analytic_controller';
+import { AnalyticUnit, AnalyticUnitId } from '../src/panel/graph_panel/models/analytic_unit';
+import { AnalyticService } from '../src/panel/graph_panel/services/analytic_service';
+import { MetricExpanded } from '../src/panel/graph_panel/models/metric';
+import { DatasourceRequest } from '../src/panel/graph_panel/models/datasource';
import { Emitter } from 'grafana/app/core/utils/emitter';