Removed old asset assignment collection (delete from the db if you have it). Added proper history associated with assigning and unassigning. Need to still add events attached to a CB which then transition to the history when the CB is checked in.

This commit is contained in:
2022-08-16 16:08:12 -07:00
parent 1501a36801
commit 2b9825159b
10 changed files with 354 additions and 130 deletions

View File

@@ -4,11 +4,17 @@ export const AssetAssignmentHistory = new Mongo.Collection('assetAssignmentHisto
/*
Maintains a historical record of asset assignments.
assetKey: The MongoID of the asset. AssetID's could be reused, so this prevents that eventuality from messing up historical records.
assetId: The asset's assigned ID (not a MongoID).
serial: The asset's serial number (part of the device, or defined by the manufacturer). In some cases this may be a partial serial. It is not a unique identifier, but should be mostly unique. This might be undefined if a serial was never provided for the original asset.
assetTypeName: The name of the asset type, or "UNK" if one could not be found (shouldn't happen). This is stored because these records could be kept longer than the assets in the system.
assigneeType: One of 'Student' or 'Staff'.
assigneeId: The MongoID of the student or staff the asset was assigned to.
startDate: The date/time of the assignment.
endDate: The date/time of the unassignment.
startCondition: TODO
endCondition: TODO
comment: A text block detailing the reason for the unassignment of the device. Eg: 'Broke Screen' or 'End of year' or 'Not charging' or 'Needs replacement'.
startCondition: One of the condition options: [New, Like New, Good, Okay, Damaged] (see assets.unassign for details).
endCondition: One of the condition options: [New, Like New, Good, Okay, Damaged] (see assets.unassign for details).
startConditionDetails: An optional text block for details on the condition.
endConditionDetails: An optional text block for details on the condition.
*/

View File

@@ -1,92 +0,0 @@
import {Mongo} from "meteor/mongo";
import {Meteor} from "meteor/meteor";
import { check } from 'meteor/check';
import { Roles } from 'meteor/alanning:roles';
//import SimpleSchema from "simpl-schema";
import {AssetTypes} from "./asset-types";
// console.log("Setting Up Asset Assignments...")
export const AssetAssignments = new Mongo.Collection('assetAssignments');
/*
const TYPE_STUDENT = 1;
const TYPE_STAFF = 2;
const AssetAssignmentsSchema = new SimpleSchema({
assetId: {
type: String,
label: "Asset ID",
optional: false,
index: 1,
unique: false
},
assigneeId: {
type: String,
label: "Assignee ID",
optional: false,
},
assigneeType: { // 0: Student, 1: Staff
type: SimpleSchema.Integer,
label: "Assignee Type",
optional: false,
min: 0,
max: 1,
exclusiveMin: false,
exclusiveMax: false,
},
});
AssetAssignments.attachSchema(AssetAssignmentsSchema);
*/
if (Meteor.isServer) {
// Drop any old indexes we no longer will use. Create indexes we need.
//try {AssetAssignments._dropIndex("name")} catch(e) {}
//AssetAssignments.createIndex({name: "text"}, {name: "name", unique: false});
//try {AssetTypes._dropIndex("AssetID")} catch(e) {} //Typo put this as an index in AssetTypes instead of AssetAssignments.
//AssetAssignments.createIndex({assetId: 1}, {name: "AssetID", unique: false});
// This code only runs on the server
Meteor.publish('assetAssignments', function(assetId) {
// let query = {};
//
// if(assetId) {
// query.assetId = assetId;
// }
//
// return AssetAssignments.find(query);
return [];
});
}
Meteor.methods({
/**
* Assigns the asset to the assignee. The assignee should either be a Student or Staff member.
* @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(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, assigneeId});
// }
},
'AssetAssignments.remove'(_id) {
// check(_id, String);
//
// if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
// //TODO: Need to first verify there are no checked out assets to the staff member.
// }
},
});
// console.log("Asset assignments setup.")

View File

@@ -4,7 +4,6 @@ import { check } from 'meteor/check';
import { Roles } from 'meteor/alanning:roles';
//import SimpleSchema from "simpl-schema";
import {AssetTypes} from "./asset-types";
import {AssetAssignments} from "/imports/api/asset-assignments";
import {AssetAssignmentHistory} from "/imports/api/asset-assignment-history";
// console.log("Setting Up Assets...")
@@ -53,6 +52,16 @@ const AssetsSchema = new SimpleSchema({
type: Date,
label: "Assignment Date",
optional: true,
},
condition: { //One of the condition options: [New, Like New, Good, Okay, Damaged] (see assets.unassign for details).
type: String,
label: "Condition",
optional: false,
},
conditionDetails: { //An optional text block for details on the condition.
type: String,
label: "Condition Details",
optional: true,
}
});
Assets.attachSchema(AssetsSchema);
@@ -70,10 +79,18 @@ if (Meteor.isServer) {
});
}
Meteor.methods({
'assets.add'(assetTypeId, assetId, serial) {
'assets.add'(assetTypeId, assetId, serial, condition, conditionDetails) {
check(assetTypeId, String);
check(assetId, String);
check(serial, String);
check(condition, String);
if(conditionDetails) check(conditionDetails, String);
if(condition !== 'New' && condition !== 'Like New' && condition !== 'Good' && condition !== 'Okay' && condition !== 'Damaged') {
//Should never happen.
console.error("Invalid condition option in assets.add(..)");
throw new Meteor.Error("Invalid condition option.");
}
// Convert the asset ID's to uppercase for storage to make searching easier.
assetId = assetId.toUpperCase();
@@ -83,25 +100,33 @@ Meteor.methods({
if(Assets.findOne({assetId})) {
//return {error: true, errorType: 'duplicateAssetId'}
throw new Meteor.Error("duplicateAssetId", "Cannot use the same asset ID twice.")
throw new Meteor.Error("Duplicate Asset Id", "Cannot use the same asset ID twice.")
}
else if(serial) {
Assets.insert({assetTypeId, assetId, serial});
Assets.insert({assetTypeId, assetId, serial, condition, conditionDetails});
}
else {
Assets.insert({assetTypeId, assetId});
Assets.insert({assetTypeId, assetId, condition, conditionDetails});
}
}
else throw new Meteor.Error("User Permission Error");
},
'assets.update'(_id, assetId, serial) {
'assets.update'(_id, assetId, serial, condition, conditionDetails) {
check(_id, String);
check(assetId, String);
if(serial) check(serial, String);
check(condition, String);
if(conditionDetails) check(conditionDetails, String);
if(condition !== 'New' && condition !== 'Like New' && condition !== 'Good' && condition !== 'Okay' && condition !== 'Damaged') {
//Should never happen.
console.error("Invalid condition option in assets.update(..)");
throw new Meteor.Error("Invalid condition option.");
}
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
//TODO: Need to first verify there are no checked out assets to the staff member.
Assets.update({_id}, {$set: {assetId, serial}});
Assets.update({_id}, {$set: {assetId, serial, condition, conditionDetail}});
}
else throw new Meteor.Error("User Permission Error");
},
@@ -109,9 +134,22 @@ Meteor.methods({
check(_id, String);
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
//TODO: Ensure we have not assigned this asset??? Not sure if we should require unassigning first.
let asset = Assets.findOne({_id});
if(asset) {
// Ensure the asset is not assigned still. Must unassign then remove. That allows us to maintain historical records for assignees.
if(asset.assigneeId) {
throw new Meteor.Error("Must unassign the asset before removal.");
}
else {
Assets.remove({_id});
}
}
else {
//This should never happen.
throw new Meteor.Error("Could not find the asset: " + _id);
}
}
else throw new Meteor.Error("User Permission Error");
},
/**
@@ -119,16 +157,26 @@ Meteor.methods({
* @param assetId The Asset ID (eg: 'Z1Q') of the asset (asset.assetId).
* @param assigneeType One of: 'Student', 'Staff'
* @param assigneeId The Mongo ID of the Student or Staff (person._id).
* @param condition One of the condition options: [New, Like New, Good, Okay, Damaged]. 'Like New' is defined as very minor cosmetic damage. 'Good' is defined as some cosmetic damage or very minor screen damage. 'Okay' is defined as significant cosmetic damage, or screen/keyboard/trackpad damage but is still useable. 'Damaged' indicates significant damage and the device should not be reissued until it is repaired.
* @param conditionDetails A text block detailing the current condition (if it is needed).
* @param date The date/time of the action. Will be set to the current date/time if not provided.
*/
'assets.assign'(assetId, assigneeType, assigneeId, date) {
'assets.assign'(assetId, assigneeType, assigneeId, condition, conditionDetails, date) {
check(assigneeId, String);
check(assigneeType, String);
check(assetId, String);
check(condition, String);
if(conditionDetails) check(conditionDetails, String);
if(date) check(date, Date);
if(!date) date = new Date();
if(condition !== 'New' && condition !== 'Like New' && condition !== 'Good' && condition !== 'Okay' && condition !== 'Damaged') {
//Should never happen.
console.error("Invalid condition option in assets.unassign(..)");
throw new Meteor.Error("Invalid condition option.");
}
if(assigneeType !== 'Student' && assigneeType !== 'Staff') {
// Should never happen.
console.error("Error: Received incorrect assignee type in adding an assignment.");
@@ -145,7 +193,7 @@ Meteor.methods({
throw new Meteor.Error("Asset is already assigned.", "Cannot assign an asset that has already been assigned.");
}
else {
Assets.update({assetId}, {$set: {assigneeType, assigneeId, assignmentDate: date}});
Assets.update({assetId}, {$set: {assigneeType, assigneeId, assignmentDate: date, condition, conditionDetails}});
}
}
else {
@@ -158,24 +206,38 @@ Meteor.methods({
* Removes an assignment for the asset.
* TODO: Should create a historical record.
* @param assetId The Asset ID (eg: 'Z1Q') of the asset (asset.assetId).
* @param comment A textual comment on the reason for unassigning the asset. Should not contain condition information.
* @param condition One of the condition options: [New, Like New, Good, Okay, Damaged]. 'Like New' is defined as very minor cosmetic damage. 'Good' is defined as some cosmetic damage or very minor screen damage. 'Okay' is defined as significant cosmetic damage, or screen/keyboard/trackpad damage but is still useable. 'Damaged' indicates significant damage and the device should not be reissued until it is repaired.
* @param conditionDetails A text block detailing the current condition (if it is needed).
* @param date The date/time of the action. Will be set to the current date/time if not provided.
*/
'assets.unassign'(assetId, date) {
'assets.unassign'(assetId, comment, condition, conditionDetails, date) {
check(assetId, String);
if(date) check(date, Date);
if(comment) check(comment, String);
check(condition, String);
if(conditionDetails) check(conditionDetails, String);
if(!date) date = new Date();
if(condition !== 'New' && condition !== 'Like New' && condition !== 'Good' && condition !== 'Okay' && condition !== 'Damaged') {
//Should never happen.
console.error("Invalid condition option in assets.unassign(..)");
throw new Meteor.Error("Invalid condition option.");
}
if(Roles.userIsInRole(Meteor.userId(), "laptop-management", {anyScope:true})) {
let asset = Assets.findOne({assetId});
if(asset) {
let assetType = AssetTypes.findOne({_id: asset.assetTypeId});
try {
AssetAssignmentHistory.insert({assetId, assigneeType: asset.assigneeType, assigneeId: asset.assigneeId, startDate: asset.assignmentDate, endDate: date});
AssetAssignmentHistory.insert({assetKey: asset._id, assetId, serial: asset.serial, assetTypeName: (assetType ? assetType.name : "UNK"), assigneeType: asset.assigneeType, assigneeId: asset.assigneeId, startDate: asset.assignmentDate, endDate: date, startCondition: asset.condition, endCondition: condition, startConditionDetails: asset.conditionDetails, endConditionDetails: conditionDetails, comment});
} catch (e) {
console.error(e);
}
Assets.update({assetId}, {$unset: {assigneeType, assigneeId, assignmentDate}});
Assets.update({assetId}, {$unset: {assigneeType: "", assigneeId: "", assignmentDate: ""}, $set: {condition, conditionDetails}});
}
else {
console.error("Could not find the asset: " + assetId);
@@ -213,6 +275,22 @@ Meteor.methods({
// console.log(Assets.findOne({assetId: asset.assetId}));
// }
// }
},
/**
* A fix to remove the AssetAssignment collection and merge it with the Asset collection.
*/
'assets.fixAssetCondition'() {
// Removed this since it should no longer be relevant.
if(Roles.userIsInRole(Meteor.userId(), "admin", {anyScope:true})) {
Assets.update({assetTypeId: 'xPu8YK39pmQW93Fuz'}, {$set: {condition: 'Okay', conditionDetails: 'Automated Condition'}}, {multi: true}); //Lenovo E100 CB
Assets.update({assetTypeId: 'casMp4pJ9t8FtpyuR'}, {$set: {condition: 'Good', conditionDetails: 'Automated Condition'}}, {multi: true}); //Lenovo E100 Charger
Assets.update({assetTypeId: 'ZD9XiHqGr6TcKH9Nv'}, {$set: {condition: 'New'}}, {multi: true}); //Acer CB315 CB
Assets.update({assetTypeId: 'mfE9NtiFBotb8kp4v'}, {$set: {condition: 'New'}}, {multi: true}); //Acer CB315 Charger
Assets.update({assetTypeId: 'btEsKYxW4Sgf7T8nA'}, {$set: {condition: 'Good',conditionDetails: 'Automated Condition'}}, {multi: true}); //Dell 3100 Charger
Assets.update({assetTypeId: '9bszeFJNPteMDbye5'}, {$set: {condition: 'Like New',conditionDetails: 'Automated Condition'}}, {multi: true}); //HP 11A CB
Assets.update({assetTypeId: 'tCj7s5T2YcFXZEaqE'}, {$set: {condition: 'Like New',conditionDetails: 'Automated Condition'}}, {multi: true}); //HP 11A Charger
}
}
});

View File

@@ -6,7 +6,6 @@ import "./staff.js";
import "./sites.js";
import "./asset-types.js";
import "./assets.js";
import "./asset-assignments.js";
import "./asset-assignment-history.js";
// console.log("Finished setting up server side models.");

View File

@@ -4,12 +4,18 @@
const fixAssetAssignments = () => {
Meteor.call('assets.fixAssetAssignments');
}
const fixAssetCondition = () => {
Meteor.call('assets.fixAssetCondition');
}
</script>
<div class="container">
<Button variant="raised" touch on:click={fixAssetAssignments}>
<Label style="color: white">Fix Assignments</Label>
</Button>
<Button variant="raised" touch on:click={fixAssetCondition}>
<Label style="color: white">Fix Missing Asset Condition</Label>
</Button>
</div>
<style>

View File

@@ -63,11 +63,14 @@
}
let assetId = "";
let serial = "";
let conditions = ['New', 'Like New', 'Good', 'Okay', 'Damaged'];
let condition = "New";
let conditionDetails = "";
const addAsset = () => {
if(selectedAssetType && selectedAssetType._id && assetId) {
let result = Meteor.call("assets.add", selectedAssetType._id, assetId, serial, (err, res) => {
let result = Meteor.call("assets.add", selectedAssetType._id, assetId, serial, condition, conditionDetails, (err, res) => {
if (err) {
if (err.error === 'duplicateAssetId')
if (err.error === 'Duplicate Asset Id')
alert("The asset ID `" + assetId + "` has already been used.");
else
alert(err);
@@ -138,6 +141,15 @@
<TextField type="text" style="width: 100%" bind:value={serial} label="Serial">
</TextField>
</div>
<Select bind:value={condition} label="Condition">
{#each conditions as next}
<Option value={next}>{next}</Option>
{/each}
</Select>
<div style="grid-column: 1/span 1">
<TextField type="text" style="width: 100%" bind:value={conditionDetails} label="Condition Details">
</TextField>
</div>
<div style="text-align: right; margin-top: 2rem">
<Button on:click={addAsset} variant="raised">Add</Button>
</div>

View File

@@ -64,11 +64,14 @@
],
};
const deleteAsset = asset => {
if(asset && asset._id) Meteor.call("assets.remove", asset._id);
if(asset && asset._id) {
if(confirm("Delete Asset? This is permanent.")) Meteor.call("assets.remove", asset._id);
}
};
// 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.
let editedAsset = writable(null);
let dirtyAsset = null;
let conditions = ['New', 'Like New', 'Good', 'Okay', 'Damaged'];
// Copy the edited site when ever it changes, set some defaults for a new site object (to make the view happy).
editedAsset.subscribe(site => {
if(site) {
@@ -126,6 +129,15 @@
<TextField type="text" style="width: 100%" bind:value={dirtyAsset.serial} label="Serial">
</TextField>
</div>
<Select bind:value={dirtyAsset.condition} label="Condition">
{#each conditions as next}
<Option value={next}>{next}</Option>
{/each}
</Select>
<div style="grid-column: 1/span 1">
<TextField type="text" style="width: 100%" bind:value={dirtyAsset.conditionDetails} label="Condition Details">
</TextField>
</div>
<div style="grid-column: 1/span 1; white-space: nowrap; text-align: right; margin-top: 0.5rem">
<button type="button" style="grid-column: 2/span 1;" class="button accept-button material-icons material-symbols-outlined" on:click={applyAssetChanges}>

View File

@@ -14,10 +14,12 @@
import List, {Item, Graphic, Meta, Text, PrimaryText, SecondaryText} from '@smui/list';
import Paper from '@smui/paper';
import LayoutGrid, {Cell} from '@smui/layout-grid';
import {Assets} from "/imports/api/assets";
let grades = ['All'];
onMount(async () => {
Meteor.subscribe('sites');
Meteor.subscribe('assets');
Meteor.call('students.getPossibleGrades', (err, result) => {
if(err) console.log(err);
else {
@@ -55,9 +57,32 @@
}
}
let conditions = ['New', 'Like New', 'Good', 'Okay', 'Damaged'];
let condition = "New";
let conditionDetails = "";
const createAssignment = () => {
let asset = Assets.findOne({assetId});
if(asset) {
condition = asset.condition;
conditionDetails = asset.conditionDetails;
}
openCreateDialog();
}
let openDialog = false;
const openCreateDialog = () => {
// assetTypeDialogSelectedIndex = -1;
openDialog = true;
}
const dialogClosed = (e) => {
switch (e.detail.action) {
case 'create':
if(assetId && assetId.length && selectedAssignee) {
Meteor.call("assets.assign", assetId, selectedCategory === 'Student' ? "Student" : "Staff", selectedAssignee._id, (err, result) => {
Meteor.call("assets.assign", assetId, selectedCategory === 'Student' ? "Student" : "Staff", selectedAssignee._id, condition, conditionDetails, (err, result) => {
if(err) {
console.error(err);
//TODO: Display an error!
@@ -68,10 +93,39 @@
}
});
}
break;
default:
case 'cancel':
break;
}
}
</script>
<div class="container">
<Dialog bind:open={openDialog} surface$style="width: 850px; max-width: calc(100vw - 32px);"
on:SMUIDialog:closed={dialogClosed}>
<Title id="large-scroll-title">Report Asset Condition</Title>
<Content id="large-scroll-content">
<Select bind:value={condition} label="Condition">
{#each conditions as next}
<Option value={next}>{next}</Option>
{/each}
</Select>
<div style="grid-column: 1/span 1">
<TextField textarea style="width: 100%; height: 20rem; margin-top: 1rem" helperLine$style="width: 100%" bind:value={conditionDetails} label="Condition Details">
</TextField>
</div>
</Content>
<Actions>
<Button action="create" default>
<Label>Ok</Label>
</Button>
<Button action="cancel">
<Label>Cancel</Label>
</Button>
</Actions>
</Dialog>
<h1 style="display: block">Assign Assets</h1>
<Paper>

View File

@@ -9,6 +9,7 @@
import {Assets} from "/imports/api/assets";
import {Students} from "/imports/api/students";
import {AssetTypes} from "/imports/api/asset-types";
import Select, { Option } from '@smui/select';
import Button, { Label } from '@smui/button';
import Dialog, { Title, Content, Actions } from '@smui/dialog';
@@ -52,18 +53,82 @@
}
}
let conditions = ['New', 'Like New', 'Good', 'Okay', 'Damaged'];
let condition = "New";
let comment = "";
let conditionDetails = "";
const formatDate = (date) => {
return date.toLocaleDateString('en-us', {weekday: 'long', year: 'numeric', month: 'short', day: 'numeric'});
}
const unassign = () => {
if(confirm("Unassign Asset?")) {
Meteor.call("assets.unassign", foundAsset.assetId);
// if(confirm("Unassign Asset?")) {
// Meteor.call("assets.unassign", foundAsset.assetId);
// }
condition = foundAsset.condition;
conditionDetails = foundAsset.conditionDetails;
openDialog();
}
let isDialogOpen = false;
const openDialog = () => {
// assetTypeDialogSelectedIndex = -1;
isDialogOpen = true;
}
const dialogClosed = (e) => {
switch (e.detail.action) {
case 'unassign':
if(foundAsset && foundAsset.assetId) {
Meteor.call("assets.unassign", foundAsset.assetId, comment, condition, conditionDetails, (err, result) => {
if(err) {
console.error(err);
//TODO: Display an error!
}
else {
// TODO: Set focus to the asset ID field.
}
});
}
break;
default:
case 'cancel':
break;
}
}
</script>
<div class="container">
<h1 style="display: block">Asset Assignments</h1>
<Dialog bind:open={isDialogOpen} surface$style="width: 850px; max-width: calc(100vw - 32px);"
on:SMUIDialog:closed={dialogClosed}>
<Title id="large-scroll-title">Report Asset Condition</Title>
<Content id="large-scroll-content">
<Select bind:value={condition} label="Condition">
{#each conditions as next}
<Option value={next}>{next}</Option>
{/each}
</Select>
<div style="grid-column: 1/span 1">
<TextField type="text" style="width: 100%; margin-top: 1rem" bind:value={comment} label="Comment"></TextField>
</div>
<div style="grid-column: 1/span 1">
<TextField textarea style="width: 100%; height: 20rem; margin-top: 1rem" helperLine$style="width: 100%" bind:value={conditionDetails} label="Condition Details">
</TextField>
</div>
</Content>
<Actions>
<Button action="unassign" default>
<Label>Ok</Label>
</Button>
<Button action="cancel">
<Label>Cancel</Label>
</Button>
</Actions>
</Dialog>
<h1 style="display: block">Asset Assignments By Asset</h1>
<Paper>
<LayoutGrid>
@@ -75,6 +140,10 @@
{#if foundAsset}
<div>Asset ID: {foundAsset.assetId}</div>
<div>Condition: {foundAsset.condition}</div>
{#if foundAsset.conditionDetails}
<div>Condition Details: {foundAsset.conditionDetails}</div>
{/if}
{#if foundAssetType}
<div>{foundAssetType.name}</div>
{/if}

View File

@@ -11,6 +11,8 @@
import LayoutGrid, {Cell} from '@smui/layout-grid';
import {Assets} from "/imports/api/assets";
import {AssetTypes} from "/imports/api/asset-types";
import Button, { Label } from '@smui/button';
import Dialog, { Title, Content, Actions } from '@smui/dialog';
onMount(async () => {
Meteor.subscribe('students');
@@ -53,10 +55,82 @@
return result;
}
let conditions = ['New', 'Like New', 'Good', 'Okay', 'Damaged'];
let condition = "New";
let conditionDetails = "";
let comment = "";
let unassignAsset;
const unassign = (asset) => {
unassignAsset = asset;
condition = asset.condition;
conditionDetails = asset.conditionDetails;
// if(confirm("Unassign Asset?")) {
// Meteor.call("assets.unassign", asset.assetId);
// }
openDialog();
}
let isDialogOpen = false;
let dialogAsset;
const openDialog = () => {
// assetTypeDialogSelectedIndex = -1;
isDialogOpen = true;
}
const dialogClosed = (e) => {
switch (e.detail.action) {
case 'unassign':
if(unassignAsset && unassignAsset.assetId) {
Meteor.call("assets.unassign", unassignAsset.assetId, comment, condition, conditionDetails, (err, result) => {
if(err) {
console.error(err);
//TODO: Display an error!
}
else {
// TODO: Set focus to the asset ID field.
unassignAsset = undefined;
}
});
}
break;
default:
case 'cancel':
break;
}
}
</script>
<div class="container">
<h1 style="display: block">Asset Assignments</h1>
<Dialog bind:open={isDialogOpen} surface$style="width: 850px; max-width: calc(100vw - 32px);"
on:SMUIDialog:closed={dialogClosed}>
<Title id="large-scroll-title">Report Asset Condition</Title>
<Content id="large-scroll-content">
<Select bind:value={condition} label="Condition">
{#each conditions as next}
<Option value={next}>{next}</Option>
{/each}
</Select>
<div style="grid-column: 1/span 1">
<TextField type="text" style="width: 100%; margin-top: 1rem" bind:value={comment} label="Comment"></TextField>
</div>
<div style="grid-column: 1/span 1">
<TextField textarea style="width: 100%; height: 20rem; margin-top: 1rem" helperLine$style="width: 100%" bind:value={conditionDetails} label="Condition Details">
</TextField>
</div>
</Content>
<Actions>
<Button action="unassign" default>
<Label>Ok</Label>
</Button>
<Button action="cancel">
<Label>Cancel</Label>
</Button>
</Actions>
</Dialog>
<h1 style="display: block">Asset Assignments By Student/Staff</h1>
<Paper>
<LayoutGrid>
@@ -91,6 +165,9 @@
Type: {asset.type.name}<br/>
AssetId: {asset.assetId}<br/>
Serial: {asset.serial}<br/>
<Button variant="raised" touch on:click={() => {unassign(asset)}}>
<Label style="color: white">Unassign</Label>
</Button>
{/each}
</div>
</li>
@@ -107,6 +184,9 @@
Type: {asset.type.name}<br/>
AssetId: {asset.assetId}<br/>
Serial: {asset.serial}<br/>
<Button variant="raised" touch on:click={() => {unassign(asset)}}>
<Label style="color: white">Unassign</Label>
</Button>
{/each}
</div>
</li>