Commit 5ee2d1de by Daniel Lee

dashfolders: select with description for permissions

The dropdown for selecting permission is a new component built on
react-select that includes a description for the permission for
every option in the select.
parent a7fba593
......@@ -83,18 +83,18 @@ func (g *DashboardGuardian) checkAcl(permission m.PermissionType, acl []*m.Dashb
}
}
// do we have group rules?
// do we have team rules?
if len(teamAclItems) == 0 {
return false, nil
}
// load groups
// load teams
teams, err := g.getTeams()
if err != nil {
return false, err
}
// evalute group rules
// evalute team rules
for _, p := range acl {
for _, ug := range teams {
if ug.Id == p.TeamId && p.Permission >= permission {
......@@ -140,7 +140,7 @@ func (g *DashboardGuardian) CheckPermissionBeforeUpdate(permission m.PermissionT
return g.checkAcl(permission, acl)
}
// Returns dashboard acl
// GetAcl returns dashboard acl
func (g *DashboardGuardian) GetAcl() ([]*m.DashboardAclInfoDTO, error) {
if g.acl != nil {
return g.acl, nil
......
import React, { Component } from 'react';
import { observer } from 'mobx-react';
import { store } from 'app/stores/store';
import Permissions from 'app/core/components/Permissions/Permissions';
......@@ -9,7 +8,6 @@ export interface IProps {
backendSrv: any;
}
@observer
class DashboardPermissions extends Component<IProps, any> {
permissions: any;
......
import React, { Component } from 'react';
import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker';
import { permissionOptions } from 'app/stores/PermissionsStore/PermissionsStore';
export interface IProps {
......@@ -18,16 +19,13 @@ export default class DisabledPermissionListItem extends Component<IProps, any> {
<td />
<td className="query-keyword">Can</td>
<td>
<div className="gf-form-select-wrapper">
<select value={item.permission} className="gf-form-input gf-size-auto" disabled={true}>
{permissionOptions.map((option, idx) => {
return (
<option key={idx} value={option.value}>
{option.text}
</option>
);
})}
</select>
<div className="gf-form">
<DescriptionPicker
optionsWithDesc={permissionOptions}
handlePicked={() => {}}
value={item.permission}
disabled={true}
/>
</div>
</td>
<td>
......
......@@ -142,7 +142,7 @@ class Permissions extends Component<IProps, any> {
</div>
) : null}
</div>
<div className="empty-list-cta m-t-3">
{/* <div className="empty-list-cta m-t-3">
<div className="grafana-info-box">
<h5>What are Permissions?</h5>
<p>
......@@ -157,7 +157,7 @@ class Permissions extends Component<IProps, any> {
</a>{' '}
for more information.
</div>
</div>
</div> */}
</div>
);
}
......
import React from 'react';
import { observer } from 'mobx-react';
import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker';
import { permissionOptions } from 'app/stores/PermissionsStore/PermissionsStore';
const setClassNameHelper = inherited => {
......@@ -12,12 +13,8 @@ export default observer(({ item, removeItem, permissionChanged, itemIndex, folde
removeItem(itemIndex);
};
const handleChangePermission = evt => {
evt.preventDefault();
const value = evt.target.value;
const valueAsInt = parseInt(value, 10);
const newPermission = permissionOptions.find(opt => opt.value === valueAsInt);
permissionChanged(itemIndex, newPermission.value, newPermission.text);
const handleChangePermission = permissionOption => {
permissionChanged(itemIndex, permissionOption.value, permissionOption.label);
};
return (
......@@ -29,21 +26,13 @@ export default observer(({ item, removeItem, permissionChanged, itemIndex, folde
<td>{item.inherited ? <em className="muted no-wrap">Inherited from folder {folderTitle} </em> : null}</td>
<td className="query-keyword">Can</td>
<td>
<div className="gf-form-select-wrapper">
<select
<div className="gf-form">
<DescriptionPicker
optionsWithDesc={permissionOptions}
handlePicked={handleChangePermission}
value={item.permission}
className="gf-form-input gf-size-auto"
onChange={handleChangePermission}
disabled={item.inherited}
>
{permissionOptions.map((option, idx) => {
return (
<option key={idx} value={option.value}>
{option.text}
</option>
);
})}
</select>
/>
</div>
</td>
<td>
......
import React, { Component } from 'react';
export interface IProps {
onSelect: any;
onFocus: any;
option: any;
isFocused: any;
className: any;
}
class DescriptionOption extends Component<IProps, any> {
constructor(props) {
super(props);
this.handleMouseDown = this.handleMouseDown.bind(this);
this.handleMouseEnter = this.handleMouseEnter.bind(this);
this.handleMouseMove = this.handleMouseMove.bind(this);
}
handleMouseDown(event) {
event.preventDefault();
event.stopPropagation();
this.props.onSelect(this.props.option, event);
}
handleMouseEnter(event) {
this.props.onFocus(this.props.option, event);
}
handleMouseMove(event) {
if (this.props.isFocused) {
return;
}
this.props.onFocus(this.props.option, event);
}
render() {
const { option, children, className } = this.props;
return (
<button
onMouseDown={this.handleMouseDown}
onMouseEnter={this.handleMouseEnter}
onMouseMove={this.handleMouseMove}
title={option.title}
className={`user-picker-option__button btn btn-link ${className} width-19`}
style={{
whiteSpace: 'normal',
// height: '55px',
}}
>
<div className="gf-form">{children}</div>
<div className="gf-form">
<div className="muted width-17">{option.description}</div>
{className.indexOf('is-selected') > -1 && (
<i style={{ paddingLeft: '2px' }} className="fa fa-check" aria-hidden="true" />
)}
</div>
</button>
);
}
}
export default DescriptionOption;
import React, { Component } from 'react';
import Select from 'react-select';
import DescriptionOption from './DescriptionOption';
export interface IProps {
optionsWithDesc: OptionWithDescription[];
handlePicked: (permission) => void;
value: number;
disabled: boolean;
}
export interface OptionWithDescription {
value: any;
label: string;
description: string;
}
class DescriptionPicker extends Component<IProps, any> {
constructor(props) {
super(props);
this.state = {};
}
render() {
const { optionsWithDesc, handlePicked, value, disabled } = this.props;
return (
<div className="permissions-picker">
<Select
value={value}
valueKey="value"
multi={false}
clearable={false}
labelKey="label"
options={optionsWithDesc}
onChange={handlePicked}
className="width-7 gf-form-input gf-form-input--form-dropdown"
optionComponent={DescriptionOption}
placeholder="Choose"
disabled={disabled}
/>
</div>
);
}
}
export default DescriptionPicker;
......@@ -3,7 +3,15 @@ import { PermissionsStoreItem } from './PermissionsStoreItem';
const duplicateError = 'This permission exists already.';
export const permissionOptions = [{ value: 1, text: 'View' }, { value: 2, text: 'Edit' }, { value: 4, text: 'Admin' }];
export const permissionOptions = [
{ value: 1, label: 'View', description: 'Can view dashboards.' },
{ value: 2, label: 'Edit', description: 'Can add, edit and delete dashboards.' },
{
value: 4,
label: 'Admin',
description: 'Can add/remove permissions and can add, edit and delete dashboards.',
},
];
export const aclTypes = [
{ value: 'Group', text: 'Team' },
......
......@@ -9,6 +9,9 @@ $select-noresults-color: $text-color;
$select-input-bg: $input-bg;
$select-input-border-color: $input-border-color;
$select-menu-box-shadow: $menu-dropdown-shadow;
$select-text-color: $text-color;
$select-input-bg-disabled: $input-bg-disabled;
$select-option-selected-bg: $dropdownLinkBackgroundActive;
@import '../../../node_modules/react-select/scss/default.scss';
......@@ -36,6 +39,10 @@ $select-menu-box-shadow: $menu-dropdown-shadow;
color: $input-color-placeholder;
}
.Select-menu-outer {
right: 0;
}
> .Select-control {
@include select-control();
border-color: $dark-3;
......@@ -51,15 +58,11 @@ $select-menu-box-shadow: $menu-dropdown-shadow;
.Select-value {
display: inline-block;
padding: 2px 4px;
font-size: $font-size-base * 0.846;
font-weight: bold;
line-height: 14px; // ensure proper line-height if floated
color: $white;
padding: $input-padding-y $input-padding-x;
font-size: $font-size-md;
line-height: $input-line-height;
vertical-align: baseline;
white-space: nowrap;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
background-color: $gray-1;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment