This commit is contained in:
Leon
2022-01-27 11:30:48 +02:00
parent d7a0f5ff6f
commit 9c45d63237
6 changed files with 148 additions and 45 deletions

View File

@@ -9,6 +9,21 @@
background-size: 26px background-size: 26px
margin-right: 10px margin-right: 10px
.invite-link
&-row
display: flex
justify-content: space-between
align-items: center
align-content: center
& .done-btn
box-sizing: border-box
height: 30px
width: 78px
&-field
width: 80%
max-width: 435px
.generate-link-button .generate-link-button
&:disabled &:disabled
@@ -20,11 +35,7 @@
&__icon &__icon
@include generate-icon @include generate-icon
background-image: url('../../assets/copy-enabled.svg') background-image: url('../../assets/copy-enabled.svg')
.user .user
&__details &__details
display: flex; display: flex;
@@ -35,6 +46,10 @@
& .user__email & .user__email
width : 40% width : 40%
height: 30px;
box-sizing: border-box;
& .user__role & .user__role
width : 40% width : 40%

View File

@@ -1,4 +1,4 @@
import { Button, FormControl, InputLabel, MenuItem, Select } from '@material-ui/core'; import { Button, FormControl, IconButton, InputAdornment, InputLabel, MenuItem, OutlinedInput, Select } from '@material-ui/core';
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import Api from '../../../helpers/api'; import Api from '../../../helpers/api';
import { useCommonStyles } from '../../../helpers/commonStyle'; import { useCommonStyles } from '../../../helpers/commonStyle';
@@ -6,10 +6,11 @@ import ConfirmationModal from '../../UI/Modals/ConfirmationModal';
import SelectList from '../../UI/SelectList'; import SelectList from '../../UI/SelectList';
import './AddUserModal.sass'; import './AddUserModal.sass';
import spinner from "../../assets/spinner.svg"; import spinner from "../../assets/spinner.svg";
import { useForm,Controller } from "react-hook-form";
export type UserData = { export type UserData = {
role:string; role:string;
email : string; username : string;
workspace : string; workspace : string;
} }
@@ -17,17 +18,22 @@ interface AddUserModalProps {
isOpen : boolean, isOpen : boolean,
onCloseModal : () => void onCloseModal : () => void
userData : UserData; userData : UserData;
setShowAlert : ({open:boolean,sevirity: Color}) => void;
} }
const api = Api.getInstance(); const api = Api.getInstance();
export const AddUserModal: FC<AddUserModalProps> = ({isOpen, onCloseModal, userData = {}}) => { export const AddUserModal: FC<AddUserModalProps> = ({isOpen, onCloseModal, userData = {}, setShowAlert}) => {
const [isOpenModal,setIsOpen] = useState(isOpen) const [isOpenModal,setIsOpen] = useState(isOpen)
//const [editUserData, setEditUserData] = useState(userData) //const [editUserData, setEditUserData] = useState(userData)
const [searchValue, setSearchValue] = useState(""); const [searchValue, setSearchValue] = useState("");
const [workspaces, setWorkspaces] = useState({}) const [workspaces, setWorkspaces] = useState([])
const roles = [{key:"1",value:"Admin"}] //const { control, handleSubmit,register } = useForm<UserData>();
const [disable, setDisable] = useState(true);
const [invite, setInvite] = useState({sent:false,isSuceeded:false,link : null});
const roles = [{key:"1",value:"Admin"},{key:"2",value:"User"}]
const classes = useCommonStyles() const classes = useCommonStyles()
const [userDataModel, setUserData] = useState(userData as UserData) const [userDataModel, setUserData] = useState(userData as UserData)
@@ -40,7 +46,16 @@ export const AddUserModal: FC<AddUserModalProps> = ({isOpen, onCloseModal, userD
useEffect(() => { useEffect(() => {
(async () => { (async () => {
try { try {
const workspacesList = {"default":true} //await api.getWorkspaces() const workspacesList = [
{
"id": "f54b18ec-aa15-4b2c-a4d5-8eda17e44c93",
"name": "sock-shop"
},
{
"id": "c7ad9158-d840-46c0-b5ce-2487c013723f",
"name": "test"
}
]//{"default":true} //await api.getWorkspaces()
setWorkspaces(workspacesList) setWorkspaces(workspacesList)
} catch (e) { } catch (e) {
@@ -57,56 +72,109 @@ export const AddUserModal: FC<AddUserModalProps> = ({isOpen, onCloseModal, userD
// setIsOpen(false) // setIsOpen(false)
// } // }
const onConfirm = () => {} const onConfirm = () => {
setUserData({} as UserData)
onCloseModal()
}
const workspaceChange = (newVal) => { const workspaceChange = (newVal) => {
setWorkspaces(newVal); //setWorkspaces(newVal);
const data = {...userDataModel, workspace : newVal} const data = {...userDataModel, workspace : newVal}
setUserData(data) setUserData(data)
setGenarateDisabledState()
} }
const userRoleChange = (e) => { const userRoleChange = (e) => {
const data = {...userDataModel, role : e.currentTarget.value} const data = {...userDataModel, role : e.target.value}
setUserData(data) setUserData(data)
setGenarateDisabledState()
} }
function isFormValid(): boolean { const userNameChange = (e) => {
return true; const data = {...userDataModel, username : e.currentTarget.value}
setUserData(data)
setGenarateDisabledState()
} }
const generateLink = () => { const handleChange = (prop) => (event) => {
//setValues({ ...values, [prop]: event.target.value });
};
const isFormValid = () : boolean => {
return (Object.values(userDataModel).length === 3) && Object.values(userDataModel).every(val => val !== null)
}
const setGenarateDisabledState = () => {
const isValid = isFormValid()
setDisable(!isValid)
}
const generateLink = () => {
try { try {
api.genareteInviteLink(userDataModel) //const res = await api.genareteInviteLink(userDataModel)
//setInvite({...invite,isSuceeded:true,sent:true,link:res})
setInvite({...invite,isSuceeded:true,sent:true,link:"asdasdasdasdasdasdasdasdads"})
setShowAlert({open:true,sevirity:"error"})
} catch (e) { } catch (e) {
console.error(e); setShowAlert({open:true,sevirity:"error"})
} }
} }
const modalCustomActions = <> const handleCopyinviteLink = (e) => {navigator.clipboard.writeText(invite.link)}
const modalCustomActions = <>
{(!invite.isSuceeded || !(invite.link && invite.sent)) && <Button
className={classes.button + " generate-link-button"} size={"small"} onClick={generateLink}
disabled={disable}
endIcon={isLoading && <img src={spinner} alt="spinner"/>}>
<span className='generate-link-button__icon'></span>
{"Generate Invite Link"}
</Button>}
{invite.isSuceeded && invite.link && <div className="invite-link-row">
<FormControl variant="outlined" size={"small"} className='invite-link-field'>
<InputLabel htmlFor="outlined-adornment-password">Invite link</InputLabel>
<OutlinedInput
type={'text'}
value={invite.link}
onChange={handleChange('password')}
endAdornment={
<InputAdornment position="end">
<IconButton aria-label="cpoy invite link" onClick={handleCopyinviteLink} edge="end">
{<span className='generate-link-button__icon'></span>}
</IconButton>
</InputAdornment>
}
label="Invite link"
/>
</FormControl>
<Button style={{height: '100%'}} className={classes.button} size={"small"} onClick={onConfirm}>
Done
</Button>
</div>}
</>; </>;
return (<> return (<>
<ConfirmationModal isOpen={isOpen} onClose={onCloseModal} onConfirm={onConfirm} title='Add User'> <ConfirmationModal isOpen={isOpen} onClose={onCloseModal} onConfirm={onConfirm} title='Add User' customActions={modalCustomActions}>
<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> <h3 className='comfirmation-modal__sub-section-header'>DETAILS</h3>
<div className='comfirmation-modal__sub-section'> <div className='comfirmation-modal__sub-section'>
<div className='user__details'> <div className='user__details'>
<input type="text" value={userDataModel?.email ?? ""} className={classes.textField + " user__email"} placeholder={"User Email"} <input type="text" value={userDataModel?.username ?? ""} className={classes.textField + " user__email"}
onChange={(e) => {}}></input> placeholder={"User Email"} onChange={userNameChange}>
<FormControl size='small' variant="outlined" className='user__role'> </input>
{/* <Controller name="role" control={control} rules={{ required: true }}
render={({ field }) => }
/> */}
<FormControl size='small' variant="outlined" className='user__role'>
<InputLabel>User Role</InputLabel> <InputLabel>User Role</InputLabel>
<Select value={userDataModel.role} onChange={userRoleChange} > <Select value={userDataModel.role ?? ""} onChange={userRoleChange} >
<MenuItem value=""> <MenuItem value="0">
<em>None</em> <em>None</em>
</MenuItem> </MenuItem>
{roles.map((role) => ( {roles.map((role) => (
@@ -118,16 +186,17 @@ export const AddUserModal: FC<AddUserModalProps> = ({isOpen, onCloseModal, userD
</FormControl> </FormControl>
</div> </div>
</div> </div>
<h3 className='comfirmation-modal__sub-section-header'>WORKSPACE ACCESS </h3> <h3 className='comfirmation-modal__sub-section-header'>WORKSPACE ACCESS </h3>
<div className="namespacesSettingsContainer"> <div className="namespacesSettingsContainer">
<div style={{margin: "10px 0"}}> <div style={{margin: "10px 0"}}>
<input className={classes.textField + " searchNamespace"} placeholder="Search" value={searchValue} <input className={classes.textField + " searchNamespace"} placeholder="Search" value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}/> onChange={(event) => setSearchValue(event.target.value)}/>
</div> </div>
<SelectList valuesListInput={workspaces} tableName={''} multiSelect={false} searchValue={searchValue} setValues={workspaceChange} tabelClassName={''} ></SelectList> <SelectList valuesListInput={workspaces} tableName={''} multiSelect={false} searchValue={searchValue}
setValues= {workspaceChange} tabelClassName={''} >
</SelectList>
</div> </div>
</ConfirmationModal> </ConfirmationModal>
</>); </>);
}; };

View File

@@ -62,7 +62,7 @@ const ConfirmationModal: React.FC<ConfirmationModalProps> = observer(({title, is
</div> </div>
<div className="confirmationActions"> <div className="confirmationActions">
{customActions} {customActions ?? defualtActions}
</div> </div>
</CustomModal> </CustomModal>
) )

View File

@@ -18,4 +18,11 @@
@include status-base(rgba(111, 207, 151, 0.5), #247E4B, 1px solid #219653) @include status-base(rgba(111, 207, 151, 0.5), #247E4B, 1px solid #219653)
&--pending &--pending
@include status-base(rgba(242, 201, 76, 0.5), #8C7325, 1px solid #F2994A) @include status-base(rgba(242, 201, 76, 0.5), #8C7325, 1px solid #F2994A)
.alert--right.MuiSnackbar-root
display: flex;
justify-content: flex-end;
left: auto;
right: 1vw;
transform: unset;

View File

@@ -4,6 +4,8 @@ import {ColsType, FilterableTableAction} from "../UI/FilterableTableAction"
import Api from "../../helpers/api" import Api from "../../helpers/api"
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { UserData,AddUserModal } from "../Modals/AddUserModal/AddUserModal"; import { UserData,AddUserModal } from "../Modals/AddUserModal/AddUserModal";
import {Snackbar} from "@material-ui/core";
import MuiAlert from "@material-ui/lab/Alert";
import { Select } from "../UI/Select"; import { Select } from "../UI/Select";
import { MenuItem } from "@material-ui/core"; import { MenuItem } from "@material-ui/core";
import { settings } from "cluster"; import { settings } from "cluster";
@@ -26,14 +28,14 @@ export const UserSettings : React.FC<Props> = ({}) => {
return val === "Active" ? "status--active" : "status--pending" return val === "Active" ? "status--active" : "status--pending"
}}] }}]
const [isOpenModal,setIsOpen] = useState(false) const [isOpenModal,setIsOpen] = useState(false)
const [alert,setAlert] = useState({open:false,sevirity:"success"})
useEffect(() => { useEffect(() => {
(async () => { (async () => {
try { try {
const users = [{userName:"asd",role:"Admin",status:"Active"}]//await api.getUsers() const users = [{userName:"asd",role:"Admin",status:"Active"}]//await api.getUsers()
setUserRows(users) setUserRows(users)
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
@@ -55,7 +57,8 @@ export const UserSettings : React.FC<Props> = ({}) => {
} }
const onRowEdit = (row) => { const onRowEdit = (row) => {
// open Edit user Modal SetUsetData(row)
setIsOpen(true)
} }
@@ -66,7 +69,14 @@ export const UserSettings : React.FC<Props> = ({}) => {
<FilterableTableAction onRowEdit={onRowEdit} onRowDelete={onRowDelete} searchConfig={searchConfig} <FilterableTableAction onRowEdit={onRowEdit} onRowDelete={onRowDelete} searchConfig={searchConfig}
buttonConfig={buttonConfig} rows={usersRows} cols={cols}> buttonConfig={buttonConfig} rows={usersRows} cols={cols}>
</FilterableTableAction> </FilterableTableAction>
<AddUserModal isOpen={isOpenModal} onCloseModal={() => { setIsOpen(false); } } userData={userData}></AddUserModal> <AddUserModal isOpen={isOpenModal} onCloseModal={() => { setIsOpen(false); } } userData={userData} setShowAlert={setAlert}>
</AddUserModal>
<Snackbar open={alert.open} classes={{root: "alert--right"}}>
<MuiAlert classes={{filledWarning: 'customWarningStyle'}} elevation={6} variant="filled"
onClose={() => setAlert({...alert,open:false})} severity={"success"}>
User has been added
</MuiAlert>
</Snackbar>
{/* <SettingsModal isOpen={false} onClose={function (): void { {/* <SettingsModal isOpen={false} onClose={function (): void {
throw new Error("Function not implemented."); throw new Error("Function not implemented.");
} } isFirstLogin={false}></SettingsModal> */} } } isFirstLogin={false}></SettingsModal> */}

View File

@@ -7,7 +7,7 @@ export const useCommonStyles = makeStyles(() => ({
color: "white", color: "white",
fontWeight: "600 !important", fontWeight: "600 !important",
fontSize: 12, fontSize: 12,
padding: "8px 12px", padding: "9px 12px",
borderRadius: "6px ! important", borderRadius: "6px ! important",
"&:hover": { "&:hover": {
@@ -34,7 +34,9 @@ export const useCommonStyles = makeStyles(() => ({
padding: "8px 10px", padding: "8px 10px",
border: "1px #9D9D9D solid", border: "1px #9D9D9D solid",
fontSize: "14px", fontSize: "14px",
color: "#494677" color: "#494677",
height: "30px",
boxSizing: "border-box"
}, },
modal :{ modal :{
position: 'absolute', position: 'absolute',