Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
44ea0ff7
Commit
44ea0ff7
authored
Dec 04, 2017
by
Alexander Zobnin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move import dashboard from modal to the page
parent
15f46b85
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
299 additions
and
5 deletions
+299
-5
pkg/api/index.go
+1
-1
public/app/core/routes/routes.ts
+5
-0
public/app/features/dashboard/all.ts
+2
-1
public/app/features/dashboard/dashboard_import_ctrl.ts
+163
-0
public/app/features/dashboard/partials/dashboardImport.html
+125
-0
public/app/features/dashboard/specs/dashboard_import_ctrl.ts
+3
-3
No files found.
pkg/api/index.go
View file @
44ea0ff7
...
...
@@ -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"
},
}
...
...
public/app/core/routes/routes.ts
View file @
44ea0ff7
...
...
@@ -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'
,
...
...
public/app/features/dashboard/all.ts
View file @
44ea0ff7
...
...
@@ -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
);
public/app/features/dashboard/dashboard_import_ctrl.ts
0 → 100644
View file @
44ea0ff7
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
=
''
;
}
}
public/app/features/dashboard/partials/dashboardImport.html
0 → 100644
View file @
44ea0ff7
<page-header
model=
"ctrl.navModel"
></page-header>
<div
class=
"page-container page-body"
ng-cloak
>
<div
ng-if=
"ctrl.step === 1"
>
<form
class=
"gf-form-group"
>
<dash-upload
on-upload=
"ctrl.onUpload(dash)"
></dash-upload>
</form>
<h5
class=
"section-heading"
>
Grafana.com Dashboard
</h5>
<div
class=
"gf-form-group"
>
<div
class=
"gf-form gf-form--grow"
>
<input
type=
"text"
class=
"gf-form-input max-width-30"
ng-model=
"ctrl.gnetUrl"
placeholder=
"Paste Grafana.com dashboard url or id"
ng-blur=
"ctrl.checkGnetDashboard()"
></textarea>
</div>
<div
class=
"gf-form"
ng-if=
"ctrl.gnetError"
>
<label
class=
"gf-form-label text-warning"
>
<i
class=
"fa fa-warning"
></i>
{{ctrl.gnetError}}
</label>
</div>
</div>
<h5
class=
"section-heading"
>
Or paste JSON
</h5>
<div
class=
"gf-form-group"
>
<div
class=
"gf-form"
>
<textarea
rows=
"10"
data-share-panel-url=
""
class=
"gf-form-input"
ng-model=
"ctrl.jsonText"
></textarea>
</div>
<button
type=
"button"
class=
"btn btn-secondary"
ng-click=
"ctrl.loadJsonText()"
>
<i
class=
"fa fa-paste"
></i>
Load
</button>
<span
ng-if=
"ctrl.parseError"
class=
"text-error p-l-1"
>
<i
class=
"fa fa-warning"
></i>
{{ctrl.parseError}}
</span>
</div>
</div>
<div
ng-if=
"ctrl.step === 2"
>
<div
class=
"gf-form-group"
ng-if=
"ctrl.dash.gnetId"
>
<h3
class=
"section-heading"
>
Importing Dashboard from
<a
href=
"https://grafana.com/dashboards/{{ctrl.dash.gnetId}}"
class=
"external-link"
target=
"_blank"
>
Grafana.com
</a>
</h3>
<div
class=
"gf-form"
>
<label
class=
"gf-form-label width-15"
>
Published by
</label>
<label
class=
"gf-form-label width-15"
>
{{ctrl.gnetInfo.orgName}}
</label>
</div>
<div
class=
"gf-form"
>
<label
class=
"gf-form-label width-15"
>
Updated on
</label>
<label
class=
"gf-form-label width-15"
>
{{ctrl.gnetInfo.updatedAt | date : 'yyyy-MM-dd HH:mm:ss'}}
</label>
</div>
</div>
<h3
class=
"section-heading"
>
Options
</h3>
<div
class=
"gf-form-group"
>
<div
class=
"gf-form-inline"
>
<div
class=
"gf-form gf-form--grow"
>
<label
class=
"gf-form-label width-15"
>
Name
</label>
<input
type=
"text"
class=
"gf-form-input"
ng-model=
"ctrl.dash.title"
give-focus=
"true"
ng-change=
"ctrl.titleChanged()"
ng-class=
"{'validation-error': ctrl.nameExists || !ctrl.dash.title}"
>
<label
class=
"gf-form-label text-success"
ng-if=
"!ctrl.nameExists && ctrl.dash.title"
>
<i
class=
"fa fa-check"
></i>
</label>
</div>
</div>
<div
class=
"gf-form-inline"
ng-if=
"ctrl.nameExists"
>
<div
class=
"gf-form offset-width-15 gf-form--grow"
>
<label
class=
"gf-form-label text-warning gf-form-label--grow"
>
<i
class=
"fa fa-warning"
></i>
A Dashboard with the same name already exists
</label>
</div>
</div>
<div
class=
"gf-form-inline"
ng-if=
"!ctrl.dash.title"
>
<div
class=
"gf-form offset-width-15 gf-form--grow"
>
<label
class=
"gf-form-label text-warning gf-form-label--grow"
>
<i
class=
"fa fa-warning"
></i>
A Dashboard should have a name
</label>
</div>
</div>
<div
ng-repeat=
"input in ctrl.inputs"
>
<div
class=
"gf-form"
>
<label
class=
"gf-form-label width-15"
>
{{input.label}}
<info-popover
mode=
"right-normal"
>
{{input.info}}
</info-popover>
</label>
<!-- Data source input -->
<div
class=
"gf-form-select-wrapper"
style=
"width: 100%"
ng-if=
"input.type === 'datasource'"
>
<select
class=
"gf-form-input"
ng-model=
"input.value"
ng-options=
"v.value as v.text for v in input.options"
ng-change=
"ctrl.inputValueChanged()"
>
<option
value=
""
ng-hide=
"input.value"
>
{{input.info}}
</option>
</select>
</div>
<!-- Constant input -->
<input
ng-if=
"input.type === 'constant'"
type=
"text"
class=
"gf-form-input"
ng-model=
"input.value"
placeholder=
"{{input.default}}"
ng-change=
"ctrl.inputValueChanged()"
>
<label
class=
"gf-form-label text-success"
ng-show=
"input.value"
>
<i
class=
"fa fa-check"
></i>
</label>
</div>
</div>
</div>
<div
class=
"gf-form-button-row"
>
<button
type=
"button"
class=
"btn gf-form-btn btn-success width-12"
ng-click=
"ctrl.saveDashboard()"
ng-hide=
"ctrl.nameExists"
ng-disabled=
"!ctrl.inputsValid"
>
<i
class=
"fa fa-save"
></i>
Import
</button>
<button
type=
"button"
class=
"btn gf-form-btn btn-danger width-12"
ng-click=
"ctrl.saveDashboard()"
ng-show=
"ctrl.nameExists"
ng-disabled=
"!ctrl.inputsValid"
>
<i
class=
"fa fa-save"
></i>
Import (Overwrite)
</button>
<a
class=
"btn btn-link"
ng-click=
"ctrl.back()"
>
Cancel
</a>
</div>
</div>
</div>
public/app/features/dashboard/specs/dash
_import_ctrl_specs
.ts
→
public/app/features/dashboard/specs/dash
board_import_ctrl
.ts
View file @
44ea0ff7
import
{
describe
,
beforeEach
,
it
,
sinon
,
expect
,
angularMocks
}
from
'test/lib/common'
;
import
{
Dash
ImportCtrl
}
from
'app/features/dashboard/import/dash_import
'
;
import
{
Dash
boardImportCtrl
}
from
'../dashboard_import_ctrl
'
;
import
config
from
'app/core/config'
;
describe
(
'DashImportCtrl'
,
function
()
{
describe
(
'Dash
board
ImportCtrl'
,
function
()
{
var
ctx
:
any
=
{};
var
backendSrv
=
{
search
:
sinon
.
stub
().
returns
(
Promise
.
resolve
([])),
...
...
@@ -15,7 +15,7 @@ describe('DashImportCtrl', function() {
beforeEach
(
angularMocks
.
inject
((
$rootScope
,
$controller
,
$q
)
=>
{
ctx
.
$q
=
$q
;
ctx
.
scope
=
$rootScope
.
$new
();
ctx
.
ctrl
=
$controller
(
DashImportCtrl
,
{
ctx
.
ctrl
=
$controller
(
Dash
board
ImportCtrl
,
{
$scope
:
ctx
.
scope
,
backendSrv
:
backendSrv
,
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment