Commit d74a98fe by Daniel Lee

dashfolders: link to folder for inherited permissions

In the permissions view in dashboard settings, this adds a
link to the parent folder for inherited permissions. Which
allows the user to easily navigate to the folder and change
inherited permissions.
parent 7900fd4a
...@@ -99,6 +99,7 @@ func GetDashboard(c *middleware.Context) Response { ...@@ -99,6 +99,7 @@ func GetDashboard(c *middleware.Context) Response {
return ApiError(500, "Dashboard folder could not be read", err) return ApiError(500, "Dashboard folder could not be read", err)
} }
meta.FolderTitle = query.Result.Title meta.FolderTitle = query.Result.Title
meta.FolderSlug = query.Result.Slug
} }
// make sure db version is in sync with json model version // make sure db version is in sync with json model version
......
...@@ -26,6 +26,7 @@ type DashboardMeta struct { ...@@ -26,6 +26,7 @@ type DashboardMeta struct {
IsFolder bool `json:"isFolder"` IsFolder bool `json:"isFolder"`
FolderId int64 `json:"folderId"` FolderId int64 `json:"folderId"`
FolderTitle string `json:"folderTitle"` FolderTitle string `json:"folderTitle"`
FolderSlug string `json:"folderSlug"`
} }
type DashboardFullWithMeta struct { type DashboardFullWithMeta struct {
......
...@@ -20,5 +20,11 @@ export function registerAngularDirectives() { ...@@ -20,5 +20,11 @@ export function registerAngularDirectives() {
['tagOptions', { watchDepth: 'reference' }], ['tagOptions', { watchDepth: 'reference' }],
]); ]);
react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'handlePicked']); react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'handlePicked']);
react2AngularDirective('dashboardPermissions', DashboardPermissions, ['backendSrv', 'dashboardId', 'folderTitle']); react2AngularDirective('dashboardPermissions', DashboardPermissions, [
'backendSrv',
'dashboardId',
'folderTitle',
'folderSlug',
'folderId',
]);
} }
...@@ -6,7 +6,9 @@ import PermissionsInfo from 'app/core/components/Permissions/PermissionsInfo'; ...@@ -6,7 +6,9 @@ import PermissionsInfo from 'app/core/components/Permissions/PermissionsInfo';
export interface IProps { export interface IProps {
dashboardId: number; dashboardId: number;
folderId: number;
folderTitle: string; folderTitle: string;
folderSlug: string;
backendSrv: any; backendSrv: any;
} }
...@@ -19,7 +21,7 @@ class DashboardPermissions extends Component<IProps, any> { ...@@ -19,7 +21,7 @@ class DashboardPermissions extends Component<IProps, any> {
} }
render() { render() {
const { dashboardId, folderTitle, backendSrv } = this.props; const { dashboardId, folderTitle, folderSlug, folderId, backendSrv } = this.props;
return ( return (
<div> <div>
...@@ -33,7 +35,7 @@ class DashboardPermissions extends Component<IProps, any> { ...@@ -33,7 +35,7 @@ class DashboardPermissions extends Component<IProps, any> {
permissions={this.permissions} permissions={this.permissions}
isFolder={false} isFolder={false}
dashboardId={dashboardId} dashboardId={dashboardId}
folderTitle={folderTitle} folderInfo={{ title: folderTitle, slug: folderSlug, id: folderId }}
backendSrv={backendSrv} backendSrv={backendSrv}
/> />
</div> </div>
......
export interface FolderInfo {
title: string;
id: number;
slug: string;
}
...@@ -4,6 +4,7 @@ import { observer } from 'mobx-react'; ...@@ -4,6 +4,7 @@ import { observer } from 'mobx-react';
import UserPicker, { User } from 'app/core/components/Picker/UserPicker'; import UserPicker, { User } from 'app/core/components/Picker/UserPicker';
import TeamPicker, { Team } from 'app/core/components/Picker/TeamPicker'; import TeamPicker, { Team } from 'app/core/components/Picker/TeamPicker';
import { aclTypes } from 'app/stores/PermissionsStore/PermissionsStore'; import { aclTypes } from 'app/stores/PermissionsStore/PermissionsStore';
import { FolderInfo } from './FolderInfo';
export interface DashboardAcl { export interface DashboardAcl {
id?: number; id?: number;
...@@ -25,7 +26,7 @@ export interface DashboardAcl { ...@@ -25,7 +26,7 @@ export interface DashboardAcl {
export interface IProps { export interface IProps {
dashboardId: number; dashboardId: number;
folderTitle?: string; folderInfo?: FolderInfo;
permissions?: any; permissions?: any;
isFolder: boolean; isFolder: boolean;
backendSrv: any; backendSrv: any;
...@@ -87,7 +88,7 @@ class Permissions extends Component<IProps, any> { ...@@ -87,7 +88,7 @@ class Permissions extends Component<IProps, any> {
} }
render() { render() {
const { permissions, folderTitle, backendSrv } = this.props; const { permissions, folderInfo, backendSrv } = this.props;
return ( return (
<div className="gf-form-group"> <div className="gf-form-group">
...@@ -96,7 +97,7 @@ class Permissions extends Component<IProps, any> { ...@@ -96,7 +97,7 @@ class Permissions extends Component<IProps, any> {
removeItem={this.removeItem} removeItem={this.removeItem}
permissionChanged={this.permissionChanged} permissionChanged={this.permissionChanged}
fetching={permissions.fetching} fetching={permissions.fetching}
folderTitle={folderTitle} folderInfo={folderInfo}
/> />
<div className="gf-form-inline"> <div className="gf-form-inline">
<form name="addPermission" className="gf-form-group"> <form name="addPermission" className="gf-form-group">
......
...@@ -2,19 +2,20 @@ ...@@ -2,19 +2,20 @@
import PermissionsListItem from './PermissionsListItem'; import PermissionsListItem from './PermissionsListItem';
import DisabledPermissionsListItem from './DisabledPermissionsListItem'; import DisabledPermissionsListItem from './DisabledPermissionsListItem';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { FolderInfo } from './FolderInfo';
export interface IProps { export interface IProps {
permissions: any[]; permissions: any[];
removeItem: any; removeItem: any;
permissionChanged: any; permissionChanged: any;
fetching: boolean; fetching: boolean;
folderTitle: string; folderInfo?: FolderInfo;
} }
@observer @observer
class PermissionsList extends Component<IProps, any> { class PermissionsList extends Component<IProps, any> {
render() { render() {
const { permissions, removeItem, permissionChanged, fetching, folderTitle } = this.props; const { permissions, removeItem, permissionChanged, fetching, folderInfo } = this.props;
return ( return (
<table className="filter-table gf-form-group"> <table className="filter-table gf-form-group">
...@@ -35,7 +36,7 @@ class PermissionsList extends Component<IProps, any> { ...@@ -35,7 +36,7 @@ class PermissionsList extends Component<IProps, any> {
itemIndex={idx} itemIndex={idx}
removeItem={removeItem} removeItem={removeItem}
permissionChanged={permissionChanged} permissionChanged={permissionChanged}
folderTitle={folderTitle} folderInfo={folderInfo}
/> />
); );
})} })}
......
...@@ -7,7 +7,7 @@ const setClassNameHelper = inherited => { ...@@ -7,7 +7,7 @@ const setClassNameHelper = inherited => {
return inherited ? 'gf-form-disabled' : ''; return inherited ? 'gf-form-disabled' : '';
}; };
export default observer(({ item, removeItem, permissionChanged, itemIndex, folderTitle }) => { export default observer(({ item, removeItem, permissionChanged, itemIndex, folderInfo }) => {
const handleRemoveItem = evt => { const handleRemoveItem = evt => {
evt.preventDefault(); evt.preventDefault();
removeItem(itemIndex); removeItem(itemIndex);
...@@ -23,7 +23,16 @@ export default observer(({ item, removeItem, permissionChanged, itemIndex, folde ...@@ -23,7 +23,16 @@ export default observer(({ item, removeItem, permissionChanged, itemIndex, folde
<i className={item.icon} /> <i className={item.icon} />
<span dangerouslySetInnerHTML={{ __html: item.nameHtml }} /> <span dangerouslySetInnerHTML={{ __html: item.nameHtml }} />
</td> </td>
<td>{item.inherited ? <em className="muted no-wrap">Inherited from folder {folderTitle} </em> : null}</td> <td>
{item.inherited && folderInfo ? (
<em className="muted no-wrap">
Inherited from folder{' '}
<a className="text-link" href={`dashboards/folder/${folderInfo.id}/${folderInfo.slug}/permissions`}>
{folderInfo.title}
</a>{' '}
</em>
) : null}
</td>
<td className="query-keyword">Can</td> <td className="query-keyword">Can</td>
<td> <td>
<div className="gf-form"> <div className="gf-form">
...@@ -41,7 +50,11 @@ export default observer(({ item, removeItem, permissionChanged, itemIndex, folde ...@@ -41,7 +50,11 @@ export default observer(({ item, removeItem, permissionChanged, itemIndex, folde
<a className="btn btn-danger btn-small" onClick={handleRemoveItem}> <a className="btn btn-danger btn-small" onClick={handleRemoveItem}>
<i className="fa fa-remove" /> <i className="fa fa-remove" />
</a> </a>
) : null} ) : (
<button className="btn btn-inverse btn-small">
<i className="fa fa-lock" />
</button>
)}
</td> </td>
</tr> </tr>
); );
......
...@@ -100,6 +100,8 @@ ...@@ -100,6 +100,8 @@
dashboardId="ctrl.dashboard.id" dashboardId="ctrl.dashboard.id"
backendSrv="ctrl.backendSrv" backendSrv="ctrl.backendSrv"
folderTitle="ctrl.dashboard.meta.folderTitle" folderTitle="ctrl.dashboard.meta.folderTitle"
folderSlug="ctrl.dashboard.meta.folderSlug"
folderId="ctrl.dashboard.meta.folderId"
/> />
</div> </div>
......
...@@ -191,6 +191,7 @@ export class SettingsCtrl { ...@@ -191,6 +191,7 @@ export class SettingsCtrl {
onFolderChange(folder) { onFolderChange(folder) {
this.dashboard.meta.folderId = folder.id; this.dashboard.meta.folderId = folder.id;
this.dashboard.meta.folderTitle = folder.title; this.dashboard.meta.folderTitle = folder.title;
this.dashboard.meta.folderSlug = folder.slug;
} }
} }
......
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