Initial check in; All but the history pages working.
This commit is contained in:
282
imports/ui/pages/Assignments/ByPerson.jsx
Normal file
282
imports/ui/pages/Assignments/ByPerson.jsx
Normal file
@@ -0,0 +1,282 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTracker } from 'meteor/react-meteor-data';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import _ from 'lodash';
|
||||
import SimpleTable from "/imports/ui/util/SimpleTable";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import Button from "@mui/material/Button";
|
||||
import Select from '@mui/material/Select';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import {InputLabel, List, ListItem, ListItemButton, ListItemText} from "@mui/material";
|
||||
import Box from "@mui/material/Box";
|
||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import ToggleButton from '@mui/material/ToggleButton';
|
||||
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import DialogActions from '@mui/material/DialogActions';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import DialogContentText from '@mui/material/DialogContentText';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import {Assets, conditions} from "/imports/api/assets";
|
||||
import {AssetTypes} from "/imports/api/asset-types";
|
||||
import {Students} from "/imports/api/students";
|
||||
import {Staff} from "/imports/api/staff";
|
||||
|
||||
const cssTwoColumnContainer = {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
columnGap: '1rem',
|
||||
rowGap: '0.4rem',
|
||||
}
|
||||
const cssEditorField = {
|
||||
minWidth: '10rem'
|
||||
}
|
||||
|
||||
const AssignmentsByPerson = () => {
|
||||
const theme = useTheme();
|
||||
const [searchType, setSearchType] = useState("Email")
|
||||
const [search, setSearch] = useState("")
|
||||
const [selectedPerson, setSelectedPerson] = useState("")
|
||||
const [assetId, setAssetId] = useState("")
|
||||
const [openAssignDialog, setOpenAssignDialog] = useState(false)
|
||||
const [assignCondition, setAssignCondition] = useState(conditions[2])
|
||||
const [assignConditionDetails, setAssignConditionDetails] = useState("")
|
||||
|
||||
//Dialog stuff.
|
||||
const [openUnassignDialog, setOpenUnassignDialog] = useState(false)
|
||||
const [unassignCondition, setUnassignCondition] = useState(conditions[2])
|
||||
const [unassignComment, setUnassignComment] = useState("")
|
||||
const [unassignConditionDetails, setUnassignConditionDetails] = useState("")
|
||||
const [unassignAsset, setUnassignAsset] = useState(undefined)
|
||||
|
||||
const [assetIdInput, setAssetIdInput] = useState(undefined)
|
||||
|
||||
const {people} = useTracker(() => {
|
||||
let people = [];
|
||||
|
||||
if(search && search.length > 1) {
|
||||
let query;
|
||||
|
||||
if(searchType === "Email") {
|
||||
query = {email: {$regex: search, $options: 'i'}};
|
||||
} else if(searchType === 'First Name') {
|
||||
query = {firstName: {$regex: search, $options: 'i'}}
|
||||
} else {
|
||||
query = {lastName: {$regex: search, $options: 'i'}}
|
||||
}
|
||||
|
||||
const students = Students.find(query).fetch();
|
||||
const staff = Staff.find(query).fetch();
|
||||
|
||||
for(let next of students) next.type = "Student"
|
||||
for(let next of staff) next.type = "Staff"
|
||||
|
||||
people = [...staff, ...students]
|
||||
}
|
||||
|
||||
return {people}
|
||||
});
|
||||
|
||||
const {assets} = useTracker(() => {
|
||||
let assets = [];
|
||||
|
||||
if(selectedPerson) {
|
||||
assets = Assets.find({assigneeId: selectedPerson._id}).fetch();
|
||||
|
||||
for(let next of assets) {
|
||||
next.assetType = AssetTypes.findOne({_id: next.assetTypeId})
|
||||
}
|
||||
}
|
||||
|
||||
return {assets}
|
||||
});
|
||||
|
||||
const {foundAsset} = useTracker(() => {
|
||||
let foundAsset = null;
|
||||
|
||||
if(assetId) {
|
||||
foundAsset = Assets.findOne({assetId: assetId});
|
||||
|
||||
if(foundAsset) {
|
||||
foundAsset.assetType = AssetTypes.findOne({_id: foundAsset.assetTypeId})
|
||||
|
||||
if(foundAsset.assigneeId)
|
||||
foundAsset.assignee = foundAsset.assigneeType === "Student" ? Students.findOne({_id: foundAsset.assigneeId}) : Staff.findOne({_id: foundAsset.assigneeId})
|
||||
}
|
||||
}
|
||||
|
||||
return {foundAsset}
|
||||
});
|
||||
|
||||
const getListItemStyle = (item) => {
|
||||
return {
|
||||
backgroundColor: selectedPerson === item ? '#EECFA6' : 'white'
|
||||
}
|
||||
}
|
||||
const assign = () => {
|
||||
if(foundAsset) {
|
||||
//Open the dialog to get condition.
|
||||
setUnassignCondition(foundAsset.condition ? foundAsset.condition : conditions[2])
|
||||
setUnassignConditionDetails(foundAsset.conditionDetails || "")
|
||||
setOpenAssignDialog(true)
|
||||
}
|
||||
}
|
||||
const assignDialogClosed = (assign) => {
|
||||
setOpenAssignDialog(false)
|
||||
|
||||
if(assign === true) {
|
||||
// Call assets.assign
|
||||
Meteor.call('assets.assign', foundAsset.assetId, selectedPerson.type, selectedPerson._id, assignCondition, assignConditionDetails)
|
||||
setAssetId("")
|
||||
// Set the focus back to the asset id text field
|
||||
// document.getElementById('assetIdInput').focus()
|
||||
// useEffect(() => {
|
||||
// if(assetIdInput) assetIdInput.focus()
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if(assetIdInput) assetIdInput.focus()
|
||||
})
|
||||
|
||||
const unassign = (asset) => {
|
||||
// Open the dialog to get condition and comment.
|
||||
setUnassignAsset(asset);
|
||||
setUnassignComment("")
|
||||
setUnassignCondition(asset.condition ? asset.condition : conditions[2])
|
||||
setUnassignConditionDetails(asset.conditionDetails || "")
|
||||
setOpenUnassignDialog(true);
|
||||
}
|
||||
const unassignDialogClosed = (unassign) => {
|
||||
setOpenUnassignDialog(false)
|
||||
|
||||
if(unassign === true) {
|
||||
// Call assets.unassign(assetId, comment, condition, conditionDetails, date)
|
||||
Meteor.call('assets.unassign', unassignAsset.assetId, unassignComment, unassignCondition, unassignConditionDetails)
|
||||
}
|
||||
}
|
||||
|
||||
const getAssetTileStyles = (index) => {
|
||||
return index % 2 ? {backgroundColor: '#FFF'} : {backgroundColor: '#d2d2d2'}
|
||||
}
|
||||
const cssAssetTile = {
|
||||
padding: '.8rem',
|
||||
userSelect: 'none',
|
||||
// '&:nthChild(even)': {backgroundColor: '#935e5e'}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dialog open={openAssignDialog} onClose={assignDialogClosed}>
|
||||
<DialogTitle>Assign Asset</DialogTitle>
|
||||
<DialogContent style={{display: 'flex', flexDirection: 'column'}}>
|
||||
<div>
|
||||
<TextField style={cssEditorField} select variant="standard" label="Condition" value={assignCondition} onChange={(e)=>{setAssignCondition(e.target.value)}}>
|
||||
{conditions.map((condition, i) => {
|
||||
return <MenuItem key={i} value={condition}>{condition}</MenuItem>
|
||||
})}
|
||||
</TextField>
|
||||
</div>
|
||||
<TextField style={{marginTop: '1rem',minWidth: '30rem'}} multiline rows={4} variant="outlined" label="Condition Details" value={assignConditionDetails} onChange={(e) => {setAssignConditionDetails(e.target.value)}}/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => assignDialogClosed(true)}>Assign</Button>
|
||||
<Button onClick={() => assignDialogClosed(false)}>Cancel</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<Dialog open={openUnassignDialog} onClose={unassignDialogClosed}>
|
||||
<DialogTitle>Unassign Asset</DialogTitle>
|
||||
<DialogContent style={{display: 'flex', flexDirection: 'column'}}>
|
||||
<div>
|
||||
<TextField style={cssEditorField} select variant="standard" label="Condition" value={unassignCondition} onChange={(e)=>{setUnassignCondition(e.target.value)}}>
|
||||
{conditions.map((condition, i) => {
|
||||
return <MenuItem key={i} value={condition}>{condition}</MenuItem>
|
||||
})}
|
||||
</TextField>
|
||||
</div>
|
||||
<TextField style={{marginTop: '1rem',minWidth: '30rem'}} variant="standard" label="Comment" value={unassignComment} onChange={(e) => {setUnassignComment(e.target.value)}}/>
|
||||
<TextField style={{marginTop: '1rem',minWidth: '30rem'}} multiline rows={4} variant="outlined" label="Condition Details" value={unassignConditionDetails} onChange={(e) => {setUnassignConditionDetails(e.target.value)}}/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => unassignDialogClosed(true)}>Unassign</Button>
|
||||
<Button onClick={() => unassignDialogClosed(false)}>Cancel</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<Box style={{marginTop: '1rem',...cssTwoColumnContainer}}>
|
||||
<ToggleButtonGroup color="primary" value={searchType} exclusive onChange={(e, type)=>setSearchType(type)} aria-label="Search Type">
|
||||
<ToggleButton value="Email">Email</ToggleButton>
|
||||
<ToggleButton value="First Name">First Name</ToggleButton>
|
||||
<ToggleButton value="Last Name">Last Name</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
<TextField style={cssEditorField} variant="standard" label="Search" value={search} onChange={(e) => {setSearch(e.target.value)}}/>
|
||||
</Box>
|
||||
<Box style={cssTwoColumnContainer}>
|
||||
<div style={{maxHeight: '26rem', overflowY:'auto', minWidth: '10rem', minHeight: '10rem'}}>
|
||||
<List>
|
||||
{people.map((next, i) => {
|
||||
return (
|
||||
<ListItemButton key={next._id} style={getListItemStyle(next)} selected={selectedPerson === next} onClick={(e) => {setSelectedPerson(next)}}>
|
||||
<ListItemText primary={next.firstName + " " + next.lastName} secondary={next.email} tertiary={"Hello World"}/>
|
||||
</ListItemButton>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
</div>
|
||||
<div style={{display: 'flex', flexDirection: 'column', margin: '1rem 0 0 .5rem'}}>
|
||||
{selectedPerson && (
|
||||
<div style={cssAssetTile}>
|
||||
<div style={{marginBottom: '1rem'}}><TextField id='assetIdInput' inputRef={input=>setAssetIdInput(input)} style={cssEditorField} variant="standard" label="Asset ID" value={assetId} onChange={(e) => {setAssetId(e.target.value)}}/></div>
|
||||
<div>{foundAsset && foundAsset.assetType.name}</div>
|
||||
<div>{foundAsset && foundAsset.serial}</div>
|
||||
{foundAsset && foundAsset.assignee && (
|
||||
<div>Assigned To: {foundAsset.assignee.firstName} {foundAsset.assignee.lastName}</div>
|
||||
)}
|
||||
<Button variant="contained" color='primary' className="button" disabled={!foundAsset || foundAsset.assignee !== undefined} onClick={()=>assign()}>Assign</Button>
|
||||
</div>
|
||||
)}
|
||||
{assets.map((next, i) => {
|
||||
return (
|
||||
<div key={next._id} style={{...getAssetTileStyles(i), ...cssAssetTile}}>
|
||||
<div>{next.assetType.name}</div>
|
||||
<div>{next.assetId}</div>
|
||||
<div>{next.serial}</div>
|
||||
<Button variant="contained" color='secondary' className="button" onClick={()=>unassign(next)}>Unassign</Button>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{/*<div style={{display: 'flex', flexDirection: 'row'}}>*/}
|
||||
{/* <TextField style={cssEditorField} variant="standard" label="Asset ID" value={assetId} onChange={(e) => {setAssetId(e.target.value)}}/>*/}
|
||||
{/* <TextField style={cssEditorField} variant="standard" label="Serial" value={serial} onChange={(e) => {setSerial(e.target.value)}}/>*/}
|
||||
{/*</div>*/}
|
||||
{/*<div style={{display: 'flex', flexDirection: 'row'}}>*/}
|
||||
{/* <TextField style={cssEditorField} select variant="standard" label="Condition" value={condition} onChange={(e)=>{setCondition(e.target.value)}}>*/}
|
||||
{/* {conditions.map((condition, i) => {*/}
|
||||
{/* return <MenuItem key={i} value={condition}>{condition}</MenuItem>*/}
|
||||
{/* })}*/}
|
||||
{/* </TextField>*/}
|
||||
{/*</div>*/}
|
||||
{/*<div style={{display: 'flex', flexDirection: 'row'}}>*/}
|
||||
{/* <TextField style={{width: '100%', margin: '1rem'}} multiline variant="outlined" rows={4} label="Condition Details" value={conditionDetails} onChange={(e) => {setConditionDetails(e.target.value)}}/>*/}
|
||||
{/*</div>*/}
|
||||
</div>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default () => {
|
||||
Meteor.subscribe('students');
|
||||
Meteor.subscribe('staff');
|
||||
Meteor.subscribe('assetTypes');
|
||||
Meteor.subscribe('assets');
|
||||
|
||||
return (
|
||||
<AssignmentsByPerson/>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user