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
8e8c3d2e
Commit
8e8c3d2e
authored
Dec 05, 2017
by
Marcus Efraimsson
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into develop_searchresults
parents
781349d3
35f97c9a
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
355 additions
and
215 deletions
+355
-215
pkg/api/index.go
+3
-2
public/app/core/angular_wrappers.ts
+2
-0
public/app/core/components/EmptyListCTA/EmptyListCTA.jest.tsx
+22
-0
public/app/core/components/EmptyListCTA/EmptyListCTA.tsx
+34
-0
public/app/core/components/EmptyListCTA/__snapshots__/EmptyListCTA.jest.tsx.snap
+38
-0
public/app/core/nav_model_srv.ts
+0
-8
public/app/core/routes/routes.ts
+5
-0
public/app/features/dashboard/all.ts
+2
-1
public/app/features/dashboard/dashboard_import_ctrl.ts
+6
-19
public/app/features/dashboard/dashboard_list_ctrl.ts
+1
-1
public/app/features/dashboard/dashboard_migration.ts
+3
-2
public/app/features/dashboard/partials/dashboardImport.html
+101
-113
public/app/features/dashboard/specs/dashboard_import_ctrl.jest.ts
+25
-28
public/app/features/dashboard/specs/dashboard_migration.jest.ts
+24
-2
public/app/features/dashboard/upload.ts
+1
-1
public/app/features/plugins/partials/ds_list.html
+46
-35
public/sass/_grafana.scss
+1
-0
public/sass/_variables.scss
+5
-2
public/sass/base/_type.scss
+2
-0
public/sass/components/_buttons.scss
+11
-0
public/sass/components/_empty_list_cta.scss
+22
-0
public/sass/components/_tabbed_view.scss
+1
-1
No files found.
pkg/api/index.go
View file @
8e8c3d2e
...
@@ -90,12 +90,13 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
...
@@ -90,12 +90,13 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
if
c
.
OrgRole
==
m
.
ROLE_ADMIN
||
c
.
OrgRole
==
m
.
ROLE_EDITOR
{
if
c
.
OrgRole
==
m
.
ROLE_ADMIN
||
c
.
OrgRole
==
m
.
ROLE_EDITOR
{
data
.
NavTree
=
append
(
data
.
NavTree
,
&
dtos
.
NavLink
{
data
.
NavTree
=
append
(
data
.
NavTree
,
&
dtos
.
NavLink
{
Text
:
"Create"
,
Text
:
"Create"
,
Id
:
"create"
,
Icon
:
"fa fa-fw fa-plus"
,
Icon
:
"fa fa-fw fa-plus"
,
Url
:
"#"
,
Url
:
"#"
,
Children
:
[]
*
dtos
.
NavLink
{
Children
:
[]
*
dtos
.
NavLink
{
{
Text
:
"Dashboard"
,
Icon
:
"gicon gicon-dashboard-new"
,
Url
:
setting
.
AppSubUrl
+
"/dashboard/new"
},
{
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
:
"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"
},
{
Text
:
"Import"
,
SubTitle
:
"Import dashboard from file or Grafana.com"
,
Id
:
"import"
,
Icon
:
"gicon gicon-dashboard-import"
,
Url
:
setting
.
AppSubUrl
+
"/dashboard/
import"
},
},
},
})
})
}
}
...
@@ -103,7 +104,7 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
...
@@ -103,7 +104,7 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
dashboardChildNavs
:=
[]
*
dtos
.
NavLink
{
dashboardChildNavs
:=
[]
*
dtos
.
NavLink
{
{
Text
:
"Home"
,
Url
:
setting
.
AppSubUrl
+
"/"
,
Icon
:
"fa fa-fw fa-home"
,
HideFromTabs
:
true
},
{
Text
:
"Home"
,
Url
:
setting
.
AppSubUrl
+
"/"
,
Icon
:
"fa fa-fw fa-home"
,
HideFromTabs
:
true
},
{
Divider
:
true
,
HideFromTabs
:
true
},
{
Divider
:
true
,
HideFromTabs
:
true
},
{
Text
:
"Manage"
,
Id
:
"dashboards"
,
Url
:
setting
.
AppSubUrl
+
"/dashboards"
,
Icon
:
"fa fa-fw fa-sitemap"
},
{
Text
:
"Manage"
,
Id
:
"
manage-
dashboards"
,
Url
:
setting
.
AppSubUrl
+
"/dashboards"
,
Icon
:
"fa fa-fw fa-sitemap"
},
{
Text
:
"Playlists"
,
Id
:
"playlists"
,
Url
:
setting
.
AppSubUrl
+
"/playlists"
,
Icon
:
"fa fa-fw fa-film"
},
{
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"
},
{
Text
:
"Snapshots"
,
Id
:
"snapshots"
,
Url
:
setting
.
AppSubUrl
+
"/dashboard/snapshots"
,
Icon
:
"icon-gf icon-gf-fw icon-gf-snapshot"
},
}
}
...
...
public/app/core/angular_wrappers.ts
View file @
8e8c3d2e
import
{
react2AngularDirective
}
from
'app/core/utils/react2angular'
;
import
{
react2AngularDirective
}
from
'app/core/utils/react2angular'
;
import
{
PasswordStrength
}
from
'./components/PasswordStrength'
;
import
{
PasswordStrength
}
from
'./components/PasswordStrength'
;
import
PageHeader
from
'./components/PageHeader'
;
import
PageHeader
from
'./components/PageHeader'
;
import
EmptyListCTA
from
'./components/EmptyListCTA/EmptyListCTA'
;
export
function
registerAngularDirectives
()
{
export
function
registerAngularDirectives
()
{
react2AngularDirective
(
'passwordStrength'
,
PasswordStrength
,
[
'password'
]);
react2AngularDirective
(
'passwordStrength'
,
PasswordStrength
,
[
'password'
]);
react2AngularDirective
(
'pageHeader'
,
PageHeader
,
[
'model'
,
"noTabs"
]);
react2AngularDirective
(
'pageHeader'
,
PageHeader
,
[
'model'
,
"noTabs"
]);
react2AngularDirective
(
'emptyListCta'
,
EmptyListCTA
,
[
'model'
]);
}
}
public/app/core/components/EmptyListCTA/EmptyListCTA.jest.tsx
0 → 100644
View file @
8e8c3d2e
import
React
from
'react'
;
import
renderer
from
'react-test-renderer'
;
import
EmptyListCTA
from
'./EmptyListCTA'
;
const
model
=
{
title
:
'Title'
,
buttonIcon
:
'ga css class'
,
buttonLink
:
'http://url/to/destination'
,
buttonTitle
:
'Click me'
,
proTip
:
'This is a tip'
,
proTipLink
:
'http://url/to/tip/destination'
,
proTipLinkTitle
:
'Learn more'
,
proTipTarget
:
'_blank'
};
describe
(
'CollorPalette'
,
()
=>
{
it
(
'renders correctly'
,
()
=>
{
const
tree
=
renderer
.
create
(<
EmptyListCTA
model=
{
model
}
/>).
toJSON
();
expect
(
tree
).
toMatchSnapshot
();
});
});
public/app/core/components/EmptyListCTA/EmptyListCTA.tsx
0 → 100644
View file @
8e8c3d2e
import
React
,
{
Component
}
from
'react'
;
export
interface
IProps
{
model
:
any
;
}
class
EmptyListCTA
extends
Component
<
IProps
,
any
>
{
render
()
{
const
{
title
,
buttonIcon
,
buttonLink
,
buttonTitle
,
proTip
,
proTipLink
,
proTipLinkTitle
,
proTipTarget
}
=
this
.
props
.
model
;
return
(
<
div
className=
"empty-list-cta p-t-2 p-b-1"
>
<
div
className=
"empty-list-cta__title"
>
{
title
}
</
div
>
<
a
href=
{
buttonLink
}
className=
"empty-list-cta__button btn btn-xlarge btn-success"
><
i
className=
{
buttonIcon
}
/>
{
buttonTitle
}
</
a
>
<
div
className=
"empty-list-cta__pro-tip"
>
<
i
className=
"fa fa-rocket"
/>
ProTip:
{
proTip
}
<
a
className=
"text-link empty-list-cta__pro-tip-link"
href=
{
proTipLink
}
target=
{
proTipTarget
}
>
{
proTipLinkTitle
}
</
a
>
</
div
>
</
div
>
);
}
}
export
default
EmptyListCTA
;
public/app/core/components/EmptyListCTA/__snapshots__/EmptyListCTA.jest.tsx.snap
0 → 100644
View file @
8e8c3d2e
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`CollorPalette renders correctly 1`] = `
<div
className="empty-list-cta p-t-2 p-b-1"
>
<div
className="empty-list-cta__title"
>
Title
</div>
<a
className="empty-list-cta__button btn btn-xlarge btn-success"
href="http://url/to/destination"
>
<i
className="ga css class"
/>
Click me
</a>
<div
className="empty-list-cta__pro-tip"
>
<i
className="fa fa-rocket"
/>
ProTip:
This is a tip
<a
className="text-link empty-list-cta__pro-tip-link"
href="http://url/to/tip/destination"
target="_blank"
>
Learn more
</a>
</div>
</div>
`;
public/app/core/nav_model_srv.ts
View file @
8e8c3d2e
...
@@ -119,14 +119,6 @@ export class NavModelSrv {
...
@@ -119,14 +119,6 @@ export class NavModelSrv {
clickHandler
:
()
=>
dashNavCtrl
.
openEditView
(
'annotations'
)
clickHandler
:
()
=>
dashNavCtrl
.
openEditView
(
'annotations'
)
});
});
if
(
dashboard
.
meta
.
canAdmin
)
{
menu
.
push
({
title
:
'Permissions...'
,
icon
:
'fa fa-fw fa-lock'
,
clickHandler
:
()
=>
dashNavCtrl
.
openEditView
(
'permissions'
)
});
}
if
(
!
dashboard
.
meta
.
isHome
)
{
if
(
!
dashboard
.
meta
.
isHome
)
{
menu
.
push
({
menu
.
push
({
title
:
'Version history'
,
title
:
'Version history'
,
...
...
public/app/core/routes/routes.ts
View file @
8e8c3d2e
...
@@ -48,6 +48,11 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
...
@@ -48,6 +48,11 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
reloadOnSearch
:
false
,
reloadOnSearch
:
false
,
pageClass
:
'page-dashboard'
,
pageClass
:
'page-dashboard'
,
})
})
.
when
(
'/dashboard/import'
,
{
templateUrl
:
'public/app/features/dashboard/partials/dashboardImport.html'
,
controller
:
'DashboardImportCtrl'
,
controllerAs
:
'ctrl'
,
})
.
when
(
'/datasources'
,
{
.
when
(
'/datasources'
,
{
templateUrl
:
'public/app/features/plugins/partials/ds_list.html'
,
templateUrl
:
'public/app/features/plugins/partials/ds_list.html'
,
controller
:
'DataSourcesCtrl'
,
controller
:
'DataSourcesCtrl'
,
...
...
public/app/features/dashboard/all.ts
View file @
8e8c3d2e
...
@@ -15,7 +15,6 @@ import './unsavedChangesSrv';
...
@@ -15,7 +15,6 @@ import './unsavedChangesSrv';
import
'./unsaved_changes_modal'
;
import
'./unsaved_changes_modal'
;
import
'./timepicker/timepicker'
;
import
'./timepicker/timepicker'
;
import
'./upload'
;
import
'./upload'
;
import
'./import/dash_import'
;
import
'./export/export_modal'
;
import
'./export/export_modal'
;
import
'./export_data/export_data_modal'
;
import
'./export_data/export_data_modal'
;
import
'./ad_hoc_filters'
;
import
'./ad_hoc_filters'
;
...
@@ -30,5 +29,7 @@ import './move_to_folder_modal/move_to_folder';
...
@@ -30,5 +29,7 @@ import './move_to_folder_modal/move_to_folder';
import
coreModule
from
'app/core/core_module'
;
import
coreModule
from
'app/core/core_module'
;
import
{
DashboardListCtrl
}
from
'./dashboard_list_ctrl'
;
import
{
DashboardListCtrl
}
from
'./dashboard_list_ctrl'
;
import
{
DashboardImportCtrl
}
from
'./dashboard_import_ctrl'
;
coreModule
.
controller
(
'DashboardListCtrl'
,
DashboardListCtrl
);
coreModule
.
controller
(
'DashboardListCtrl'
,
DashboardListCtrl
);
coreModule
.
controller
(
'DashboardImportCtrl'
,
DashboardImportCtrl
);
public/app/features/dashboard/
import/dash_import
.ts
→
public/app/features/dashboard/
dashboard_import_ctrl
.ts
View file @
8e8c3d2e
///<reference path="../../../headers/common.d.ts" />
import
coreModule
from
'app/core/core_module'
;
import
config
from
'app/core/config'
;
import
_
from
'lodash'
;
import
_
from
'lodash'
;
import
config
from
'app/core/config'
;
export
class
DashImportCtrl
{
export
class
DashboardImportCtrl
{
navModel
:
any
;
step
:
number
;
step
:
number
;
jsonText
:
string
;
jsonText
:
string
;
parseError
:
string
;
parseError
:
string
;
...
@@ -17,7 +15,9 @@ export class DashImportCtrl {
...
@@ -17,7 +15,9 @@ export class DashImportCtrl {
gnetInfo
:
any
;
gnetInfo
:
any
;
/** @ngInject */
/** @ngInject */
constructor
(
private
backendSrv
,
private
$location
,
private
$scope
,
$routeParams
)
{
constructor
(
private
backendSrv
,
navModelSrv
,
private
$location
,
private
$scope
,
$routeParams
)
{
this
.
navModel
=
navModelSrv
.
getNav
(
'create'
,
'import'
);
this
.
step
=
1
;
this
.
step
=
1
;
this
.
nameExists
=
false
;
this
.
nameExists
=
false
;
...
@@ -160,17 +160,4 @@ export class DashImportCtrl {
...
@@ -160,17 +160,4 @@ export class DashImportCtrl {
this
.
gnetError
=
''
;
this
.
gnetError
=
''
;
this
.
gnetInfo
=
''
;
this
.
gnetInfo
=
''
;
}
}
}
export
function
dashImportDirective
()
{
return
{
restrict
:
'E'
,
templateUrl
:
'public/app/features/dashboard/import/dash_import.html'
,
controller
:
DashImportCtrl
,
bindToController
:
true
,
controllerAs
:
'ctrl'
,
};
}
}
coreModule
.
directive
(
'dashImport'
,
dashImportDirective
);
public/app/features/dashboard/dashboard_list_ctrl.ts
View file @
8e8c3d2e
...
@@ -17,7 +17,7 @@ export class DashboardListCtrl {
...
@@ -17,7 +17,7 @@ export class DashboardListCtrl {
/** @ngInject */
/** @ngInject */
constructor
(
private
backendSrv
,
navModelSrv
,
private
$q
,
private
searchSrv
:
SearchSrv
)
{
constructor
(
private
backendSrv
,
navModelSrv
,
private
$q
,
private
searchSrv
:
SearchSrv
)
{
this
.
navModel
=
navModelSrv
.
getNav
(
'dashboards'
,
'dashboards'
,
0
);
this
.
navModel
=
navModelSrv
.
getNav
(
'dashboards'
,
'
manage-
dashboards'
,
0
);
this
.
query
=
{
query
:
''
,
mode
:
'tree'
,
tag
:
[],
starred
:
false
,
skipRecent
:
true
,
skipStarred
:
true
};
this
.
query
=
{
query
:
''
,
mode
:
'tree'
,
tag
:
[],
starred
:
false
,
skipRecent
:
true
,
skipStarred
:
true
};
this
.
selectedStarredFilter
=
this
.
starredFilterOptions
[
0
];
this
.
selectedStarredFilter
=
this
.
starredFilterOptions
[
0
];
...
...
public/app/features/dashboard/dashboard_migration.ts
View file @
8e8c3d2e
...
@@ -383,8 +383,8 @@ export class DashboardMigrator {
...
@@ -383,8 +383,8 @@ export class DashboardMigrator {
return
;
return
;
}
}
// Add special "row" panels if even one row is collapsed or has visible title
// Add special "row" panels if even one row is collapsed
, repeated
or has visible title
const
showRows
=
_
.
some
(
old
.
rows
,
(
row
)
=>
row
.
collapse
||
row
.
showTitle
);
const
showRows
=
_
.
some
(
old
.
rows
,
(
row
)
=>
row
.
collapse
||
row
.
showTitle
||
row
.
repeat
);
for
(
let
row
of
old
.
rows
)
{
for
(
let
row
of
old
.
rows
)
{
let
height
:
any
=
row
.
height
||
DEFAULT_ROW_HEIGHT
;
let
height
:
any
=
row
.
height
||
DEFAULT_ROW_HEIGHT
;
...
@@ -398,6 +398,7 @@ export class DashboardMigrator {
...
@@ -398,6 +398,7 @@ export class DashboardMigrator {
rowPanel
.
type
=
'row'
;
rowPanel
.
type
=
'row'
;
rowPanel
.
title
=
row
.
title
;
rowPanel
.
title
=
row
.
title
;
rowPanel
.
collapsed
=
row
.
collapse
;
rowPanel
.
collapsed
=
row
.
collapse
;
rowPanel
.
repeat
=
row
.
repeat
;
rowPanel
.
panels
=
[];
rowPanel
.
panels
=
[];
rowPanel
.
gridPos
=
{
x
:
0
,
y
:
yPos
,
w
:
GRID_COLUMN_COUNT
,
h
:
rowGridHeight
};
rowPanel
.
gridPos
=
{
x
:
0
,
y
:
yPos
,
w
:
GRID_COLUMN_COUNT
,
h
:
rowGridHeight
};
rowPanelModel
=
new
PanelModel
(
rowPanel
);
rowPanelModel
=
new
PanelModel
(
rowPanel
);
...
...
public/app/features/dashboard/
import/dash_i
mport.html
→
public/app/features/dashboard/
partials/dashboardI
mport.html
View file @
8e8c3d2e
This diff is collapsed.
Click to expand it.
public/app/features/dashboard/specs/dash
_import_ctrl_specs
.ts
→
public/app/features/dashboard/specs/dash
board_import_ctrl.jest
.ts
View file @
8e8c3d2e
import
{
describe
,
beforeEach
,
it
,
sinon
,
expect
,
angularMocks
}
from
'test/lib/common'
;
import
{
DashboardImportCtrl
}
from
'../dashboard_import_ctrl'
;
import
config
from
'../../../core/config'
;
import
{
DashImportCtrl
}
from
'app/features/dashboard/import/dash_import'
;
describe
(
'DashboardImportCtrl'
,
function
()
{
import
config
from
'app/core/config'
;
describe
(
'DashImportCtrl'
,
function
()
{
var
ctx
:
any
=
{};
var
ctx
:
any
=
{};
var
backendSrv
=
{
search
:
sinon
.
stub
().
returns
(
Promise
.
resolve
([])),
get
:
sinon
.
stub
()
};
beforeEach
(
angularMocks
.
module
(
'grafana.core'
));
let
navModelSrv
;
let
backendSrv
;
beforeEach
(
angularMocks
.
inject
((
$rootScope
,
$controller
,
$q
)
=>
{
beforeEach
(()
=>
{
ctx
.
$q
=
$q
;
navModelSrv
=
{
ctx
.
scope
=
$rootScope
.
$new
();
getNav
:
()
=>
{}
ctx
.
ctrl
=
$controller
(
DashImportCtrl
,
{
};
$scope
:
ctx
.
scope
,
backendSrv
:
backendSrv
,
backendSrv
=
{
});
search
:
jest
.
fn
().
mockReturnValue
(
Promise
.
resolve
([])),
}));
get
:
jest
.
fn
()
};
ctx
.
ctrl
=
new
DashboardImportCtrl
(
backendSrv
,
navModelSrv
,
{},
{},
{});
});
describe
(
'when uploading json'
,
function
()
{
describe
(
'when uploading json'
,
function
()
{
beforeEach
(
function
()
{
beforeEach
(
function
()
{
...
@@ -37,13 +36,13 @@ describe('DashImportCtrl', function() {
...
@@ -37,13 +36,13 @@ describe('DashImportCtrl', function() {
});
});
it
(
'should build input model'
,
function
()
{
it
(
'should build input model'
,
function
()
{
expect
(
ctx
.
ctrl
.
inputs
.
length
).
to
.
eql
(
1
);
expect
(
ctx
.
ctrl
.
inputs
.
length
).
to
Be
(
1
);
expect
(
ctx
.
ctrl
.
inputs
[
0
].
name
).
to
.
eql
(
'ds'
);
expect
(
ctx
.
ctrl
.
inputs
[
0
].
name
).
to
Be
(
'ds'
);
expect
(
ctx
.
ctrl
.
inputs
[
0
].
info
).
to
.
eql
(
'Select a Test DB data source'
);
expect
(
ctx
.
ctrl
.
inputs
[
0
].
info
).
to
Be
(
'Select a Test DB data source'
);
});
});
it
(
'should set inputValid to false'
,
function
()
{
it
(
'should set inputValid to false'
,
function
()
{
expect
(
ctx
.
ctrl
.
inputsValid
).
to
.
eql
(
false
);
expect
(
ctx
.
ctrl
.
inputsValid
).
to
Be
(
false
);
});
});
});
});
...
@@ -51,7 +50,7 @@ describe('DashImportCtrl', function() {
...
@@ -51,7 +50,7 @@ describe('DashImportCtrl', function() {
beforeEach
(
function
()
{
beforeEach
(
function
()
{
ctx
.
ctrl
.
gnetUrl
=
'http://grafana.com/dashboards/123'
;
ctx
.
ctrl
.
gnetUrl
=
'http://grafana.com/dashboards/123'
;
// setup api mock
// setup api mock
backendSrv
.
get
=
sinon
.
spy
(()
=>
{
backendSrv
.
get
=
jest
.
fn
(()
=>
{
return
Promise
.
resolve
({
return
Promise
.
resolve
({
json
:
{}
json
:
{}
});
});
...
@@ -60,7 +59,7 @@ describe('DashImportCtrl', function() {
...
@@ -60,7 +59,7 @@ describe('DashImportCtrl', function() {
});
});
it
(
'should call gnet api with correct dashboard id'
,
function
()
{
it
(
'should call gnet api with correct dashboard id'
,
function
()
{
expect
(
backendSrv
.
get
.
getCall
(
0
).
args
[
0
]).
to
.
eql
(
'api/gnet/dashboards/123'
);
expect
(
backendSrv
.
get
.
mock
.
calls
[
0
][
0
]).
toBe
(
'api/gnet/dashboards/123'
);
});
});
});
});
...
@@ -68,7 +67,7 @@ describe('DashImportCtrl', function() {
...
@@ -68,7 +67,7 @@ describe('DashImportCtrl', function() {
beforeEach
(
function
()
{
beforeEach
(
function
()
{
ctx
.
ctrl
.
gnetUrl
=
'2342'
;
ctx
.
ctrl
.
gnetUrl
=
'2342'
;
// setup api mock
// setup api mock
backendSrv
.
get
=
sinon
.
spy
(()
=>
{
backendSrv
.
get
=
jest
.
fn
(()
=>
{
return
Promise
.
resolve
({
return
Promise
.
resolve
({
json
:
{}
json
:
{}
});
});
...
@@ -77,10 +76,8 @@ describe('DashImportCtrl', function() {
...
@@ -77,10 +76,8 @@ describe('DashImportCtrl', function() {
});
});
it
(
'should call gnet api with correct dashboard id'
,
function
()
{
it
(
'should call gnet api with correct dashboard id'
,
function
()
{
expect
(
backendSrv
.
get
.
getCall
(
0
).
args
[
0
]).
to
.
eql
(
'api/gnet/dashboards/2342'
);
expect
(
backendSrv
.
get
.
mock
.
calls
[
0
][
0
]).
toBe
(
'api/gnet/dashboards/2342'
);
});
});
});
});
});
});
public/app/features/dashboard/specs/dashboard_migration.jest.ts
View file @
8e8c3d2e
...
@@ -2,6 +2,7 @@ import _ from 'lodash';
...
@@ -2,6 +2,7 @@ import _ from 'lodash';
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
GRID_CELL_HEIGHT
,
GRID_CELL_VMARGIN
}
from
'app/core/constants'
;
import
{
GRID_CELL_HEIGHT
,
GRID_CELL_VMARGIN
}
from
'app/core/constants'
;
import
{
expect
}
from
'test/lib/common'
;
jest
.
mock
(
'app/core/services/context_srv'
,
()
=>
({}));
jest
.
mock
(
'app/core/services/context_srv'
,
()
=>
({}));
...
@@ -315,12 +316,33 @@ describe('DashboardModel', function() {
...
@@ -315,12 +316,33 @@ describe('DashboardModel', function() {
expect
(
panelGridPos
).
toEqual
(
expectedGrid
);
expect
(
panelGridPos
).
toEqual
(
expectedGrid
);
});
});
it
(
'should add repeated row if repeat set'
,
function
()
{
model
.
rows
=
[
createRow
({
showTitle
:
true
,
title
:
"Row"
,
height
:
8
,
repeat
:
"server"
},
[[
6
]]),
createRow
({
height
:
8
},
[[
12
]])
];
let
dashboard
=
new
DashboardModel
(
model
);
let
panelGridPos
=
getGridPositions
(
dashboard
);
let
expectedGrid
=
[
{
x
:
0
,
y
:
0
,
w
:
24
,
h
:
8
},
{
x
:
0
,
y
:
1
,
w
:
12
,
h
:
8
},
{
x
:
0
,
y
:
9
,
w
:
24
,
h
:
8
},
{
x
:
0
,
y
:
10
,
w
:
24
,
h
:
8
}
];
expect
(
panelGridPos
).
toEqual
(
expectedGrid
);
expect
(
dashboard
.
panels
[
0
].
repeat
).
toBe
(
"server"
);
expect
(
dashboard
.
panels
[
1
].
repeat
).
toBeUndefined
();
expect
(
dashboard
.
panels
[
2
].
repeat
).
toBeUndefined
();
expect
(
dashboard
.
panels
[
3
].
repeat
).
toBeUndefined
();
});
});
});
});
});
function
createRow
(
options
,
panelDescriptions
:
any
[])
{
function
createRow
(
options
,
panelDescriptions
:
any
[])
{
const
PANEL_HEIGHT_STEP
=
GRID_CELL_HEIGHT
+
GRID_CELL_VMARGIN
;
const
PANEL_HEIGHT_STEP
=
GRID_CELL_HEIGHT
+
GRID_CELL_VMARGIN
;
let
{
collapse
,
height
,
showTitle
,
title
}
=
options
;
let
{
collapse
,
height
,
showTitle
,
title
,
repeat
}
=
options
;
height
=
height
*
PANEL_HEIGHT_STEP
;
height
=
height
*
PANEL_HEIGHT_STEP
;
let
panels
=
[];
let
panels
=
[];
_
.
each
(
panelDescriptions
,
panelDesc
=>
{
_
.
each
(
panelDescriptions
,
panelDesc
=>
{
...
@@ -330,7 +352,7 @@ function createRow(options, panelDescriptions: any[]) {
...
@@ -330,7 +352,7 @@ function createRow(options, panelDescriptions: any[]) {
}
}
panels
.
push
(
panel
);
panels
.
push
(
panel
);
});
});
let
row
=
{
collapse
,
height
,
showTitle
,
title
,
panels
};
let
row
=
{
collapse
,
height
,
showTitle
,
title
,
panels
,
repeat
};
return
row
;
return
row
;
}
}
...
...
public/app/features/dashboard/upload.ts
View file @
8e8c3d2e
...
@@ -4,7 +4,7 @@ import coreModule from 'app/core/core_module';
...
@@ -4,7 +4,7 @@ import coreModule from 'app/core/core_module';
var
template
=
`
var
template
=
`
<input type="file" id="dashupload" name="dashupload" class="hide"/>
<input type="file" id="dashupload" name="dashupload" class="hide"/>
<label class="btn btn-s
econdary
" for="dashupload">
<label class="btn btn-s
uccess
" for="dashupload">
<i class="fa fa-upload"></i>
<i class="fa fa-upload"></i>
Upload .json File
Upload .json File
</label>
</label>
...
...
public/app/features/plugins/partials/ds_list.html
View file @
8e8c3d2e
<page-header
model=
"ctrl.navModel"
></page-header>
<page-header
model=
"ctrl.navModel"
></page-header>
<div
class=
"page-container page-body"
>
<div
class=
"page-container page-body"
>
<div
class=
"page-action-bar"
>
<div
ng-if=
"ctrl.datasources.length"
>
<div
class=
"page-action-bar__spacer"
></div>
<div
class=
"page-action-bar"
>
<a
class=
"page-header__cta btn btn-success"
href=
"datasources/new"
>
<div
class=
"page-action-bar__spacer"
></div>
<i
class=
"fa fa-plus"
></i>
<a
class=
"page-header__cta btn btn-success"
href=
"datasources/new"
>
Add data source
<i
class=
"fa fa-plus"
></i>
</a>
Add data source
</div>
</a>
</div>
<section
class=
"card-section"
layout-mode
>
<section
class=
"card-section"
layout-mode
>
<layout-selector></layout-selector>
<layout-selector></layout-selector>
<ol
class=
"card-list"
>
<ol
class=
"card-list"
>
<li
class=
"card-item-wrapper"
ng-repeat=
"ds in ctrl.datasources"
>
<li
class=
"card-item-wrapper"
ng-repeat=
"ds in ctrl.datasources"
>
<a
class=
"card-item"
href=
"datasources/edit/{{ds.id}}/"
>
<a
class=
"card-item"
href=
"datasources/edit/{{ds.id}}/"
>
<div
class=
"card-item-header"
>
<div
class=
"card-item-header"
>
<div
class=
"card-item-type"
>
<div
class=
"card-item-type"
>
{{ds.type}}
{{ds.type}}
</div>
</div>
<div
class=
"card-item-body"
>
<figure
class=
"card-item-figure"
>
<img
ng-src=
"{{ds.typeLogoUrl}}"
>
</figure>
<div
class=
"card-item-details"
>
<div
class=
"card-item-name"
>
{{ds.name}}
<span
ng-if=
"ds.isDefault"
>
<span
class=
"btn btn-secondary btn-mini"
>
default
</span>
</span>
</div>
</div>
<div
class=
"card-item-sub-name"
>
</div>
{{ds.url}}
<div
class=
"card-item-body"
>
<figure
class=
"card-item-figure"
>
<img
ng-src=
"{{ds.typeLogoUrl}}"
>
</figure>
<div
class=
"card-item-details"
>
<div
class=
"card-item-name"
>
{{ds.name}}
<span
ng-if=
"ds.isDefault"
>
<span
class=
"btn btn-secondary btn-mini"
>
default
</span>
</span>
</div>
<div
class=
"card-item-sub-name"
>
{{ds.url}}
</div>
</div>
</div>
</div>
</div>
</
div
>
</
a
>
</
a
>
</
li
>
</
li
>
</
ol
>
</
ol
>
</
section
>
</
section
>
</
div
>
<div
ng-if=
"ctrl.datasources.length === 0"
>
<div
ng-if=
"ctrl.datasources.length === 0"
>
<em>
No data sources defined
</em>
<empty-list-cta
model=
"{
title: 'There are no data sources defined yet',
buttonIcon: 'gicon gicon-dashboard-new',
buttonLink: '/datasources/new',
buttonTitle: 'Add data source',
proTip: 'You can also define data sources through configuration files.',
proTipLink: 'http://docs.grafana.org/administration/provisioning/#datasources?utm_source=grafana_ds_list',
proTipLinkTitle: 'Learn more',
proTipTarget: '_blank'
}"
/>
</div>
</div>
</div>
</div>
public/sass/_grafana.scss
View file @
8e8c3d2e
...
@@ -86,6 +86,7 @@
...
@@ -86,6 +86,7 @@
@import
"components/dashboard_grid"
;
@import
"components/dashboard_grid"
;
@import
"components/dashboard_list"
;
@import
"components/dashboard_list"
;
@import
"components/page_header"
;
@import
"components/page_header"
;
@import
"components/empty_list_cta"
;
// PAGES
// PAGES
...
...
public/sass/_variables.scss
View file @
8e8c3d2e
...
@@ -218,8 +218,11 @@ $btn-font-weight: 500 !default;
...
@@ -218,8 +218,11 @@ $btn-font-weight: 500 !default;
$btn-padding-x-sm
:
.5rem
!
default
;
$btn-padding-x-sm
:
.5rem
!
default
;
$btn-padding-y-sm
:
.25rem
!
default
;
$btn-padding-y-sm
:
.25rem
!
default
;
$btn-padding-x-lg
:
1
.5rem
!
default
;
$btn-padding-x-lg
:
21px
!
default
;
$btn-padding-y-lg
:
.75rem
!
default
;
$btn-padding-y-lg
:
11px
!
default
;
$btn-padding-x-xl
:
21px
!
default
;
$btn-padding-y-xl
:
11px
!
default
;
$btn-border-radius
:
3px
;
$btn-border-radius
:
3px
;
...
...
public/sass/base/_type.scss
View file @
8e8c3d2e
...
@@ -48,6 +48,8 @@ a.text-success:hover,
...
@@ -48,6 +48,8 @@ a.text-success:hover,
a
.text-success
:focus
{
color
:
darken
(
$success-text-color
,
10%
);
}
a
.text-success
:focus
{
color
:
darken
(
$success-text-color
,
10%
);
}
a
{
cursor
:
pointer
;
}
a
{
cursor
:
pointer
;
}
.text-link
{
text-decoration
:
underline
;
}
a
:focus
{
a
:focus
{
outline
:
0
none
!
important
;
outline
:
0
none
!
important
;
}
}
...
...
public/sass/components/_buttons.scss
View file @
8e8c3d2e
...
@@ -51,10 +51,21 @@
...
@@ -51,10 +51,21 @@
// Button Sizes
// Button Sizes
// --------------------------------------------------
// --------------------------------------------------
// XLarge
.btn-xlarge
{
@include
button-size
(
$btn-padding-y-xl
,
$btn-padding-x-xl
,
$font-size-lg
,
$btn-border-radius
);
font-weight
:
normal
;
padding-bottom
:
$btn-padding-y-xl
-
3
;
.gicon
{
font-size
:
31px
;
margin-right
:
1rem
;
}
}
// Large
// Large
.btn-large
{
.btn-large
{
@include
button-size
(
$btn-padding-y-lg
,
$btn-padding-x-lg
,
$font-size-lg
,
$btn-border-radius
);
@include
button-size
(
$btn-padding-y-lg
,
$btn-padding-x-lg
,
$font-size-lg
,
$btn-border-radius
);
font-weight
:
normal
;
}
}
.btn-small
{
.btn-small
{
...
...
public/sass/components/_empty_list_cta.scss
0 → 100644
View file @
8e8c3d2e
.empty-list-cta
{
background-color
:
$search-filter-box-bg
;
text-align
:
center
;
}
.empty-list-cta__title
{
padding-bottom
:
30px
;
font-style
:
italic
;
}
.empty-list-cta__button
{
margin-bottom
:
50px
;
}
.empty-list-cta__pro-tip
{
padding-bottom
:
20px
;
}
.empty-list-cta__pro-tip-link
{
margin-left
:
5px
;
}
\ No newline at end of file
public/sass/components/_tabbed_view.scss
View file @
8e8c3d2e
...
@@ -26,7 +26,7 @@
...
@@ -26,7 +26,7 @@
.tabbed-view-panel-title
{
.tabbed-view-panel-title
{
float
:
left
;
float
:
left
;
padding-top
:
1rem
;
padding-top
:
9px
;
margin
:
0
2rem
0
0
;
margin
:
0
2rem
0
0
;
}
}
...
...
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