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
d35eca33
Commit
d35eca33
authored
Sep 13, 2018
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
folder permissions in redux
parent
f360b618
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
231 additions
and
21 deletions
+231
-21
public/app/core/components/PermissionList/AddPermission.tsx
+142
-0
public/app/core/components/PermissionList/PermissionList.tsx
+2
-1
public/app/core/components/PermissionList/PermissionListItem.tsx
+2
-2
public/app/features/folders/FolderPermissions.tsx
+27
-9
public/app/features/folders/FolderSettingsPage.test.tsx
+1
-0
public/app/features/folders/state/actions.ts
+28
-3
public/app/features/folders/state/reducers.ts
+2
-1
public/app/types/acl.ts
+27
-0
public/app/types/index.ts
+0
-5
No files found.
public/app/core/components/PermissionList/AddPermission.tsx
0 → 100644
View file @
d35eca33
import
React
,
{
Component
}
from
'react'
;
import
{
UserPicker
,
User
}
from
'app/core/components/Picker/UserPicker'
;
import
{
TeamPicker
,
Team
}
from
'app/core/components/Picker/TeamPicker'
;
import
DescriptionPicker
,
{
OptionWithDescription
}
from
'app/core/components/Picker/DescriptionPicker'
;
import
{
dashboardPermissionLevels
,
dashboardAclTargets
,
AclTarget
,
PermissionLevel
,
NewDashboardAclItem
,
}
from
'app/types/acl'
;
export
interface
Props
{
onAddPermission
:
(
item
:
NewDashboardAclItem
)
=>
void
;
onCancel
:
()
=>
void
;
}
class
AddPermissions
extends
Component
<
Props
,
NewDashboardAclItem
>
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
this
.
getCleanState
();
}
getCleanState
()
{
return
{
userId
:
0
,
teamId
:
0
,
role
:
''
,
type
:
AclTarget
.
Team
,
permission
:
PermissionLevel
.
View
,
};
}
onTypeChanged
=
evt
=>
{
this
.
setState
({
type
:
evt
.
target
.
value
as
AclTarget
});
};
onUserSelected
=
(
user
:
User
)
=>
{
this
.
setState
({
userId
:
user
?
user
.
id
:
0
,
teamId
:
0
,
});
};
onTeamSelected
=
(
team
:
Team
)
=>
{
this
.
setState
({
userId
:
0
,
teamId
:
team
?
team
.
id
:
0
,
});
};
onPermissionChanged
=
(
permission
:
OptionWithDescription
)
=>
{
this
.
setState
({
permission
:
permission
.
value
});
};
onSubmit
=
async
evt
=>
{
evt
.
preventDefault
();
await
this
.
props
.
onAddPermission
(
this
.
state
);
this
.
setState
(
this
.
getCleanState
());
};
isValid
()
{
switch
(
this
.
state
.
type
)
{
case
AclTarget
.
Team
:
return
this
.
state
.
teamId
>
0
;
case
AclTarget
.
User
:
return
this
.
state
.
userId
>
0
;
}
return
true
;
}
render
()
{
const
{
onCancel
}
=
this
.
props
;
const
newItem
=
this
.
state
;
const
pickerClassName
=
'width-20'
;
const
isValid
=
this
.
isValid
();
return
(
<
div
className=
"gf-form-inline cta-form"
>
<
button
className=
"cta-form__close btn btn-transparent"
onClick=
{
onCancel
}
>
<
i
className=
"fa fa-close"
/>
</
button
>
<
form
name=
"addPermission"
onSubmit=
{
this
.
onSubmit
}
>
<
h5
>
Add Permission For
</
h5
>
<
div
className=
"gf-form-inline"
>
<
div
className=
"gf-form"
>
<
div
className=
"gf-form-select-wrapper"
>
<
select
className=
"gf-form-input gf-size-auto"
value=
{
newItem
.
type
}
onChange=
{
this
.
onTypeChanged
}
>
{
dashboardAclTargets
.
map
((
option
,
idx
)
=>
{
return
(
<
option
key=
{
idx
}
value=
{
option
.
value
}
>
{
option
.
text
}
</
option
>
);
})
}
</
select
>
</
div
>
</
div
>
{
newItem
.
type
===
AclTarget
.
User
?
(
<
div
className=
"gf-form"
>
<
UserPicker
onSelected=
{
this
.
onUserSelected
}
value=
{
newItem
.
userId
.
toString
()
}
className=
{
pickerClassName
}
/>
</
div
>
)
:
null
}
{
newItem
.
type
===
AclTarget
.
Team
?
(
<
div
className=
"gf-form"
>
<
TeamPicker
onSelected=
{
this
.
onTeamSelected
}
value=
{
newItem
.
teamId
.
toString
()
}
className=
{
pickerClassName
}
/>
</
div
>
)
:
null
}
<
div
className=
"gf-form"
>
<
DescriptionPicker
optionsWithDesc=
{
dashboardPermissionLevels
}
onSelected=
{
this
.
onPermissionChanged
}
value=
{
newItem
.
permission
}
disabled=
{
false
}
className=
{
'gf-form-input--form-dropdown-right'
}
/>
</
div
>
<
div
className=
"gf-form"
>
<
button
data
-
save
-
permission
className=
"btn btn-success"
type=
"submit"
disabled=
{
!
isValid
}
>
Save
</
button
>
</
div
>
</
div
>
</
form
>
</
div
>
);
}
}
export
default
AddPermissions
;
public/app/core/components/PermissionList/PermissionList.tsx
View file @
d35eca33
import
React
,
{
PureComponent
}
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
PermissionsListItem
from
'./PermissionListItem'
;
import
PermissionsListItem
from
'./PermissionListItem'
;
import
DisabledPermissionsListItem
from
'./DisabledPermissionListItem'
;
import
DisabledPermissionsListItem
from
'./DisabledPermissionListItem'
;
import
{
DashboardAcl
,
FolderInfo
}
from
'app/types'
;
import
{
FolderInfo
}
from
'app/types'
;
import
{
DashboardAcl
}
from
'app/types/acl'
;
export
interface
Props
{
export
interface
Props
{
items
:
DashboardAcl
[];
items
:
DashboardAcl
[];
...
...
public/app/core/components/PermissionList/PermissionListItem.tsx
View file @
d35eca33
import
React
,
{
PureComponent
}
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
DescriptionPicker
from
'app/core/components/Picker/DescriptionPicker'
;
import
DescriptionPicker
from
'app/core/components/Picker/DescriptionPicker'
;
import
{
dashboardPermissionLevels
}
from
'app/types/acl'
;
import
{
dashboardPermissionLevels
,
DashboardAcl
,
PermissionLevel
}
from
'app/types/acl'
;
import
{
DashboardAcl
,
FolderInfo
,
PermissionLevel
}
from
'app/types'
;
import
{
FolderInfo
}
from
'app/types'
;
const
setClassNameHelper
=
inherited
=>
{
const
setClassNameHelper
=
inherited
=>
{
return
inherited
?
'gf-form-disabled'
:
''
;
return
inherited
?
'gf-form-disabled'
:
''
;
...
...
public/app/features/folders/FolderPermissions.tsx
View file @
d35eca33
import
React
,
{
Component
}
from
'react'
;
import
React
,
{
Pure
Component
}
from
'react'
;
import
{
hot
}
from
'react-hot-loader'
;
import
{
hot
}
from
'react-hot-loader'
;
import
{
connect
}
from
'react-redux'
;
import
{
connect
}
from
'react-redux'
;
import
PageHeader
from
'app/core/components/PageHeader/PageHeader'
;
import
PageHeader
from
'app/core/components/PageHeader/PageHeader'
;
import
Permissions
from
'app/core/components/Permissions/Permissions'
;
import
Tooltip
from
'app/core/components/Tooltip/Tooltip'
;
import
Tooltip
from
'app/core/components/Tooltip/Tooltip'
;
import
PermissionsInfo
from
'app/core/components/Permissions/PermissionsInfo'
;
import
AddPermissions
from
'app/core/components/Permissions/AddPermissions'
;
import
SlideDown
from
'app/core/components/Animations/SlideDown'
;
import
SlideDown
from
'app/core/components/Animations/SlideDown'
;
import
{
getNavModel
}
from
'app/core/selectors/navModel'
;
import
{
getNavModel
}
from
'app/core/selectors/navModel'
;
import
{
NavModel
,
StoreState
,
FolderState
,
DashboardAcl
,
PermissionLevel
}
from
'app/types'
;
import
{
NavModel
,
StoreState
,
FolderState
}
from
'app/types'
;
import
{
getFolderByUid
,
getFolderPermissions
,
updateFolderPermission
,
removeFolderPermission
}
from
'./state/actions'
;
import
{
DashboardAcl
,
PermissionLevel
,
NewDashboardAclItem
}
from
'app/types/acl'
;
import
{
getFolderByUid
,
getFolderPermissions
,
updateFolderPermission
,
removeFolderPermission
,
addFolderPermission
,
}
from
'./state/actions'
;
import
{
getLoadingNav
}
from
'./state/navModel'
;
import
{
getLoadingNav
}
from
'./state/navModel'
;
import
PermissionList
from
'app/core/components/PermissionList/PermissionList'
;
import
PermissionList
from
'app/core/components/PermissionList/PermissionList'
;
import
AddPermission
from
'app/core/components/PermissionList/AddPermission'
;
import
PermissionsInfo
from
'app/core/components/Permissions/PermissionsInfo'
;
export
interface
Props
{
export
interface
Props
{
navModel
:
NavModel
;
navModel
:
NavModel
;
...
@@ -21,13 +27,14 @@ export interface Props {
...
@@ -21,13 +27,14 @@ export interface Props {
getFolderPermissions
:
typeof
getFolderPermissions
;
getFolderPermissions
:
typeof
getFolderPermissions
;
updateFolderPermission
:
typeof
updateFolderPermission
;
updateFolderPermission
:
typeof
updateFolderPermission
;
removeFolderPermission
:
typeof
removeFolderPermission
;
removeFolderPermission
:
typeof
removeFolderPermission
;
addFolderPermission
:
typeof
addFolderPermission
;
}
}
export
interface
State
{
export
interface
State
{
isAdding
:
boolean
;
isAdding
:
boolean
;
}
}
export
class
FolderPermissions
extends
Component
<
Props
,
State
>
{
export
class
FolderPermissions
extends
Pure
Component
<
Props
,
State
>
{
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
);
super
(
props
);
...
@@ -53,6 +60,14 @@ export class FolderPermissions extends Component<Props, State> {
...
@@ -53,6 +60,14 @@ export class FolderPermissions extends Component<Props, State> {
this
.
props
.
updateFolderPermission
(
item
,
level
);
this
.
props
.
updateFolderPermission
(
item
,
level
);
};
};
onAddPermission
=
(
newItem
:
NewDashboardAclItem
)
=>
{
return
this
.
props
.
addFolderPermission
(
newItem
);
};
onCancelAddPermission
=
()
=>
{
this
.
setState
({
isAdding
:
false
});
};
render
()
{
render
()
{
const
{
navModel
,
folder
}
=
this
.
props
;
const
{
navModel
,
folder
}
=
this
.
props
;
const
{
isAdding
}
=
this
.
state
;
const
{
isAdding
}
=
this
.
state
;
...
@@ -61,8 +76,7 @@ export class FolderPermissions extends Component<Props, State> {
...
@@ -61,8 +76,7 @@ export class FolderPermissions extends Component<Props, State> {
return
<
PageHeader
model=
{
navModel
}
/>;
return
<
PageHeader
model=
{
navModel
}
/>;
}
}
const
dashboardId
=
folder
.
id
;
const
folderInfo
=
{
title
:
folder
.
title
,
url
:
folder
.
url
,
id
:
folder
.
id
};
const
folderInfo
=
{
title
:
folder
.
tile
,
url
:
folder
.
url
,
id
:
folder
.
id
};
return
(
return
(
<
div
>
<
div
>
...
@@ -78,6 +92,9 @@ export class FolderPermissions extends Component<Props, State> {
...
@@ -78,6 +92,9 @@ export class FolderPermissions extends Component<Props, State> {
<
i
className=
"fa fa-plus"
/>
Add Permission
<
i
className=
"fa fa-plus"
/>
Add Permission
</
button
>
</
button
>
</
div
>
</
div
>
<
SlideDown
in=
{
isAdding
}
>
<
AddPermission
onAddPermission=
{
this
.
onAddPermission
}
onCancel=
{
this
.
onCancelAddPermission
}
/>
</
SlideDown
>
<
PermissionList
<
PermissionList
items=
{
folder
.
permissions
}
items=
{
folder
.
permissions
}
onRemoveItem=
{
this
.
onRemoveItem
}
onRemoveItem=
{
this
.
onRemoveItem
}
...
@@ -105,6 +122,7 @@ const mapDispatchToProps = {
...
@@ -105,6 +122,7 @@ const mapDispatchToProps = {
getFolderPermissions
,
getFolderPermissions
,
updateFolderPermission
,
updateFolderPermission
,
removeFolderPermission
,
removeFolderPermission
,
addFolderPermission
,
};
};
export
default
hot
(
module
)(
connect
(
mapStateToProps
,
mapDispatchToProps
)(
FolderPermissions
));
export
default
hot
(
module
)(
connect
(
mapStateToProps
,
mapDispatchToProps
)(
FolderPermissions
));
public/app/features/folders/FolderSettingsPage.test.tsx
View file @
d35eca33
...
@@ -15,6 +15,7 @@ const setup = (propOverrides?: object) => {
...
@@ -15,6 +15,7 @@ const setup = (propOverrides?: object) => {
url
:
'url'
,
url
:
'url'
,
hasChanged
:
false
,
hasChanged
:
false
,
version
:
1
,
version
:
1
,
permissions
:
[],
},
},
getFolderByUid
:
jest
.
fn
(),
getFolderByUid
:
jest
.
fn
(),
setFolderTitle
:
jest
.
fn
(),
setFolderTitle
:
jest
.
fn
(),
...
...
public/app/features/folders/state/actions.ts
View file @
d35eca33
import
{
getBackendSrv
}
from
'app/core/services/backend_srv'
;
import
{
getBackendSrv
}
from
'app/core/services/backend_srv'
;
import
{
StoreState
}
from
'app/types'
;
import
{
StoreState
}
from
'app/types'
;
import
{
ThunkAction
}
from
'redux-thunk'
;
import
{
ThunkAction
}
from
'redux-thunk'
;
import
{
FolderDTO
,
FolderState
}
from
'app/types'
;
import
{
import
{
FolderDTO
,
FolderState
,
DashboardAcl
,
DashboardAcl
,
DashboardAclDTO
,
DashboardAclDTO
,
PermissionLevel
,
PermissionLevel
,
DashboardAclUpdateDTO
,
DashboardAclUpdateDTO
,
}
from
'app/types'
;
NewDashboardAclItem
,
}
from
'app/types/acl'
;
import
{
updateNavIndex
,
updateLocation
}
from
'app/core/actions'
;
import
{
updateNavIndex
,
updateLocation
}
from
'app/core/actions'
;
import
{
buildNavModel
}
from
'./navModel'
;
import
{
buildNavModel
}
from
'./navModel'
;
import
appEvents
from
'app/core/app_events'
;
import
appEvents
from
'app/core/app_events'
;
...
@@ -140,3 +141,27 @@ export function removeFolderPermission(itemToDelete: DashboardAcl): ThunkResult<
...
@@ -140,3 +141,27 @@ export function removeFolderPermission(itemToDelete: DashboardAcl): ThunkResult<
await
dispatch
(
getFolderPermissions
(
folder
.
uid
));
await
dispatch
(
getFolderPermissions
(
folder
.
uid
));
};
};
}
}
export
function
addFolderPermission
(
newItem
:
NewDashboardAclItem
):
ThunkResult
<
void
>
{
return
async
(
dispatch
,
getStore
)
=>
{
const
folder
=
getStore
().
folder
;
const
itemsToUpdate
=
[];
for
(
const
item
of
folder
.
permissions
)
{
if
(
item
.
inherited
)
{
continue
;
}
itemsToUpdate
.
push
(
toUpdateItem
(
item
));
}
itemsToUpdate
.
push
({
userId
:
newItem
.
userId
,
teamId
:
newItem
.
teamId
,
role
:
item
.
role
,
permission
:
item
.
permission
,
});
await
getBackendSrv
().
post
(
`/api/folders/
${
folder
.
uid
}
/permissions`
,
{
items
:
itemsToUpdate
});
await
dispatch
(
getFolderPermissions
(
folder
.
uid
));
};
}
public/app/features/folders/state/reducers.ts
View file @
d35eca33
import
{
FolderState
,
DashboardAcl
,
DashboardAclDTO
}
from
'app/types'
;
import
{
FolderState
}
from
'app/types'
;
import
{
DashboardAcl
,
DashboardAclDTO
}
from
'app/types/acl'
;
import
{
Action
,
ActionTypes
}
from
'./actions'
;
import
{
Action
,
ActionTypes
}
from
'./actions'
;
export
const
inititalState
:
FolderState
=
{
export
const
inititalState
:
FolderState
=
{
...
...
public/app/types/acl.ts
View file @
d35eca33
...
@@ -43,12 +43,39 @@ export interface DashboardPermissionInfo {
...
@@ -43,12 +43,39 @@ export interface DashboardPermissionInfo {
description
:
string
;
description
:
string
;
}
}
export
interface
NewDashboardAclItem
{
teamId
:
number
;
userId
:
number
;
role
:
string
;
permission
:
PermissionLevel
;
type
:
AclTarget
;
}
export
enum
PermissionLevel
{
export
enum
PermissionLevel
{
View
=
1
,
View
=
1
,
Edit
=
2
,
Edit
=
2
,
Admin
=
4
,
Admin
=
4
,
}
}
export
enum
AclTarget
{
Team
=
'team'
,
User
=
'user'
,
Viewer
=
'viewer'
,
Editor
=
'editor'
,
}
export
interface
AclTargetInfo
{
value
:
AclTarget
;
text
:
string
;
}
export
const
dashboardAclTargets
:
AclTargetInfo
[]
=
[
{
value
:
AclTarget
.
Team
,
text
:
'Team'
},
{
value
:
AclTarget
.
User
,
text
:
'User'
},
{
value
:
AclTarget
.
Viewer
,
text
:
'Everyone With Viewer Role'
},
{
value
:
AclTarget
.
Editor
,
text
:
'Everyone With Editor Role'
},
];
export
const
dashboardPermissionLevels
:
DashboardPermissionInfo
[]
=
[
export
const
dashboardPermissionLevels
:
DashboardPermissionInfo
[]
=
[
{
value
:
PermissionLevel
.
View
,
label
:
'View'
,
description
:
'Can view dashboards.'
},
{
value
:
PermissionLevel
.
View
,
label
:
'View'
,
description
:
'Can view dashboards.'
},
{
value
:
PermissionLevel
.
Edit
,
label
:
'Edit'
,
description
:
'Can add, edit and delete dashboards.'
},
{
value
:
PermissionLevel
.
Edit
,
label
:
'Edit'
,
description
:
'Can add, edit and delete dashboards.'
},
...
...
public/app/types/index.ts
View file @
d35eca33
...
@@ -3,7 +3,6 @@ import { AlertRuleDTO, AlertRule, AlertRulesState } from './alerting';
...
@@ -3,7 +3,6 @@ import { AlertRuleDTO, AlertRule, AlertRulesState } from './alerting';
import
{
LocationState
,
LocationUpdate
,
UrlQueryMap
,
UrlQueryValue
}
from
'./location'
;
import
{
LocationState
,
LocationUpdate
,
UrlQueryMap
,
UrlQueryValue
}
from
'./location'
;
import
{
NavModel
,
NavModelItem
,
NavIndex
}
from
'./navModel'
;
import
{
NavModel
,
NavModelItem
,
NavIndex
}
from
'./navModel'
;
import
{
FolderDTO
,
FolderState
,
FolderInfo
}
from
'./folder'
;
import
{
FolderDTO
,
FolderState
,
FolderInfo
}
from
'./folder'
;
import
{
DashboardAcl
,
DashboardAclDTO
,
PermissionLevel
,
DashboardAclUpdateDTO
}
from
'./acl'
;
export
{
export
{
Team
,
Team
,
...
@@ -24,10 +23,6 @@ export {
...
@@ -24,10 +23,6 @@ export {
FolderDTO
,
FolderDTO
,
FolderState
,
FolderState
,
FolderInfo
,
FolderInfo
,
DashboardAcl
,
DashboardAclDTO
,
DashboardAclUpdateDTO
,
PermissionLevel
,
};
};
export
interface
StoreState
{
export
interface
StoreState
{
...
...
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