Files
DistrictCentral/imports/ui/Chromebooks.svelte

308 lines
10 KiB
Svelte

<script>
import {Route, router, meta} from 'tinro';
import ChromebookScan from './ChromebookScan.svelte';
import {Meteor} from "meteor/meteor";
import TextField from '@smui/textfield';
import HelperText from '@smui/textfield/helper-text';
import Icon from '@smui/textfield/icon';
import { Icon as CommonIcon } from '@smui/common';
import DateInput from "./DateInput.svelte";
import Button, { Label } from '@smui/button';
import IconButton from '@smui/icon-button';
import {onMount} from "svelte";
import {Students} from "/imports/api/students";
import {Staff} from "/imports/api/staff";
import {AssetTypes} from "/imports/api/asset-types";
let serialInput = null;
let emailInput = null;
let dateInput = null;
let assetIdInput = null;
onMount(async () => {
Meteor.subscribe('assets');
Meteor.subscribe('students');
Meteor.subscribe('staff');
Meteor.subscribe('assetTypes');
});
function serialSearch() {
router.goto("/chromebooks?serial=" + encodeURIComponent(serialInput) + "&regex=true");
}
function assetIdSearch() {
router.goto("/chromebooks?assetId=" + encodeURIComponent(assetIdInput.toUpperCase()) + "&regex=false");
}
function emailSearch() {
router.goto("/chromebooks?email=" + encodeURIComponent(emailInput) + "&regex=true");
}
function dateSearch() {
// console.log("Date Search")
// console.log(dateInput);
if(dateInput) {
if(typeof dateInput === 'string' || dateInput instanceof String) {
let parts = dateInput.split('-');
dateInput = new Date(parts[0], parts[1]-1, parts[2]);
}
// console.log(dateInput instanceof Date)
//console.log(!isNaN(date.valueOf()));
// console.log(dateInput.getTime())
}
if(dateInput && dateInput instanceof Date)
router.goto("/chromebooks?date=" + encodeURIComponent(dateInput.getTime()));
}
// console.log("Loading Script");
// //Attempt to listen for URL changes (query portion specifically).
// (function(history){
// const pushState = history.pushState;
// history.pushState = function(state) {
// if (typeof history.onpushstate == "function") {
// history.onpushstate({state: state});
// }
// // Call your custom function here
// console.log("Push state");
// console.log(history);
// console.log(arguments);
// return pushState.apply(history, arguments);
// }
// })(window.history);
// const params = Object.fromEntries(new URLSearchParams(window.location.search));
//
// console.log("Params: ");
// console.log(params);
let deviceId = null;
let serial = null;
let assetId = null;
let email = null;
let date = null;
let regex = false;
$: router.subscribe(query => {
deviceId = router.location.query.get("deviceId");
serial = router.location.query.get("serial");
assetId = router.location.query.get('assetId');
email = router.location.query.get("email");
regex = router.location.query.get("regex");
date = router.location.query.get("date");
if(deviceId) deviceId = decodeURIComponent(deviceId);
if(serial) serial = decodeURIComponent(serial);
if(assetId) assetId = decodeURIComponent(assetId);
if(email) email = decodeURIComponent(email);
if(date) date = decodeURIComponent(date);
if(regex) regex = true;
// console.log("Query:");
// console.log(deviceId);
// console.log(serial);
// console.log(assetId);
// console.log(email);
// console.log(date);
});
let chromebookData = null;
$: {
if(deviceId || serial || email || date) {
let params = {};
if(deviceId) params.deviceId = deviceId;
else if(serial) params.serial = serial;
else if(assetId) params.assetId = assetId;
else if(email) params.email = email;
else if(date) params.date = parseInt(date, 10);
if(!date && regex) params.regex = true;
// console.log("Calling DataCollection.chromebookData")
// console.log(params);
Meteor.call("DataCollection.chromebookData", params, (error, result) => {
if (error) {
console.error(error);
} else {
for(let next of result) {
if(next.assetId) {
next.asset = Assets.findOne({assetId: next.assetId});
}
if(next.email) {
next.person = Students.findOne({email: next.email});
if(!next.person) next.person = Staff.findOne({email: next.email});
}
if(next.asset) {
next.assetType = AssetTypes.findOne({_id: next.asset.assetType})
if(next.asset.assigneeId) {
next.assignedTo = next.asset.assigneeType === "Student" ? Students.findOne({_id: next.asset.assigneeId}) : Staff.findOne({_id: next.asset.assigneeId})
}
}
}
chromebookData = result;
}
});
}
else {
chromebookData = null;
}
}
</script>
<Route path="/" let:meta>
{#if chromebookData}
<div class="container">
<div class="row col-12">
<ul>
{#each chromebookData as data}
<li>
{#if data.person}
{data.person.firstName} {data.person.lastName} (<a href="/chromebooks?email={encodeURIComponent(data.email)}">{data.email}</a>)<br/>
{:else}
<a href="/chromebooks?email={encodeURIComponent(data.email)}">{data.email}</a><br/>
{/if}
<a href="/chromebooks?deviceId={encodeURIComponent(data.deviceId)}">{data.deviceId}</a><br/>
<a href="/chromebooks?serial={encodeURIComponent(data.serial)}">{data.serial}</a><br/>
{new Date(data.startTime).toLocaleDateString("en-US") + "-" + new Date(data.endTime).toLocaleDateString("en-US")}
{#if data.assetType}
<br/>Asset Type: {data.assetType.name}
{/if}
{#if data.assignedTo}
<br/>Currently assigned to: {next.assignedTo.firstName} {next.assignedTo.lastName} ({next.assignedTo.email})
{/if}
</li>
{/each}
</ul>
</div>
</div>
{:else}
<div class="container">
<div class="row col-12">
<div class="options">
<h1>Chromebook Management</h1>
<ul>
<li>
<TextField type="text" bind:value={emailInput} on:keypress={(e) => {if(e.keyCode === 13) emailSearch()}} label="Email">
<!-- <svelte:fragment slot="label">-->
<!-- <CommonIcon class="material-icons" style="font-size: 1em; line-height: normal; vertical-align: top;">email</CommonIcon> Email-->
<!-- </svelte:fragment>-->
<IconButton slot="trailingIcon" class="material-icons" on:click={emailSearch}>search</IconButton>
<HelperText slot="helper">Type any part of an email address.</HelperText>
</TextField>
</li>
<li style="display: flex; flex-direction: row; flex-wrap: wrap; justify-content: flex-start; align-items: center; align-content: flex-start; gap: 2rem;">
<div style="display: inline-block;">
<TextField type="text" bind:value={serialInput} on:keypress={(e) => {if(e.keyCode === 13) serialSearch()}} label="Serial Number">
<IconButton slot="trailingIcon" class="material-icons" on:click={serialSearch}>search</IconButton>
<HelperText slot="helper">Type any part of a device serial number.</HelperText>
</TextField>
</div>
<div style="display: inline-block">
or
<Button style="margin-left: 2rem;" color="secondary" touch variant="raised" on:click={() => {document.location.href="/chromebooks/scan"}}>
<Label style="color: white">Scan</Label>
<Icon style="color: white" class="material-icons">qr_code_scanner</Icon>
</Button>
</div>
</li>
<li>
<TextField type="text" bind:value={assetIdInput} on:keypress={(e) => {if(e.keyCode === 13) assetIdSearch()}} label="Asset ID">
<IconButton slot="trailingIcon" class="material-icons" on:click={assetIdSearch}>search</IconButton>
<HelperText slot="helper">Type any part of an Asset ID.</HelperText>
</TextField>
</li>
<!-- <li>-->
<!-- By Chromebook Serial Number: <br/>-->
<!-- <input type="text" bind:value="{serialInput}" placeholder="Serial Number"/><br/>-->
<!-- <button type="button" role="button" on:click={serialSearch}>Search</button>-->
<!-- </li>-->
<!-- <li>-->
<!-- By Email Address: <br/>-->
<!-- <input type="text" bind:value="{emailInput}" placeholder="Email"/>@avpanthers.org<br/>-->
<!-- <button type="button" role="button" on:click={emailSearch}>Search</button>-->
<!-- </li>-->
<li>
<TextField type="date" bind:value={dateInput} on:keypress={(e) => {if(e.keyCode === 13) dateSearch()}} label="Date Search">
<IconButton slot="trailingIcon" class="material-icons" on:click={dateSearch}>search</IconButton>
<HelperText slot="helper">Find records since...</HelperText>
</TextField>
<!-- All records since: <br/>-->
<!-- <DateInput bind:date={dateInput}/>-->
<!-- <button type="button" role="button" on:click={dateSearch}>Search</button>-->
</li>
</ul>
</div>
</div>
</div>
{/if}
</Route>
<Route path="/byDevice/:deviceId">
<div class="container">
<div class="row col-12">
<ul>
{#each chromebookData as data}
<li>{data.email}<br/>{data.serial}
<br/>{new Date(data.startTime).toLocaleDateString("en-US") + "-" + new Date(data.endTime).toLocaleDateString("en-US")}
</li>
{/each}
</ul>
</div>
</div>
</Route>
<Route path="/scan">
<ChromebookScan/>
</Route>
<style>
a.button {
background: #7171ec;
border-radius: 999px;
box-shadow: #5E5DF0 0 10px 20px -10px;
box-sizing: border-box;
color: #FFFFFF;
cursor: pointer;
font-family: Inter,Helvetica,"Apple Color Emoji","Segoe UI Emoji",NotoColorEmoji,"Noto Color Emoji","Segoe UI Symbol","Android Emoji",EmojiSymbols,-apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans",sans-serif;
font-size: 16px;
font-weight: 700;
line-height: 24px;
opacity: 1;
outline: 0 solid transparent;
padding: 8px 18px;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
width: fit-content;
word-break: break-word;
border: 0;
text-decoration: none;
}
input {
--background: #fff;
--border-default: #D0D0DF;
--border-active: #3D6DF9;
/*--shadow-default: #{rgba(#202048, .12)};*/
/*--shadow-active: #{rgba(#3D6DF9, .25)};*/
--text-color: #818190;
--placeholder-color: #C9C9D9;
--placeholder-color-hover: #BABAC9;
--close: #818190;
--close-light: #BABAC9;
--close-background: #F1F1FA;
width: 100%;
max-width: 240px;
border-radius: 8px;
box-shadow: inset 0 0 0 1px;
}
.options {
margin: 0 auto;
max-width: 800px;
}
</style>