wip: first couple of things starting to work

This commit is contained in:
Torkel Ödegaard
2018-09-13 10:52:29 +02:00
parent 8096cd8f33
commit f360b6186b
10 changed files with 465 additions and 38 deletions

View File

@@ -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));

View File

@@ -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));
};
}

View File

@@ -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,
};