Finished the first cut of adding asset assignments; Added a page to display asset assignments (need to allow removing them).
This commit is contained in:
@@ -23,12 +23,12 @@ const AssetAssignmentsSchema = new SimpleSchema({
|
|||||||
label: "Assignee ID",
|
label: "Assignee ID",
|
||||||
optional: false,
|
optional: false,
|
||||||
},
|
},
|
||||||
assigneeType: {
|
assigneeType: { // 0: Student, 1: Staff
|
||||||
type: SimpleSchema.Integer,
|
type: SimpleSchema.Integer,
|
||||||
label: "Assignee Type",
|
label: "Assignee Type",
|
||||||
optional: false,
|
optional: false,
|
||||||
min: 1,
|
min: 0,
|
||||||
max: 2,
|
max: 1,
|
||||||
exclusiveMin: false,
|
exclusiveMin: false,
|
||||||
exclusiveMax: false,
|
exclusiveMax: false,
|
||||||
},
|
},
|
||||||
@@ -49,15 +49,26 @@ if (Meteor.isServer) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
'assetAssignments.add'(assetId) {
|
/**
|
||||||
// check(assetTypeId, String);
|
* Assigns the asset to the assignee. The assignee should either be a Student or Staff member.
|
||||||
// check(assetId, String);
|
* @param assetId The Mongo ID of the asset (asset._id).
|
||||||
|
* @param assigneeType One of: 'Student', 'Staff'
|
||||||
|
* @param assigneeId The Mongo ID of the Student or Staff (person._id).
|
||||||
|
*/
|
||||||
|
'AssetAssignments.add'(assetId, assigneeType, assigneeId) {
|
||||||
|
check(assigneeId, String);
|
||||||
|
check(assigneeType, String);
|
||||||
|
check(assetId, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
|
if(assigneeType !== 'Student' || assigneeType !== 'Staff') {
|
||||||
// Assets.insert({assetTypeId, assetId});
|
// Should never happen.
|
||||||
|
console.error("Error: Received incorrect assignee type in adding an assignment.");
|
||||||
|
}
|
||||||
|
else if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
|
||||||
|
AssetAssignments.insert({assetId, assigneeType: assigneeType === "Student" ? 0 : 1, assigneeId});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'assetAssignments.remove'(_id) {
|
'AssetAssignments.remove'(_id) {
|
||||||
check(_id, String);
|
check(_id, String);
|
||||||
|
|
||||||
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
|
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
|
||||||
|
|||||||
@@ -14,149 +14,150 @@ if (Meteor.isServer) {
|
|||||||
Meteor.publish('students', function(siteId) {
|
Meteor.publish('students', function(siteId) {
|
||||||
return Students.find({siteId});
|
return Students.find({siteId});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
async 'students.getPossibleGrades'() {
|
'students.getPossibleGrades'() {
|
||||||
return Students.rawCollection().distinct('grade', {});
|
return Students.rawCollection().distinct('grade', {});
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Sets a first name alias that can be overridden by the one that is imported.
|
* Sets a first name alias that can be overridden by the one that is imported.
|
||||||
* @param _id The student's database ID.
|
* @param _id The student's database ID.
|
||||||
* @param alias The alias to set for the student.
|
* @param alias The alias to set for the student.
|
||||||
*/
|
*/
|
||||||
'students.setAlias'(_id, alias) {
|
'students.setAlias'(_id, alias) {
|
||||||
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
|
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
|
||||||
check(_id, String);
|
check(_id, String);
|
||||||
check(alias, String);
|
check(alias, String);
|
||||||
|
|
||||||
Students.update({_id}, !alias || !alias.length() ? {$unset: {alias: true}} : {$set: {alias}});
|
Students.update({_id}, !alias || !alias.length() ? {$unset: {alias: true}} : {$set: {alias}});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Assumes that the ID field is a unique ID that never changes for a student.
|
* Assumes that the ID field is a unique ID that never changes for a student.
|
||||||
* This must be true in order for duplicate students to be avoided.
|
* This must be true in order for duplicate students to be avoided.
|
||||||
* Will automatically update a student's data, including the site he/she is associated with.
|
* Will automatically update a student's data, including the site he/she is associated with.
|
||||||
*
|
*
|
||||||
* Expects the CSV string to contain comma delimited data in the form:
|
* Expects the CSV string to contain comma delimited data in the form:
|
||||||
* email, student ID, first name, last name, grade, first name alias, last name alias
|
* email, student ID, first name, last name, grade, first name alias, last name alias
|
||||||
*
|
*
|
||||||
* The query in Aeries is: `LIST STU ID SEM FN LN NG FNA`.
|
* The query in Aeries is: `LIST STU ID SEM FN LN NG FNA`.
|
||||||
* A more complete Aeries query: `LIST STU STU.ID STU.SEM STU.FN STU.LN STU.NG BY STU.NG STU.SEM IF STU.NG >= 7 AND NG <= 12 AND STU.NS = 5`
|
* A more complete Aeries query: `LIST STU STU.ID STU.SEM STU.FN STU.LN STU.NG BY STU.NG STU.SEM IF STU.NG >= 7 AND NG <= 12 AND STU.NS = 5`
|
||||||
* Note that FNA (First Name Alias) is optional.
|
* Note that FNA (First Name Alias) is optional.
|
||||||
* Note that you might want to include a school ID in the IF if you have multiple schools in the district.
|
* Note that you might want to include a school ID in the IF if you have multiple schools in the district.
|
||||||
* The query in SQL is: `SELECT [STU].[ID] AS [Student ID], [STU].[SEM] AS [StuEmail], STU.FN AS [First Name], STU.LN AS [Last Name], [STU].[GR] AS [Grade], [STU].[FNA] AS [First Name Alias], [STU].[LNA] AS [Last Name Alias] FROM (SELECT [STU].* FROM STU WHERE [STU].DEL = 0) STU WHERE ( [STU].SC = 5) ORDER BY [STU].[LN], [STU].[FN];`.
|
* The query in SQL is: `SELECT [STU].[ID] AS [Student ID], [STU].[SEM] AS [StuEmail], STU.FN AS [First Name], STU.LN AS [Last Name], [STU].[GR] AS [Grade], [STU].[FNA] AS [First Name Alias], [STU].[LNA] AS [Last Name Alias] FROM (SELECT [STU].* FROM STU WHERE [STU].DEL = 0) STU WHERE ( [STU].SC = 5) ORDER BY [STU].[LN], [STU].[FN];`.
|
||||||
* Run the query in Aeries as a `Report`, select TXT, and upload here.
|
* Run the query in Aeries as a `Report`, select TXT, and upload here.
|
||||||
*
|
*
|
||||||
* Aeries adds a header per 'page' of data (I think 35 entries per page).
|
* Aeries adds a header per 'page' of data (I think 35 entries per page).
|
||||||
* Example:
|
* Example:
|
||||||
* Anderson Valley Jr/Sr High School,6/11/2022
|
* Anderson Valley Jr/Sr High School,6/11/2022
|
||||||
* 2021-2022,Page 1
|
* 2021-2022,Page 1
|
||||||
* Student ID, Email, First Name,Last Name,Grade,(opt) First Name Alias
|
* Student ID, Email, First Name,Last Name,Grade,(opt) First Name Alias
|
||||||
* @type: Currently only supports 'CSV' or 'Aeries Text Report'
|
* @type: Currently only supports 'CSV' or 'Aeries Text Report'
|
||||||
*/
|
*/
|
||||||
'students.loadCsv'(csv, type, siteId) {
|
'students.loadCsv'(csv, type, siteId) {
|
||||||
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
|
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
|
||||||
check(csv, String);
|
check(csv, String);
|
||||||
check(siteId, String);
|
check(siteId, String);
|
||||||
|
|
||||||
let site = Sites.findOne({_id: siteId});
|
let site = Sites.findOne({_id: siteId});
|
||||||
|
|
||||||
if(site) {
|
if(site) {
|
||||||
let cleanCsv;
|
let cleanCsv;
|
||||||
let lines = csv.split(/\r?\n/);
|
let lines = csv.split(/\r?\n/);
|
||||||
let pageHeader = type === 'Aeries Text Report' ? lines[0] : null; // Skip the repeating header lines for an Aeries text report.
|
let pageHeader = type === 'Aeries Text Report' ? lines[0] : null; // Skip the repeating header lines for an Aeries text report.
|
||||||
let skip = type === 'CSV' ? 1 : 0; // Skip the first line of a CSV file (headers).
|
let skip = type === 'CSV' ? 1 : 0; // Skip the first line of a CSV file (headers).
|
||||||
|
|
||||||
// Remove headers from the CSV.
|
// Remove headers from the CSV.
|
||||||
for(const line of lines) {
|
for(const line of lines) {
|
||||||
if (skip > 0) skip--;
|
if (skip > 0) skip--;
|
||||||
else if (pageHeader && line === pageHeader) {
|
else if (pageHeader && line === pageHeader) {
|
||||||
skip = 2;
|
skip = 2;
|
||||||
} else {
|
} else {
|
||||||
if(!cleanCsv) cleanCsv = "";
|
if(!cleanCsv) cleanCsv = "";
|
||||||
else cleanCsv += '\r\n';
|
else cleanCsv += '\r\n';
|
||||||
cleanCsv += line;
|
cleanCsv += line;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log(cleanCsv);
|
|
||||||
|
|
||||||
// Note: This doesn't work because some values are quoted and contain commas as a value character.
|
|
||||||
// Parse the CSV (now without any headers).
|
|
||||||
// lines = cleanCsv.split(/\r\n/);
|
|
||||||
// for(const line of lines) {
|
|
||||||
// let values = line.split(/\s*,\s*/);
|
|
||||||
//
|
|
||||||
// if(values.length >= 5) {
|
|
||||||
// let id = values[0];
|
|
||||||
// let email = values[1];
|
|
||||||
// let firstName = values[2];
|
|
||||||
// let lastName = values[3];
|
|
||||||
// let grade = parseInt(values[4], 10);
|
|
||||||
// let firstNameAlias = "";
|
|
||||||
// let active = true;
|
|
||||||
//
|
|
||||||
// if(values.length > 5) firstNameAlias = values[5];
|
|
||||||
//
|
|
||||||
// let student = {siteId, email, id, firstName, lastName, grade, firstNameAlias, active};
|
|
||||||
//
|
|
||||||
// // console.log(student);
|
|
||||||
// // Update or insert in the db.
|
|
||||||
// console.log("Upserting: " + student);
|
|
||||||
// Students.upsert({id}, {$set: student});
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const bound = Meteor.bindEnvironment((callback) => {callback();});
|
|
||||||
|
|
||||||
parse(cleanCsv, {}, function(err, records) {
|
|
||||||
bound(() => {
|
|
||||||
if(err) console.error(err);
|
|
||||||
else {
|
|
||||||
let foundIds = new Set();
|
|
||||||
let duplicates = [];
|
|
||||||
console.log("Found " + records.length + " records.");
|
|
||||||
|
|
||||||
for(const values of records) {
|
|
||||||
let id = values[0];
|
|
||||||
let email = values[1];
|
|
||||||
let firstName = values[2];
|
|
||||||
let lastName = values[3];
|
|
||||||
let grade = parseInt(values[4], 10);
|
|
||||||
let firstNameAlias = "";
|
|
||||||
let active = true;
|
|
||||||
|
|
||||||
if(values.length > 5) firstNameAlias = values[5];
|
|
||||||
|
|
||||||
let student = {siteId, email, id, firstName, lastName, grade, firstNameAlias, active};
|
|
||||||
|
|
||||||
// Track the student ID's and record duplicates. This is used to ensure our counts are accurate later.
|
|
||||||
if(foundIds.has(student.id)) {
|
|
||||||
duplicates.push(student.id);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
foundIds.add(student.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//console.log(student);
|
|
||||||
try {
|
|
||||||
Students.upsert({id: student.id}, {$set: student});
|
|
||||||
}
|
|
||||||
catch(err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(duplicates.length + " records were duplicates:");
|
|
||||||
console.log(duplicates);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
})
|
|
||||||
}
|
//console.log(cleanCsv);
|
||||||
else {
|
|
||||||
console.log("Failed to find the site with the ID: " + siteId);
|
// Note: This doesn't work because some values are quoted and contain commas as a value character.
|
||||||
|
// Parse the CSV (now without any headers).
|
||||||
|
// lines = cleanCsv.split(/\r\n/);
|
||||||
|
// for(const line of lines) {
|
||||||
|
// let values = line.split(/\s*,\s*/);
|
||||||
|
//
|
||||||
|
// if(values.length >= 5) {
|
||||||
|
// let id = values[0];
|
||||||
|
// let email = values[1];
|
||||||
|
// let firstName = values[2];
|
||||||
|
// let lastName = values[3];
|
||||||
|
// let grade = parseInt(values[4], 10);
|
||||||
|
// let firstNameAlias = "";
|
||||||
|
// let active = true;
|
||||||
|
//
|
||||||
|
// if(values.length > 5) firstNameAlias = values[5];
|
||||||
|
//
|
||||||
|
// let student = {siteId, email, id, firstName, lastName, grade, firstNameAlias, active};
|
||||||
|
//
|
||||||
|
// // console.log(student);
|
||||||
|
// // Update or insert in the db.
|
||||||
|
// console.log("Upserting: " + student);
|
||||||
|
// Students.upsert({id}, {$set: student});
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
const bound = Meteor.bindEnvironment((callback) => {callback();});
|
||||||
|
|
||||||
|
parse(cleanCsv, {}, function(err, records) {
|
||||||
|
bound(() => {
|
||||||
|
if(err) console.error(err);
|
||||||
|
else {
|
||||||
|
let foundIds = new Set();
|
||||||
|
let duplicates = [];
|
||||||
|
console.log("Found " + records.length + " records.");
|
||||||
|
|
||||||
|
for(const values of records) {
|
||||||
|
let id = values[0];
|
||||||
|
let email = values[1];
|
||||||
|
let firstName = values[2];
|
||||||
|
let lastName = values[3];
|
||||||
|
let grade = parseInt(values[4], 10);
|
||||||
|
let firstNameAlias = "";
|
||||||
|
let active = true;
|
||||||
|
|
||||||
|
if(values.length > 5) firstNameAlias = values[5];
|
||||||
|
|
||||||
|
let student = {siteId, email, id, firstName, lastName, grade, firstNameAlias, active};
|
||||||
|
|
||||||
|
// Track the student ID's and record duplicates. This is used to ensure our counts are accurate later.
|
||||||
|
if(foundIds.has(student.id)) {
|
||||||
|
duplicates.push(student.id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foundIds.add(student.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(student);
|
||||||
|
try {
|
||||||
|
Students.upsert({id: student.id}, {$set: student});
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(duplicates.length + " records were duplicates:");
|
||||||
|
console.log(duplicates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("Failed to find the site with the ID: " + siteId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
}
|
||||||
@@ -13,13 +13,6 @@
|
|||||||
|
|
||||||
const assetTypesColumns = [
|
const assetTypesColumns = [
|
||||||
{
|
{
|
||||||
key: "_id",
|
|
||||||
title: "ID",
|
|
||||||
value: v => v._id,
|
|
||||||
minWidth: 20,
|
|
||||||
weight: 1,
|
|
||||||
cls: "id",
|
|
||||||
}, {
|
|
||||||
key: "name",
|
key: "name",
|
||||||
title: "Name",
|
title: "Name",
|
||||||
value: v => v.name,
|
value: v => v.name,
|
||||||
|
|||||||
@@ -176,9 +176,9 @@
|
|||||||
<h3>Aeries</h3>
|
<h3>Aeries</h3>
|
||||||
<p>For the Aeries system, log into your Aeries web interface and navigate to the query page. Enter the following query:</p>
|
<p>For the Aeries system, log into your Aeries web interface and navigate to the query page. Enter the following query:</p>
|
||||||
<h4>Pre-Rollover</h4>
|
<h4>Pre-Rollover</h4>
|
||||||
<pre style="font-size: 0.7rem"><code>LIST STU STU.ID STU.SEM STU.FN STU.LN STU.NG BY STU.ID STU.NG STU.SEM IF STU.NG >= 7 AND NG <= 12 AND STU.NS = 5</code></pre>
|
<pre style="font-size: 0.7rem"><code>LIST STU STU.ID STU.SEM STU.FN STU.LN STU.NG BY STU.ID STU.NG STU.SEM IF STU.NG >= 7 AND STU.NG <= 12 AND STU.NS = 5</code></pre>
|
||||||
<h4>Post-Rollover</h4>
|
<h4>Post-Rollover</h4>
|
||||||
<pre style="font-size: 0.7rem"><code>LIST STU STU.ID STU.SEM STU.FN STU.LN STU.NG BY STU.ID STU.NG STU.SEM IF STU.NG >= 7 AND GR <= 12 AND STU.SC = 5</code></pre>
|
<pre style="font-size: 0.7rem"><code>LIST STU STU.ID STU.SEM STU.FN STU.LN STU.GR BY STU.ID STU.GR STU.SEM IF STU.GR >= 7 AND STU.GR <= 12 AND STU.SC = 5</code></pre>
|
||||||
<p>Run the query and validate that all students have an email address and a student ID. You likely also want to check that the student `next grade (NG)` field is set correctly for the students (pre-rollover).</p>
|
<p>Run the query and validate that all students have an email address and a student ID. You likely also want to check that the student `next grade (NG)` field is set correctly for the students (pre-rollover).</p>
|
||||||
<p>You have two options for export. You can:</p>
|
<p>You have two options for export. You can:</p>
|
||||||
<ol class="help">
|
<ol class="help">
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import AssetDataEntry from "/imports/ui/Assets/AssetDataEntry.svelte";
|
import AssetDataEntry from "/imports/ui/Assets/AssetDataEntry.svelte";
|
||||||
import {useTracker} from "meteor/rdb:svelte-meteor-data";
|
import {useTracker} from "meteor/rdb:svelte-meteor-data";
|
||||||
import Assign from "/imports/ui/Assets/Assign.svelte";
|
import Assign from "/imports/ui/Assets/Assign.svelte";
|
||||||
|
import Assignments from "/imports/ui/Assets/Assignments.svelte";
|
||||||
|
|
||||||
let canManageLaptops = false;
|
let canManageLaptops = false;
|
||||||
let isAdmin = false;
|
let isAdmin = false;
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
let tabs = [];
|
let tabs = [];
|
||||||
|
|
||||||
if(canManageLaptops) {
|
if(canManageLaptops) {
|
||||||
|
tabs.push({id: 'assignments', label: 'Assignments'});
|
||||||
tabs.push({id: 'assignment', label: 'Assign'});
|
tabs.push({id: 'assignment', label: 'Assign'});
|
||||||
}
|
}
|
||||||
if(isAdmin) {
|
if(isAdmin) {
|
||||||
@@ -43,6 +45,8 @@
|
|||||||
<AssetDataEntry></AssetDataEntry>
|
<AssetDataEntry></AssetDataEntry>
|
||||||
{:else if activeTab && activeTab.id === 'assignment'}
|
{:else if activeTab && activeTab.id === 'assignment'}
|
||||||
<Assign></Assign>
|
<Assign></Assign>
|
||||||
|
{:else if activeTab && activeTab.id === 'assignments'}
|
||||||
|
<Assignments></Assignments>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
let selectedGrade = 'All';
|
let selectedGrade = 'All';
|
||||||
let selectedAssignee;
|
let selectedAssignee;
|
||||||
let assetId = "";
|
let assetId = "";
|
||||||
|
let assetIdWidget;
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
if(selectedSiteId) {
|
if(selectedSiteId) {
|
||||||
if(selectedCategory === 'Student') {
|
if(selectedCategory === 'Student') {
|
||||||
@@ -52,6 +54,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createAssignment = () => {
|
||||||
|
if(assetId && assetId.length && selectedAssignee) {
|
||||||
|
Meteor.call("AssetAssignments.add", assetId, selectedCategory === 'Student' ? "Student" : "Staff", selectedAssignee._id)
|
||||||
|
assetId = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -91,10 +100,15 @@
|
|||||||
</Cell>
|
</Cell>
|
||||||
</LayoutGrid>
|
</LayoutGrid>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
<TextField type="text" style="width: 100%" bind:value={assetId} label="Asset ID">
|
<div style="width: 100%; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: flex-start; align-items: flex-end; align-content: stretch; column-gap: 2rem;">
|
||||||
|
<TextField bind:this={assetIdWidget} style="flex-grow: 999;" type="text" bind:value={assetId} label="Asset ID">
|
||||||
</TextField>
|
|
||||||
|
</TextField>
|
||||||
|
<Button variant="raised" color="secondary" on:click={createAssignment()} disabled={!assetId || assetId.length === 0 || !selectedAssignee}>
|
||||||
|
<Label style="color: white">Create</Label>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
<List twoLine singleSelection style="max-height: 60%">
|
<List twoLine singleSelection style="max-height: 60%">
|
||||||
{#if $assignees}
|
{#if $assignees}
|
||||||
{#each $assignees as assignee}
|
{#each $assignees as assignee}
|
||||||
|
|||||||
133
imports/ui/Assets/Assignments.svelte
Normal file
133
imports/ui/Assets/Assignments.svelte
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<script>
|
||||||
|
import {Meteor} from "meteor/meteor";
|
||||||
|
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';
|
||||||
|
import {Students} from "../../api/students";
|
||||||
|
import Select, { Option } from '@smui/select';
|
||||||
|
import Dialog, { Title, Content, Actions } from '@smui/dialog';
|
||||||
|
import Button, { Label } from '@smui/button';
|
||||||
|
import {Staff} from "/imports/api/staff";
|
||||||
|
import List, {Item, Graphic, Meta, Text, PrimaryText, SecondaryText} from '@smui/list';
|
||||||
|
import Paper from '@smui/paper';
|
||||||
|
import LayoutGrid, {Cell} from '@smui/layout-grid';
|
||||||
|
|
||||||
|
let grades = ['Staff', 'All Grades'];
|
||||||
|
onMount(async () => {
|
||||||
|
Meteor.subscribe('sites');
|
||||||
|
Meteor.call('students.getPossibleGrades', (err, result) => {
|
||||||
|
if(err) console.log(err);
|
||||||
|
else {
|
||||||
|
grades = ['Staff', 'All Grades', ...result];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Load the sites (reactive).
|
||||||
|
let sites = Sites.find({});
|
||||||
|
let selectedSiteId;
|
||||||
|
let categories = ['Email', 'First Name', 'Last Name'];
|
||||||
|
let selectedCategory = 'Email';
|
||||||
|
let selectedGrade = 'All';
|
||||||
|
let searchText = "";
|
||||||
|
let searchResults = [];
|
||||||
|
let selectedResult;
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if(selectedSiteId) {
|
||||||
|
Meteor.subscribe('students', selectedSiteId);
|
||||||
|
Meteor.subscribe('staff', selectedSiteId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$: {
|
||||||
|
selectedResult = null;
|
||||||
|
|
||||||
|
// Require at least two characters in the search field before we start filtering.
|
||||||
|
if(selectedSiteId && selectedGrade && selectedCategory && searchText && searchText.length > 1) {
|
||||||
|
let query = {};
|
||||||
|
|
||||||
|
if(selectedCategory === 'Email') {
|
||||||
|
query.email = {$regex: searchText, $options: 'i'};
|
||||||
|
}
|
||||||
|
else if(selectedCategory === 'First Name') {
|
||||||
|
query.firstName = {$regex: searchText, $options: 'i'};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
query.lastName = {$regex: searchText, $options: 'i'};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selectedCategory === "Staff") {
|
||||||
|
searchResults = Staff.find(query);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(selectedGrade !== 'All') {
|
||||||
|
query.grade = selectedGrade;
|
||||||
|
}
|
||||||
|
|
||||||
|
searchResults = Students.find(query).fetch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
searchResults = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1 style="display: block">Asset Assignments</h1>
|
||||||
|
|
||||||
|
<Paper>
|
||||||
|
<LayoutGrid>
|
||||||
|
<Cell span="{6}">
|
||||||
|
<Select bind:value={selectedSiteId} label="Site">
|
||||||
|
{#each $sites as site}
|
||||||
|
<Option value={site._id}>{site.name}</Option>
|
||||||
|
{/each}
|
||||||
|
</Select>
|
||||||
|
</Cell>
|
||||||
|
<Cell span="{6}">
|
||||||
|
<Select bind:value={selectedGrade} label="Grade">
|
||||||
|
{#each grades as grade}
|
||||||
|
<Option value={grade}>{grade}</Option>
|
||||||
|
{/each}
|
||||||
|
</Select>
|
||||||
|
</Cell>
|
||||||
|
<Cell span="{6}">
|
||||||
|
<Select bind:value={selectedCategory} label="Category">
|
||||||
|
{#each categories as category}
|
||||||
|
<Option value={category}>{category}</Option>
|
||||||
|
{/each}
|
||||||
|
</Select>
|
||||||
|
</Cell>
|
||||||
|
<Cell span="{6}">
|
||||||
|
<TextField type="text" bind:value={searchText} label="Search"></TextField>
|
||||||
|
</Cell>
|
||||||
|
</LayoutGrid>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
<div style="width: 100%; display: flex; flex-direction: row; flex-wrap: nowrap; justify-content: flex-start; align-items: flex-end; align-content: stretch; column-gap: 2rem;">
|
||||||
|
<!-- <TextField bind:this={assetIdWidget} style="flex-grow: 999;" type="text" bind:value={assetId} label="Asset ID">-->
|
||||||
|
|
||||||
|
<!-- </TextField>-->
|
||||||
|
<!-- <Button variant="raised" color="secondary" on:click={createAssignment()} disabled={!assetId || assetId.length === 0 || !selectedAssignee}>-->
|
||||||
|
<!-- <Label style="color: white">Create</Label>-->
|
||||||
|
<!-- </Button>-->
|
||||||
|
</div>
|
||||||
|
<List twoLine singleSelection>
|
||||||
|
{#each searchResults as result}
|
||||||
|
<Item selected={selectedResult === result}>
|
||||||
|
<Text>
|
||||||
|
<PrimaryText>{result.firstName} {result.lastName}</PrimaryText>
|
||||||
|
<SecondaryText>{result.email} {result.grade ? '(' + result.grade + ')' : ""}</SecondaryText>
|
||||||
|
</Text>
|
||||||
|
</Item>
|
||||||
|
{/each}
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user