2022-05-17 11:06:15 -07:00
< script >
import { Meteor } from "meteor/meteor";
2022-06-13 07:42:26 -07:00
import { onMount } from "svelte";
import { Sites } from "../api/sites";
import GridTable from "./GridTable.svelte";
import { writable } from "svelte/store";
import TextField from '@smui/textfield';
import HelperText from '@smui/textfield/helper-text';
2022-06-20 08:24:35 -07:00
import { Students } from "../api/students";
import { Staff } from "../api/staff";
import { AssetTypes } from "../api/asset-types";
2022-06-13 07:42:26 -07:00
onMount(async () => {
Meteor.subscribe('sites');
2022-06-20 08:24:35 -07:00
Meteor.subscribe('assetTypes');
2022-06-13 07:42:26 -07:00
});
2022-05-17 11:06:15 -07:00
2022-06-29 00:31:47 -07:00
// Should not be needed now. Did not work well - had a bug somewhere.
// const fixRecords = () => { Meteor . call ( "admin.fixRecords" );}
2022-06-13 07:42:26 -07:00
const siteColumns = [
{
key: "_id",
title: "ID",
value: v => v._id,
minWidth: 20,
weight: 1,
cls: "id",
}, {
key: "name",
title: "Name",
value: v => v.name,
minWidth: 100,
weight: 1,
cls: "name",
},
];
const actions = {
title: "Actions",
headerWidgets: [
{ icon : "add_box" , action : () => { editedSite . set ({ name : "" });}, tooltip : "Add a new Site." }
],
rowWidgets: [
{ icon : "add_circle" , action : ( v ) => { editedSite . set ( v )}} ,
{ icon : "delete" , action : ( v ) => { deleteSite ( v )}}
],
};
const deleteSite = site => {
//TODO:
};
2022-06-15 11:46:14 -07:00
// Create a holder for the site being edited. This allows us to clear the editor when the user finishes, and allows the table or parent view to setup the editor.
2022-06-13 07:42:26 -07:00
let editedSite = writable(null);
2022-06-15 11:46:14 -07:00
let dirtySite = null;
// Copy the edited site when ever it changes, set some defaults for a new site object (to make the view happy).
editedSite.subscribe(site => { dirtySite = Object . assign ({ name : "" }, site )} );
// Load the sites (reactive).
2022-06-13 07:42:26 -07:00
let sites = Sites.find({} );
const applySiteChanges = () => {
2022-06-15 11:46:14 -07:00
if(dirtySite._id)
Meteor.call("sites.update", dirtySite._id, dirtySite.name);
2022-06-13 07:42:26 -07:00
else
2022-06-15 11:46:14 -07:00
Meteor.call("sites.add", dirtySite.name);
2022-06-13 07:42:26 -07:00
editedSite.set(null);
}
const rejectSiteChanges = () => {
editedSite.set(null);
}
2022-06-20 08:24:35 -07:00
let selectedSite = null;
2022-06-29 00:31:47 -07:00
2022-06-20 08:24:35 -07:00
let students = null;
let staff = null;
$: {
if(selectedSite) {
Meteor.subscribe('students', selectedSite._id);
Meteor.subscribe('staff', selectedSite._id);
students = Students.find({ siteId : selectedSite._id } );
staff = Staff.find({ siteId : selectedSite._id } );
}
}
const onSiteSelection = (e) => {
selectedSite = Sites.findOne({ _id : e.detail } );
}
const uploadStudents = () => {
// console.log(files);
// console.log(selectedSite);
// console.log(selectedSite._id);
if(files && files.length) {
let file = files[0];
let reader = new FileReader();
reader.onload = (e) => {
// console.log("Sending Data");
// console.log(selectedSite._id);
// console.log(reader.result);
Meteor.call('students.loadCsv', reader.result, selectedSite._id);
}
reader.readAsText(file, "UTF-8");
}
}
let files;
const studentColumns = [
{
key: "_id",
title: "ID",
value: v => v._id,
minWidth: 20,
weight: 1,
cls: "id",
}, {
key: "email",
title: "Email",
value: v => v.email,
minWidth: 100,
weight: 1,
cls: "email",
}, {
key: "firstName",
title: "First Name",
value: v => v.firstName,
minWidth: 100,
weight: 1,
cls: "firstName",
}, {
key: "lastName",
title: "Last Name",
value: v => v.lastName,
minWidth: 100,
weight: 1,
cls: "lastName",
}, {
key: "grade",
title: "Grade",
value: v => v.grade,
minWidth: 100,
weight: 1,
cls: "grade",
},
];
let editedStudent = writable(null);
const onStudentSelection = (e) => {
}
const staffColumns = [
{
key: "_id",
title: "ID",
value: v => v._id,
minWidth: 20,
weight: 1,
cls: "id",
}, {
key: "email",
title: "Email",
value: v => v.email,
minWidth: 100,
weight: 1,
cls: "email",
}, {
key: "firstName",
title: "First Name",
value: v => v.firstName,
minWidth: 100,
weight: 1,
cls: "firstName",
}, {
key: "lastName",
title: "Last Name",
value: v => v.lastName,
minWidth: 100,
weight: 1,
cls: "lastName",
},
];
let editedStaff = writable(null);
const onStaffSelection = (e) => {
}
const assetTypesColumns = [
{
key: "_id",
title: "ID",
value: v => v._id,
minWidth: 20,
weight: 1,
cls: "id",
}, {
key: "name",
title: "Name",
value: v => v.name,
minWidth: 100,
weight: 1,
cls: "name",
}, {
key: "description",
title: "Description",
value: v => v.description,
minWidth: 100,
weight: 1,
cls: "description",
},
];
2022-06-29 00:31:47 -07:00
const assetTypesActions = {
title: "Actions",
headerWidgets: [
{ icon : "add_box" , action : () => { editedAssetType . set ({ name : "" });}, tooltip : "Add a new asset type." }
],
rowWidgets: [
{ icon : "add_circle" , action : ( v ) => { editedAssetType . set ( v )}} ,
{ icon : "delete" , action : ( v ) => { deleteAssetType ( v )}}
],
};
2022-06-20 08:24:35 -07:00
let editedAssetType = writable(null);
const onAssetTypeSelection = (e) => {
}
let dirtyAssetType = null;
2022-06-29 00:31:47 -07:00
// Copy the edited value when ever it changes, set some defaults for a new value object (to make the view happy).
editedAssetType.subscribe(v => { dirtyAssetType = Object . assign ({ name : "" , description : "" }, v )} );
2022-06-20 08:24:35 -07:00
// Load the sites (reactive).
let assetTypes = AssetTypes.find({} );
2022-06-29 00:31:47 -07:00
const deleteAssetType = assetType => {
//TODO:
};
const applyAssetTypeChanges = () => {
if(dirtyAssetType._id)
Meteor.call("assetTypes.update", dirtyAssetType._id, dirtyAssetType.name, dirtyAssetType.description);
else
Meteor.call("assetTypes.add", dirtyAssetType.name, dirtyAssetType.description);
editedAssetType.set(null);
}
const rejectAssetTypeChanges = () => {
editedSite.set(null);
}
2022-05-17 11:06:15 -07:00
< / script >
2022-06-13 07:42:26 -07:00
2022-05-17 11:06:15 -07:00
< div class = "container" >
2022-06-29 00:31:47 -07:00
< h2 > Sites< / h2 >
2022-06-20 08:24:35 -07:00
< GridTable bind:rows = { sites } columns=" { siteColumns } " actions = " { actions } " rowKey = " {( v ) => { return v . _id }} " bind:edited = " { editedSite } " on:selection = { onSiteSelection } >
2022-06-15 11:46:14 -07:00
{ #if dirtySite }
2022-06-13 07:42:26 -07:00
< div class = "editorContainer" >
< div style = "grid-column: 1/span 1" >
2022-06-15 11:46:14 -07:00
< TextField type = "text" style = "width: 100%" bind:value = { dirtySite . name } label="Name" >
2022-06-13 07:42:26 -07:00
< HelperText slot = "helper" > Provide a unique name for the site.< / HelperText >
< / TextField >
< / div >
< button type = "button" style = "grid-column: 2/span 1;" class = "button accept-button material-icons material-symbols-outlined" on:click = { applySiteChanges } >
check
< / button >
< button type = "button" style = "grid-column: 3/span 1;" class = "button reject-button material-icons material-symbols-outlined" on:click = { rejectSiteChanges } >
close
< / button >
< / div >
{ /if }
< / GridTable >
2022-06-20 08:24:35 -07:00
{ #if selectedSite }
< h2 > Site Students< / h2 >
< form on:submit | preventDefault = { uploadStudents } >
< input style = "display: inline-block" type = "file" multiple = "false" accept = "text/csv" bind:files = { files } / >
< input type = "submit" value = "Upload" / >
< / form >
< GridTable bind:rows = { students } columns=" { studentColumns } " actions = " { null } " rowKey = " {( v ) => { return v . _id }} " bind:edited = " { editedStudent } " on:selection = { onStudentSelection } >
{ #if dirtySite }
< div class = "editorContainer" >
< div style = "grid-column: 1/span 1" >
< TextField type = "text" style = "width: 100%" bind:value = { dirtySite . name } label="Name" >
< HelperText slot = "helper" > Provide a unique name for the site.< / HelperText >
< / TextField >
< / div >
< button type = "button" style = "grid-column: 2/span 1;" class = "button accept-button material-icons material-symbols-outlined" on:click = { applySiteChanges } >
check
< / button >
< button type = "button" style = "grid-column: 3/span 1;" class = "button reject-button material-icons material-symbols-outlined" on:click = { rejectSiteChanges } >
close
< / button >
< / div >
{ /if }
< / GridTable >
< h2 > Site Staff< / h2 >
< GridTable bind:rows = { staff } columns=" { staffColumns } " actions = " { null } " rowKey = " {( v ) => { return v . _id }} " bind:edited = " { editedStaff } " on:selection = { onStaffSelection } >
{ #if dirtySite }
< div class = "editorContainer" >
< div style = "grid-column: 1/span 1" >
< TextField type = "text" style = "width: 100%" bind:value = { dirtySite . name } label="Name" >
< HelperText slot = "helper" > Provide a unique name for the site.< / HelperText >
< / TextField >
< / div >
< button type = "button" style = "grid-column: 2/span 1;" class = "button accept-button material-icons material-symbols-outlined" on:click = { applySiteChanges } >
check
< / button >
< button type = "button" style = "grid-column: 3/span 1;" class = "button reject-button material-icons material-symbols-outlined" on:click = { rejectSiteChanges } >
close
< / button >
< / div >
{ /if }
< / GridTable >
{ /if }
< h2 > Asset Types< / h2 >
2022-06-29 00:31:47 -07:00
< GridTable bind:rows = { assetTypes } columns=" { assetTypesColumns } " actions = " { assetTypesActions } " rowKey = " {( v ) => { return v . _id }} " bind:edited = " { editedAssetType } " on:selection = { onAssetTypeSelection } >
{ #if dirtyAssetType }
2022-06-20 08:24:35 -07:00
< div class = "editorContainer" >
< div style = "grid-column: 1/span 1" >
2022-06-29 00:31:47 -07:00
< TextField type = "text" style = "width: 100%" bind:value = { dirtyAssetType . name } label="Name" >
< HelperText slot = "helper" > Provide a unique name for the asset type.< / HelperText >
< / TextField >
< TextField type = "text" style = "width: 100%" bind:value = { dirtyAssetType . description } label="Description" >
< HelperText slot = "helper" > A detailed description.< / HelperText >
2022-06-20 08:24:35 -07:00
< / TextField >
< / div >
2022-06-29 00:31:47 -07:00
< button type = "button" style = "grid-column: 2/span 1;" class = "button accept-button material-icons material-symbols-outlined" on:click = { applyAssetTypeChanges } > check</button >
< button type = "button" style = "grid-column: 3/span 1;" class = "button reject-button material-icons material-symbols-outlined" on:click = { rejectAssetTypeChanges } > close</button >
2022-06-20 08:24:35 -07:00
< / div >
{ /if }
< / GridTable >
2022-06-13 07:42:26 -07:00
<!-- {#each sites as site} -->
<!-- <div>{site.name}</div> -->
<!-- {/each} -->
<!-- <button type="button" on:click={fixRecords}>Fix Records</button> -->
2022-05-17 11:06:15 -07:00
< / div >
2022-06-13 07:42:26 -07:00
< style >
2022-06-20 08:24:35 -07:00
form {
margin: 0;
}
2022-06-13 07:42:26 -07:00
.editorContainer {
display: grid;
grid-template-columns: minmax(10px, 1fr) minmax(3rem, 3rem) minmax(3rem, 3rem);
}
.accept-button, .reject-button {
font-size: .8rem;
padding: .6rem;
margin: auto;
color: white;
border-radius: 50%;
border: 0;
font-weight: 800;
alignment: center;
cursor: pointer;
}
.accept-button {
background-color: rgba(61, 148, 61, 0.91);
}
.reject-button {
background-color: rgba(176, 64, 64, 0.61);
}
.accept-button:hover {
background-color: rgb(61, 148, 61);
}
.reject-button:hover {
background-color: rgb(176, 64, 64);
}
< / style >