Commit c8193e10 by Johannes Schill Committed by Daniel Lee

dashfolder: wip: More wip on acl.html2permissions.tsx #10275

parent 7616cfb5
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
"typescript": "^2.6.2", "typescript": "^2.6.2",
"webpack": "^3.10.0", "webpack": "^3.10.0",
"webpack-bundle-analyzer": "^2.9.0", "webpack-bundle-analyzer": "^2.9.0",
"webpack-cleanup-plugin": "^0.5.1", "webpack-cleanup-plugin": "^0.5.1",
"webpack-merge": "^4.1.0", "webpack-merge": "^4.1.0",
"zone.js": "^0.7.2" "zone.js": "^0.7.2"
}, },
...@@ -140,6 +140,7 @@ ...@@ -140,6 +140,7 @@
"lodash": "^4.17.4", "lodash": "^4.17.4",
"mobx": "^3.4.1", "mobx": "^3.4.1",
"mobx-react": "^4.3.5", "mobx-react": "^4.3.5",
"mobx-react-devtools": "^4.2.15",
"mobx-state-tree": "^1.3.1", "mobx-state-tree": "^1.3.1",
"moment": "^2.18.1", "moment": "^2.18.1",
"mousetrap": "^1.6.0", "mousetrap": "^1.6.0",
...@@ -148,8 +149,8 @@ ...@@ -148,8 +149,8 @@
"react": "^16.2.0", "react": "^16.2.0",
"react-dom": "^16.2.0", "react-dom": "^16.2.0",
"react-grid-layout": "^0.16.2", "react-grid-layout": "^0.16.2",
"react-popper": "^0.7.5",
"react-highlight-words": "^0.10.0", "react-highlight-words": "^0.10.0",
"react-popper": "^0.7.5",
"react-select": "^1.1.0", "react-select": "^1.1.0",
"react-sizeme": "^2.3.6", "react-sizeme": "^2.3.6",
"remarkable": "^1.7.1", "remarkable": "^1.7.1",
......
import React, { Component } from 'react'; import React, { Component } from 'react';
import PermissionsList from './PermissionsList'; import PermissionsList from './PermissionsList';
import _ from 'lodash'; import _ from 'lodash';
import DevTools from 'mobx-react-devtools';
import { inject, observer } from 'mobx-react';
import { Provider } from 'mobx-react';
import { store } from 'app/stores/store';
export interface DashboardAcl { export interface DashboardAcl {
id?: number; id?: number;
...@@ -24,12 +28,25 @@ export interface IProps { ...@@ -24,12 +28,25 @@ export interface IProps {
error: any; error: any;
newType: any; newType: any;
aclTypes: any; aclTypes: any;
typeChanged: any;
backendSrv: any; backendSrv: any;
dashboardId: number; dashboardId: number;
permissions: any;
} }
class Permissions extends Component<IProps, any> { class Permissions extends Component<IProps, any> {
render() {
return (
<Provider {...store}>
<PermissionsInner {...this.props} />
</Provider>
);
}
}
@inject('permissions')
@observer
class PermissionsInner extends Component<IProps, any> {
// TODO Remove Inner from Name when we get access via ReactContainer
dashboardId: any; dashboardId: any;
meta: any; meta: any;
items: DashboardAcl[]; items: DashboardAcl[];
...@@ -50,58 +67,34 @@ class Permissions extends Component<IProps, any> { ...@@ -50,58 +67,34 @@ class Permissions extends Component<IProps, any> {
constructor(props) { constructor(props) {
super(props); super(props);
this.dashboardId = this.props.dashboardId;
this.backendSrv = this.props.backendSrv; const { dashboardId, backendSrv, permissions } = this.props;
this.dashboardId = dashboardId;
this.backendSrv = backendSrv;
this.permissionChanged = this.permissionChanged.bind(this); this.permissionChanged = this.permissionChanged.bind(this);
console.log('this.setState', this.setState); this.typeChanged = this.typeChanged.bind(this);
this.removeItem = this.removeItem.bind(this);
permissions.load(this.dashboardId);
this.state = { this.state = {
items: [], newType: 'Group',
newType: '',
canUpdate: false, canUpdate: false,
error: '', error: '',
}; };
} }
componentWillMount() {
this.getAcl(this.props.dashboardId);
}
getAcl(dashboardId: number) {
return this.backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`).then(result => {
console.log('this', this.setState);
const items = result.map(this.prepareViewModel.bind(this));
// this.items = _.map(result, this.prepareViewModel.bind(this));
this.setState(prevState => {
return {
...prevState,
items: this.sortItems(items),
};
});
});
}
sortItems(items) { sortItems(items) {
return _.orderBy(items, ['sortRank', 'sortName'], ['desc', 'asc']); return _.orderBy(items, ['sortRank', 'sortName'], ['desc', 'asc']);
} }
permissionChanged() { permissionChanged(evt) {
this.setState(prevState => { // TODO
return {
...prevState,
canUpdate: true,
};
});
} }
removeItem(index) { removeItem(index) {
this.setState(prevState => { const { permissions } = this.props;
return { permissions.removeStoreItem(index);
...prevState,
items: this.state.items.splice(index, 1),
canUpdate: true,
};
});
} }
update() { update() {
...@@ -168,29 +161,91 @@ class Permissions extends Component<IProps, any> { ...@@ -168,29 +161,91 @@ class Permissions extends Component<IProps, any> {
return item; return item;
} }
// componentWillUpdate(nextProps, nextState) { isDuplicate(origItem, newItem) {
// console.log('nextProps', nextProps); if (origItem.inherited) {
// console.log('nextState', nextState); return false;
// } }
// componentWillReceiveProps(nextProps) { return (
// console.log('nextPropzzzz', nextProps); (origItem.role && newItem.role && origItem.role === newItem.role) ||
// } (origItem.userId && newItem.userId && origItem.userId === newItem.userId) ||
(origItem.teamId && newItem.teamId && origItem.teamId === newItem.teamId)
);
}
render() { isValid(item) {
const { error, newType, aclTypes, typeChanged } = this.props; const dupe = _.find(this.items, it => {
return this.isDuplicate(it, item);
});
if (dupe) {
this.error = this.duplicateError;
return false;
}
const { items, canUpdate } = this.state; return true;
}
const handleTypeChange = () => { addNewItem(item) {
typeChanged(); if (!this.isValid(item)) {
}; return;
}
this.error = '';
item.dashboardId = this.dashboardId;
let newItems = this.state.items;
newItems.push(this.prepareViewModel(item));
this.setState(prevState => {
return {
...prevState,
items: this.sortItems(newItems),
canUpdate: true,
};
});
}
resetNewType() {
this.setState(prevState => {
return {
newType: 'Group',
};
});
}
typeChanged(evt) {
const { value } = evt.target;
this.setState(prevState => {
return {
...prevState,
newType: value,
};
});
}
typeChanged___() {
const { newType } = this.state;
if (newType === 'Viewer' || newType === 'Editor') {
this.addNewItem({ permission: 1, role: newType });
this.resetNewType();
this.setState(prevState => {
return {
...prevState,
canUpdate: true,
};
});
}
}
render() {
const { error, aclTypes, permissions } = this.props;
const { newType } = this.state;
return ( return (
<div className="gf-form-group"> <div className="gf-form-group">
asd
<PermissionsList <PermissionsList
permissions={items} permissions={permissions.items.toJS()}
permissionsOptions={this.permissionOptions} permissionsOptions={this.permissionOptions}
removeItem={this.removeItem} removeItem={this.removeItem}
permissionChanged={this.permissionChanged} permissionChanged={this.permissionChanged}
...@@ -202,7 +257,7 @@ class Permissions extends Component<IProps, any> { ...@@ -202,7 +257,7 @@ class Permissions extends Component<IProps, any> {
<div className="gf-form-inline"> <div className="gf-form-inline">
<div className="gf-form"> <div className="gf-form">
<div className="gf-form-select-wrapper"> <div className="gf-form-select-wrapper">
<select className="gf-form-input gf-size-auto" onChange={handleTypeChange}> <select className="gf-form-input gf-size-auto" onChange={this.typeChanged}>
{aclTypes.map((option, idx) => { {aclTypes.map((option, idx) => {
return ( return (
<option key={idx} value={option.value}> <option key={idx} value={option.value}>
...@@ -222,12 +277,16 @@ class Permissions extends Component<IProps, any> { ...@@ -222,12 +277,16 @@ class Permissions extends Component<IProps, any> {
</div> </div>
{newType === 'User' ? ( {newType === 'User' ? (
<div className="gf-form"> <div className="gf-form">
{' '}
User picker
<user-picker user-picked="ctrl.userPicked($user)" /> <user-picker user-picked="ctrl.userPicked($user)" />
</div> </div>
) : null} ) : null}
{newType === 'Group' ? ( {newType === 'Group' ? (
<div className="gf-form"> <div className="gf-form">
{' '}
Team picker
<team-picker team-picked="ctrl.groupPicked($group)" /> <team-picker team-picked="ctrl.groupPicked($group)" />
</div> </div>
) : null} ) : null}
...@@ -243,11 +302,12 @@ class Permissions extends Component<IProps, any> { ...@@ -243,11 +302,12 @@ class Permissions extends Component<IProps, any> {
) : null} ) : null}
</div> </div>
<div className="gf-form-button-row"> <div className="gf-form-button-row">
<button type="button" className="btn btn-danger" onClick={this.update} disabled={!canUpdate}> <button type="button" className="btn btn-danger" onClick={this.update} disabled={!permissions.canUpdate}>
Update Permissions Update Permissions
</button> </button>
</div> </div>
asd3 asd3
<DevTools />
</div> </div>
); );
} }
......
...@@ -9,18 +9,8 @@ export interface IProps { ...@@ -9,18 +9,8 @@ export interface IProps {
} }
class PermissionsList extends Component<IProps, any> { class PermissionsList extends Component<IProps, any> {
// componentWillUpdate(nextProps, nextState) {
// console.log('nextProps', nextProps);
// console.log('nextState', nextState);
// }
// componentWillReceiveProps(nextProps) {
// console.log('nextPropzzzz', nextProps);
// }
render() { render() {
const { permissions, permissionsOptions, removeItem, permissionChanged } = this.props; const { permissions, permissionsOptions, removeItem, permissionChanged } = this.props;
return ( return (
<table className="filter-table gf-form-group"> <table className="filter-table gf-form-group">
<tbody> <tbody>
......
...@@ -12,7 +12,7 @@ export default ({ item, permissionsOptions, removeItem, permissionChanged, itemI ...@@ -12,7 +12,7 @@ export default ({ item, permissionsOptions, removeItem, permissionChanged, itemI
const handleChangePermission = evt => { const handleChangePermission = evt => {
evt.preventDefault(); evt.preventDefault();
permissionChanged(); permissionChanged(itemIndex, evt.target.value);
}; };
return ( return (
......
...@@ -6,21 +6,6 @@ ...@@ -6,21 +6,6 @@
dashboardId="ctrl.dashboard.id" dashboardId="ctrl.dashboard.id"
backendSrv="ctrl.backendSrv" /> backendSrv="ctrl.backendSrv" />
<per m i s sions
permissions="{{ctrl.dummyItems}}"
permissionsOptions="{{ctrl.permissionOptions}}"
removeItem="ctrl.removeItem"
permissionChanged="ctrl.permissionChanged"
error="{{ctrl.error}}"
newType="ctrl.newType"
aclTypes="{{ctrl.aclTypes}}"
typeChanged="ctrl.typeChanged"
dashboardId="ctrl.dashboard.id"
backendSrv="ctrl.backendSrv"/>
<div class="gf-form-group"> <div class="gf-form-group">
<table class="filter-table gf-form-group"> <table class="filter-table gf-form-group">
<tr ng-repeat="acl in ctrl.items" ng-class="{'gf-form-disabled': acl.inherited}"> <tr ng-repeat="acl in ctrl.items" ng-class="{'gf-form-disabled': acl.inherited}">
......
import { types, getEnv, flow } from 'mobx-state-tree';
import { PermissionsStoreItem } from './PermissionsStoreItem';
export const PermissionsStore = types
.model('PermissionsStore', {
fetching: types.boolean,
canUpdate: types.boolean,
items: types.optional(types.array(PermissionsStoreItem), []),
originalItems: types.optional(types.array(PermissionsStoreItem), []),
})
// .views(self => ({
// canUpdate: () => {
// const itemsSnapshot = getSnapshot(self.items);
// const originalItemsSnapshot = getSnapshot(self.originalItems);
// console.log('itemsSnapshot', itemsSnapshot);
// console.log('editItemsSnapshot', originalItemsSnapshot);
// return true;
// }
// }))
.actions(self => ({
load: flow(function* load(dashboardId: number) {
self.fetching = true;
const backendSrv = getEnv(self).backendSrv;
const res = yield backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`);
const items = prepareServerResponse(res, dashboardId);
self.items = items;
self.originalItems = items;
self.fetching = false;
}),
addStoreItem: () => {
self.canUpdate = true;
},
removeStoreItem: idx => {
self.items.splice(idx, 1);
self.canUpdate = true;
},
}));
const prepareServerResponse = (response, dashboardId: number) => {
return response.map(item => {
// TODO: this.meta
// item.inherited = !this.meta.isFolder && this.dashboardId !== item.dashboardId;
item.inherited = dashboardId !== item.dashboardId;
item.sortRank = 0;
if (item.userId > 0) {
item.icon = 'fa fa-fw fa-user';
// item.nameHtml = this.$sce.trustAsHtml(item.userLogin);
item.nameHtml = item.userLogin;
item.sortName = item.userLogin;
item.sortRank = 10;
} else if (item.teamId > 0) {
item.icon = 'fa fa-fw fa-users';
// item.nameHtml = this.$sce.trustAsHtml(item.team);
item.nameHtml = item.team;
item.sortName = item.team;
item.sortRank = 20;
} else if (item.role) {
item.icon = 'fa fa-fw fa-street-view';
// item.nameHtml = this.$sce.trustAsHtml(`Everyone with <span class="query-keyword">${item.role}</span> Role`);
item.nameHtml = `Everyone with <span class="query-keyword">${item.role}</span> Role`;
item.sortName = item.role;
item.sortRank = 30;
if (item.role === 'Viewer') {
item.sortRank += 1;
}
}
if (item.inherited) {
item.sortRank += 100;
}
return item;
});
};
import { types } from 'mobx-state-tree';
export const PermissionsStoreItem = types
.model('PermissionsStoreItem', {
dashboardId: types.number,
id: types.number,
permission: types.number,
permissionName: types.string,
role: types.maybe(types.string),
team: types.string,
teamId: types.number,
userEmail: types.string,
userId: types.number,
userLogin: types.string,
inherited: types.maybe(types.boolean),
sortRank: types.maybe(types.number),
icon: types.maybe(types.string),
nameHtml: types.maybe(types.string),
sortName: types.maybe(types.string),
})
.actions(self => ({
updateRole: role => {
self.role = role;
},
}));
...@@ -5,6 +5,7 @@ import { NavStore } from './../NavStore/NavStore'; ...@@ -5,6 +5,7 @@ import { NavStore } from './../NavStore/NavStore';
import { AlertListStore } from './../AlertListStore/AlertListStore'; import { AlertListStore } from './../AlertListStore/AlertListStore';
import { ViewStore } from './../ViewStore/ViewStore'; import { ViewStore } from './../ViewStore/ViewStore';
import { FolderStore } from './../FolderStore/FolderStore'; import { FolderStore } from './../FolderStore/FolderStore';
import { PermissionsStore } from './../PermissionsStore/PermissionsStore';
export const RootStore = types.model({ export const RootStore = types.model({
search: types.optional(SearchStore, { search: types.optional(SearchStore, {
...@@ -17,6 +18,11 @@ export const RootStore = types.model({ ...@@ -17,6 +18,11 @@ export const RootStore = types.model({
alertList: types.optional(AlertListStore, { alertList: types.optional(AlertListStore, {
rules: [], rules: [],
}), }),
permissions: types.optional(PermissionsStore, {
fetching: false,
canUpdate: false,
items: [],
}),
view: types.optional(ViewStore, { view: types.optional(ViewStore, {
path: '', path: '',
query: {}, query: {},
......
...@@ -6467,6 +6467,10 @@ mkdirp@0.5.1, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdi ...@@ -6467,6 +6467,10 @@ mkdirp@0.5.1, mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdi
dependencies: dependencies:
minimist "0.0.8" minimist "0.0.8"
mobx-react-devtools@^4.2.15:
version "4.2.15"
resolved "https://registry.yarnpkg.com/mobx-react-devtools/-/mobx-react-devtools-4.2.15.tgz#881c038fb83db4dffd1e72bbaf5374d26b2fdebb"
mobx-react@^4.3.5: mobx-react@^4.3.5:
version "4.3.5" version "4.3.5"
resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-4.3.5.tgz#76853f2f2ef4a6f960c374bcd9f01e875929c04c" resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-4.3.5.tgz#76853f2f2ef4a6f960c374bcd9f01e875929c04c"
......
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