mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
wip: first couple of things starting to work
This commit is contained in:
parent
8096cd8f33
commit
f360b6186b
24
public/app/core/actions/permissions.ts
Normal file
24
public/app/core/actions/permissions.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { DashboardAcl } from '../../types';
|
||||
|
||||
export enum ActionTypes {
|
||||
LoadFolderPermissions = 'LoadFolderPermissions',
|
||||
}
|
||||
|
||||
export interface LoadFolderPermissionsAction {
|
||||
type: ActionTypes.LoadFolderPermissions;
|
||||
payload: DashboardAcl[];
|
||||
}
|
||||
|
||||
export type Action = LoadFolderPermissions;
|
||||
|
||||
export const loadFolderPermissions = (items: DashboardAcl[]): LoadFolderPermissionsAction => ({
|
||||
type: ActionTypes.LoadFolderPermissions,
|
||||
payload: items,
|
||||
});
|
||||
|
||||
export function getFolderPermissions(uid: string): ThunkResult<void> {
|
||||
return async dispatch => {
|
||||
const permissions = await backendSrv.get(`/api/folders/${uid}/permissions`);
|
||||
dispatch(loadFolderPermissions(permissions));
|
||||
};
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
import React, { Component } from 'react';
|
||||
import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker';
|
||||
import { permissionOptions } from 'app/stores/PermissionsStore/PermissionsStore';
|
||||
|
||||
export interface Props {
|
||||
item: any;
|
||||
}
|
||||
|
||||
export default class DisabledPermissionListItem extends Component<Props, any> {
|
||||
render() {
|
||||
const { item } = this.props;
|
||||
|
||||
return (
|
||||
<tr className="gf-form-disabled">
|
||||
<td style={{ width: '1%' }}>
|
||||
<i style={{ width: '25px', height: '25px' }} className="gicon gicon-shield" />
|
||||
</td>
|
||||
<td style={{ width: '90%' }}>
|
||||
{item.name}
|
||||
<span className="filter-table__weak-italic"> (Role)</span>
|
||||
</td>
|
||||
<td />
|
||||
<td className="query-keyword">Can</td>
|
||||
<td>
|
||||
<div className="gf-form">
|
||||
<DescriptionPicker
|
||||
optionsWithDesc={permissionOptions}
|
||||
onSelected={() => {}}
|
||||
value={item.permission}
|
||||
disabled={true}
|
||||
className={'gf-form-input--form-dropdown-right'}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button className="btn btn-inverse btn-small">
|
||||
<i className="fa fa-lock" />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
61
public/app/core/components/PermissionList/PermissionList.tsx
Normal file
61
public/app/core/components/PermissionList/PermissionList.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import PermissionsListItem from './PermissionListItem';
|
||||
import DisabledPermissionsListItem from './DisabledPermissionListItem';
|
||||
import { DashboardAcl, FolderInfo } from 'app/types';
|
||||
|
||||
export interface Props {
|
||||
items: DashboardAcl[];
|
||||
onRemoveItem: (item: DashboardAcl) => void;
|
||||
onPermissionChanged: any;
|
||||
isFetching: boolean;
|
||||
folderInfo?: FolderInfo;
|
||||
}
|
||||
|
||||
class PermissionList extends PureComponent<Props> {
|
||||
render() {
|
||||
const { items, onRemoveItem, onPermissionChanged, isFetching, folderInfo } = this.props;
|
||||
|
||||
return (
|
||||
<table className="filter-table gf-form-group">
|
||||
<tbody>
|
||||
<DisabledPermissionsListItem
|
||||
key={0}
|
||||
item={{
|
||||
name: 'Admin',
|
||||
permission: 4,
|
||||
icon: 'fa fa-fw fa-street-view',
|
||||
}}
|
||||
/>
|
||||
{items.map((item, idx) => {
|
||||
return (
|
||||
<PermissionsListItem
|
||||
key={idx + 1}
|
||||
item={item}
|
||||
onRemoveItem={onRemoveItem}
|
||||
onPermissionChanged={onPermissionChanged}
|
||||
folderInfo={folderInfo}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{isFetching === true && items.length < 1 ? (
|
||||
<tr>
|
||||
<td colSpan={4}>
|
||||
<em>Loading permissions...</em>
|
||||
</td>
|
||||
</tr>
|
||||
) : null}
|
||||
|
||||
{isFetching === false && items.length < 1 ? (
|
||||
<tr>
|
||||
<td colSpan={4}>
|
||||
<em>No permissions are set. Will only be accessible by admins.</em>
|
||||
</td>
|
||||
</tr>
|
||||
) : null}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PermissionList;
|
100
public/app/core/components/PermissionList/PermissionListItem.tsx
Normal file
100
public/app/core/components/PermissionList/PermissionListItem.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import DescriptionPicker from 'app/core/components/Picker/DescriptionPicker';
|
||||
import { dashboardPermissionLevels } from 'app/types/acl';
|
||||
import { DashboardAcl, FolderInfo, PermissionLevel } from 'app/types';
|
||||
|
||||
const setClassNameHelper = inherited => {
|
||||
return inherited ? 'gf-form-disabled' : '';
|
||||
};
|
||||
|
||||
function ItemAvatar({ item }) {
|
||||
if (item.userAvatarUrl) {
|
||||
return <img className="filter-table__avatar" src={item.userAvatarUrl} />;
|
||||
}
|
||||
if (item.teamAvatarUrl) {
|
||||
return <img className="filter-table__avatar" src={item.teamAvatarUrl} />;
|
||||
}
|
||||
if (item.role === 'Editor') {
|
||||
return <i style={{ width: '25px', height: '25px' }} className="gicon gicon-editor" />;
|
||||
}
|
||||
|
||||
return <i style={{ width: '25px', height: '25px' }} className="gicon gicon-viewer" />;
|
||||
}
|
||||
|
||||
function ItemDescription({ item }) {
|
||||
if (item.userId) {
|
||||
return <span className="filter-table__weak-italic">(User)</span>;
|
||||
}
|
||||
if (item.teamId) {
|
||||
return <span className="filter-table__weak-italic">(Team)</span>;
|
||||
}
|
||||
return <span className="filter-table__weak-italic">(Role)</span>;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
item: DashboardAcl;
|
||||
onRemoveItem: (item: DashboardAcl) => void;
|
||||
onPermissionChanged: (item: DashboardAcl, level: PermissionLevel) => void;
|
||||
folderInfo?: FolderInfo;
|
||||
}
|
||||
|
||||
export default class PermissionsListItem extends PureComponent<Props> {
|
||||
onPermissionChanged = option => {
|
||||
this.props.onPermissionChanged(this.props.item, option.value as PermissionLevel);
|
||||
};
|
||||
|
||||
onRemoveItem = () => {
|
||||
this.props.onRemoveItem(this.props.item);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { item, folderInfo } = this.props;
|
||||
const inheritedFromRoot = item.dashboardId === -1 && !item.inherited;
|
||||
|
||||
return (
|
||||
<tr className={setClassNameHelper(item.inherited)}>
|
||||
<td style={{ width: '1%' }}>
|
||||
<ItemAvatar item={item} />
|
||||
</td>
|
||||
<td style={{ width: '90%' }}>
|
||||
{item.name} <ItemDescription item={item} />
|
||||
</td>
|
||||
<td>
|
||||
{item.inherited &&
|
||||
folderInfo && (
|
||||
<em className="muted no-wrap">
|
||||
Inherited from folder{' '}
|
||||
<a className="text-link" href={`${folderInfo.url}/permissions`}>
|
||||
{folderInfo.title}
|
||||
</a>{' '}
|
||||
</em>
|
||||
)}
|
||||
{inheritedFromRoot && <em className="muted no-wrap">Default Permission</em>}
|
||||
</td>
|
||||
<td className="query-keyword">Can</td>
|
||||
<td>
|
||||
<div className="gf-form">
|
||||
<DescriptionPicker
|
||||
optionsWithDesc={dashboardPermissionLevels}
|
||||
onSelected={this.onPermissionChanged}
|
||||
value={item.permission}
|
||||
disabled={item.inherited}
|
||||
className={'gf-form-input--form-dropdown-right'}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{!item.inherited ? (
|
||||
<a className="btn btn-danger btn-small" onClick={this.onRemoveItem}>
|
||||
<i className="fa fa-remove" />
|
||||
</a>
|
||||
) : (
|
||||
<button className="btn btn-inverse btn-small">
|
||||
<i className="fa fa-lock" />
|
||||
</button>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { inject, observer } from 'mobx-react';
|
||||
import { connect } from 'react-redux';
|
||||
import PageHeader from 'app/core/components/PageHeader/PageHeader';
|
||||
import Permissions from 'app/core/components/Permissions/Permissions';
|
||||
@ -9,50 +8,61 @@ 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 { getNavModel } from 'app/core/selectors/navModel';
|
||||
import { NavModel, StoreState, FolderState } from 'app/types';
|
||||
import { getFolderByUid } from './state/actions';
|
||||
import { PermissionsStore } from 'app/stores/PermissionsStore/PermissionsStore';
|
||||
import { NavModel, StoreState, FolderState, DashboardAcl, PermissionLevel } from 'app/types';
|
||||
import { getFolderByUid, getFolderPermissions, updateFolderPermission, removeFolderPermission } from './state/actions';
|
||||
import { getLoadingNav } from './state/navModel';
|
||||
import PermissionList from 'app/core/components/PermissionList/PermissionList';
|
||||
|
||||
export interface Props {
|
||||
navModel: NavModel;
|
||||
getFolderByUid: typeof getFolderByUid;
|
||||
folderUid: string;
|
||||
folder: FolderState;
|
||||
permissions: typeof PermissionsStore.Type;
|
||||
backendSrv: any;
|
||||
getFolderByUid: typeof getFolderByUid;
|
||||
getFolderPermissions: typeof getFolderPermissions;
|
||||
updateFolderPermission: typeof updateFolderPermission;
|
||||
removeFolderPermission: typeof removeFolderPermission;
|
||||
}
|
||||
|
||||
@inject('permissions')
|
||||
@observer
|
||||
export class FolderPermissions extends Component<Props> {
|
||||
export interface State {
|
||||
isAdding: boolean;
|
||||
}
|
||||
|
||||
export class FolderPermissions extends Component<Props, State> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleAddPermission = this.handleAddPermission.bind(this);
|
||||
|
||||
this.state = {
|
||||
isAdding: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.getFolderByUid(this.props.folderUid);
|
||||
this.props.getFolderPermissions(this.props.folderUid);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const { permissions } = this.props;
|
||||
permissions.hideAddPermissions();
|
||||
}
|
||||
onOpenAddPermissions = () => {
|
||||
this.setState({ isAdding: true });
|
||||
};
|
||||
|
||||
handleAddPermission() {
|
||||
const { permissions } = this.props;
|
||||
permissions.toggleAddPermissions();
|
||||
}
|
||||
onRemoveItem = (item: DashboardAcl) => {
|
||||
this.props.removeFolderPermission(item);
|
||||
};
|
||||
|
||||
onPermissionChanged = (item: DashboardAcl, level: PermissionLevel) => {
|
||||
this.props.updateFolderPermission(item, level);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { navModel, permissions, backendSrv, folder } = this.props;
|
||||
const { navModel, folder } = this.props;
|
||||
const { isAdding } = this.state;
|
||||
|
||||
if (folder.id === 0) {
|
||||
return <PageHeader model={navModel} />;
|
||||
}
|
||||
|
||||
const dashboardId = folder.id;
|
||||
const folderInfo = { title: folder.tile, url: folder.url, id: folder.id };
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -64,18 +74,17 @@ export class FolderPermissions extends Component<Props> {
|
||||
<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}
|
||||
disabled={permissions.isAddPermissionsVisible}
|
||||
>
|
||||
<button className="btn btn-success pull-right" onClick={this.onOpenAddPermissions} disabled={isAdding}>
|
||||
<i className="fa fa-plus" /> Add Permission
|
||||
</button>
|
||||
</div>
|
||||
<SlideDown in={permissions.isAddPermissionsVisible}>
|
||||
<AddPermissions permissions={permissions} />
|
||||
</SlideDown>
|
||||
<Permissions permissions={permissions} isFolder={true} dashboardId={dashboardId} backendSrv={backendSrv} />
|
||||
<PermissionList
|
||||
items={folder.permissions}
|
||||
onRemoveItem={this.onRemoveItem}
|
||||
onPermissionChanged={this.onPermissionChanged}
|
||||
isFetching={false}
|
||||
folderInfo={folderInfo}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -93,6 +102,9 @@ const mapStateToProps = (state: StoreState) => {
|
||||
|
||||
const mapDispatchToProps = {
|
||||
getFolderByUid,
|
||||
getFolderPermissions,
|
||||
updateFolderPermission,
|
||||
removeFolderPermission,
|
||||
};
|
||||
|
||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(FolderPermissions));
|
||||
|
@ -1,7 +1,14 @@
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
import { StoreState } from 'app/types';
|
||||
import { ThunkAction } from 'redux-thunk';
|
||||
import { FolderDTO, FolderState } from 'app/types';
|
||||
import {
|
||||
FolderDTO,
|
||||
FolderState,
|
||||
DashboardAcl,
|
||||
DashboardAclDTO,
|
||||
PermissionLevel,
|
||||
DashboardAclUpdateDTO,
|
||||
} from 'app/types';
|
||||
import { updateNavIndex, updateLocation } from 'app/core/actions';
|
||||
import { buildNavModel } from './navModel';
|
||||
import appEvents from 'app/core/app_events';
|
||||
@ -10,6 +17,7 @@ export enum ActionTypes {
|
||||
LoadFolder = 'LOAD_FOLDER',
|
||||
SetFolderTitle = 'SET_FOLDER_TITLE',
|
||||
SaveFolder = 'SAVE_FOLDER',
|
||||
LoadFolderPermissions = 'LOAD_FOLDER_PERMISSONS',
|
||||
}
|
||||
|
||||
export interface LoadFolderAction {
|
||||
@ -22,6 +30,15 @@ export interface SetFolderTitleAction {
|
||||
payload: string;
|
||||
}
|
||||
|
||||
export interface LoadFolderPermissionsAction {
|
||||
type: ActionTypes.LoadFolderPermissions;
|
||||
payload: DashboardAcl[];
|
||||
}
|
||||
|
||||
export type Action = LoadFolderAction | SetFolderTitleAction | LoadFolderPermissionsAction;
|
||||
|
||||
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>;
|
||||
|
||||
export const loadFolder = (folder: FolderDTO): LoadFolderAction => ({
|
||||
type: ActionTypes.LoadFolder,
|
||||
payload: folder,
|
||||
@ -32,10 +49,10 @@ export const setFolderTitle = (newTitle: string): SetFolderTitleAction => ({
|
||||
payload: newTitle,
|
||||
});
|
||||
|
||||
export type Action = LoadFolderAction | SetFolderTitleAction;
|
||||
|
||||
type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>;
|
||||
|
||||
export const loadFolderPermissions = (items: DashboardAclDTO[]): LoadFolderPermissionsAction => ({
|
||||
type: ActionTypes.LoadFolderPermissions,
|
||||
payload: items,
|
||||
});
|
||||
|
||||
export function getFolderByUid(uid: string): ThunkResult<void> {
|
||||
return async dispatch => {
|
||||
@ -65,3 +82,61 @@ export function deleteFolder(uid: string): ThunkResult<void> {
|
||||
dispatch(updateLocation({ path: `dashboards` }));
|
||||
};
|
||||
}
|
||||
|
||||
export function getFolderPermissions(uid: string): ThunkResult<void> {
|
||||
return async dispatch => {
|
||||
const permissions = await getBackendSrv().get(`/api/folders/${uid}/permissions`);
|
||||
dispatch(loadFolderPermissions(permissions));
|
||||
};
|
||||
}
|
||||
|
||||
function toUpdateItem(item: DashboardAcl): DashboardAclUpdateDTO {
|
||||
return {
|
||||
userId: item.userId,
|
||||
teamId: item.teamId,
|
||||
role: item.role,
|
||||
permission: item.permission,
|
||||
};
|
||||
}
|
||||
|
||||
export function updateFolderPermission(itemToUpdate: DashboardAcl, level: PermissionLevel): ThunkResult<void> {
|
||||
return async (dispatch, getStore) => {
|
||||
const folder = getStore().folder;
|
||||
const itemsToUpdate = [];
|
||||
|
||||
for (const item of folder.permissions) {
|
||||
if (item.inherited) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const updated = toUpdateItem(itemToUpdate);
|
||||
|
||||
// if this is the item we want to update, update it's permisssion
|
||||
if (itemToUpdate === item) {
|
||||
updated.permission = level;
|
||||
}
|
||||
|
||||
itemsToUpdate.push(updated);
|
||||
}
|
||||
|
||||
await getBackendSrv().post(`/api/folders/${folder.uid}/permissions`, { items: itemsToUpdate });
|
||||
await dispatch(getFolderPermissions(folder.uid));
|
||||
};
|
||||
}
|
||||
|
||||
export function removeFolderPermission(itemToDelete: DashboardAcl): ThunkResult<void> {
|
||||
return async (dispatch, getStore) => {
|
||||
const folder = getStore().folder;
|
||||
const itemsToUpdate = [];
|
||||
|
||||
for (const item of folder.permissions) {
|
||||
if (item.inherited || item === itemToDelete) {
|
||||
continue;
|
||||
}
|
||||
itemsToUpdate.push(toUpdateItem(item));
|
||||
}
|
||||
|
||||
await getBackendSrv().post(`/api/folders/${folder.uid}/permissions`, { items: itemsToUpdate });
|
||||
await dispatch(getFolderPermissions(folder.uid));
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FolderState } from 'app/types';
|
||||
import { FolderState, DashboardAcl, DashboardAclDTO } from 'app/types';
|
||||
import { Action, ActionTypes } from './actions';
|
||||
|
||||
export const inititalState: FolderState = {
|
||||
@ -8,13 +8,15 @@ export const inititalState: FolderState = {
|
||||
url: '',
|
||||
canSave: false,
|
||||
hasChanged: false,
|
||||
version: 0,
|
||||
version: 1,
|
||||
permissions: [],
|
||||
};
|
||||
|
||||
export const folderReducer = (state = inititalState, action: Action): FolderState => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.LoadFolder:
|
||||
return {
|
||||
...state,
|
||||
...action.payload,
|
||||
hasChanged: false,
|
||||
};
|
||||
@ -24,10 +26,45 @@ export const folderReducer = (state = inititalState, action: Action): FolderStat
|
||||
title: action.payload,
|
||||
hasChanged: action.payload.trim().length > 0,
|
||||
};
|
||||
case ActionTypes.LoadFolderPermissions:
|
||||
return {
|
||||
...state,
|
||||
permissions: processAclItems(action.payload),
|
||||
};
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
function processAclItems(items: DashboardAclDTO[]): DashboardAcl[] {
|
||||
return items.map(processAclItem).sort((a, b) => b.sortRank - a.sortRank || a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
function processAclItem(dto: DashboardAclDTO): DashboardAcl {
|
||||
const item = dto as DashboardAcl;
|
||||
|
||||
item.sortRank = 0;
|
||||
if (item.userId > 0) {
|
||||
item.name = item.userLogin;
|
||||
item.sortRank = 10;
|
||||
} else if (item.teamId > 0) {
|
||||
item.name = item.team;
|
||||
item.sortRank = 20;
|
||||
} else if (item.role) {
|
||||
item.icon = 'fa fa-fw fa-street-view';
|
||||
item.name = item.role;
|
||||
item.sortRank = 30;
|
||||
if (item.role === 'Editor') {
|
||||
item.sortRank += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.inherited) {
|
||||
item.sortRank += 100;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
export default {
|
||||
folder: folderReducer,
|
||||
};
|
||||
|
60
public/app/types/acl.ts
Normal file
60
public/app/types/acl.ts
Normal file
@ -0,0 +1,60 @@
|
||||
export interface DashboardAclDTO {
|
||||
id?: number;
|
||||
dashboardId?: number;
|
||||
userId?: number;
|
||||
userLogin?: string;
|
||||
userEmail?: string;
|
||||
teamId?: number;
|
||||
team?: string;
|
||||
permission?: PermissionLevel;
|
||||
permissionName?: string;
|
||||
role?: string;
|
||||
icon?: string;
|
||||
inherited?: boolean;
|
||||
}
|
||||
|
||||
export interface DashboardAclUpdateDTO {
|
||||
userId: number;
|
||||
teamId: number;
|
||||
role: string;
|
||||
permission: PermissionLevel;
|
||||
}
|
||||
|
||||
export interface DashboardAcl {
|
||||
id?: number;
|
||||
dashboardId?: number;
|
||||
userId?: number;
|
||||
userLogin?: string;
|
||||
userEmail?: string;
|
||||
teamId?: number;
|
||||
team?: string;
|
||||
permission?: PermissionLevel;
|
||||
permissionName?: string;
|
||||
role?: string;
|
||||
icon?: string;
|
||||
name?: string;
|
||||
inherited?: boolean;
|
||||
sortRank?: number;
|
||||
}
|
||||
|
||||
export interface DashboardPermissionInfo {
|
||||
value: PermissionLevel;
|
||||
label: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export enum PermissionLevel {
|
||||
View = 1,
|
||||
Edit = 2,
|
||||
Admin = 4,
|
||||
}
|
||||
|
||||
export const dashboardPermissionLevels: DashboardPermissionInfo[] = [
|
||||
{ value: PermissionLevel.View, label: 'View', description: 'Can view dashboards.' },
|
||||
{ value: PermissionLevel.Edit, label: 'Edit', description: 'Can add, edit and delete dashboards.' },
|
||||
{
|
||||
value: PermissionLevel.Admin,
|
||||
label: 'Admin',
|
||||
description: 'Can add/remove permissions and can add, edit and delete dashboards.',
|
||||
},
|
||||
];
|
@ -1,3 +1,5 @@
|
||||
import { DashboardAcl } from './acl';
|
||||
|
||||
export interface FolderDTO {
|
||||
id: number;
|
||||
uid: string;
|
||||
@ -12,7 +14,14 @@ export interface FolderState {
|
||||
uid: string;
|
||||
title: string;
|
||||
url: string;
|
||||
version: number;
|
||||
canSave: boolean;
|
||||
hasChanged: boolean;
|
||||
version: number;
|
||||
permissions: DashboardAcl[];
|
||||
}
|
||||
|
||||
export interface FolderInfo {
|
||||
id: number;
|
||||
title: string;
|
||||
url: string;
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ import { Team, TeamsState, TeamState, TeamGroup, TeamMember } from './teams';
|
||||
import { AlertRuleDTO, AlertRule, AlertRulesState } from './alerting';
|
||||
import { LocationState, LocationUpdate, UrlQueryMap, UrlQueryValue } from './location';
|
||||
import { NavModel, NavModelItem, NavIndex } from './navModel';
|
||||
import { FolderDTO, FolderState } from './folder';
|
||||
import { FolderDTO, FolderState, FolderInfo } from './folder';
|
||||
import { DashboardAcl, DashboardAclDTO, PermissionLevel, DashboardAclUpdateDTO } from './acl';
|
||||
|
||||
export {
|
||||
Team,
|
||||
@ -22,6 +23,11 @@ export {
|
||||
UrlQueryValue,
|
||||
FolderDTO,
|
||||
FolderState,
|
||||
FolderInfo,
|
||||
DashboardAcl,
|
||||
DashboardAclDTO,
|
||||
DashboardAclUpdateDTO,
|
||||
PermissionLevel,
|
||||
};
|
||||
|
||||
export interface StoreState {
|
||||
|
Loading…
Reference in New Issue
Block a user