change(ui) - userlist form
This commit is contained in:
parent
5ef382c9b8
commit
7e655d513c
8 changed files with 95 additions and 32 deletions
|
|
@ -1,14 +1,32 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import UserList from './components/UserList';
|
||||
import { PageTitle } from 'UI';
|
||||
import { PageTitle, Popup, IconButton } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import UserSearch from './components/UserSearch';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import UserForm from './components/UserForm';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
function UsersView(props) {
|
||||
interface Props {
|
||||
account: any;
|
||||
isEnterprise: boolean;
|
||||
}
|
||||
function UsersView(props: Props) {
|
||||
const { account, isEnterprise } = props;
|
||||
const { userStore, roleStore } = useStore();
|
||||
const userCount = useObserver(() => userStore.list.length);
|
||||
const roles = useObserver(() => roleStore.list);
|
||||
const { showModal } = useModal();
|
||||
|
||||
const isAdmin = account.admin || account.superAdmin;
|
||||
// const canAddUsers = isAdmin && userCount !== 0; // TODO fetch limits and disable button if limit reached
|
||||
|
||||
const editHandler = (user = null) => {
|
||||
userStore.initUser(user).then(() => {
|
||||
showModal(<UserForm />, { right: true });
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (roles.length === 0) {
|
||||
|
|
@ -22,7 +40,26 @@ function UsersView(props) {
|
|||
<PageTitle
|
||||
title={<div>Team <span className="color-gray-medium">{userCount}</span></div>}
|
||||
actionButton={(
|
||||
<div className="ml-2">test</div>
|
||||
<Popup
|
||||
trigger={
|
||||
<div>
|
||||
<IconButton
|
||||
id="add-button"
|
||||
// disabled={ !canAddUsers }
|
||||
circle
|
||||
icon="plus"
|
||||
outline
|
||||
className="ml-3"
|
||||
onClick={ () => editHandler(null) }
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
// disabled={ canAddUsers }
|
||||
// content={ `${ !canAddUsers ? (!isAdmin ? PERMISSION_WARNING : LIMIT_WARNING) : 'Add team member' }` }
|
||||
size="tiny"
|
||||
inverted
|
||||
position="top left"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<div>
|
||||
|
|
@ -34,4 +71,7 @@ function UsersView(props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default UsersView;
|
||||
export default connect(state => ({
|
||||
account: state.getIn([ 'user', 'account' ]),
|
||||
isEnterprise: state.getIn([ 'user', 'client', 'edition' ]) === 'ee',
|
||||
}))(UsersView);
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Input, CopyButton, Button, Select } from 'UI'
|
||||
import { Input, CopyButton, Button } from 'UI'
|
||||
import cn from 'classnames';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import Select from 'Shared/Select';
|
||||
|
||||
interface Props {
|
||||
isSmtp?: boolean;
|
||||
|
|
@ -16,18 +17,21 @@ function UserForm(props: Props) {
|
|||
const { userStore, roleStore } = useStore();
|
||||
const user: any = useObserver(() => userStore.instance);
|
||||
const roles = useObserver(() => roleStore.list.map(r => ({ label: r.name, value: r.roleId })));
|
||||
console.log('roles', roles)
|
||||
|
||||
const onChangeCheckbox = (e: any) => {
|
||||
user.updateKey('isAdmin', !user.isAdmin);
|
||||
}
|
||||
|
||||
const onSave = () => {
|
||||
userStore.saveUser(user).then(() => {
|
||||
hideModal();
|
||||
});
|
||||
}
|
||||
|
||||
const write = ({ target: { name, value } }) => {
|
||||
user.updateKey(name, value);
|
||||
}
|
||||
|
||||
return useObserver(() => (
|
||||
<div className="bg-white h-screen p-6" style={{ width: '400px'}}>
|
||||
<div className="">
|
||||
|
|
@ -87,8 +91,8 @@ function UserForm(props: Props) {
|
|||
selection
|
||||
options={ roles }
|
||||
name="roleId"
|
||||
value={ user.roleId }
|
||||
onChange={ write }
|
||||
defaultValue={ user.roleId }
|
||||
onChange={({ value }) => user.updateKey('roleId', value)}
|
||||
className="block"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -111,7 +115,7 @@ function UserForm(props: Props) {
|
|||
onClick={ hideModal }
|
||||
outline
|
||||
>
|
||||
{ 'Cancel' }
|
||||
{ 'Cancel' }
|
||||
</Button>
|
||||
</div>
|
||||
{ !user.isJoined && user.invitationLink &&
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ function UserSearch(props) {
|
|||
value={query}
|
||||
name="searchQuery"
|
||||
className="bg-white p-2 border border-gray-light rounded w-full pl-10"
|
||||
placeholder="Filter by Name, Project"
|
||||
placeholder="Filter by Name, Role"
|
||||
onChange={write}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ function DefaultTimezone(props) {
|
|||
const { settingsStore } = useStore();
|
||||
const [timezone, setTimezone] = React.useState(settingsStore.sessionSettings.timezone);
|
||||
const sessionSettings = useObserver(() => settingsStore.sessionSettings)
|
||||
console.log('timezone', timezone)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export default class Role implements IRole {
|
|||
|
||||
fromJson(json: any) {
|
||||
runInAction(() => {
|
||||
this.roleId = json.id;
|
||||
this.roleId = json.roleId;
|
||||
this.name = json.name;
|
||||
this.description = json.description;
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { runInAction, makeAutoObservable, observable } from 'mobx'
|
||||
import { DateTime } from 'luxon';
|
||||
import { validateEmail } from 'App/validate';
|
||||
import { validateEmail, validateName } from 'App/validate';
|
||||
|
||||
export interface IUser {
|
||||
userId: string
|
||||
|
|
@ -16,6 +16,7 @@ export interface IUser {
|
|||
|
||||
fromJson(json: any): IUser
|
||||
toJson(): any
|
||||
toSave(): any
|
||||
}
|
||||
|
||||
export default class User implements IUser {
|
||||
|
|
@ -55,7 +56,7 @@ export default class User implements IUser {
|
|||
|
||||
fromJson(json: any) {
|
||||
runInAction(() => {
|
||||
this.userId = json.id;
|
||||
this.userId = json.userId || json.id; // TODO api returning id
|
||||
this.name = json.name;
|
||||
this.email = json.email;
|
||||
this.createdAt = json.createdAt && DateTime.fromISO(json.createdAt || 0)
|
||||
|
|
@ -72,15 +73,26 @@ export default class User implements IUser {
|
|||
|
||||
toJson() {
|
||||
return {
|
||||
userId: this.userId,
|
||||
name: this.name,
|
||||
email: this.email,
|
||||
isAdmin: this.isAdmin,
|
||||
admin: this.isAdmin,
|
||||
isSuperAdmin: this.isSuperAdmin,
|
||||
roleId: this.roleId,
|
||||
}
|
||||
}
|
||||
|
||||
toSave() {
|
||||
return {
|
||||
name: this.name,
|
||||
email: this.email,
|
||||
admin: this.isAdmin,
|
||||
roleId: this.roleId,
|
||||
}
|
||||
}
|
||||
|
||||
valid() {
|
||||
return validateEmail(this.email) && !!this.roleId;
|
||||
return validateName(this.name, { empty: false }) && validateEmail(this.email) && !!this.roleId;
|
||||
}
|
||||
|
||||
exists() {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
import { makeAutoObservable, observable, action } from "mobx"
|
||||
import User, { IUser } from "./types/user";
|
||||
import { userService } from "App/services";
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
export default class UserStore {
|
||||
list: IUser[] = [];
|
||||
instance: IUser|null = null;
|
||||
loading: boolean = false;
|
||||
page: number = 1;
|
||||
pageSize: number = 10;
|
||||
searchQuery: string = "";
|
||||
|
||||
loading: boolean = false;
|
||||
saving: boolean = false;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
instance: observable,
|
||||
|
|
@ -22,7 +25,7 @@ export default class UserStore {
|
|||
initUser(user?: any ): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (user) {
|
||||
this.instance = user;
|
||||
this.instance = new User().fromJson(user.toJson());
|
||||
} else {
|
||||
this.instance = new User();
|
||||
}
|
||||
|
|
@ -38,8 +41,11 @@ export default class UserStore {
|
|||
}
|
||||
}
|
||||
|
||||
updateUser(user: any) {
|
||||
Object.assign(this.instance, user);
|
||||
updateUser(user: IUser) {
|
||||
const index = this.list.findIndex(u => u.userId === user.userId);
|
||||
if (index > -1) {
|
||||
this.list[index] = user;
|
||||
}
|
||||
}
|
||||
|
||||
fetchUser(userId: string): Promise<any> {
|
||||
|
|
@ -75,22 +81,24 @@ export default class UserStore {
|
|||
}
|
||||
|
||||
saveUser(user: IUser): Promise<any> {
|
||||
this.loading = true;
|
||||
this.saving = true;
|
||||
const wasCreating = !user.userId;
|
||||
return new Promise((resolve, reject) => {
|
||||
userService.save(user)
|
||||
.then(response => {
|
||||
userService.save(user).then(response => {
|
||||
const newUser = new User().fromJson(response);
|
||||
if (wasCreating) {
|
||||
this.list.push(new User().fromJson(response.data));
|
||||
this.list.push(new User().fromJson(newUser));
|
||||
toast.success('User created successfully');
|
||||
} else {
|
||||
this.updateUser(response.data);
|
||||
this.updateUser(newUser);
|
||||
toast.success('User updated successfully');
|
||||
}
|
||||
resolve(response);
|
||||
}).catch(error => {
|
||||
this.loading = false;
|
||||
this.saving = false;
|
||||
reject(error);
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
this.saving = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ export default class UserService {
|
|||
.then(response => response.data || {});
|
||||
}
|
||||
|
||||
save(user: IUser) {
|
||||
const data = user.toJson();
|
||||
save(user: IUser): Promise<any> {
|
||||
const data = user.toSave();
|
||||
if (user.userId) {
|
||||
return this.client.put('/users/' + user.userId, data)
|
||||
return this.client.put('/client/members/' + user.userId, data)
|
||||
.then(response => response.json())
|
||||
.then(response => response.data || {});
|
||||
.then(response => response.data || {})
|
||||
} else {
|
||||
return this.client.post('/users', data)
|
||||
return this.client.post('/client/members', data)
|
||||
.then(response => response.json())
|
||||
.then(response => response.data || {});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue