diff --git a/pkg/api/index.go b/pkg/api/index.go
index eb9e70bb404..d2069441b81 100644
--- a/pkg/api/index.go
+++ b/pkg/api/index.go
@@ -95,7 +95,6 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
Children: []*dtos.NavLink{
{Text: "Dashboard", Icon: "gicon gicon-dashboard-new", Url: setting.AppSubUrl + "/dashboard/new"},
{Text: "Folder", Icon: "gicon gicon-folder-new", Url: setting.AppSubUrl + "/dashboard/new/?editview=new-folder"},
- {Text: "Import", Icon: "gicon gicon-dashboard-import", Url: setting.AppSubUrl + "/dashboard/new/?editview=import"},
},
})
}
@@ -104,6 +103,7 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
{Text: "Home", Url: setting.AppSubUrl + "/", Icon: "fa fa-fw fa-home", HideFromTabs: true},
{Divider: true, HideFromTabs: true},
{Text: "Manage", Id: "dashboards", Url: setting.AppSubUrl + "/dashboards", Icon: "fa fa-fw fa-sitemap"},
+ {Text: "Import", Id: "import", Url: setting.AppSubUrl + "/dashboards/import", Icon: "gicon gicon-dashboard-import"},
{Text: "Playlists", Id: "playlists", Url: setting.AppSubUrl + "/playlists", Icon: "fa fa-fw fa-film"},
{Text: "Snapshots", Id: "snapshots", Url: setting.AppSubUrl + "/dashboard/snapshots", Icon: "icon-gf icon-gf-fw icon-gf-snapshot"},
}
diff --git a/public/app/core/routes/routes.ts b/public/app/core/routes/routes.ts
index 68595da4296..a965cd406d3 100644
--- a/public/app/core/routes/routes.ts
+++ b/public/app/core/routes/routes.ts
@@ -68,6 +68,11 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
controller : 'DashboardListCtrl',
controllerAs: 'ctrl',
})
+ .when('/dashboards/import', {
+ templateUrl: 'public/app/features/dashboard/partials/dashboardImport.html',
+ controller : 'DashboardImportCtrl',
+ controllerAs: 'ctrl',
+ })
.when('/org', {
templateUrl: 'public/app/features/org/partials/orgDetails.html',
controller : 'OrgDetailsCtrl',
diff --git a/public/app/features/dashboard/all.ts b/public/app/features/dashboard/all.ts
index b4f1f4e77f0..f2f2087a24e 100644
--- a/public/app/features/dashboard/all.ts
+++ b/public/app/features/dashboard/all.ts
@@ -15,7 +15,6 @@ import './unsavedChangesSrv';
import './unsaved_changes_modal';
import './timepicker/timepicker';
import './upload';
-import './import/dash_import';
import './export/export_modal';
import './export_data/export_data_modal';
import './ad_hoc_filters';
@@ -30,5 +29,7 @@ import './move_to_folder_modal/move_to_folder';
import coreModule from 'app/core/core_module';
import {DashboardListCtrl} from './dashboard_list_ctrl';
+import {DashboardImportCtrl} from './dashboard_import_ctrl';
coreModule.controller('DashboardListCtrl', DashboardListCtrl);
+coreModule.controller('DashboardImportCtrl', DashboardImportCtrl);
diff --git a/public/app/features/dashboard/dashboard_import_ctrl.ts b/public/app/features/dashboard/dashboard_import_ctrl.ts
new file mode 100644
index 00000000000..f2b3fb90fc9
--- /dev/null
+++ b/public/app/features/dashboard/dashboard_import_ctrl.ts
@@ -0,0 +1,163 @@
+import _ from 'lodash';
+import config from 'app/core/config';
+
+export class DashboardImportCtrl {
+ navModel: any;
+ step: number;
+ jsonText: string;
+ parseError: string;
+ nameExists: boolean;
+ dash: any;
+ inputs: any[];
+ inputsValid: boolean;
+ gnetUrl: string;
+ gnetError: string;
+ gnetInfo: any;
+
+ /** @ngInject */
+ constructor(private backendSrv, navModelSrv, private $location, private $scope, $routeParams) {
+ this.navModel = navModelSrv.getNav('dashboards', 'import', 0);
+
+ this.step = 1;
+ this.nameExists = false;
+
+ // check gnetId in url
+ if ($routeParams.gnetId) {
+ this.gnetUrl = $routeParams.gnetId ;
+ this.checkGnetDashboard();
+ }
+ }
+
+ onUpload(dash) {
+ this.dash = dash;
+ this.dash.id = null;
+ this.step = 2;
+ this.inputs = [];
+
+ if (this.dash.__inputs) {
+ for (let input of this.dash.__inputs) {
+ var inputModel = {
+ name: input.name,
+ label: input.label,
+ info: input.description,
+ value: input.value,
+ type: input.type,
+ pluginId: input.pluginId,
+ options: []
+ };
+
+ if (input.type === 'datasource') {
+ this.setDatasourceOptions(input, inputModel);
+ } else if (!inputModel.info) {
+ inputModel.info = 'Specify a string constant';
+ }
+
+ this.inputs.push(inputModel);
+ }
+ }
+
+ this.inputsValid = this.inputs.length === 0;
+ this.titleChanged();
+ }
+
+ setDatasourceOptions(input, inputModel) {
+ var sources = _.filter(config.datasources, val => {
+ return val.type === input.pluginId;
+ });
+
+ if (sources.length === 0) {
+ inputModel.info = "No data sources of type " + input.pluginName + " found";
+ } else if (!inputModel.info) {
+ inputModel.info = "Select a " + input.pluginName + " data source";
+ }
+
+ inputModel.options = sources.map(val => {
+ return {text: val.name, value: val.name};
+ });
+ }
+
+ inputValueChanged() {
+ this.inputsValid = true;
+ for (let input of this.inputs) {
+ if (!input.value) {
+ this.inputsValid = false;
+ }
+ }
+ }
+
+ titleChanged() {
+ this.backendSrv.search({query: this.dash.title}).then(res => {
+ this.nameExists = false;
+ for (let hit of res) {
+ if (this.dash.title === hit.title) {
+ this.nameExists = true;
+ break;
+ }
+ }
+ });
+ }
+
+ saveDashboard() {
+ var inputs = this.inputs.map(input => {
+ return {
+ name: input.name,
+ type: input.type,
+ pluginId: input.pluginId,
+ value: input.value
+ };
+ });
+
+ return this.backendSrv.post('api/dashboards/import', {
+ dashboard: this.dash,
+ overwrite: true,
+ inputs: inputs
+ }).then(res => {
+ this.$location.url('dashboard/' + res.importedUri);
+ this.$scope.dismiss();
+ });
+ }
+
+ loadJsonText() {
+ try {
+ this.parseError = '';
+ var dash = JSON.parse(this.jsonText);
+ this.onUpload(dash);
+ } catch (err) {
+ console.log(err);
+ this.parseError = err.message;
+ return;
+ }
+ }
+
+ checkGnetDashboard() {
+ this.gnetError = '';
+
+ var match = /(^\d+$)|dashboards\/(\d+)/.exec(this.gnetUrl);
+ var dashboardId;
+
+ if (match && match[1]) {
+ dashboardId = match[1];
+ } else if (match && match[2]) {
+ dashboardId = match[2];
+ } else {
+ this.gnetError = 'Could not find dashboard';
+ }
+
+ return this.backendSrv.get('api/gnet/dashboards/' + dashboardId).then(res => {
+ this.gnetInfo = res;
+ // store reference to grafana.com
+ res.json.gnetId = res.id;
+ this.onUpload(res.json);
+ }).catch(err => {
+ err.isHandled = true;
+ this.gnetError = err.data.message || err;
+ });
+ }
+
+ back() {
+ this.gnetUrl = '';
+ this.step = 1;
+ this.gnetError = '';
+ this.gnetInfo = '';
+ }
+}
diff --git a/public/app/features/dashboard/partials/dashboardImport.html b/public/app/features/dashboard/partials/dashboardImport.html
new file mode 100644
index 00000000000..be43078d32a
--- /dev/null
+++ b/public/app/features/dashboard/partials/dashboardImport.html
@@ -0,0 +1,125 @@
+