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
d86e773c
Commit
d86e773c
authored
Feb 02, 2019
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
wip: minor progress
parent
60f700a1
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
171 additions
and
119 deletions
+171
-119
public/app/features/dashboard/containers/DashboardPage.tsx
+50
-80
public/app/features/dashboard/state/actions.ts
+18
-23
public/app/features/dashboard/state/initDashboard.ts
+66
-1
public/app/features/dashboard/state/reducers.test.ts
+2
-2
public/app/features/dashboard/state/reducers.ts
+21
-12
public/app/types/dashboard.ts
+14
-1
No files found.
public/app/features/dashboard/containers/DashboardPage.tsx
View file @
d86e773c
...
...
@@ -3,21 +3,16 @@ import React, { Component } from 'react';
import
{
hot
}
from
'react-hot-loader'
;
import
{
connect
}
from
'react-redux'
;
// Utils & Services
import
locationUtil
from
'app/core/utils/location_util'
;
import
{
getBackendSrv
}
from
'app/core/services/backend_srv'
;
import
{
createErrorNotification
}
from
'app/core/copy/appNotification'
;
// Components
import
{
LoadingPlaceholder
}
from
'@grafana/ui'
;
// Redux
import
{
updateLocation
}
from
'app/core/actions'
;
import
{
notifyApp
}
from
'app/core/actions'
;
import
{
initDashboard
}
from
'../state/initDashboard'
;
// Types
import
{
StoreState
}
from
'app/types'
;
import
{
DashboardModel
}
from
'app/features/dashboard/state'
;
import
{
DashboardLoadingState
}
from
'app/types/dashboard'
;
interface
Props
{
panelId
:
string
;
...
...
@@ -26,8 +21,9 @@ interface Props {
urlType
?:
string
;
$scope
:
any
;
$injector
:
any
;
updateLocation
:
typeof
updateLocation
;
notifyApp
:
typeof
notifyApp
;
initDashboard
:
typeof
initDashboard
;
loadingState
:
DashboardLoadingState
;
dashboard
:
DashboardModel
;
}
interface
State
{
...
...
@@ -42,81 +38,54 @@ export class DashboardPage extends Component<Props, State> {
};
async
componentDidMount
()
{
const
{
$injector
,
urlUid
,
urlType
,
urlSlug
}
=
this
.
props
;
// handle old urls with no uid
if
(
!
urlUid
&&
!
(
urlType
===
'script'
||
urlType
===
'snapshot'
))
{
this
.
redirectToNewUrl
();
return
;
}
const
loaderSrv
=
$injector
.
get
(
'dashboardLoaderSrv'
);
const
dashDTO
=
await
loaderSrv
.
loadDashboard
(
urlType
,
urlSlug
,
urlUid
);
try
{
this
.
initDashboard
(
dashDTO
);
}
catch
(
err
)
{
this
.
props
.
notifyApp
(
createErrorNotification
(
'Failed to init dashboard'
,
err
.
toString
()));
console
.
log
(
err
);
}
}
redirectToNewUrl
()
{
getBackendSrv
()
.
getDashboardBySlug
(
this
.
props
.
urlSlug
)
.
then
(
res
=>
{
if
(
res
)
{
const
url
=
locationUtil
.
stripBaseFromUrl
(
res
.
meta
.
url
.
replace
(
'/d/'
,
'/d-solo/'
));
this
.
props
.
updateLocation
(
url
);
}
});
this
.
props
.
initDashboard
({
injector
:
this
.
props
.
$injector
,
scope
:
this
.
props
.
$scope
,
urlSlug
:
this
.
props
.
urlSlug
,
urlUid
:
this
.
props
.
urlUid
,
urlType
:
this
.
props
.
urlType
,
})
// const { $injector, urlUid, urlType, urlSlug } = this.props;
//
// // handle old urls with no uid
// if (!urlUid && !(urlType === 'script' || urlType === 'snapshot')) {
// this.redirectToNewUrl();
// return;
// }
//
// const loaderSrv = $injector.get('dashboardLoaderSrv');
// const dashDTO = await loaderSrv.loadDashboard(urlType, urlSlug, urlUid);
//
// try {
// this.initDashboard(dashDTO);
// } catch (err) {
// this.props.notifyApp(createErrorNotification('Failed to init dashboard', err.toString()));
// console.log(err);
// }
}
initDashboard
(
dashDTO
:
any
)
{
const
dashboard
=
new
DashboardModel
(
dashDTO
.
dashboard
,
dashDTO
.
meta
);
// init services
this
.
timeSrv
.
init
(
dashboard
);
this
.
annotationsSrv
.
init
(
dashboard
);
// template values service needs to initialize completely before
// the rest of the dashboard can load
this
.
variableSrv
.
init
(
dashboard
)
// template values failes are non fatal
.
catch
(
this
.
onInitFailed
.
bind
(
this
,
'Templating init failed'
,
false
))
// continue
.
finally
(()
=>
{
this
.
dashboard
=
dashboard
;
this
.
dashboard
.
processRepeats
();
this
.
dashboard
.
updateSubmenuVisibility
();
this
.
dashboard
.
autoFitPanels
(
window
.
innerHeight
);
this
.
unsavedChangesSrv
.
init
(
dashboard
,
this
.
$scope
);
// TODO refactor ViewStateSrv
this
.
$scope
.
dashboard
=
dashboard
;
this
.
dashboardViewState
=
this
.
dashboardViewStateSrv
.
create
(
this
.
$scope
);
this
.
keybindingSrv
.
setupDashboardBindings
(
this
.
$scope
,
dashboard
);
this
.
setWindowTitleAndTheme
();
appEvents
.
emit
(
'dashboard-initialized'
,
dashboard
);
})
.
catch
(
this
.
onInitFailed
.
bind
(
this
,
'Dashboard init failed'
,
true
));
this
.
setState
({
dashboard
});
}
// redirectToNewUrl() {
// getBackendSrv()
// .getDashboardBySlug(this.props.urlSlug)
// .then(res => {
// if (res) {
// const url = locationUtil.stripBaseFromUrl(res.meta.url.replace('/d/', '/d-solo/'));
// this.props.updateLocation(url);
// }
// });
// }
//
// initDashboard(dashDTO: any) {
// const dashboard = new DashboardModel(dashDTO.dashboard, dashDTO.meta);
// this.setState({ dashboard });
// }
render
()
{
const
{
notFound
,
dashboard
}
=
this
.
state
;
if
(
notFound
)
{
return
<
div
className=
"alert alert-error"
>
Dashboard not found
</
div
>;
}
const
{
loadingState
,
dashboard
}
=
this
.
props
;
if
(
!
dashboard
)
{
return
<
LoadingPlaceholder
text=
"Loading dashboard"
/>;
return
<
LoadingPlaceholder
text=
{
loadingState
.
toString
()
}
/>;
}
return
<
div
>
title:
{
dashboard
.
title
}
</
div
>;
...
...
@@ -128,11 +97,12 @@ const mapStateToProps = (state: StoreState) => ({
urlSlug
:
state
.
location
.
routeParams
.
slug
,
urlType
:
state
.
location
.
routeParams
.
type
,
panelId
:
state
.
location
.
query
.
panelId
,
loadingState
:
state
.
dashboard
.
loadingState
,
dashboard
:
state
.
dashboard
as
DashboardModel
,
});
const
mapDispatchToProps
=
{
updateLocation
,
notifyApp
,
initDashboard
};
export
default
hot
(
module
)(
connect
(
mapStateToProps
,
mapDispatchToProps
)(
DashboardPage
));
public/app/features/dashboard/state/actions.ts
View file @
d86e773c
// Libaries
import
{
StoreState
}
from
'app/types'
;
import
{
ThunkAction
}
from
'redux-thunk'
;
// Services & Utils
import
{
getBackendSrv
}
from
'app/core/services/backend_srv'
;
import
appEvents
from
'app/core/app_events'
;
import
{
actionCreatorFactory
}
from
'app/core/redux'
;
import
{
ActionOf
}
from
'app/core/redux/actionCreatorFactory'
;
import
{
createSuccessNotification
}
from
'app/core/copy/appNotification'
;
// Actions
import
{
loadPluginDashboards
}
from
'../../plugins/state/actions'
;
import
{
notifyApp
}
from
'app/core/actions'
;
// Types
import
{
DashboardAcl
,
DashboardAclDTO
,
...
...
@@ -10,30 +20,14 @@ import {
DashboardAclUpdateDTO
,
NewDashboardAclItem
,
}
from
'app/types/acl'
;
import
{
DashboardLoadingState
}
from
'app/types/dashboard'
;
export
enum
ActionTypes
{
LoadDashboardPermissions
=
'LOAD_DASHBOARD_PERMISSIONS'
,
LoadStarredDashboards
=
'LOAD_STARRED_DASHBOARDS'
,
}
export
interface
LoadDashboardPermissionsAction
{
type
:
ActionTypes
.
LoadDashboardPermissions
;
payload
:
DashboardAcl
[];
}
export
interface
LoadStarredDashboardsAction
{
type
:
ActionTypes
.
LoadStarredDashboards
;
payload
:
DashboardAcl
[];
}
export
const
loadDashboardPermissions
=
actionCreatorFactory
<
DashboardAclDTO
[]
>
(
'LOAD_DASHBOARD_PERMISSIONS'
).
create
();
export
const
setDashboardLoadingState
=
actionCreatorFactory
<
DashboardLoadingState
>
(
'SET_DASHBOARD_LOADING_STATE'
).
create
();
export
type
Action
=
LoadDashboardPermissionsAction
|
LoadStarredDashboardsAction
;
export
type
Action
=
ActionOf
<
DashboardAclDTO
[]
>
;
type
ThunkResult
<
R
>
=
ThunkAction
<
R
,
StoreState
,
undefined
,
any
>
;
export
const
loadDashboardPermissions
=
(
items
:
DashboardAclDTO
[]):
LoadDashboardPermissionsAction
=>
({
type
:
ActionTypes
.
LoadDashboardPermissions
,
payload
:
items
,
});
export
type
ThunkResult
<
R
>
=
ThunkAction
<
R
,
StoreState
,
undefined
,
any
>
;
export
function
getDashboardPermissions
(
id
:
number
):
ThunkResult
<
void
>
{
return
async
dispatch
=>
{
...
...
@@ -124,7 +118,7 @@ export function addDashboardPermission(dashboardId: number, newItem: NewDashboar
export
function
importDashboard
(
data
,
dashboardTitle
:
string
):
ThunkResult
<
void
>
{
return
async
dispatch
=>
{
await
getBackendSrv
().
post
(
'/api/dashboards/import'
,
data
);
appEvents
.
emit
(
'alert-success'
,
[
'Dashboard Imported'
,
dashboardTitle
]
);
dispatch
(
notifyApp
(
createSuccessNotification
(
'Dashboard Imported'
,
dashboardTitle
))
);
dispatch
(
loadPluginDashboards
());
};
}
...
...
@@ -135,3 +129,4 @@ export function removeDashboard(uri: string): ThunkResult<void> {
dispatch
(
loadPluginDashboards
());
};
}
public/app/features/dashboard/state/initDashboard.ts
View file @
d86e773c
// Libaries
import
{
StoreState
}
from
'app/types'
;
import
{
ThunkAction
}
from
'redux-thunk'
;
// Services & Utils
import
{
getBackendSrv
}
from
'app/core/services/backend_srv'
;
import
{
createErrorNotification
}
from
'app/core/copy/appNotification'
;
export
function
initDashboard
(
dashboard
:
DashboardModel
,
$injector
:
any
,
$scope
:
any
)
{
// Actions
import
{
updateLocation
}
from
'app/core/actions'
;
import
{
notifyApp
}
from
'app/core/actions'
;
import
locationUtil
from
'app/core/utils/location_util'
;
import
{
setDashboardLoadingState
,
ThunkResult
}
from
'./actions'
;
// Types
import
{
DashboardLoadingState
}
from
'app/types/dashboard'
;
import
{
DashboardModel
}
from
'./DashboardModel'
;
export
interface
InitDashboardArgs
{
injector
:
any
;
scope
:
any
;
urlUid
?:
string
;
urlSlug
?:
string
;
urlType
?:
string
;
}
export
function
initDashboard
({
injector
,
scope
,
urlUid
,
urlSlug
,
urlType
}:
InitDashboardArgs
):
ThunkResult
<
void
>
{
return
async
dispatch
=>
{
const
loaderSrv
=
injector
.
get
(
'dashboardLoaderSrv'
);
dispatch
(
setDashboardLoadingState
(
DashboardLoadingState
.
Fetching
));
try
{
// fetch dashboard from api
const
dashDTO
=
await
loaderSrv
.
loadDashboard
(
urlType
,
urlSlug
,
urlUid
);
// set initializing state
dispatch
(
setDashboardLoadingState
(
DashboardLoadingState
.
Initializing
));
// create model
const
dashboard
=
new
DashboardModel
(
dashDTO
.
dashboard
,
dashDTO
.
meta
);
// init services
injector
.
get
(
'timeSrv'
).
init
(
dashboard
);
injector
.
get
(
'annotationsSrv'
).
init
(
dashboard
);
// template values service needs to initialize completely before
// the rest of the dashboard can load
injector
.
get
(
'variableSrv'
).
init
(
dashboard
)
.
catch
(
err
=>
{
dispatch
(
notifyApp
(
createErrorNotification
(
'Templating init failed'
)));
})
.
finally
(()
=>
{
dashboard
.
processRepeats
();
dashboard
.
updateSubmenuVisibility
();
dashboard
.
autoFitPanels
(
window
.
innerHeight
);
injector
.
get
(
'unsavedChangesSrv'
).
init
(
dashboard
,
scope
);
scope
.
dashboard
=
dashboard
;
injector
.
get
(
'dashboardViewStateSrv'
).
create
(
scope
);
injector
.
get
(
'keybindingSrv'
).
setupDashboardBindings
(
scope
,
dashboard
);
})
.
catch
(
err
=>
{
dispatch
(
setDashboardLoadingState
(
DashboardLoadingState
.
Error
));
});
}
catch
(
err
)
{
dispatch
(
setDashboardLoadingState
(
DashboardLoadingState
.
Error
));
}
};
}
public/app/features/dashboard/state/reducers.test.ts
View file @
d86e773c
import
{
Action
,
ActionTypes
}
from
'./actions'
;
import
{
Action
}
from
'./actions'
;
import
{
OrgRole
,
PermissionLevel
,
DashboardState
}
from
'app/types'
;
import
{
initialState
,
dashboardReducer
}
from
'./reducers'
;
...
...
@@ -8,7 +8,7 @@ describe('dashboard reducer', () => {
beforeEach
(()
=>
{
const
action
:
Action
=
{
type
:
ActionTypes
.
LoadDashboardPermissions
,
type
:
'LOAD_DASHBOARD_PERMISSIONS'
,
payload
:
[
{
id
:
2
,
dashboardId
:
1
,
role
:
OrgRole
.
Viewer
,
permission
:
PermissionLevel
.
View
},
{
id
:
3
,
dashboardId
:
1
,
role
:
OrgRole
.
Editor
,
permission
:
PermissionLevel
.
Edit
},
...
...
public/app/features/dashboard/state/reducers.ts
View file @
d86e773c
import
{
DashboardState
}
from
'app/types'
;
import
{
Action
,
ActionTypes
}
from
'./actions'
;
import
{
DashboardState
,
DashboardLoadingState
}
from
'app/types/dashboard'
;
import
{
loadDashboardPermissions
,
setDashboardLoadingState
}
from
'./actions'
;
import
{
reducerFactory
}
from
'app/core/redux'
;
import
{
processAclItems
}
from
'app/core/utils/acl'
;
export
const
initialState
:
DashboardState
=
{
loadingState
:
DashboardLoadingState
.
NotStarted
,
dashboard
:
null
,
permissions
:
[],
};
export
const
dashboardReducer
=
(
state
=
initialState
,
action
:
Action
):
DashboardState
=>
{
switch
(
action
.
type
)
{
case
ActionTypes
.
LoadDashboardPermissions
:
return
{
...
state
,
permissions
:
processAclItems
(
action
.
payload
),
};
}
return
state
;
};
export
const
dashboardReducer
=
reducerFactory
(
initialState
)
.
addMapper
({
filter
:
loadDashboardPermissions
,
mapper
:
(
state
,
action
)
=>
({
...
state
,
permissions
:
processAclItems
(
action
.
payload
),
}),
})
.
addMapper
({
filter
:
setDashboardLoadingState
,
mapper
:
(
state
,
action
)
=>
({
...
state
,
loadingState
:
action
.
payload
}),
})
.
create
()
export
default
{
dashboard
:
dashboardReducer
,
...
...
public/app/types/dashboard.ts
View file @
d86e773c
import
{
DashboardAcl
}
from
'./acl'
;
export
interface
Dashboard
{
}
export
enum
DashboardLoadingState
{
NotStarted
=
'Not started'
,
Fetching
=
'Fetching'
,
Initializing
=
'Initializing'
,
Error
=
'Error'
,
Done
=
'Done'
,
}
export
interface
DashboardState
{
permissions
:
DashboardAcl
[];
dashboard
:
Dashboard
|
null
;
loadingState
:
DashboardLoadingState
;
permissions
:
DashboardAcl
[]
|
null
;
}
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