diff --git a/public/app/core/utils/file_export.ts b/public/app/core/utils/file_export.ts
index ad203f58495..944b6ae8a80 100644
--- a/public/app/core/utils/file_export.ts
+++ b/public/app/core/utils/file_export.ts
@@ -14,6 +14,41 @@ export function exportSeriesListToCsv(seriesList) {
saveSaveBlob(text, 'grafana_data_export.csv');
};
+export function exportSeriesListToCsvColumns(seriesList) {
+ var text = 'Time;';
+ // add header
+ _.each(seriesList, function(series) {
+ text += series.alias + ';';
+ });
+ text = text.substring(0,text.length-1);
+ text += '\n';
+
+ // process data
+ var dataArr = [[]];
+ var sIndex = 1;
+ _.each(seriesList, function(series) {
+ var cIndex = 0;
+ dataArr.push([]);
+ _.each(series.datapoints, function(dp) {
+ dataArr[0][cIndex] = new Date(dp[1]).toISOString();
+ dataArr[sIndex][cIndex] = dp[0];
+ cIndex++;
+ });
+ sIndex++;
+ });
+
+ // make text
+ for (var i = 0; i < dataArr[0].length; i++) {
+ text += dataArr[0][i] + ';';
+ for (var j = 1; j < dataArr.length; j++) {
+ text += dataArr[j][i] + ';';
+ }
+ text = text.substring(0,text.length-1);
+ text += '\n';
+ }
+ saveSaveBlob(text, 'grafana_data_export.csv');
+};
+
export function exportTableDataToCsv(table) {
var text = '';
// add header
diff --git a/public/app/features/dashboard/all.js b/public/app/features/dashboard/all.js
index 073ca2ae1d9..d5cc13b4270 100644
--- a/public/app/features/dashboard/all.js
+++ b/public/app/features/dashboard/all.js
@@ -16,4 +16,5 @@ define([
'./graphiteImportCtrl',
'./dynamicDashboardSrv',
'./importCtrl',
+ './impressionStore',
], function () {});
diff --git a/public/app/features/dashboard/dashboardLoaderSrv.js b/public/app/features/dashboard/dashboardLoaderSrv.js
index f578a9d1075..f975c47800f 100644
--- a/public/app/features/dashboard/dashboardLoaderSrv.js
+++ b/public/app/features/dashboard/dashboardLoaderSrv.js
@@ -5,8 +5,9 @@ define([
'jquery',
'app/core/utils/kbn',
'app/core/utils/datemath',
+ './impressionStore',
],
-function (angular, moment, _, $, kbn, dateMath) {
+function (angular, moment, _, $, kbn, dateMath, impressionStore) {
'use strict';
var module = angular.module('grafana.services');
@@ -24,19 +25,27 @@ function (angular, moment, _, $, kbn, dateMath) {
};
this.loadDashboard = function(type, slug) {
- if (type === 'script') {
- return this._loadScriptedDashboard(slug);
- }
+ var promise;
- if (type === 'snapshot') {
- return backendSrv.get('/api/snapshots/' + $routeParams.slug).catch(function() {
+ if (type === 'script') {
+ promise = this._loadScriptedDashboard(slug);
+ } else if (type === 'snapshot') {
+ promise = backendSrv.get('/api/snapshots/' + $routeParams.slug).catch(function() {
return {meta:{isSnapshot: true, canSave: false, canEdit: false}, dashboard: {title: 'Snapshot not found'}};
});
+ } else {
+ promise = backendSrv.getDashboard($routeParams.type, $routeParams.slug)
+ .catch(function() {
+ return self._dashboardLoadFailed("Not found");
+ });
}
- return backendSrv.getDashboard($routeParams.type, $routeParams.slug).catch(function() {
- return self._dashboardLoadFailed("Not found");
+ promise.then(function(result) {
+ impressionStore.impressions.addDashboardImpression(slug);
+ return result;
});
+
+ return promise;
};
this._loadScriptedDashboard = function(file) {
diff --git a/public/app/features/dashboard/impressionStore.ts b/public/app/features/dashboard/impressionStore.ts
new file mode 100644
index 00000000000..61be1131cb6
--- /dev/null
+++ b/public/app/features/dashboard/impressionStore.ts
@@ -0,0 +1,41 @@
+///
+
+import store from 'app/core/store';
+import _ from 'lodash';
+
+export class ImpressionsStore {
+ constructor() {}
+
+ addDashboardImpression(slug) {
+ var impressions = [];
+ if (store.exists("dashboard_impressions")) {
+ impressions = JSON.parse(store.get("dashboard_impressions"));
+ if (!_.isArray(impressions)) {
+ impressions = [];
+ }
+ }
+
+ var exists = impressions.indexOf(slug);
+ if (exists >= 0) {
+ impressions.splice(exists, 1);
+ }
+
+ impressions.unshift(slug);
+
+ if (impressions.length > 20) {
+ impressions.shift();
+ }
+ store.set("dashboard_impressions", JSON.stringify(impressions));
+ }
+
+ getDashboardOpened() {
+ var k = store.get("dashboard_impressions");
+ return JSON.parse(k);
+ }
+}
+
+var impressions = new ImpressionsStore();
+
+export {
+ impressions
+};
diff --git a/public/app/plugins/panel/dashlist/module.html b/public/app/plugins/panel/dashlist/module.html
index 455291409d5..79952d0032c 100644
--- a/public/app/plugins/panel/dashlist/module.html
+++ b/public/app/plugins/panel/dashlist/module.html
@@ -5,7 +5,7 @@
{{dash.title}}
-
+
diff --git a/public/app/plugins/panel/dashlist/module.ts b/public/app/plugins/panel/dashlist/module.ts
index a1c72434b38..fd0e905d923 100644
--- a/public/app/plugins/panel/dashlist/module.ts
+++ b/public/app/plugins/panel/dashlist/module.ts
@@ -3,6 +3,7 @@
import _ from 'lodash';
import config from 'app/core/config';
import {PanelCtrl} from 'app/plugins/sdk';
+import {impressions} from 'app/features/dashboard/impressionStore';
// Set and populate defaults
var panelDefaults = {
@@ -31,7 +32,7 @@ class DashListCtrl extends PanelCtrl {
initEditMode() {
super.initEditMode();
- this.modes = ['starred', 'search'];
+ this.modes = ['starred', 'search', 'last viewed'];
this.icon = "fa fa-star";
this.addEditorTab('Options', () => {
return {templateUrl: 'public/app/plugins/panel/dashlist/editor.html'};
@@ -41,6 +42,19 @@ class DashListCtrl extends PanelCtrl {
refresh() {
var params: any = {limit: this.panel.limit};
+ if (this.panel.mode === 'last viewed') {
+ var dashListNames = _.first(impressions.getDashboardOpened(), this.panel.limit).map((dashboard) => {
+ return {
+ title: dashboard,
+ uri: 'db/' + dashboard
+ };
+ });
+
+ this.dashList = dashListNames;
+ this.renderingCompleted();
+ return;
+ }
+
if (this.panel.mode === 'starred') {
params.starred = "true";
} else {
diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts
index 1c022d460bb..357da9b6877 100644
--- a/public/app/plugins/panel/graph/module.ts
+++ b/public/app/plugins/panel/graph/module.ts
@@ -125,7 +125,8 @@ class GraphCtrl extends MetricsPanelCtrl {
getExtendedMenu() {
var menu = super.getExtendedMenu();
- menu.push({text: 'Export CSV', click: 'ctrl.exportCsv()'});
+ menu.push({text: 'Export CSV (series as rows)', click: 'ctrl.exportCsv()'});
+ menu.push({text: 'Export CSV (series as columns)', click: 'ctrl.exportCsvColumns()'});
menu.push({text: 'Toggle legend', click: 'ctrl.toggleLegend()'});
return menu;
}
@@ -295,6 +296,10 @@ class GraphCtrl extends MetricsPanelCtrl {
exportCsv() {
fileExport.exportSeriesListToCsv(this.seriesList);
}
+
+ exportCsvColumns() {
+ fileExport.exportSeriesListToCsvColumns(this.seriesList);
+ }
}
export {GraphCtrl, GraphCtrl as PanelCtrl}
diff --git a/public/dashboards/home.json b/public/dashboards/home.json
index e05a882ef57..d54e276db5c 100644
--- a/public/dashboards/home.json
+++ b/public/dashboards/home.json
@@ -47,11 +47,11 @@
{
"id": 3,
"limit": 10,
- "mode": "search",
+ "mode": "last viewed",
"query": "",
"span": 6,
"tags": [],
- "title": "Dashboards",
+ "title": "Last 10 viewed dashboards",
"type": "dashlist"
}
],