2022-07-12 11:26:36 -07:00
< script >
import { Meteor } from "meteor/meteor";
import { onMount } from "svelte";
2022-08-08 22:15:55 -07:00
import { writable , derived } from "svelte/store";
2022-07-12 11:26:36 -07:00
import TextField from '@smui/textfield';
import HelperText from '@smui/textfield/helper-text';
import Select, { Option } from '@smui/select';
import { AssetTypes } from "../../api/asset-types";
import { useTracker } from 'meteor/rdb:svelte-meteor-data';
import GridTable from "./../GridTable.svelte";
import { Assets } from "../../api/assets";
import u from 'umbrellajs';
onMount(async () => {
Meteor.subscribe('assetTypes');
Meteor.subscribe('assets');
});
let assetTypes;
2022-08-08 22:15:55 -07:00
$: assetTypes = AssetTypes.find({} , { sort : { year : - 1 }} );
$: assetTypeNameMap = derived(assetTypes, $assetTypes => $assetTypes.reduce((map, obj) => {
map[obj._id] = obj.name;
return map;
}, {} ));
2022-07-12 11:26:36 -07:00
// Asset Table //
const assetColumns = [
{
key: "assetId",
title: "Asset ID",
value: v => v.assetId,
minWidth: 100,
weight: 1,
cls: "assetId",
}, {
key: "serial",
title: "Serial",
value: v => v.serial ? v.serial : "-",
minWidth: 100,
weight: 1,
cls: "serial",
2022-08-08 22:15:55 -07:00
}, {
key: "asset",
title: "Asset Type",
value: v => {
$: {
return v.assetTypeId ? $assetTypeNameMap[v.assetTypeId] : "-"
}
},
minWidth: 100,
weight: 1,
cls: "serial",
2022-07-12 11:26:36 -07:00
},
];
const assetActions = {
title: "",
headerWidgets: [
{ icon : "add_box" , action : () => { editedAsset . update (( v ) => { return v ? null : {}})}, tooltip : "Add a new asset." }
],
rowWidgets: [
{ icon : "add_circle" , action : ( v ) => { editedAsset . set ( v )}} ,
{ icon : "delete" , action : ( v ) => { deleteAsset ( v )}}
],
};
const deleteAsset = asset => {
2022-08-16 16:08:12 -07:00
if(asset && asset._id) {
if(confirm("Delete Asset? This is permanent.")) Meteor.call("assets.remove", asset._id);
}
2022-07-12 11:26:36 -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.
let editedAsset = writable(null);
let dirtyAsset = null;
2022-08-16 16:08:12 -07:00
let conditions = ['New', 'Like New', 'Good', 'Okay', 'Damaged'];
2022-07-12 11:26:36 -07:00
// 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) {
dirtyAsset = Object.assign({ serial : "" , assetId : "" , assetTypeId : "" } , site);
//document.getElementsByClassName('select').focus();
}
else dirtyAsset = null;
});
// Load the sites (reactive).
let assets = Assets.find({} );
const applyAssetChanges = () => {
if(dirtyAsset._id)
Meteor.call("assets.update", dirtyAsset._id, dirtyAsset.assetId, dirtyAsset.serial);
else
Meteor.call("assets.add", dirtyAsset.assetTypeId, dirtyAsset.assetId, dirtyAsset.serial);
editedAsset.set(null);
}
const rejectAssetChanges = () => {
editedAsset.set(null);
}
let selectedAsset = null;
const onAssetSelection = (e) => {
selectedAsset = Assets.findOne({ _id : e.detail } );
}
let editorFirstComponent = null;
$: if(editorFirstComponent) editorFirstComponent.focus();
const initEditor = (e) => {
//editorFirstComponent.focus();
//document.getElementsByClassName("focusMe")[0].children[0].children[2].focus();
// u('.focusMe .mdc-select__selected-text').first().focus();
//$('.select').focus();
}
// End Asset Table //
< / script >
< div class = "container" >
< div class = "assetsContainer" >
< h2 > Assets< / h2 >
< GridTable bind:rows = { assets } columns=" { assetColumns } " actions = " { assetActions } " rowKey = " {( v ) => { return v . _id }} " bind:edited = " { editedAsset } " on:selection = { onAssetSelection } >
{ #if dirtyAsset }
< div class = "editorContainer" use:initEditor >
< div style = "grid-column: 1/span 1" >
< Select class = "focusMe select" bind:value = { dirtyAsset . assetTypeId } label="Asset Type " bind:this = { editorFirstComponent } >
{ #each $assetTypes as assetType }
< Option value = { assetType . _id } > { assetType . name } </Option >
{ /each }
< / Select >
< / div >
< div style = "grid-column: 1/span 1" >
< TextField type = "text" style = "width: 100%" bind:value = { dirtyAsset . assetId } label="AssetId" >
< / TextField >
< / div >
< div style = "grid-column: 1/span 1" >
< TextField type = "text" style = "width: 100%" bind:value = { dirtyAsset . serial } label="Serial" >
< / TextField >
< / div >
2022-08-16 16:08:12 -07:00
< 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 >
2022-07-12 11:26:36 -07:00
< 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 } >
check
< / button >
< button type = "button" style = "grid-column: 3/span 1;" class = "button reject-button material-icons material-symbols-outlined" on:click = { rejectAssetChanges } >
close
< / button >
< / div >
< / div >
{ /if }
< / GridTable >
< / div >
< / div >
< style >
.assetsContainer {
display: block;
}
.editorContainer {
display: grid;
grid-template-columns: minmax(10px, 1fr);
column-gap: 2rem;
background-color: #e0e3e7;
padding: 1rem;
}
:global(.select) {
width: 100%;
}
.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 >