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
545d7b94
Commit
545d7b94
authored
Jan 11, 2018
by
Daniel Lee
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashfolders: convert folder settings to React
parent
e1aff1d5
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
408 additions
and
27 deletions
+408
-27
pkg/api/index.go
+2
-2
public/app/containers/IContainerProps.ts
+2
-0
public/app/containers/ManageDashboards/FolderSettings.jest.tsx
+78
-0
public/app/containers/ManageDashboards/FolderSettings.tsx
+153
-0
public/app/core/components/manage_dashboards/manage_dashboards.html
+3
-2
public/app/core/services/bridge_srv.ts
+3
-3
public/app/core/specs/bridge_srv.jest.ts
+1
-1
public/app/features/dashboard/folder_page_loader.ts
+14
-14
public/app/features/dashboard/folder_settings_ctrl.ts
+1
-1
public/app/routes/routes.ts
+5
-3
public/app/stores/FolderStore/FolderStore.ts
+45
-0
public/app/stores/NavStore/NavStore.jest.ts
+47
-0
public/app/stores/NavStore/NavStore.ts
+39
-0
public/app/stores/RootStore/RootStore.ts
+3
-0
public/app/stores/ViewStore/ViewStore.ts
+10
-1
public/test/mocks/common.ts
+2
-0
No files found.
pkg/api/index.go
View file @
545d7b94
...
...
@@ -102,8 +102,8 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
}
dashboardChildNavs
:=
[]
*
dtos
.
NavLink
{
{
Text
:
"Home"
,
Url
:
setting
.
AppSubUrl
+
"/"
,
Icon
:
"gicon gicon-home"
,
HideFromTabs
:
true
},
{
Divider
:
true
,
HideFromTabs
:
true
},
{
Text
:
"Home"
,
Id
:
"home"
,
Url
:
setting
.
AppSubUrl
+
"/"
,
Icon
:
"gicon gicon-home"
,
HideFromTabs
:
true
},
{
Text
:
"Divider"
,
Divider
:
true
,
Id
:
"divider"
,
HideFromTabs
:
true
},
{
Text
:
"Manage"
,
Id
:
"manage-dashboards"
,
Url
:
setting
.
AppSubUrl
+
"/dashboards"
,
Icon
:
"gicon gicon-manage"
},
{
Text
:
"Playlists"
,
Id
:
"playlists"
,
Url
:
setting
.
AppSubUrl
+
"/playlists"
,
Icon
:
"gicon gicon-playlists"
},
{
Text
:
"Snapshots"
,
Id
:
"snapshots"
,
Url
:
setting
.
AppSubUrl
+
"/dashboard/snapshots"
,
Icon
:
"gicon gicon-snapshots"
},
...
...
public/app/containers/IContainerProps.ts
View file @
545d7b94
...
...
@@ -3,6 +3,7 @@ import { ServerStatsStore } from './../stores/ServerStatsStore/ServerStatsStore'
import
{
NavStore
}
from
'./../stores/NavStore/NavStore'
;
import
{
AlertListStore
}
from
'./../stores/AlertListStore/AlertListStore'
;
import
{
ViewStore
}
from
'./../stores/ViewStore/ViewStore'
;
import
{
FolderStore
}
from
'./../stores/FolderStore/FolderStore'
;
interface
IContainerProps
{
search
:
typeof
SearchStore
.
Type
;
...
...
@@ -10,6 +11,7 @@ interface IContainerProps {
nav
:
typeof
NavStore
.
Type
;
alertList
:
typeof
AlertListStore
.
Type
;
view
:
typeof
ViewStore
.
Type
;
folder
:
typeof
FolderStore
.
Type
;
}
export
default
IContainerProps
;
public/app/containers/ManageDashboards/FolderSettings.jest.tsx
0 → 100644
View file @
545d7b94
import
React
from
'react'
;
import
{
FolderSettings
}
from
'./FolderSettings'
;
import
{
RootStore
}
from
'app/stores/RootStore/RootStore'
;
import
{
backendSrv
}
from
'test/mocks/common'
;
import
{
shallow
}
from
'enzyme'
;
describe
(
'FolderSettings'
,
()
=>
{
let
wrapper
;
let
page
;
beforeAll
(()
=>
{
backendSrv
.
getDashboard
.
mockReturnValue
(
Promise
.
resolve
({
dashboard
:
{
id
:
1
,
title
:
'Folder Name'
,
},
meta
:
{
slug
:
'folder-name'
,
canSave
:
true
,
},
})
);
const
store
=
RootStore
.
create
(
{},
{
backendSrv
:
backendSrv
,
}
);
wrapper
=
shallow
(<
FolderSettings
{
...
store
}
/>);
return
wrapper
.
dive
()
.
instance
()
.
loadStore
()
.
then
(()
=>
{
page
=
wrapper
.
dive
();
});
});
it
(
'should set the title input field'
,
()
=>
{
const
titleInput
=
page
.
find
(
'.gf-form-input'
);
expect
(
titleInput
).
toHaveLength
(
1
);
expect
(
titleInput
.
prop
(
'value'
)).
toBe
(
'Folder Name'
);
});
it
(
'should update title and enable save button when changed'
,
()
=>
{
const
titleInput
=
page
.
find
(
'.gf-form-input'
);
const
disabledSubmitButton
=
page
.
find
(
'button[type="submit"]'
);
expect
(
disabledSubmitButton
.
prop
(
'disabled'
)).
toBe
(
true
);
titleInput
.
simulate
(
'change'
,
{
target
:
{
value
:
'New Title'
}
});
const
updatedTitleInput
=
page
.
find
(
'.gf-form-input'
);
expect
(
updatedTitleInput
.
prop
(
'value'
)).
toBe
(
'New Title'
);
const
enabledSubmitButton
=
page
.
find
(
'button[type="submit"]'
);
expect
(
enabledSubmitButton
.
prop
(
'disabled'
)).
toBe
(
false
);
});
it
(
'should disable save button if title is changed back to old title'
,
()
=>
{
const
titleInput
=
page
.
find
(
'.gf-form-input'
);
titleInput
.
simulate
(
'change'
,
{
target
:
{
value
:
'Folder Name'
}
});
const
enabledSubmitButton
=
page
.
find
(
'button[type="submit"]'
);
expect
(
enabledSubmitButton
.
prop
(
'disabled'
)).
toBe
(
true
);
});
it
(
'should disable save button if title is changed to empty string'
,
()
=>
{
const
titleInput
=
page
.
find
(
'.gf-form-input'
);
titleInput
.
simulate
(
'change'
,
{
target
:
{
value
:
''
}
});
const
enabledSubmitButton
=
page
.
find
(
'button[type="submit"]'
);
expect
(
enabledSubmitButton
.
prop
(
'disabled'
)).
toBe
(
true
);
});
});
public/app/containers/ManageDashboards/FolderSettings.tsx
0 → 100644
View file @
545d7b94
import
React
from
'react'
;
import
{
inject
,
observer
}
from
'mobx-react'
;
import
{
toJS
}
from
'mobx'
;
import
PageHeader
from
'app/core/components/PageHeader/PageHeader'
;
import
IContainerProps
from
'app/containers/IContainerProps'
;
import
{
getSnapshot
}
from
'mobx-state-tree'
;
import
appEvents
from
'app/core/app_events'
;
@
inject
(
'nav'
,
'folder'
,
'view'
)
@
observer
export
class
FolderSettings
extends
React
.
Component
<
IContainerProps
,
any
>
{
formSnapshot
:
any
;
dashboard
:
any
;
constructor
(
props
)
{
super
(
props
);
this
.
loadStore
();
}
loadStore
()
{
const
{
nav
,
folder
,
view
}
=
this
.
props
;
return
folder
.
load
(
view
.
routeParams
.
get
(
'slug'
)
as
string
).
then
(
res
=>
{
this
.
formSnapshot
=
getSnapshot
(
folder
);
this
.
dashboard
=
res
.
dashboard
;
return
nav
.
initFolderNav
(
toJS
(
folder
.
folder
),
'manage-folder-settings'
);
});
}
onTitleChange
(
evt
)
{
this
.
props
.
folder
.
setTitle
(
this
.
getFormSnapshot
().
folder
.
title
,
evt
.
target
.
value
);
}
getFormSnapshot
()
{
if
(
!
this
.
formSnapshot
)
{
this
.
formSnapshot
=
getSnapshot
(
this
.
props
.
folder
);
}
return
this
.
formSnapshot
;
}
save
(
evt
)
{
if
(
evt
)
{
evt
.
stopPropagation
();
evt
.
preventDefault
();
}
const
{
nav
,
folder
,
view
}
=
this
.
props
;
folder
.
saveDashboard
(
this
.
dashboard
,
{
overwrite
:
false
})
.
then
(
newUrl
=>
{
view
.
updatePathAndQuery
(
newUrl
,
''
,
''
);
appEvents
.
emit
(
'dashboard-saved'
);
appEvents
.
emit
(
'alert-success'
,
[
'Folder saved'
]);
})
.
then
(()
=>
{
return
nav
.
initFolderNav
(
toJS
(
folder
.
folder
),
'manage-folder-settings'
);
})
.
catch
(
this
.
handleSaveFolderError
);
}
delete
(
evt
)
{
if
(
evt
)
{
evt
.
stopPropagation
();
evt
.
preventDefault
();
}
const
{
folder
,
view
}
=
this
.
props
;
const
title
=
folder
.
folder
.
title
;
appEvents
.
emit
(
'confirm-modal'
,
{
title
:
'Delete'
,
text
:
`Do you want to delete this folder and all its dashboards?`
,
icon
:
'fa-trash'
,
yesText
:
'Delete'
,
onConfirm
:
()
=>
{
return
this
.
props
.
folder
.
deleteFolder
().
then
(()
=>
{
appEvents
.
emit
(
'alert-success'
,
[
'Folder Deleted'
,
`
${
title
}
has been deleted`
]);
view
.
updatePathAndQuery
(
'dashboards'
,
''
,
''
);
});
},
});
}
handleSaveFolderError
(
err
)
{
if
(
err
.
data
&&
err
.
data
.
status
===
'version-mismatch'
)
{
err
.
isHandled
=
true
;
appEvents
.
emit
(
'confirm-modal'
,
{
title
:
'Conflict'
,
text
:
'Someone else has updated this folder.'
,
text2
:
'Would you still like to save this folder?'
,
yesText
:
'Save & Overwrite'
,
icon
:
'fa-warning'
,
onConfirm
:
()
=>
{
this
.
props
.
folder
.
saveDashboard
(
this
.
dashboard
,
{
overwrite
:
true
});
},
});
}
if
(
err
.
data
&&
err
.
data
.
status
===
'name-exists'
)
{
err
.
isHandled
=
true
;
appEvents
.
emit
(
'alert-error'
,
[
'A folder or dashboard with this name exists already.'
]);
}
}
render
()
{
const
{
nav
,
folder
}
=
this
.
props
;
if
(
!
folder
.
folder
||
!
nav
.
main
)
{
return
<
h2
>
Loading
</
h2
>;
}
return
(
<
div
>
<
PageHeader
model=
{
nav
as
any
}
/>
<
div
className=
"page-container page-body"
>
<
h2
className=
"page-sub-heading"
>
Folder Settings
</
h2
>
<
div
className=
"section gf-form-group"
>
<
form
name=
"folderSettingsForm"
onSubmit=
{
this
.
save
.
bind
(
this
)
}
>
<
div
className=
"gf-form"
>
<
label
className=
"gf-form-label width-7"
>
Name
</
label
>
<
input
type=
"text"
className=
"gf-form-input width-30"
value=
{
folder
.
folder
.
title
}
onChange=
{
this
.
onTitleChange
.
bind
(
this
)
}
/>
</
div
>
<
div
className=
"gf-form-button-row"
>
<
button
type=
"submit"
className=
"btn btn-success"
disabled=
{
!
folder
.
folder
.
canSave
||
!
folder
.
folder
.
hasChanged
}
>
<
i
className=
"fa fa-trash"
/>
Save
</
button
>
<
button
className=
"btn btn-danger"
onClick=
{
this
.
delete
.
bind
(
this
)
}
disabled=
{
!
folder
.
folder
.
canSave
}
>
<
i
className=
"fa fa-trash"
/>
Delete
</
button
>
</
div
>
</
form
>
</
div
>
</
div
>
</
div
>
);
}
}
public/app/core/components/manage_dashboards/manage_dashboards.html
View file @
545d7b94
...
...
@@ -95,11 +95,12 @@
</div>
</div>
<div
class=
"search-results-container"
>
<dashboard-search-results
<dashboard-search-results
results=
"ctrl.sections"
editable=
"true"
on-selection-changed=
"ctrl.selectionChanged()"
on-tag-selected=
"ctrl.filterByTag($tag)"
/>
on-tag-selected=
"ctrl.filterByTag($tag)"
/>
</div>
</div>
</div>
...
...
public/app/core/services/bridge_srv.ts
View file @
545d7b94
...
...
@@ -10,7 +10,7 @@ export class BridgeSrv {
private
fullPageReloadRoutes
;
/** @ngInject */
constructor
(
private
$location
,
private
$timeout
,
private
$window
,
private
$rootScope
)
{
constructor
(
private
$location
,
private
$timeout
,
private
$window
,
private
$rootScope
,
private
$route
)
{
this
.
appSubUrl
=
config
.
appSubUrl
;
this
.
fullPageReloadRoutes
=
[
'/logout'
];
}
...
...
@@ -29,14 +29,14 @@ export class BridgeSrv {
this
.
$rootScope
.
$on
(
'$routeUpdate'
,
(
evt
,
data
)
=>
{
let
angularUrl
=
this
.
$location
.
url
();
if
(
store
.
view
.
currentUrl
!==
angularUrl
)
{
store
.
view
.
updatePathAndQuery
(
this
.
$location
.
path
(),
this
.
$location
.
search
());
store
.
view
.
updatePathAndQuery
(
this
.
$location
.
path
(),
this
.
$location
.
search
()
,
this
.
$route
.
current
.
params
);
}
});
this
.
$rootScope
.
$on
(
'$routeChangeSuccess'
,
(
evt
,
data
)
=>
{
let
angularUrl
=
this
.
$location
.
url
();
if
(
store
.
view
.
currentUrl
!==
angularUrl
)
{
store
.
view
.
updatePathAndQuery
(
this
.
$location
.
path
(),
this
.
$location
.
search
());
store
.
view
.
updatePathAndQuery
(
this
.
$location
.
path
(),
this
.
$location
.
search
()
,
this
.
$route
.
current
.
params
);
}
});
...
...
public/app/core/specs/bridge_srv.jest.ts
View file @
545d7b94
...
...
@@ -10,7 +10,7 @@ describe('BridgeSrv', () => {
let
searchSrv
;
beforeEach
(()
=>
{
searchSrv
=
new
BridgeSrv
(
null
,
null
,
null
,
null
);
searchSrv
=
new
BridgeSrv
(
null
,
null
,
null
,
null
,
null
);
});
describe
(
'With /subUrl as appSubUrl'
,
()
=>
{
...
...
public/app/features/dashboard/folder_page_loader.ts
View file @
545d7b94
...
...
@@ -43,33 +43,33 @@ export class FolderPageLoader {
ctrl
.
navModel
.
main
.
text
=
''
;
ctrl
.
navModel
.
main
.
breadcrumbs
=
[{
title
:
'Dashboards'
,
url
:
'dashboards'
},
{
title
:
folderTitle
}];
const
folderUrl
=
this
.
createFolderUrl
(
folderId
,
result
.
meta
.
type
,
result
.
meta
.
slug
);
const
folderUrl
=
this
.
createFolderUrl
(
folderId
,
result
.
meta
.
slug
);
const
dashTab
=
_
.
find
(
ctrl
.
navModel
.
main
.
children
,
{
id
:
'manage-folder-dashboards'
,
});
dashTab
.
url
=
folderUrl
;
if
(
result
.
meta
.
canAdmin
)
{
const
permTab
=
_
.
find
(
ctrl
.
navModel
.
main
.
children
,
{
id
:
'manage-folder-permissions'
,
});
if
(
result
.
meta
.
canAdmin
)
{
const
permTab
=
_
.
find
(
ctrl
.
navModel
.
main
.
children
,
{
id
:
'manage-folder-permissions'
,
});
permTab
.
url
=
folderUrl
+
'/permissions'
;
permTab
.
url
=
folderUrl
+
'/permissions'
;
const
settingsTab
=
_
.
find
(
ctrl
.
navModel
.
main
.
children
,
{
id
:
'manage-folder-settings'
,
});
settingsTab
.
url
=
folderUrl
+
'/settings'
;
}
else
{
ctrl
.
navModel
.
main
.
children
=
[
dashTab
];
}
const
settingsTab
=
_
.
find
(
ctrl
.
navModel
.
main
.
children
,
{
id
:
'manage-folder-settings'
,
});
settingsTab
.
url
=
folderUrl
+
'/settings'
;
}
else
{
ctrl
.
navModel
.
main
.
children
=
[
dashTab
];
}
return
result
;
});
}
createFolderUrl
(
folderId
:
number
,
type
:
string
,
slug
:
string
)
{
createFolderUrl
(
folderId
:
number
,
slug
:
string
)
{
return
`dashboards/folder/
${
folderId
}
/
${
slug
}
`
;
}
}
public/app/features/dashboard/folder_settings_ctrl.ts
View file @
545d7b94
...
...
@@ -38,7 +38,7 @@ export class FolderSettingsCtrl {
return
this
.
backendSrv
.
saveDashboard
(
this
.
dashboard
,
{
overwrite
:
false
})
.
then
(
result
=>
{
var
folderUrl
=
this
.
folderPageLoader
.
createFolderUrl
(
this
.
folderId
,
this
.
meta
.
type
,
result
.
slug
);
var
folderUrl
=
this
.
folderPageLoader
.
createFolderUrl
(
this
.
folderId
,
result
.
slug
);
if
(
folderUrl
!==
this
.
$location
.
path
())
{
this
.
$location
.
url
(
folderUrl
+
'/settings'
);
}
...
...
public/app/routes/routes.ts
View file @
545d7b94
...
...
@@ -2,6 +2,7 @@ import './dashboard_loaders';
import
'./ReactContainer'
;
import
{
ServerStats
}
from
'app/containers/ServerStats/ServerStats'
;
import
{
AlertRuleList
}
from
'app/containers/AlertRuleList/AlertRuleList'
;
import
{
FolderSettings
}
from
'app/containers/ManageDashboards/FolderSettings'
;
/** @ngInject **/
export
function
setupAngularRoutes
(
$routeProvider
,
$locationProvider
)
{
...
...
@@ -68,9 +69,10 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
controllerAs
:
'ctrl'
,
})
.
when
(
'/dashboards/folder/:folderId/:slug/settings'
,
{
templateUrl
:
'public/app/features/dashboard/partials/folder_settings.html'
,
controller
:
'FolderSettingsCtrl'
,
controllerAs
:
'ctrl'
,
template
:
'<react-container />'
,
resolve
:
{
component
:
()
=>
FolderSettings
,
},
})
.
when
(
'/dashboards/folder/:folderId/:slug'
,
{
templateUrl
:
'public/app/features/dashboard/partials/folder_dashboards.html'
,
...
...
public/app/stores/FolderStore/FolderStore.ts
0 → 100644
View file @
545d7b94
import
{
types
,
getEnv
,
flow
}
from
'mobx-state-tree'
;
export
const
Folder
=
types
.
model
(
'Folder'
,
{
id
:
types
.
identifier
(
types
.
number
),
slug
:
types
.
string
,
title
:
types
.
string
,
canSave
:
types
.
boolean
,
hasChanged
:
types
.
boolean
,
});
export
const
FolderStore
=
types
.
model
(
'FolderStore'
,
{
folder
:
types
.
maybe
(
Folder
),
})
.
actions
(
self
=>
({
load
:
flow
(
function
*
load
(
slug
:
string
)
{
const
backendSrv
=
getEnv
(
self
).
backendSrv
;
const
res
=
yield
backendSrv
.
getDashboard
(
'db'
,
slug
);
self
.
folder
=
Folder
.
create
({
id
:
res
.
dashboard
.
id
,
title
:
res
.
dashboard
.
title
,
slug
:
res
.
meta
.
slug
,
canSave
:
res
.
meta
.
canSave
,
hasChanged
:
false
,
});
return
res
;
}),
setTitle
:
function
(
originalTitle
:
string
,
title
:
string
)
{
self
.
folder
.
title
=
title
;
self
.
folder
.
hasChanged
=
originalTitle
.
toLowerCase
()
!==
title
.
trim
().
toLowerCase
()
&&
title
.
trim
().
length
>
0
;
},
saveDashboard
:
flow
(
function
*
saveDashboard
(
dashboard
:
any
,
options
:
any
)
{
const
backendSrv
=
getEnv
(
self
).
backendSrv
;
dashboard
.
title
=
self
.
folder
.
title
.
trim
();
const
res
=
yield
backendSrv
.
saveDashboard
(
dashboard
,
options
);
self
.
folder
.
slug
=
res
.
slug
;
return
`dashboards/folder/
${
self
.
folder
.
id
}
/
${
res
.
slug
}
/settings`
;
}),
deleteFolder
:
flow
(
function
*
deleteFolder
()
{
const
backendSrv
=
getEnv
(
self
).
backendSrv
;
return
backendSrv
.
deleteDashboard
(
self
.
folder
.
slug
);
}),
}));
public/app/stores/NavStore/NavStore.jest.ts
0 → 100644
View file @
545d7b94
import
{
NavStore
}
from
'./NavStore'
;
describe
(
'NavStore'
,
()
=>
{
const
folderId
=
1
;
const
folderTitle
=
'Folder Name'
;
const
folderSlug
=
'folder-name'
;
const
canAdmin
=
true
;
const
folder
=
{
id
:
folderId
,
slug
:
folderSlug
,
title
:
folderTitle
,
canAdmin
:
canAdmin
,
};
let
store
;
beforeEach
(()
=>
{
store
=
NavStore
.
create
();
store
.
initFolderNav
(
folder
,
'manage-folder-settings'
);
});
it
(
'Should set text'
,
()
=>
{
expect
(
store
.
main
.
text
).
toBe
(
folderTitle
);
});
it
(
'Should load nav with tabs'
,
()
=>
{
expect
(
store
.
main
.
children
.
length
).
toBe
(
3
);
expect
(
store
.
main
.
children
[
0
].
id
).
toBe
(
'manage-folder-dashboards'
);
expect
(
store
.
main
.
children
[
1
].
id
).
toBe
(
'manage-folder-permissions'
);
expect
(
store
.
main
.
children
[
2
].
id
).
toBe
(
'manage-folder-settings'
);
});
it
(
'Should set correct urls for each tab'
,
()
=>
{
expect
(
store
.
main
.
children
.
length
).
toBe
(
3
);
expect
(
store
.
main
.
children
[
0
].
url
).
toBe
(
`dashboards/folder/
${
folderId
}
/
${
folderSlug
}
`
);
expect
(
store
.
main
.
children
[
1
].
url
).
toBe
(
`dashboards/folder/
${
folderId
}
/
${
folderSlug
}
/permissions`
);
expect
(
store
.
main
.
children
[
2
].
url
).
toBe
(
`dashboards/folder/
${
folderId
}
/
${
folderSlug
}
/settings`
);
});
it
(
'Should set active tab'
,
()
=>
{
expect
(
store
.
main
.
children
.
length
).
toBe
(
3
);
expect
(
store
.
main
.
children
[
0
].
active
).
toBe
(
false
);
expect
(
store
.
main
.
children
[
1
].
active
).
toBe
(
false
);
expect
(
store
.
main
.
children
[
2
].
active
).
toBe
(
true
);
});
});
public/app/stores/NavStore/NavStore.ts
View file @
545d7b94
...
...
@@ -38,4 +38,43 @@ export const NavStore = types
self
.
main
=
NavItem
.
create
(
main
);
self
.
node
=
NavItem
.
create
(
node
);
},
initFolderNav
(
folder
:
any
,
activeChildId
:
string
)
{
const
folderUrl
=
createFolderUrl
(
folder
.
id
,
folder
.
slug
);
self
.
main
=
{
icon
:
'fa fa-folder-open'
,
id
:
'manage-folder'
,
subTitle
:
'Manage folder dashboards & permissions'
,
url
:
''
,
text
:
folder
.
title
,
breadcrumbs
:
[{
title
:
'Dashboards'
,
url
:
'dashboards'
}],
children
:
[
{
active
:
activeChildId
===
'manage-folder-dashboards'
,
icon
:
'fa fa-fw fa-th-large'
,
id
:
'manage-folder-dashboards'
,
text
:
'Dashboards'
,
url
:
folderUrl
,
},
{
active
:
activeChildId
===
'manage-folder-permissions'
,
icon
:
'fa fa-fw fa-lock'
,
id
:
'manage-folder-permissions'
,
text
:
'Permissions'
,
url
:
folderUrl
+
'/permissions'
,
},
{
active
:
activeChildId
===
'manage-folder-settings'
,
icon
:
'fa fa-fw fa-cog'
,
id
:
'manage-folder-settings'
,
text
:
'Settings'
,
url
:
folderUrl
+
'/settings'
,
},
],
};
},
}));
function
createFolderUrl
(
folderId
:
number
,
slug
:
string
)
{
return
`dashboards/folder/
${
folderId
}
/
${
slug
}
`
;
}
public/app/stores/RootStore/RootStore.ts
View file @
545d7b94
...
...
@@ -4,6 +4,7 @@ import { ServerStatsStore } from './../ServerStatsStore/ServerStatsStore';
import
{
NavStore
}
from
'./../NavStore/NavStore'
;
import
{
AlertListStore
}
from
'./../AlertListStore/AlertListStore'
;
import
{
ViewStore
}
from
'./../ViewStore/ViewStore'
;
import
{
FolderStore
}
from
'./../FolderStore/FolderStore'
;
export
const
RootStore
=
types
.
model
({
search
:
types
.
optional
(
SearchStore
,
{
...
...
@@ -19,7 +20,9 @@ export const RootStore = types.model({
view
:
types
.
optional
(
ViewStore
,
{
path
:
''
,
query
:
{},
routeParams
:
{},
}),
folder
:
types
.
optional
(
FolderStore
,
{}),
});
type
IRootStoreType
=
typeof
RootStore
.
Type
;
...
...
public/app/stores/ViewStore/ViewStore.ts
View file @
545d7b94
...
...
@@ -15,6 +15,7 @@ export const ViewStore = types
.
model
({
path
:
types
.
string
,
query
:
types
.
map
(
QueryValueType
),
routeParams
:
types
.
map
(
QueryValueType
),
})
.
views
(
self
=>
({
get
currentUrl
()
{
...
...
@@ -34,9 +35,17 @@ export const ViewStore = types
}
}
function
updatePathAndQuery
(
path
:
string
,
query
:
any
)
{
function
updateRouteParams
(
routeParams
:
any
)
{
self
.
routeParams
.
clear
();
for
(
let
key
of
Object
.
keys
(
routeParams
))
{
self
.
routeParams
.
set
(
key
,
routeParams
[
key
]);
}
}
function
updatePathAndQuery
(
path
:
string
,
query
:
any
,
routeParams
:
any
)
{
self
.
path
=
path
;
updateQuery
(
query
);
updateRouteParams
(
routeParams
);
}
return
{
...
...
public/test/mocks/common.ts
View file @
545d7b94
export
const
backendSrv
=
{
get
:
jest
.
fn
(),
getDashboard
:
jest
.
fn
(),
post
:
jest
.
fn
(),
};
...
...
@@ -11,5 +12,6 @@ export function createNavTree(...args) {
node
.
push
(
child
);
node
=
child
.
children
;
}
return
root
;
}
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