Merge branch 'origin/ui/TRA-4204_user_managment' of github.com:up9inc/mizu into feature/ui/TRA-4192_workspace_management

# Conflicts:
#	ui/src/components/Modals/AddUserModal/AddUserModal.tsx
#	ui/src/components/UserSettings/UserSettings.tsx
This commit is contained in:
Amit Fainholts
2022-01-26 19:10:50 +02:00
7 changed files with 109 additions and 27 deletions

View File

@@ -1,5 +1,30 @@
@import '../../../variables.module'
@mixin generate-icon
display: block
text-indent: -9999px
width: 26px
height: 26px
background-repeat: no-repeat
background-size: 26px
margin-right: 10px
.generate-link-button
&:disabled
background: #BCC6DD;
.generate-link-button__icon
@include generate-icon
background-image: url('../../assets/copy-disabled.svg')
&__icon
@include generate-icon
background-image: url('../../assets/copy-enabled.svg')
.user
&__details
display: flex;

View File

@@ -1,10 +1,11 @@
import { FormControl, InputLabel, MenuItem, Select } from '@material-ui/core';
import { Button, FormControl, InputLabel, MenuItem, Select } from '@material-ui/core';
import { FC, useEffect, useState } from 'react';
// import Api from '../../../helpers/api';
import { useCommonStyles } from '../../../helpers/commonStyle';
import ConfirmationModal from '../../UI/Modals/ConfirmationModal';
import SelectList from '../../UI/SelectList';
import './AddUserModal.sass';
import spinner from "../../assets/spinner.svg";
export type UserData = {
role:string;
@@ -24,12 +25,12 @@ export const AddUserModal: FC<AddUserModalProps> = ({isOpen, onCloseModal, userD
//const [editUserData, setEditUserData] = useState(userData)
const [searchValue, setSearchValue] = useState("");
//const [userRole,setUserRole] = useState("")
const [workspaces, setWorkspaces] = useState({})
const roles = [{key:"1",value:"Admin"}]
const classes = useCommonStyles()
const [userDataModel, setUserData] = useState(userData as UserData)
const isLoading = false;
// useEffect(() => {
// setIsOpen(isOpen)
@@ -68,20 +69,39 @@ export const AddUserModal: FC<AddUserModalProps> = ({isOpen, onCloseModal, userD
setUserData(data)
}
function isFormValid(): boolean {
return true;
}
const generateLink = () => {
try {
api.genareteInviteLink(userDataModel)
} catch (e) {
console.error(e);
}
}
const modalCustomActions = <>
</>;
return (<>
<ConfirmationModal isOpen={isOpen} onClose={onCloseModal} onConfirm={onConfirm} title='Add User'>
<Button
className={classes.button + " generate-link-button"} size={"small"} onClick={generateLink}
//disabled={isFormValid()}
endIcon={isLoading && <img src={spinner} alt="spinner"/>}>
<span className='generate-link-button__icon'></span>
{"Generate Invite Link"}
</Button>
<h3 className='comfirmation-modal__sub-section-header'>DETAILS</h3>
<div className='comfirmation-modal__sub-section'>
<div className='user__details'>
<input type="text" value={userDataModel?.email ?? ""} className={classes.textField + " user__email"} placeholder={"User Email"}
onChange={(e) => {}}></input>
{/* <TextField select size='small' onChange={userRoleChange} value={userDataModel.role} fullWidth variant="filled">
{roles.map((role) => (
<MenuItem key={role.value} value={role.value}>
{role.value}
</MenuItem>
))}
</TextField> */}
<FormControl size='small' variant="outlined" className='user__role'>
<InputLabel>User Role</InputLabel>
<Select value={userDataModel.role} onChange={userRoleChange} >
@@ -104,10 +124,9 @@ export const AddUserModal: FC<AddUserModalProps> = ({isOpen, onCloseModal, userD
<input className={classes.textField + " searchNamespace"} placeholder="Search" value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}/>
</div>
<SelectList valuesListInput={workspaces} tableName={'Workspace'} multiSelect={false} searchValue={searchValue} setValues={workspaceChange} tabelClassName={''} ></SelectList>
<SelectList valuesListInput={workspaces} tableName={''} multiSelect={false} searchValue={searchValue} setValues={workspaceChange} tabelClassName={''} ></SelectList>
</div>
</ConfirmationModal>
</>);
};
export default AddUserModal;

View File

@@ -22,14 +22,26 @@ interface ConfirmationModalProps {
img?: ReactElement;
isLoading?: boolean;
className?: any;
customActions? : ReactElement
}
const ConfirmationModal: React.FC<ConfirmationModalProps> = observer(({title, isOpen, onClose, onConfirm, confirmButtonText,
closeButtonText, subContent, confirmDisabled = false, isWide,
confirmButtonColor, titleColor, img, isLoading,children,
className}) => {
className, customActions}) => {
const classes = useCommonStyles();
const confirmStyle = {width: 100, marginLeft: 20}
const defualtActions = <><Button disabled={isLoading} style={{width: 100}} className={classes.outlinedButton} size={"small"}
variant='outlined' onClick={onClose}>{closeButtonText ?? "CANCEL"}
</Button>
<Button style={confirmButtonColor ? {backgroundColor: confirmButtonColor,...confirmStyle} : {...confirmStyle}}
className={classes.button} size={"small"}
onClick={onConfirm}
disabled={confirmDisabled || isLoading}
endIcon={isLoading && <img src={spinner} alt="spinner"/>}>{confirmButtonText ?? "YES"}
</Button></>
return (
<CustomModal open={isOpen} onClose={onClose} disableBackdropClick={true} isWide={isWide} className={`${className} comfirmation-modal`}>
<div className="confirmationHeader">
@@ -50,15 +62,7 @@ const ConfirmationModal: React.FC<ConfirmationModalProps> = observer(({title, is
</div>
<div className="confirmationActions">
<Button disabled={isLoading} style={{width: 100}} className={classes.outlinedButton} size={"small"}
variant='outlined' onClick={onClose}>{closeButtonText ?? "CANCEL"}
</Button>
<Button style={confirmButtonColor ? {backgroundColor: confirmButtonColor,...confirmStyle} : {...confirmStyle}}
className={classes.button} size={"small"}
onClick={onConfirm}
disabled={confirmDisabled || isLoading}
endIcon={isLoading && <img src={spinner} alt="spinner"/>}>{confirmButtonText ?? "YES"}
</Button>
{customActions}
</div>
</CustomModal>
)

View File

@@ -2,7 +2,7 @@ import "./UserSettings.sass"
import {ColsType, FilterableTableAction} from "../UI/FilterableTableAction"
// import Api from "../../helpers/api"
import { useEffect, useState } from "react";
import AddUserModal, { UserData } from "../Modals/AddUserModal/AddUserModal";
import { UserData,AddUserModal } from "../Modals/AddUserModal/AddUserModal";
interface Props {

View File

@@ -0,0 +1,17 @@
<svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2252_358)">
<path d="M4.00005 3.22263V2.125C4.00005 1.82663 4.11857 1.54048 4.32955 1.3295C4.54053 1.11853 4.82668 1 5.12505 1H14.875C15.1734 1 15.4596 1.11853 15.6705 1.3295C15.8815 1.54048 16 1.82663 16 2.125V11.875C16 12.1734 15.8815 12.4595 15.6705 12.6705C15.4596 12.8815 15.1734 13 14.875 13H13.7564" fill="#E9EBF8"/>
<path d="M4.00005 3.22263V2.125C4.00005 1.82663 4.11857 1.54048 4.32955 1.3295C4.54053 1.11853 4.82668 1 5.12505 1H14.875C15.1734 1 15.4596 1.11853 15.6705 1.3295C15.8815 1.54048 16 1.82663 16 2.125V11.875C16 12.1734 15.8815 12.4595 15.6705 12.6705C15.4596 12.8815 15.1734 13 14.875 13H13.7564" stroke="#E9EBF8"/>
<path d="M3.00005 4.22263V3.125C3.00005 2.82663 3.11857 2.54048 3.32955 2.3295C3.54053 2.11853 3.82668 2 4.12505 2H13.875C14.1734 2 14.4596 2.11853 14.6705 2.3295C14.8815 2.54048 15 2.82663 15 3.125V12.875C15 13.1734 14.8815 13.4595 14.6705 13.6705C14.4596 13.8815 14.1734 14 13.875 14H12.7564" fill="white"/>
<path d="M12.3958 4.0415H2.47917C1.89237 4.0415 1.41667 4.5172 1.41667 5.104V15.0207C1.41667 15.6075 1.89237 16.0832 2.47917 16.0832H12.3958C12.9826 16.0832 13.4583 15.6075 13.4583 15.0207V5.104C13.4583 4.5172 12.9826 4.0415 12.3958 4.0415Z" fill="#E9EBF8" stroke="#E9EBF8" stroke-linejoin="round"/>
<path d="M6.53084 8.68467L8.40509 6.73322C8.91934 6.21932 9.76403 6.2303 10.2921 6.75872C10.8205 7.28643 10.8318 8.13147 10.3176 8.64572L9.64113 9.36219" stroke="#8F9BB2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.76922 10.6812C4.58859 10.8618 4.21495 11.223 4.21495 11.223C3.7007 11.7366 3.68653 12.6532 4.21495 13.1816C4.74266 13.7093 5.5877 13.7206 6.10195 13.2064L7.93086 11.546" stroke="#8F9BB2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.60982 10.5325C6.37468 10.2987 6.23246 9.98746 6.20961 9.65665C6.19597 9.47111 6.22237 9.28479 6.28702 9.11034C6.35167 8.93589 6.45306 8.77736 6.58431 8.64551" stroke="#8F9BB2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.90572 9.65918C8.43343 10.1872 8.44511 11.0323 7.93086 11.5462" stroke="#8F9BB2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_2252_358">
<rect width="17" height="17" fill="white" transform="translate(0 0.5)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,17 @@
<svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2252_4609)">
<path d="M4.00005 3.22263V2.125C4.00005 1.82663 4.11857 1.54048 4.32955 1.3295C4.54053 1.11853 4.82668 1 5.12505 1H14.875C15.1734 1 15.4596 1.11853 15.6705 1.3295C15.8815 1.54048 16 1.82663 16 2.125V11.875C16 12.1734 15.8815 12.4595 15.6705 12.6705C15.4596 12.8815 15.1734 13 14.875 13H13.7564" fill="#BCCEFD"/>
<path d="M4.00005 3.22263V2.125C4.00005 1.82663 4.11857 1.54048 4.32955 1.3295C4.54053 1.11853 4.82668 1 5.12505 1H14.875C15.1734 1 15.4596 1.11853 15.6705 1.3295C15.8815 1.54048 16 1.82663 16 2.125V11.875C16 12.1734 15.8815 12.4595 15.6705 12.6705C15.4596 12.8815 15.1734 13 14.875 13H13.7564" stroke="#BCCEFD"/>
<path d="M3.00005 4.22263V3.125C3.00005 2.82663 3.11857 2.54048 3.32955 2.3295C3.54053 2.11853 3.82668 2 4.12505 2H13.875C14.1734 2 14.4596 2.11853 14.6705 2.3295C14.8815 2.54048 15 2.82663 15 3.125V12.875C15 13.1734 14.8815 13.4595 14.6705 13.6705C14.4596 13.8815 14.1734 14 13.875 14H12.7564" fill="white"/>
<path d="M12.3958 4.0415H2.47917C1.89237 4.0415 1.41667 4.5172 1.41667 5.104V15.0207C1.41667 15.6075 1.89237 16.0832 2.47917 16.0832H12.3958C12.9826 16.0832 13.4583 15.6075 13.4583 15.0207V5.104C13.4583 4.5172 12.9826 4.0415 12.3958 4.0415Z" fill="#BCCEFD" stroke="#BCCEFD" stroke-linejoin="round"/>
<path d="M6.53084 8.68467L8.40509 6.73322C8.91934 6.21932 9.76403 6.2303 10.2921 6.75872C10.8205 7.28643 10.8318 8.13147 10.3176 8.64572L9.64113 9.36219" stroke="#205CF5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.76922 10.6812C4.58859 10.8618 4.21495 11.223 4.21495 11.223C3.7007 11.7366 3.68653 12.6532 4.21495 13.1816C4.74266 13.7093 5.5877 13.7206 6.10195 13.2064L7.93086 11.546" stroke="#205CF5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.60982 10.5325C6.37468 10.2987 6.23246 9.98746 6.20961 9.65665C6.19597 9.47111 6.22237 9.28479 6.28702 9.11034C6.35167 8.93589 6.45306 8.77736 6.58431 8.64551" stroke="#205CF5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.90572 9.65918C8.43343 10.1872 8.44511 11.0323 7.93086 11.5462" stroke="#205CF5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_2252_4609">
<rect width="17" height="17" fill="white" transform="translate(0 0.5)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -53,10 +53,10 @@ export default class Api {
return response.data;
}
// getRoles = async(filter = "") =>{
// const response = await this.client.get(`/user/listUsers?usernameFilter=${filter}`);
// return response.data;
// }
genareteInviteLink = async(userData) =>{
const response = await this.client.post(`/user/createUserAndInvite`,userData);
return response.data;
}
getWorkspaces = async() =>{
const response = await this.client.get(``);