Fixed a number of bugs; added a few fields.

This commit is contained in:
2022-08-08 22:15:55 -07:00
parent 4560d7203d
commit c96b4a6901
10 changed files with 3791 additions and 160 deletions

View File

@@ -60,12 +60,14 @@ Meteor.methods({
check(assigneeType, String);
check(assetId, String);
if(assigneeType !== 'Student' || assigneeType !== 'Staff') {
if(assigneeType !== 'Student' && assigneeType !== 'Staff') {
// Should never happen.
console.error("Error: Received incorrect assignee type in adding an assignment.");
console.error(assigneeType);
}
else if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
AssetAssignments.insert({assetId, assigneeType: assigneeType === "Student" ? 0 : 1, assigneeId});
AssetAssignments.insert({assetId, assigneeType, assigneeId});
}
},
'AssetAssignments.remove'(_id) {

View File

@@ -42,25 +42,27 @@ if (Meteor.isServer) {
// This code only runs on the server
Meteor.publish('assetTypes', function() {
return AssetTypes.find({}, {sort: {name: 1}});
return AssetTypes.find({});
});
}
Meteor.methods({
'assetTypes.add'(name, description) {
'assetTypes.add'(name, description, year) {
check(name, String);
check(description, String);
check(year, String);
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
AssetTypes.insert({name, description});
AssetTypes.insert({name, description, year});
}
},
'assetTypes.update'(_id, name, description) {
'assetTypes.update'(_id, name, description, year) {
check(_id, String);
check(name, String);
check(description, String);
check(year, String);
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
AssetTypes.update({_id}, {$set: {name, description}});
AssetTypes.update({_id}, {$set: {name, description, year}});
}
},
'assetTypes.remove'(_id) {

View File

@@ -13,6 +13,13 @@
const assetTypesColumns = [
{
key: "year",
title: "Year",
value: v => v.year,
minWidth: 100,
weight: 1,
cls: "year",
}, {
key: "name",
title: "Name",
value: v => v.name,
@@ -43,17 +50,17 @@
}
let dirtyAssetType;
// 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)});
editedAssetType.subscribe(v => {dirtyAssetType = Object.assign({name: "", description: "", year: ""}, v)});
// Load the sites (reactive).
let assetTypes = AssetTypes.find({});
let assetTypes = AssetTypes.find({}, {sort: {year: -1}});
const deleteAssetType = assetType => {
//TODO:
};
const applyAssetTypeChanges = () => {
if(dirtyAssetType._id)
Meteor.call("assetTypes.update", dirtyAssetType._id, dirtyAssetType.name, dirtyAssetType.description);
Meteor.call("assetTypes.update", dirtyAssetType._id, dirtyAssetType.name, dirtyAssetType.description, dirtyAssetType.year);
else
Meteor.call("assetTypes.add", dirtyAssetType.name, dirtyAssetType.description);
Meteor.call("assetTypes.add", dirtyAssetType.name, dirtyAssetType.description, dirtyAssetType.year);
editedAssetType.set(null);
dirtyAssetType = null;
}
@@ -68,6 +75,9 @@
{#if dirtyAssetType}
<div class="editorContainer">
<div style="grid-column: 1/span 1">
<TextField type="text" style="width: 100%" bind:value={dirtyAssetType.year} label="Year">
<HelperText slot="helper">The manufacture or purchase year. Used for sorting assets so most recent ones appear on top.</HelperText>
</TextField>
<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>

View File

@@ -4,9 +4,9 @@
import {Meteor} from "meteor/meteor";
import {onMount} from "svelte";
import AssetList from "/imports/ui/Assets/AssetList.svelte";
import AssetDataEntry from "/imports/ui/Assets/AssetDataEntry.svelte";
import AddAssets from "/imports/ui/Assets/AddAssets.svelte";
import {useTracker} from "meteor/rdb:svelte-meteor-data";
import Assign from "/imports/ui/Assets/Assign.svelte";
import AssignAssets from "/imports/ui/Assets/AssignAssets.svelte";
import Assignments from "/imports/ui/Assets/Assignments.svelte";
let canManageLaptops = false;
@@ -23,12 +23,12 @@
let tabs = [];
if(canManageLaptops) {
tabs.push({id: 'assignments', label: 'Assignments'});
tabs.push({id: 'assignment', label: 'Assign'});
tabs.push({id: 'listAssignments', label: 'Assignment List'});
tabs.push({id: 'assignAssets', label: 'Assign Assets'});
}
if(isAdmin) {
tabs.push({id: 'list', label: 'Asset List'});
tabs.push({id: 'entry', label: 'Data Entry'});
tabs.push({id: 'listAssets', label: 'Asset List'});
tabs.push({id: 'addAssets', label: 'Add Assets'});
}
let activeTab = tabs[0];
</script>
@@ -39,13 +39,13 @@
<Label>{tab.label}</Label>
</Tab>
</TabBar>
{#if activeTab && activeTab.id === 'list'}
{#if activeTab && activeTab.id === 'listAssets'}
<AssetList></AssetList>
{:else if activeTab && activeTab.id === 'entry'}
<AssetDataEntry></AssetDataEntry>
{:else if activeTab && activeTab.id === 'assignment'}
<Assign></Assign>
{:else if activeTab && activeTab.id === 'assignments'}
{:else if activeTab && activeTab.id === 'addAssets'}
<AddAssets></AddAssets>
{:else if activeTab && activeTab.id === 'assignAssets'}
<AssignAssets></AssignAssets>
{:else if activeTab && activeTab.id === 'listAssignments'}
<Assignments></Assignments>
{/if}
</div>

View File

@@ -9,6 +9,7 @@
import TextField from '@smui/textfield';
import u from 'umbrellajs';
import {AssetTypes} from "/imports/api/asset-types";
import Paper from '@smui/paper';
onMount(async () => {
Meteor.subscribe('assetTypes');
@@ -17,7 +18,7 @@
let assetTypes;
//$m: assetTypes = AssetTypes.find({}).fetch();
//$: assetTypes = useTracker(() => AssetTypes.find({}).fetch());
$: assetTypes = AssetTypes.find({});
$: assetTypes = AssetTypes.find({}, {sort: {year: -1}});
let selectedAssetTypes = [];
let selectedType = null;
@@ -116,10 +117,11 @@
</Actions>
</Dialog>
<h3 style="display: inline-block">Asset Types</h3>
<h3 style="display: block">Asset Types</h3>
<Button class="addBtn" on:click={openAssetTypesDialog}>
<Label>Add...</Label>
</Button>
<Paper>
<List class="assetTypeList" singleSelection dense>
{#each selectedAssetTypes as type}
<Item on:SMUI:action={() => (selectedAssetType = type)} selected={selectedAssetType === type}>
@@ -127,6 +129,7 @@
</Item>
{/each}
</List>
</Paper>
<div style="grid-column: 1/span 1">
<TextField id="assetIdField" type="text" style="width: 100%" bind:value={assetId} label="AssetId">
</TextField>
@@ -147,7 +150,7 @@
}
:global(.addBtn) {
margin-left: 4rem;
/*margin-left: 4rem;*/
}
:global(.assetTypeList) {

View File

@@ -1,7 +1,7 @@
<script>
import {Meteor} from "meteor/meteor";
import {onMount} from "svelte";
import {writable} from "svelte/store";
import {writable, derived} from "svelte/store";
import TextField from '@smui/textfield';
import HelperText from '@smui/textfield/helper-text';
import Select, { Option } from '@smui/select';
@@ -16,7 +16,12 @@
Meteor.subscribe('assets');
});
let assetTypes;
$: assetTypes = AssetTypes.find({});
$: assetTypes = AssetTypes.find({}, {sort: {year: -1}});
$: assetTypeNameMap = derived(assetTypes, $assetTypes => $assetTypes.reduce((map, obj) => {
map[obj._id] = obj.name;
return map;
}, {}));
// Asset Table //
@@ -35,6 +40,17 @@
minWidth: 100,
weight: 1,
cls: "serial",
}, {
key: "asset",
title: "Asset Type",
value: v => {
$: {
return v.assetTypeId ? $assetTypeNameMap[v.assetTypeId] : "-"
}
},
minWidth: 100,
weight: 1,
cls: "serial",
},
];
const assetActions = {

View File

@@ -58,6 +58,7 @@
const createAssignment = () => {
if(assetId && assetId.length && selectedAssignee) {
Meteor.call("AssetAssignments.add", assetId, selectedCategory === 'Student' ? "Student" : "Staff", selectedAssignee._id)
// TODO: Set focus to the asset ID field.
assetId = "";
}
}
@@ -105,7 +106,7 @@
<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}>
<Button variant="raised" color="secondary" on:click={createAssignment} disabled={!assetId || assetId.length === 0 || !selectedAssignee}>
<Label style="color: white">Create</Label>
</Button>
</div>

View File

@@ -2,14 +2,9 @@
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';
@@ -30,12 +25,14 @@
let selectedSiteId;
let categories = ['Email', 'First Name', 'Last Name'];
let selectedCategory = 'Email';
let selectedGrade = 'All';
let selectedGrade = 'All Grades';
let searchText = "";
let searchResults = [];
let searchResults;
let selectedResult;
$: {
console.log("Site ID")
console.log(selectedSiteId)
if(selectedSiteId) {
Meteor.subscribe('students', selectedSiteId);
Meteor.subscribe('staff', selectedSiteId);
@@ -44,34 +41,37 @@
$: {
selectedResult = null;
console.log("Starting search")
// Require at least two characters in the search field before we start filtering.
if(selectedSiteId && selectedGrade && selectedCategory && searchText && searchText.length > 1) {
if(selectedSiteId && selectedGrade && selectedCategory) {
let query = {};
if(searchText && searchText.length > 0) {
if (selectedCategory === 'Email') {
query.email = {$regex: searchText, $options: 'i'};
}
else if(selectedCategory === 'First Name') {
} else if (selectedCategory === 'First Name') {
query.firstName = {$regex: searchText, $options: 'i'};
}
else {
} else {
query.lastName = {$regex: searchText, $options: 'i'};
}
}
if(selectedCategory === "Staff") {
searchResults = Staff.find(query);
}
else {
if(selectedGrade !== 'All') {
if(selectedGrade !== 'All Grades') {
query.grade = selectedGrade;
}
searchResults = Students.find(query).fetch();
console.log("Searching")
console.log(query)
searchResults = Students.find(query);
}
}
else {
searchResults = [];
searchResults = undefined;
}
}
</script>
@@ -117,7 +117,8 @@
<!-- </Button>-->
</div>
<List twoLine singleSelection>
{#each searchResults as result}
{#if searchResults}
{#each $searchResults as result}
<Item selected={selectedResult === result}>
<Text>
<PrimaryText>{result.firstName} {result.lastName}</PrimaryText>
@@ -125,6 +126,7 @@
</Text>
</Item>
{/each}
{/if}
</List>
</div>

3795
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,9 @@
"private": true,
"scripts": {
"start": "meteor run",
"build": "npm install --product && meteor build --architecture os.linux.x86_64 --server-only ../",
"update": "npx browserslist@latest --update-db",
"build": "npm install --omit=dev && meteor build --architecture os.linux.x86_64 --server-only ../",
"build_old": "npm install --product && meteor build --architecture os.linux.x86_64 --server-only ../",
"test": "meteor test --once --driver-package meteortesting:mocha",
"test-app": "TEST_WATCH=1 meteor test --full-app --driver-package meteortesting:mocha",
"visualize": "meteor --production --extra-packages bundle-visualizer",
@@ -21,6 +23,7 @@
"meteor-node-stubs": "^1.0.0",
"moment": "^2.29.2",
"mongodb": "^4.4.1",
"smui-theme": "^6.0.0-beta.16",
"svelte": "^3.46.4",
"svelte-material-ui": "^6.0.0-beta.16",
"tinro": "^0.6.12",
@@ -61,7 +64,6 @@
"@smui/textfield": "^6.0.0-beta.16",
"chai": "^4.2.0",
"rollup-plugin-css-only": "^3.1.0",
"smui-theme": "^6.0.0-beta.16",
"typescript": "^4.7.4"
}
}