diff --git a/client/_app.sass b/client/_app.sass index c17ef49..ff83aff 100644 --- a/client/_app.sass +++ b/client/_app.sass @@ -63,11 +63,13 @@ ul table min-width: 650px - -table > thead > tr > th.headerCell - color: white - background-color: #333447 - +// +//table > thead > tr > th.headerCell +// color: white +// background-color: #333447 +// +//table > thead > tr > th.headerCell .MuiTableSortLabel-icon +// background-color: white table > thead.sticky > tr > th.headerCell position: sticky top: 0 diff --git a/client/_page.sass b/client/_page.sass index 7712f07..da063dc 100644 --- a/client/_page.sass +++ b/client/_page.sass @@ -54,6 +54,21 @@ nav a + a color: white font-family: "KaushanScript-Regular", sans-serif font-size: 4rem + text-shadow: 0 0 .5rem black + display: inline-block + +.k12 + font-family: "KaushanScript-Regular", sans-serif + font-size: 1.5rem + text-shadow: 0 0 .4rem black + padding: 0 .4rem 0 .2rem + position: relative + top: -1rem + color: white + transform: rotate(-12deg) + border: .2rem solid white + box-shadow: 0 0 .2rem black + border-radius: .5rem display: inline-block .logo diff --git a/client/main.css b/client/main.css index 86b764c..95b10f6 100644 --- a/client/main.css +++ b/client/main.css @@ -282,11 +282,6 @@ table { min-width: 650px; } -table > thead > tr > th.headerCell { - color: white; - background-color: #333447; -} - table > thead.sticky > tr > th.headerCell { position: sticky; top: 0; @@ -470,6 +465,22 @@ nav a + a { color: white; font-family: "KaushanScript-Regular", sans-serif; font-size: 4rem; + text-shadow: 0 0 0.5rem black; + display: inline-block; +} + +.k12 { + font-family: "KaushanScript-Regular", sans-serif; + font-size: 1.5rem; + text-shadow: 0 0 0.4rem black; + padding: 0 0.4rem 0 0.2rem; + position: relative; + top: -1rem; + color: white; + transform: rotate(-12deg); + border: 0.2rem solid white; + box-shadow: 0 0 0.2rem black; + border-radius: 0.5rem; display: inline-block; } diff --git a/client/main.css.map b/client/main.css.map index 0ce04eb..96fc719 100644 --- a/client/main.css.map +++ b/client/main.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["_simple-grid.sass","_app.sass","_material-icons.sass","_roboto.sass","_page.sass","pages/_Users.sass"],"names":[],"mappings":"AAAQ;AAER;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;AAEA;EACC;EACA;EACA;;;AAED;AAEA;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;AAEA;EACC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;;;AAED;AAEA;EAEC;EACA;EACA;;;AAED;EACC;;AAGA;EACC;EACA;EACA;;;AAEF;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;;;AAED;AACC;EAEA;IACC;;;AAEF;AACC;EAEA;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;;AAEF;AACC;EAEA;IACC;IACA;;;ACzLF;AACA;EACC;;;AAED;EACC;;;AAED;EACC;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAQD;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;;;AAGA;EACC;;;AAEF;EACC;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;IACC;;;AAEF;EACC;IACC;;EAED;IACC;IACA;;EAED;IACC;;EAED;IACC;;;AClIF;EACC;EACA;EACA;EACA;;AAED;EACC;EACA;EACA;EACA;AACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACA;EACA;AACA;EACA;AACA;EACA;AACA;EACA;;;AAED;EACC;;;AC7BD;EACC;EACA;EACA;EACA;;ACND;EACC;EACA;EACA;EACA;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;;;AACD;EACC;EACA;;;AAED;EACC;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EAEC;AACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;IACC;IACA;IACA;IACA;IACA;IACA;;EAED;IACC;;;ACvGD;EACC;;AAED;EACC;EACA;EACA;;AAED;EACC","file":"main.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["_simple-grid.sass","_app.sass","_material-icons.sass","_roboto.sass","_page.sass","pages/_Users.sass"],"names":[],"mappings":"AAAQ;AAER;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;AAEA;EACC;EACA;EACA;;;AAED;AAEA;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;AAEA;EACC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;;;AAED;AAEA;EAEC;EACA;EACA;;;AAED;EACC;;AAGA;EACC;EACA;EACA;;;AAEF;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;;;AAED;AACC;EAEA;IACC;;;AAEF;AACC;EAEA;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;EAED;IACC;;;AAEF;AACC;EAEA;IACC;IACA;;;ACzLF;AACA;EACC;;;AAED;EACC;;;AAED;EACC;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAQD;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;;;AAQD;EACC;EACA;;;AAED;EACC;EACA;;;AAED;EACC;;;AAGA;EACC;;;AAEF;EACC;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;EACA;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;;;AAED;EACC;IACC;;;AAEF;EACC;IACC;;EAED;IACC;IACA;;EAED;IACC;;EAED;IACC;;;ACpIF;EACC;EACA;EACA;EACA;;AAED;EACC;EACA;EACA;EACA;AACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACA;EACA;AACA;EACA;AACA;EACA;AACA;EACA;;;AAED;EACC;;;AC7BD;EACC;EACA;EACA;EACA;;ACND;EACC;EACA;EACA;EACA;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;;;AACD;EACC;EACA;;;AAED;EACC;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EAEC;AACA;EACA;EACA;;;AAED;EACC;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;EACA;EACA;EACA;;;AAED;EACC;EACA;;;AAED;EACC;EACA;EACA;;;AAED;EACC;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAED;EACC;IACC;IACA;IACA;IACA;IACA;IACA;;EAED;IACC;;;ACtHD;EACC;;AAED;EACC;EACA;EACA;;AAED;EACC","file":"main.css"} \ No newline at end of file diff --git a/imports/ui/App.jsx b/imports/ui/App.jsx index f1aa6b3..44e86d3 100644 --- a/imports/ui/App.jsx +++ b/imports/ui/App.jsx @@ -1,6 +1,7 @@ import { Meteor } from 'meteor/meteor'; import {Roles} from 'meteor/alanning:roles'; import React, { useState } from 'react'; +import {createTheme, ThemeProvider} from '@mui/material/styles' import { useTracker } from 'meteor/react-meteor-data'; import _ from 'lodash'; import {BrowserRouter, Routes, Route} from 'react-router-dom'; @@ -11,6 +12,58 @@ import History from './pages/History' import Users from './pages/Users' import Admin from './pages/Admin' +const appTheme = createTheme({ + components: { + MuiTableSortLabel: { + styleOverrides: { + root: { + "&.Mui-active": { + color: 'white', + "&:hover": { + color: '#d2d1d1' + }, + }, + color: 'white', + backgroundColor: '#333447', + "&:hover": { + color: '#d2d1d1', + }, + }, + icon: { + '& path': { + fill: 'white' + } + } + } + }, + MuiTableCell: { + styleOverrides: { + // root: { + // '&:hover': { + // color: 'white !important' + // } + // }, + head: { + color: 'white !important', + backgroundColor: '#333447', + '&:hover': { + color: 'white !important' + }, + hover: { + color: 'white !important' + } + }, + // hover: { + // color: 'white !important', + // '&:hover': { + // color: 'white !important' + // } + // } + } + }, + } +}) + export const App = () => { const {user, canManageLaptops, isAdmin} = useTracker(() => { const user = Meteor.user(); @@ -25,31 +78,33 @@ export const App = () => { }) return ( - - - -
-
- TODO: Some statistics and such. + + + + +
+
+ TODO: Some statistics and such. +
-
- }/> - - {canManageLaptops && } - }/> - - {isAdmin && } - }/> - - {isAdmin && } - }/> - - {canManageLaptops && } }/> - - {isAdmin && } - }/> - - + + {canManageLaptops && } + }/> + + {isAdmin && } + }/> + + {isAdmin && } + }/> + + {canManageLaptops && } + }/> + + {isAdmin && } + }/> + + + ) } \ No newline at end of file diff --git a/imports/ui/Page.jsx b/imports/ui/Page.jsx index b26b23c..9536427 100644 --- a/imports/ui/Page.jsx +++ b/imports/ui/Page.jsx @@ -48,10 +48,10 @@ export const Page = (props) => { }
-
K12 Tempest
-
-
-
+
K-12
Tempest
+ {/*
*/} + {/*
*/} + {/*
*/}
diff --git a/imports/ui/pages/Admin/Staff.jsx b/imports/ui/pages/Admin/Staff.jsx index 1b0be5f..4827e87 100644 --- a/imports/ui/pages/Admin/Staff.jsx +++ b/imports/ui/pages/Admin/Staff.jsx @@ -113,6 +113,15 @@ export default () => { { 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", diff --git a/imports/ui/pages/Admin/Students.jsx b/imports/ui/pages/Admin/Students.jsx index 3655308..d1f7a29 100644 --- a/imports/ui/pages/Admin/Students.jsx +++ b/imports/ui/pages/Admin/Students.jsx @@ -114,6 +114,15 @@ export default () => { { 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", @@ -130,6 +139,15 @@ export default () => { { 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 + } }, ] diff --git a/imports/ui/pages/Assets/AddAssets.jsx b/imports/ui/pages/Assets/AddAssets.jsx index 8736d41..8acd69f 100644 --- a/imports/ui/pages/Assets/AddAssets.jsx +++ b/imports/ui/pages/Assets/AddAssets.jsx @@ -95,7 +95,7 @@ const AddAssets = ({assetTypes}) => {
- {setAssetId(e.target.value)}}/> + {setAssetId(e.target.value.toUpperCase())}}/> {setSerial(e.target.value)}}/>
diff --git a/imports/ui/pages/Assets/AssetList.jsx b/imports/ui/pages/Assets/AssetList.jsx index 286d6af..efd9887 100644 --- a/imports/ui/pages/Assets/AssetList.jsx +++ b/imports/ui/pages/Assets/AssetList.jsx @@ -105,18 +105,45 @@ export default () => { { name: "Asset ID", value: (row) => row.assetId, + descendingComparator: (a, b) => { + if(a.assetId === b.assetId) return 0 + else if(!a.assetId) return -1 + else if(!b.assetId) return 1 + else if(a.assetId.length < b.assetId.length) return 1 + else if(a.assetId.length > b.assetId.length) return -1 + else if(b.assetId < a.assetId) return -1 + else return 1 + } }, { name: "Serial", value: (row) => row.serial, + descendingComparator: (a, b) => { + if(a.serial === b.serial) return 0 + else if(!a.serial) return -1 + else if(!b.serial) return 1 + else if(a.serial.length < b.serial.length) return 1 + else if(a.serial.length > b.serial.length) return -1 + else if(b.serial < a.serial) return -1 + else return 1 + } }, { name: "Condition", value: (row) => row.condition, + descendingComparator: (a, b) => { + if(b.condition === a.condition) return 0 //Most common case + // Find the first matching condition in order. + for(let condition of conditions) { + if(b.condition === condition) return -1 + else if(a.condition === condition) return 1 + } + return 0 + } }, { name: "AssetType", - value: (row) => row.assetType.name, + value: (row) => row.assetType ? row.assetType.name : "", }, ] diff --git a/imports/ui/pages/Assignments/ByAsset.jsx b/imports/ui/pages/Assignments/ByAsset.jsx index 405b4f8..1b629e5 100644 --- a/imports/ui/pages/Assignments/ByAsset.jsx +++ b/imports/ui/pages/Assignments/ByAsset.jsx @@ -107,7 +107,7 @@ const AssignmentsByAsset = () => { - setAssetIdInput(input)} value={assetId} onChange={(e) => {setAssetId(e.target.value)}}/> + setAssetIdInput(input)} value={assetId} onChange={(e) => {setAssetId(e.target.value.toUpperCase())}}/> {foundAsset && (
diff --git a/imports/ui/util/SimpleTable.jsx b/imports/ui/util/SimpleTable.jsx index 9c7833b..3900b30 100644 --- a/imports/ui/util/SimpleTable.jsx +++ b/imports/ui/util/SimpleTable.jsx @@ -5,15 +5,19 @@ import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; +import TableSortLabel from '@mui/material/TableSortLabel'; import Paper from '@mui/material/Paper'; import classNames from 'classnames'; import Button from "@mui/material/Button"; +import { visuallyHidden } from '@mui/utils'; import _ from 'lodash'; +import Box from "@mui/material/Box"; // let columns = [ // { // name: "ID", -// value: (row) => row._id +// value: (row) => row._id, +// descendingComparator: (a, b) => {return value(b) < value(a) ? 1 : value(b) > value(a) ? -1 : 0} // } // ] // @@ -46,6 +50,8 @@ export default ({columns, rows, options}) => { } const [edited, setEdited] = useState(undefined); + const [order, setOrder] = useState('asc') //'asc' or 'desc' + const [orderBy, setOrderBy] = useState(undefined); //Column name being sorted. let editRow = (e, row) => { setEdited(row); @@ -75,6 +81,42 @@ export default ({columns, rows, options}) => { } } + const sort = (e, column) => { + const isAscending = orderBy === column && order === 'asc' //Descending if this is the first click on the column or toggling from ascending. + setOrder(isAscending ? 'desc' : 'asc') + setOrderBy(column) + } + + const descendingComparator = (a, b, orderBy) => { + let av = orderBy.value(a) + let bv = orderBy.value(b) + + if(bv < av) return -1 + else if(bv > av) return 1 + else return 0 + } + const getComparator = (order, orderBy) => { + if(!orderBy) return undefined + else if(orderBy.descendingComparator) return order === 'desc' ? (a,b) => orderBy.descendingComparator(a,b) : (a,b) => -orderBy.descendingComparator(a,b) + else return order === 'desc' + ? (a, b) => descendingComparator(a, b, orderBy) + : (a, b) => -descendingComparator(a, b, orderBy); + } + const stableSort = (array, comparator) => { + if(comparator) { + const stabilizedThis = array.map((el, index) => [el, index]); + stabilizedThis.sort((a, b) => { + const order = comparator(a[0], b[0]); + if (order !== 0) { + return order; + } + return a[1] - b[1]; + }); + return stabilizedThis.map((el) => el[0]); + } + else return array + } + // console.log(rows) return (
{options.add &&
} @@ -83,11 +125,17 @@ export default ({columns, rows, options}) => { {columns.map((column, i) => {return ( - {column.name} + + {sort(e, column)}}> + {column.name} + {orderBy === column.name && ( + + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + )} + + )})} - {/*Name*/} - {/*Email*/} - {/*Roles*/} @@ -98,9 +146,7 @@ export default ({columns, rows, options}) => { )} - {rows.map((row, i)=>{ - // console.log("Rendering Row " + i) - // console.log(row); + {stableSort(rows, getComparator(order, orderBy)).map((row, i) => { return ( {editRow(e, row)}} onClick={(e) => selectRow(e, row)}> {edited && options.key(edited) === options.key(row) ? @@ -117,6 +163,8 @@ export default ({columns, rows, options}) => { if(_.isObject(value)) { console.error("Cannot have an object returned as the value in a table.") + console.log("Cell value: ") + console.log(value) value = JSON.stringify(value) } diff --git a/public/images/logo.svg b/public/images/logo.svg index 488e19d..7eed071 100644 --- a/public/images/logo.svg +++ b/public/images/logo.svg @@ -1,3922 +1,2 @@ - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +image/svg+xml