import { Meteor } from 'meteor/meteor';
import React, { useState } from 'react';
import { useTracker } from 'meteor/react-meteor-data';
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 MenuItem from '@mui/material/MenuItem';
import {Students} from "/imports/api/students";
import {Sites} from "/imports/api/sites";
import Box from "@mui/material/Box";
import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
import ToggleButton from "@mui/material/ToggleButton";
import {InputLabel, List, ListItemButton, ListItemText, Switch} from "@mui/material";
import FormControl from "@mui/material/FormControl";
import Dialog from "@mui/material/Dialog";
import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from "@mui/material/DialogContent";
import DialogActions from "@mui/material/DialogActions";
import FormControlLabel from "@mui/material/FormControlLabel";
import Checkbox from "@mui/material/Checkbox";
const cssSitesSelect = {
margin: '0.6rem 0',
minWidth: '20rem',
}
const cssFieldColumnContainer = {
display: 'flex',
flexDirection: 'column',
backgroundColor: '#DDD',
padding: '0.5rem',
border: '1px solid #999',
borderRadius: '0.2rem'
}
const cssGridFieldContainer = {
display: 'grid',
gridTemplateColumns: "1fr 1fr 1fr 1fr",
columnGap: '1rem',
rowGap: '0.4rem',
marginBottom: '1.5rem'
}
const cssButtonContainer = {
display: 'flex',
gap: '1rem',
justifyContent: 'flex-end'
}
const StudentEditor = ({value, close, defaultSiteId}) => {
const [email, setEmail] = useState(value.email || "")
const [id, setId] = useState(value.id || "")
const [firstName, setFirstName] = useState(value.firstName || "")
const [firstNameAlias, setFirstNameAlias] = useState(value.firstNameAlias || "")
const [lastName, setLastName] = useState(value.lastName || "")
const [grade, setGrade] = useState(value.grade || "")
const [active, setActive] = useState(value.active)
const [siteId, setSiteId] = useState(value.siteId ? value.siteId : defaultSiteId)
const {sites} = useTracker(() => {
let sites = Sites.find({}).fetch();
return {sites}
});
if(!siteId && sites && sites.length > 0) {
setSiteId(sites[0]._id)
}
const applyChanges = () => {
close()
//TODO Should invert this and only close if there was success on the server.
if(value._id)
Meteor.call("students.update", value._id, id, firstName, firstNameAlias, lastName, email, siteId, grade, active);
else
Meteor.call("students.add", id, firstName, firstNameAlias, lastName, email, siteId, grade, active);
}
const rejectChanges = () => {
close()
}
return (
Student Editor
{setId(e.target.value)}}/>
{setEmail(e.target.value)}}/>
{setGrade(e.target.value)}}/>
{setActive(e.target.checked)}}/>} label="Active"/>
{setFirstName(e.target.value)}}/>
{setFirstNameAlias(e.target.value)}}/>
{setLastName(e.target.value)}}/>
{setSiteId(e.target.value)}}>
{sites.map((next, i) => {
return
})}
)
}
export default () => {
const siteAll = {_id: 0, name: "All"}
const [site, setSite] = useState(siteAll._id)
Meteor.subscribe('sites');
Meteor.subscribe('students');
const {sites} = useTracker(() => {
const sites = Sites.find({}).fetch();
sites.push(siteAll);
return {sites}
});
const ACTIVE_BOTH = "both"
const ACTIVE_ONLY = "active"
const ACTIVE_OFF = "inactive"
const [active, setActive] = useState(ACTIVE_BOTH)
const [nameSearch, setNameSearch] = useState("")
const {students} = useTracker(() => {
const studentQuery = site === siteAll._id ? {} : {siteId: site}
if(active !== ACTIVE_BOTH) {
studentQuery["active"] = active === ACTIVE_ONLY
}
if(nameSearch && nameSearch.length > 2) {
studentQuery["$or"] = [{firstName: {$regex: nameSearch, $options: 'i'}}, {firstNameAlias: {$regex: nameSearch, $options: 'i'}}, {lastName: {$regex: nameSearch, $options: 'i'}}]
}
let students = Students.find(studentQuery).fetch();
return {students}
});
const columns = [
{
name: "ID",
value: (row) => row.id,
descendingComparator: (a, b) => {
if(a.id === b.id) return 0
else if(!a.id) return -1
else if(!b.id) return 1
else if(a.id.length < b.id.length) return 1
else if(a.id.length > b.id.length) return -1
else if(b.id < a.id) return -1
else return 1
}
},
{
name: "Email",
value: (row) => row.email,
},
{
name: "First Name",
value: (row) => row.firstName,
},
{
name: "Alias",
value: (row) => row.firstNameAlias,
},
{
name: "Last Name",
value: (row) => row.lastName,
},
{
name: "GRD",
value: (row) => row.grade,
descendingComparator: (a, b) => {
if(a.grade === b.grade) return 0
else if(!a.grade) return -1
else if(!b.grade) return 1
else if(a.grade.length < b.grade.length) return 1
else if(a.grade.length > b.grade.length) return -1
else if(b.grade < a.grade) return -1
else return 1
}
},
{
name: "Active",
value: (row) => row.active ? "Active" : "Inactive",
},
]
const options = {
key: (row) => row._id,
editor: (row, close) => {return ()},
add: true,
maxHeight: '40rem',
keyHandler: (e, selected) => {
if(selected && selected._id && e.key === "Delete") {
Meteor.call("students.remove", selected._id);
}
}
}
const importData = (type) => {
let input = document.createElement('input')
input.type = 'file'
input.onchange = _ => {
let files = Array.from(input.files)
if(files.length === 1) {
let reader = new FileReader()
reader.onload = () => {
Meteor.call("students.loadCsv", reader.result, type, testImportOnly, (err, result) => {
//Note: It would be nice to have feedback about the operation, but right now I cannot figure out how to wait on the server for the result of the callback that is wrapped by a bindEnvironment call.
if(err) console.log(err)
// else if(testImportOnly) console.log(result)
})
}
reader.readAsText(input.files[0])
}
}
input.click()
}
const [showImportDialog, setShowImportDialog] = useState(false)
const [testImportOnly, setTestImportOnly] = useState(false)
const openImportDialog = () => {
setTestImportOnly(false)
setShowImportDialog(true)
}
const closeImportDialog = (cause, importType) => {
if(importType) importData(importType)
if(showImportDialog) setShowImportDialog(false)
}
return (
<>
{setSite(e.target.value)}}>
{sites.map((next, i) => {
return
})}
Active Students
{setActive(e.target.value)}} aria-label="Active Students">
All
Active
Inactive
{setNameSearch(e.target.value)}}/>
>
)
}