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
666d29fa
Commit
666d29fa
authored
Jan 31, 2018
by
Johannes Schill
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dashfolders: POC - Use separate component for "Add permission" #10676
parent
ee57ed10
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
315 additions
and
111 deletions
+315
-111
public/app/containers/ManageDashboards/FolderPermissions.tsx
+17
-2
public/app/core/components/Permissions/AddPermissions.tsx
+144
-0
public/app/core/components/Permissions/Permissions.tsx
+1
-60
public/app/core/components/Picker/TeamPicker.tsx
+3
-1
public/app/core/components/Picker/UserPicker.tsx
+5
-2
public/app/core/components/Picker/withPicker.tsx
+1
-0
public/app/stores/PermissionsStore/PermissionsStore.ts
+138
-46
public/sass/components/_gf-form.scss
+6
-0
No files found.
public/app/containers/ManageDashboards/FolderPermissions.tsx
View file @
666d29fa
...
...
@@ -6,11 +6,14 @@ 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
PermissionsInfo
from
'app/core/components/Permissions/PermissionsInfo'
;
import
AddPermissions
from
'app/core/components/Permissions/AddPermissions'
;
@
inject
(
'nav'
,
'folder'
,
'view'
,
'permissions'
)
@
observer
export
class
FolderPermissions
extends
Component
<
IContainerProps
,
any
>
{
constructor
(
props
)
{
super
(
props
);
this
.
handleAddPermission
=
this
.
handleAddPermission
.
bind
(
this
);
this
.
loadStore
();
}
...
...
@@ -21,6 +24,11 @@ export class FolderPermissions extends Component<IContainerProps, any> {
});
}
handleAddPermission
()
{
const
{
permissions
}
=
this
.
props
;
permissions
.
toggleAddPermissions
();
}
render
()
{
const
{
nav
,
folder
,
permissions
,
backendSrv
}
=
this
.
props
;
...
...
@@ -34,13 +42,20 @@ export class FolderPermissions extends Component<IContainerProps, any> {
<
div
>
<
PageHeader
model=
{
nav
as
any
}
/>
<
div
className=
"page-container page-body"
>
<
div
className=
"page-
sub-heading
"
>
<
div
className=
"page-
action-bar
"
>
<
h2
className=
"d-inline-block"
>
Folder Permissions
</
h2
>
<
Tooltip
className=
"page-sub-heading-icon"
placement=
"auto"
content=
{
PermissionsInfo
}
>
<
i
className=
"gicon gicon-question gicon--has-hover"
/>
</
Tooltip
>
<
div
className=
"page-action-bar__spacer"
/>
<
button
className=
"btn btn-success pull-right"
onClick=
{
this
.
handleAddPermission
}
>
<
i
className=
"fa fa-plus"
/>
Add Permission
</
button
>
</
div
>
{
permissions
.
isAddPermissionsVisible
?
(
<
AddPermissions
permissions=
{
permissions
}
backendSrv=
{
backendSrv
}
dashboardId=
{
dashboardId
}
/>
)
:
null
}
<
Permissions
permissions=
{
permissions
}
isFolder=
{
true
}
dashboardId=
{
dashboardId
}
backendSrv=
{
backendSrv
}
/>
</
div
>
</
div
>
...
...
public/app/core/components/Permissions/AddPermissions.tsx
0 → 100644
View file @
666d29fa
import
React
,
{
Component
}
from
'react'
;
import
{
observer
}
from
'mobx-react'
;
import
{
aclTypes
}
from
'app/stores/PermissionsStore/PermissionsStore'
;
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
{
permissionOptions
}
from
'app/stores/PermissionsStore/PermissionsStore'
;
export
interface
IProps
{
permissions
:
any
;
backendSrv
:
any
;
dashboardId
:
any
;
}
@
observer
class
AddPermissions
extends
Component
<
IProps
,
any
>
{
constructor
(
props
)
{
super
(
props
);
this
.
userPicked
=
this
.
userPicked
.
bind
(
this
);
this
.
teamPicked
=
this
.
teamPicked
.
bind
(
this
);
this
.
permissionPicked
=
this
.
permissionPicked
.
bind
(
this
);
this
.
typeChanged
=
this
.
typeChanged
.
bind
(
this
);
this
.
handleSubmit
=
this
.
handleSubmit
.
bind
(
this
);
}
componentWillMount
()
{
const
{
permissions
}
=
this
.
props
;
permissions
.
resetNewType
();
}
typeChanged
(
evt
)
{
const
{
value
}
=
evt
.
target
;
const
{
permissions
}
=
this
.
props
;
// if (value === 'Viewer' || value === 'Editor') {
// // permissions.addStoreItem({ permission: 1, role: value, dashboardId: dashboardId }, dashboardId);
// // this.resetNewType();
// return;
// }
permissions
.
setNewType
(
value
);
}
userPicked
(
user
:
User
)
{
const
{
permissions
}
=
this
.
props
;
if
(
!
user
)
{
permissions
.
newItem
.
setUser
(
null
,
null
);
return
;
}
permissions
.
newItem
.
setUser
(
user
.
id
,
user
.
login
);
// return permissions.addStoreItem({ userId: user.id, userLogin: user.login, permission: 1 });
}
teamPicked
(
team
:
Team
)
{
const
{
permissions
}
=
this
.
props
;
if
(
!
team
)
{
permissions
.
newItem
.
setTeam
(
null
,
null
);
return
;
}
permissions
.
newItem
.
setTeam
(
team
.
id
,
team
.
name
);
}
permissionPicked
(
permission
:
OptionWithDescription
)
{
const
{
permissions
}
=
this
.
props
;
permissions
.
newItem
.
setPermission
(
permission
.
value
);
}
resetNewType
()
{
const
{
permissions
}
=
this
.
props
;
permissions
.
resetNewType
();
}
handleSubmit
(
evt
)
{
evt
.
preventDefault
();
const
{
permissions
}
=
this
.
props
;
permissions
.
addStoreItem
();
}
render
()
{
const
{
permissions
,
backendSrv
}
=
this
.
props
;
const
newItem
=
permissions
.
newItem
;
return
(
<
div
className=
"gf-form-inline cta-form"
>
<
form
name=
"addPermission"
className=
"gf-form-group"
onSubmit=
{
this
.
handleSubmit
}
>
<
h6
className=
"muted"
>
Add Permission For
</
h6
>
<
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
.
typeChanged
}
>
{
aclTypes
.
map
((
option
,
idx
)
=>
{
return
(
<
option
key=
{
idx
}
value=
{
option
.
value
}
>
{
option
.
text
}
</
option
>
);
})
}
</
select
>
</
div
>
</
div
>
{
newItem
.
type
===
'User'
?
(
<
div
className=
"gf-form"
>
<
UserPicker
backendSrv=
{
backendSrv
}
handlePicked=
{
this
.
userPicked
}
value=
{
newItem
.
userId
}
/>
</
div
>
)
:
null
}
{
newItem
.
type
===
'Group'
?
(
<
div
className=
"gf-form"
>
<
TeamPicker
backendSrv=
{
backendSrv
}
handlePicked=
{
this
.
teamPicked
}
value=
{
newItem
.
teamId
}
/>
</
div
>
)
:
null
}
<
div
className=
"gf-form"
>
<
DescriptionPicker
optionsWithDesc=
{
permissionOptions
}
handlePicked=
{
this
.
permissionPicked
}
value=
{
newItem
.
permission
}
disabled=
{
false
}
className=
{
'gf-form-input--form-dropdown-right'
}
/>
</
div
>
<
div
className=
"gf-form"
>
<
button
className=
"btn btn-success"
type=
"submit"
disabled=
{
!
newItem
.
isValid
()
}
>
Save
</
button
>
</
div
>
</
div
>
</
form
>
{
permissions
.
error
?
(
<
div
className=
"gf-form width-17"
>
<
span
ng
-
if=
"ctrl.error"
className=
"text-error p-l-1"
>
<
i
className=
"fa fa-warning"
/>
{
permissions
.
error
}
</
span
>
</
div
>
)
:
null
}
</
div
>
);
}
}
export
default
AddPermissions
;
public/app/core/components/Permissions/Permissions.tsx
View file @
666d29fa
import
React
,
{
Component
}
from
'react'
;
import
PermissionsList
from
'./PermissionsList'
;
import
{
observer
}
from
'mobx-react'
;
import
UserPicker
,
{
User
}
from
'app/core/components/Picker/UserPicker'
;
import
TeamPicker
,
{
Team
}
from
'app/core/components/Picker/TeamPicker'
;
import
{
aclTypes
}
from
'app/stores/PermissionsStore/PermissionsStore'
;
import
{
FolderInfo
}
from
'./FolderInfo'
;
export
interface
DashboardAcl
{
...
...
@@ -40,8 +37,6 @@ class Permissions extends Component<IProps, any> {
this
.
permissionChanged
=
this
.
permissionChanged
.
bind
(
this
);
this
.
typeChanged
=
this
.
typeChanged
.
bind
(
this
);
this
.
removeItem
=
this
.
removeItem
.
bind
(
this
);
this
.
userPicked
=
this
.
userPicked
.
bind
(
this
);
this
.
teamPicked
=
this
.
teamPicked
.
bind
(
this
);
this
.
loadStore
(
dashboardId
,
isFolder
);
}
...
...
@@ -77,18 +72,8 @@ class Permissions extends Component<IProps, any> {
permissions
.
setNewType
(
value
);
}
userPicked
(
user
:
User
)
{
const
{
permissions
}
=
this
.
props
;
return
permissions
.
addStoreItem
({
userId
:
user
.
id
,
userLogin
:
user
.
login
,
permission
:
1
});
}
teamPicked
(
team
:
Team
)
{
const
{
permissions
}
=
this
.
props
;
return
permissions
.
addStoreItem
({
teamId
:
team
.
id
,
team
:
team
.
name
,
permission
:
1
});
}
render
()
{
const
{
permissions
,
folderInfo
,
backendSrv
}
=
this
.
props
;
const
{
permissions
,
folderInfo
}
=
this
.
props
;
return
(
<
div
className=
"gf-form-group"
>
...
...
@@ -99,50 +84,6 @@ class Permissions extends Component<IProps, any> {
fetching=
{
permissions
.
fetching
}
folderInfo=
{
folderInfo
}
/>
<
div
className=
"gf-form-inline"
>
<
form
name=
"addPermission"
className=
"gf-form-group"
>
<
h6
className=
"muted"
>
Add Permission For
</
h6
>
<
div
className=
"gf-form-inline"
>
<
div
className=
"gf-form"
>
<
div
className=
"gf-form-select-wrapper"
>
<
select
className=
"gf-form-input gf-size-auto"
value=
{
permissions
.
newType
}
onChange=
{
this
.
typeChanged
}
>
{
aclTypes
.
map
((
option
,
idx
)
=>
{
return
(
<
option
key=
{
idx
}
value=
{
option
.
value
}
>
{
option
.
text
}
</
option
>
);
})
}
</
select
>
</
div
>
</
div
>
{
permissions
.
newType
===
'User'
?
(
<
div
className=
"gf-form"
>
<
UserPicker
backendSrv=
{
backendSrv
}
handlePicked=
{
this
.
userPicked
}
/>
</
div
>
)
:
null
}
{
permissions
.
newType
===
'Group'
?
(
<
div
className=
"gf-form"
>
<
TeamPicker
backendSrv=
{
backendSrv
}
handlePicked=
{
this
.
teamPicked
}
/>
</
div
>
)
:
null
}
</
div
>
</
form
>
{
permissions
.
error
?
(
<
div
className=
"gf-form width-17"
>
<
span
ng
-
if=
"ctrl.error"
className=
"text-error p-l-1"
>
<
i
className=
"fa fa-warning"
/>
{
permissions
.
error
}
</
span
>
</
div
>
)
:
null
}
</
div
>
</
div
>
);
}
...
...
public/app/core/components/Picker/TeamPicker.tsx
View file @
666d29fa
...
...
@@ -9,6 +9,7 @@ export interface IProps {
isLoading
:
boolean
;
toggleLoading
:
any
;
handlePicked
:
(
user
)
=>
void
;
value
?:
string
;
}
export
interface
Team
{
...
...
@@ -54,7 +55,7 @@ class TeamPicker extends Component<IProps, any> {
render
()
{
const
AsyncComponent
=
this
.
state
.
creatable
?
Select
.
AsyncCreatable
:
Select
.
Async
;
const
{
isLoading
,
handlePicked
}
=
this
.
props
;
const
{
isLoading
,
handlePicked
,
value
}
=
this
.
props
;
return
(
<
div
className=
"user-picker"
>
...
...
@@ -70,6 +71,7 @@ class TeamPicker extends Component<IProps, any> {
className=
"width-8 gf-form-input gf-form-input--form-dropdown"
optionComponent=
{
PickerOption
}
placeholder=
"Choose"
value=
{
value
}
/>
</
div
>
);
...
...
public/app/core/components/Picker/UserPicker.tsx
View file @
666d29fa
...
...
@@ -9,6 +9,7 @@ export interface IProps {
isLoading
:
boolean
;
toggleLoading
:
any
;
handlePicked
:
(
user
)
=>
void
;
value
?:
string
;
}
export
interface
User
{
...
...
@@ -53,8 +54,8 @@ class UserPicker extends Component<IProps, any> {
render
()
{
const
AsyncComponent
=
this
.
state
.
creatable
?
Select
.
AsyncCreatable
:
Select
.
Async
;
const
{
isLoading
,
handlePicked
}
=
this
.
props
;
const
{
isLoading
,
handlePicked
,
value
}
=
this
.
props
;
console
.
log
(
'value'
,
value
);
return
(
<
div
className=
"user-picker"
>
<
AsyncComponent
...
...
@@ -70,6 +71,8 @@ class UserPicker extends Component<IProps, any> {
className=
"width-8 gf-form-input gf-form-input--form-dropdown"
optionComponent=
{
PickerOption
}
placeholder=
"Choose"
value=
{
value
}
autosize=
{
true
}
/>
</
div
>
);
...
...
public/app/core/components/Picker/withPicker.tsx
View file @
666d29fa
...
...
@@ -3,6 +3,7 @@
export
interface
IProps
{
backendSrv
:
any
;
handlePicked
:
(
data
)
=>
void
;
value
?:
string
;
}
export
default
function
withPicker
(
WrappedComponent
)
{
...
...
public/app/stores/PermissionsStore/PermissionsStore.ts
View file @
666d29fa
...
...
@@ -13,15 +13,62 @@ export const permissionOptions = [
},
];
export
const
aclTypes
=
[
{
value
:
'Group'
,
text
:
'Team'
},
{
value
:
'User'
,
text
:
'User'
},
{
value
:
'Viewer'
,
text
:
'Everyone With Viewer Role'
},
{
value
:
'Editor'
,
text
:
'Everyone With Editor Role'
},
];
export
const
aclTypeValues
=
{
GROUP
:
{
value
:
'Group'
,
text
:
'Team'
},
USER
:
{
value
:
'User'
,
text
:
'User'
},
VIEWER
:
{
value
:
'Viewer'
,
text
:
'Everyone With Viewer Role'
},
EDITOR
:
{
value
:
'Editor'
,
text
:
'Everyone With Editor Role'
},
};
export
const
aclTypes
=
Object
.
keys
(
aclTypeValues
).
map
(
item
=>
aclTypeValues
[
item
]);
const
defaultNewType
=
aclTypes
[
0
].
value
;
const
NewPermissionsItem
=
types
.
model
(
'NewPermissionsItem'
,
{
type
:
types
.
optional
(
types
.
enumeration
(
Object
.
keys
(
aclTypeValues
).
map
(
item
=>
aclTypeValues
[
item
].
value
)),
defaultNewType
),
userId
:
types
.
maybe
(
types
.
number
),
userLogin
:
types
.
maybe
(
types
.
string
),
teamId
:
types
.
maybe
(
types
.
number
),
team
:
types
.
maybe
(
types
.
string
),
permission
:
types
.
optional
(
types
.
number
,
1
),
})
.
views
(
self
=>
({
isValid
:
()
=>
{
switch
(
self
.
type
)
{
case
aclTypeValues
.
GROUP
.
value
:
return
self
.
teamId
&&
self
.
team
;
case
aclTypeValues
.
USER
.
value
:
return
self
.
userId
&&
self
.
userLogin
;
case
aclTypeValues
.
VIEWER
.
value
:
case
aclTypeValues
.
EDITOR
.
value
:
return
true
;
default
:
return
false
;
}
},
}))
.
actions
(
self
=>
({
setUser
(
userId
:
number
,
userLogin
:
string
)
{
self
.
userId
=
userId
;
self
.
userLogin
=
userLogin
;
self
.
teamId
=
null
;
self
.
team
=
null
;
},
setTeam
(
teamId
:
number
,
team
:
string
)
{
self
.
userId
=
null
;
self
.
userLogin
=
null
;
self
.
teamId
=
teamId
;
self
.
team
=
team
;
},
setPermission
(
permission
:
number
)
{
self
.
permission
=
permission
;
},
}));
export
const
PermissionsStore
=
types
.
model
(
'PermissionsStore'
,
{
fetching
:
types
.
boolean
,
...
...
@@ -31,6 +78,8 @@ export const PermissionsStore = types
error
:
types
.
maybe
(
types
.
string
),
originalItems
:
types
.
optional
(
types
.
array
(
PermissionsStoreItem
),
[]),
newType
:
types
.
optional
(
types
.
string
,
defaultNewType
),
newItem
:
types
.
maybe
(
NewPermissionsItem
),
isAddPermissionsVisible
:
types
.
optional
(
types
.
boolean
,
false
),
})
.
views
(
self
=>
({
isValid
:
item
=>
{
...
...
@@ -46,48 +95,91 @@ export const PermissionsStore = types
return
true
;
},
}))
.
actions
(
self
=>
({
load
:
flow
(
function
*
load
(
dashboardId
:
number
,
isFolder
:
boolean
)
{
const
backendSrv
=
getEnv
(
self
).
backendSrv
;
self
.
fetching
=
true
;
self
.
isFolder
=
isFolder
;
self
.
dashboardId
=
dashboardId
;
const
res
=
yield
backendSrv
.
get
(
`/api/dashboards/id/
${
dashboardId
}
/acl`
);
const
items
=
prepareServerResponse
(
res
,
dashboardId
,
isFolder
);
self
.
items
=
items
;
self
.
originalItems
=
items
;
self
.
fetching
=
false
;
}),
addStoreItem
:
flow
(
function
*
addStoreItem
(
item
)
{
.
actions
(
self
=>
{
const
resetNewType
=
()
=>
{
self
.
error
=
null
;
if
(
!
self
.
isValid
(
item
))
{
return
undefined
;
}
self
.
newItem
=
NewPermissionsItem
.
create
();
};
self
.
items
.
push
(
prepareItem
(
item
,
self
.
dashboardId
,
self
.
isFolder
));
return
updateItems
(
self
);
}),
removeStoreItem
:
flow
(
function
*
removeStoreItem
(
idx
:
number
)
{
self
.
error
=
null
;
self
.
items
.
splice
(
idx
,
1
);
return
updateItems
(
self
);
}),
updatePermissionOnIndex
:
flow
(
function
*
updatePermissionOnIndex
(
idx
:
number
,
permission
:
number
,
permissionName
:
string
)
{
self
.
error
=
null
;
self
.
items
[
idx
].
updatePermission
(
permission
,
permissionName
);
return
updateItems
(
self
);
}),
setNewType
(
newType
:
string
)
{
self
.
newType
=
newType
;
},
resetNewType
()
{
self
.
newType
=
defaultNewType
;
},
}));
return
{
load
:
flow
(
function
*
load
(
dashboardId
:
number
,
isFolder
:
boolean
)
{
const
backendSrv
=
getEnv
(
self
).
backendSrv
;
self
.
fetching
=
true
;
self
.
isFolder
=
isFolder
;
self
.
dashboardId
=
dashboardId
;
const
res
=
yield
backendSrv
.
get
(
`/api/dashboards/id/
${
dashboardId
}
/acl`
);
const
items
=
prepareServerResponse
(
res
,
dashboardId
,
isFolder
);
self
.
items
=
items
;
self
.
originalItems
=
items
;
self
.
fetching
=
false
;
}),
addStoreItem
:
flow
(
function
*
addStoreItem
()
{
self
.
error
=
null
;
let
item
=
{
type
:
self
.
newItem
.
type
,
permission
:
self
.
newItem
.
permission
,
team
:
undefined
,
teamId
:
undefined
,
userLogin
:
undefined
,
userId
:
undefined
,
role
:
undefined
,
};
switch
(
self
.
newItem
.
type
)
{
case
aclTypeValues
.
GROUP
.
value
:
item
.
team
=
self
.
newItem
.
team
;
item
.
teamId
=
self
.
newItem
.
teamId
;
break
;
case
aclTypeValues
.
USER
.
value
:
item
.
userLogin
=
self
.
newItem
.
userLogin
;
item
.
userId
=
self
.
newItem
.
userId
;
break
;
case
aclTypeValues
.
VIEWER
.
value
:
case
aclTypeValues
.
EDITOR
.
value
:
item
.
role
=
self
.
newItem
.
type
;
break
;
default
:
throw
Error
(
'Unknown type: '
+
self
.
newItem
.
type
);
}
if
(
!
self
.
isValid
(
item
))
{
throw
Error
(
'New item not valid'
);
}
self
.
items
.
push
(
prepareItem
(
item
,
self
.
dashboardId
,
self
.
isFolder
));
resetNewType
();
return
updateItems
(
self
);
}),
removeStoreItem
:
flow
(
function
*
removeStoreItem
(
idx
:
number
)
{
self
.
error
=
null
;
self
.
items
.
splice
(
idx
,
1
);
return
updateItems
(
self
);
}),
updatePermissionOnIndex
:
flow
(
function
*
updatePermissionOnIndex
(
idx
:
number
,
permission
:
number
,
permissionName
:
string
)
{
self
.
error
=
null
;
self
.
items
[
idx
].
updatePermission
(
permission
,
permissionName
);
return
updateItems
(
self
);
}),
setNewType
(
newType
:
string
)
{
self
.
newItem
=
NewPermissionsItem
.
create
({
type
:
newType
});
},
resetNewType
()
{
resetNewType
();
},
toggleAddPermissions
()
{
self
.
isAddPermissionsVisible
=
!
self
.
isAddPermissionsVisible
;
},
showAddPermissions
()
{
self
.
isAddPermissionsVisible
=
true
;
},
hideAddPermissions
()
{
self
.
isAddPermissionsVisible
=
false
;
},
};
});
const
updateItems
=
self
=>
{
self
.
error
=
null
;
...
...
public/sass/components/_gf-form.scss
View file @
666d29fa
...
...
@@ -392,3 +392,9 @@ select.gf-form-input ~ .gf-form-help-icon {
top
:
10px
;
color
:
$text-muted
;
}
.cta-form
{
padding
:
1rem
;
background-color
:
$dark-2
;
margin-bottom
:
1rem
;
}
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