Fixes and updates.

This commit is contained in:
Wynne Crisman
2020-01-16 09:31:12 -08:00
parent 2e57558ef4
commit a20e42e360
25 changed files with 346 additions and 820 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
node_modules
.idea
private
.meteor/local

View File

@@ -66,4 +66,4 @@ markdown@1.0.12
wcrisman:jquery-custom-scrollbar
underscore@1.0.10
meteorhacks:aggregate # Allows databaseName.aggragate(pipeline) calls the exact same way you would on the command line in the mongo tool.
babrahams:constellation
#babrahams:constellation # Provides client side debugging when the server is not run in production mode.

View File

@@ -12,9 +12,6 @@ arillo:flow-router-helpers@0.5.2
autoupdate@1.6.0
babel-compiler@7.3.4
babel-runtime@1.3.0
babrahams:constellation@0.4.10
babrahams:editable-json@0.6.5
babrahams:temple@0.4.7
base64@1.0.12
binary-heap@1.0.11
blaze@2.3.3
@@ -26,14 +23,6 @@ caching-html-compiler@1.1.3
callback-hook@1.1.0
check@1.3.1
coffeescript@1.0.17
constellation:autopublish@0.4.7
constellation:console@1.4.7
constellation:plugins@0.4.9
constellation:position@0.4.7
constellation:session@0.4.7
constellation:subscriptions@0.4.7
constellation:tiny@0.4.7
dburles:mongo-collection-instances@0.3.5
ddp@1.4.0
ddp-client@2.3.3
ddp-common@1.4.0
@@ -52,8 +41,6 @@ es5-shim@4.8.0
fetch@0.1.1
fortawesome:fontawesome@4.7.0
geojson-utils@1.0.10
gwendall:body-events@0.1.6
gwendall:session-json@0.1.7
hot-code-push@1.0.4
html-tools@1.0.11
htmljs@1.0.11
@@ -65,7 +52,6 @@ jquery@1.11.11
juliancwirko:s-alert@3.2.0
kadira:blaze-layout@2.3.0
kadira:flow-router@2.12.1
lai:collection-extensions@0.2.1_1
launch-screen@1.1.1
livedata@1.0.18
localstorage@1.2.0

View File

@@ -139,6 +139,7 @@ Check which version of meteor you have on the development machine (meteor is not
1. Update the meteor app as normal (copy it to the /var/www/xxx directory as a build bundle, then run the script to unpack it).
2. Run `sudo n` to get the current version of NodeJS being used. Use `sudo n x.x.x` to download and change to the new version of NodeJS.
3. Edit the app's nginx file in /etc/nginx/sites-available/ to reference the new NodeJS install location. For example my current install location is specified as `server {... passenger_nodejs /usr/local/n/versions/node/8.9.3/bin/node ...}`}
4. Validate things are running fine by opening the webapp in a browser (**currently** `app.petitteton.com`)
## Running Server Side Code

View File

@@ -3507,22 +3507,26 @@ input[type="button"].btn-block {
}
#production .table thead > tr > .date,
#production .table tbody > tr > .date {
min-width: 150px;
width: 180px;
min-width: 180px;
max-width: 180px;
}
#production .table thead > tr > .amount,
#production .table tbody > tr > .amount {
width: 100px;
min-width: 100px;
max-width: 100px;
}
#production .table thead > tr > .cook,
#production .table tbody > tr > .cook {
min-width: 150px;
width: 180px;
min-width: 180px;
max-width: 180px;
}
#production .table thead > tr > .canner,
#production .table tbody > tr > .canner {
min-width: 150px;
width: 180px;
min-width: 180px;
max-width: 180px;
}
#production .table thead > tr > .comment,
@@ -3917,6 +3921,40 @@ input[type="button"].btn-block {
overflow-y: auto;
}
@media not print {
#labelMaker .labelOptions .radioGroup input[type='radio'] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
display: inline-block;
position: relative;
background-color: #f1f1f1;
color: #666;
height: 30px;
width: 30px;
border: 0;
border-radius: 50px;
cursor: pointer;
margin-right: 7px;
outline: none;
}
#labelMaker .labelOptions .radioGroup input[type='radio']:hover {
background-color: #f7f7f7;
}
#labelMaker .labelOptions .radioGroup input[type='radio']:checked::before {
position: absolute;
font: 13px/1 'Open Sans', sans-serif;
left: 11px;
top: 7px;
content: '\02143';
transform: rotate(40deg);
}
#labelMaker .labelOptions .radioGroup input[type='radio']:checked {
background-color: #f1f1f1;
}
#labelMaker .labelOptions .radioGroup label {
position: relative;
top: -10px;
}
#labelMaker .labelOptions label {
font-family: TimesNewRoman, Times New Roman, Times;
font-weight: 200;
@@ -3951,140 +3989,14 @@ input[type="button"].btn-block {
font-weight: 100;
line-height: 14px;
}
#labelMaker .labelContainer {
#labelMaker .labelBackground {
text-align: center;
width: 100%;
width-min: 3in;
height-min: 2in;
width-min: 5in;
height-min: 5in;
background-color: #808080;
padding: 20px;
}
#labelMaker .labels {
display: none;
}
#labelMaker .printableLabel {
display: none;
}
#labelMaker .label {
display: inline-block;
width: 3in;
height: 2in;
}
#labelMaker .canvasContainer {
padding: 10px;
background-color: #808080;
}
}
@media all {
#labelMaker .label {
position: relative;
background-color: #fff;
color: #000;
text-align: center;
font-family: TimesNewRoman, Times New Roman, Times;
font-size: 0.1in;
width: 3in;
height: 2in;
}
#labelMaker .label .barcodeContainer {
position: absolute;
transform: rotate(270deg) scale(0.7);
right: -10em;
top: 7em;
}
#labelMaker .label .qrcode {
position: absolute;
left: 3px;
top: 3px;
}
#labelMaker .label .labelLogo {
width: 8em;
padding: 0;
margin: 0;
padding-top: 0.15em;
margin-bottom: 0.2em;
}
#labelMaker .label .labelLogo3 {
width: 14em;
padding: 0;
margin: 0;
padding-top: 0.15em;
margin-bottom: 0.8em;
}
#labelMaker .label .labelTagline {
font-size: 1em;
font-weight: 100;
line-height: 1em;
}
#labelMaker .label .title1 {
width: 100%;
font-size: 2.5em;
line-height: 0.9em;
font-weight: 800;
text-transform: uppercase;
}
#labelMaker .label .title2 {
width: 100%;
font-size: 1.5em;
line-height: 0.9em;
font-weight: 800;
padding-bottom: 0.2em;
}
#labelMaker .label .ingredients {
width: 100%;
font-size: 1.2em;
font-weight: 100;
line-height: 1em;
min-height: 2em;
}
#labelMaker .label .ingredientsEnding {
width: 100%;
font-size: 1.2em;
font-weight: 100;
}
#labelMaker .label .instructions {
width: 100%;
font-size: 1.2em;
font-weight: 800;
}
#labelMaker .label .address {
width: 100%;
font-size: 1.2em;
font-weight: 100;
}
#labelMaker .label .website {
width: 100%;
font-size: 1.2em;
font-weight: 100;
}
}
@media print {
@page {
size: 3in 2in;
margin: 0;
padding: 0;
}
#labelMaker .labelOptions,
#labelMaker .labelContainer,
#labelMaker .canvasContainer,
#labelMaker .labelCanvas {
display: none;
}
#labelMaker .printableLabel {
display: block;
margin: 0;
padding: 0;
}
#labelMaker .canvasContainer {
display: none;
}
}
@media print {
.labelMaker {
margin: 0;
padding: 0;
overflow: visible;
}
}
#testList {
margin: 10px 20px;
@@ -4092,25 +4004,6 @@ input[type="button"].btn-block {
}
#PrintLabel .labelContainer {
text-align: center;
width-min: 3in;
width: 3in;
height-min: 2in;
height: 2in;
}
#PrintLabel .labels {
display: none;
}
#PrintLabel .printableLabel {
display: none;
}
#PrintLabel .label {
display: inline-block;
width: 3in;
height: 2in;
}
#PrintLabel .canvasContainer {
padding: 10px;
background-color: #808080;
}
#PrintLabel .label {
position: relative;
@@ -4119,19 +4012,13 @@ input[type="button"].btn-block {
text-align: center;
font-family: TimesNewRoman, Times New Roman, Times;
font-size: 0.1in;
width: 3in;
height: 2in;
}
#PrintLabel .label .barcodeContainer {
position: absolute;
transform: rotate(270deg);
right: -4.5em;
top: 5em;
}
#PrintLabel .label .qrcode {
position: absolute;
left: 10px;
top: 10px;
width: 60px;
height: 60px;
}
#PrintLabel .label .labelLogo {
width: 8em;
@@ -4193,3 +4080,22 @@ input[type="button"].btn-block {
font-size: 1.2em;
font-weight: 100;
}
#PrintLabel .label.oz8 {
width: 76.2mm;
height: 50.8mm;
}
#PrintLabel .label.barcode {
width: 30.5mm;
height: 30.5mm;
}
#PrintLabel .label.barcode .qrcode {
position: absolute;
top: 50%;
left: 50%;
margin-top: -30px;
margin-left: -30px;
}
#PrintLabel .label.barcode .labelText,
#PrintLabel .label.barcode .labelLogo {
display: none;
}

6
imports/LabelFormats.js Normal file
View File

@@ -0,0 +1,6 @@
let formats = {
"oz8": {width: "76.2mm", height: "50.8mmm"},
"barcode": {width: "30.5mm", height: "30.5mm"}
};
export default formats;

View File

@@ -128,13 +128,15 @@ if(Meteor.isServer) {
if(!_.isNumber(skipCount) || skipCount < 0) skipCount = 0;
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
return Meteor.collections.Batches.find(dbQuery, {limit: limit, sort, skip: skipCount});
//console.log("dbQuery=" + JSON.stringify(dbQuery));
//console.log("Result Count: " + Batches.find(query).count());
return Batches.find(dbQuery, {limit: limit, sort, skip: skipCount});
});
Meteor.methods({
getBatchCount: function(query) {
//TODO: Validate the query?
return Sales.find(query).count();
return Batches.find(query).count();
},
insertBatches: function(batches) { //Insert one or more batches (if one, you can pass just the batch).
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
@@ -198,40 +200,44 @@ if(Meteor.isServer) {
}
else throw new Meteor.Error(403, "Not authorized.");
},
editBatchComment: function(id, comment) {
//editBatchComment: function(id, comment) {
// check(id, String);
// check(comment, String);
// //Trim and convert empty comment to undefined.
// comment = comment ? comment.trim() : undefined;
// comment = comment && comment.length > 0 ? comment : undefined;
//
// if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
// console.log("Changed comment of " + id + " to: " + comment);
//
// if(comment) {
// Batches.update(id, {$set: {comment}}, function(error, count) {
// if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
// });
// }
// else {
// Batches.update(id, {$unset: {comment: ""}}, function(error, count) {
// if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
// });
// }
// }
// else throw new Meteor.Error(403, "Not authorized.");
//},
updateBatch: function(id, amount, comment) {
check(id, String);
check(comment, String);
check(amount, Number);
check(comment, Match.OneOf(String, undefined));
//Trim and convert empty comment to undefined.
comment = comment ? comment.trim() : undefined;
comment = comment && comment.length > 0 ? comment : undefined;
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
console.log("Changed comment of " + id + " to: " + comment);
if(comment) {
Batches.update(id, {$set: {comment}}, function(error, count) {
if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
});
}
else {
Batches.update(id, {$unset: {comment: ""}}, function(error, count) {
if(error) throw new Meteor.Error(400, "Unexpected database error: " + error);
});
}
}
else throw new Meteor.Error(403, "Not authorized.");
},
updateBatch: function(id, date, amount) {
check(id, String);
check(date, Number); // TODO: Check that the format is YYYYMMDD
check(amount, Number);
let dateString = date.toString();
let timestamp = new Date(dateString.substring(0, 4) + "-" + dateString.substring(4, 6) + "-" + dateString.substring(6, 8) + "T00:00:00Z");
let weekOfYear = timestamp.getWeek().toString();
//let dateString = date.toString();
//let timestamp = new Date(dateString.substring(0, 4) + "-" + dateString.substring(4, 6) + "-" + dateString.substring(6, 8) + "T00:00:00Z");
//let weekOfYear = timestamp.getWeek().toString();
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
Batches.update(id, {$set: {date, amount, timestamp, weekOfYear}}, function(err, id) {
Batches.update(id, {$set: {comment, amount}}, function(err, id) {
if(err) console.log(err);
}, {bypassCollection2: true});
}

View File

@@ -2,54 +2,15 @@ import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { check } from 'meteor/check';
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
import LabelFormats from '/imports/LabelFormats.js';
if(Meteor.isServer) {
const puppeteer = require('puppeteer');
//let Future = Npm.require('fibers/future');
//
//async function printLabels(data, callback) {
// let params = "";
// let url = Meteor.absoluteUrl("/LabelPrint");
//
// params = Object.keys(data).map(function(k) {
// return encodeURIComponent(k) + "=" + encodeURIComponent(data[k]);
// }).join('&');
//
// url += "?" + params;
//
// const browser = await puppeteer.launch();
// const page = await browser.newPage();
// console.log("Going to: " + url);
// await page.goto(url, {waitUntil: 'networkidle0'});
// // By removing the `path` option, we will receive a `Buffer` from `page.pdf`.
// const pdf = await page.pdf({ width: "6in", height: "4in"}); // format: "A4" //path: 'C:\\Users\\Grumpy\\label.pdf'
//
// await browser.close();
// callback(null, pdf);
//}
Meteor.methods({
//printLabels: function(width, height, layout, title1, title2, ingredients, date) {
// console.log("Loaded Label");
// let future = new Future();
//
// let boundCallback = Meteor.bindEnvironment(function(err, res) {
// if(err) {
// future.throw(err);
// }
// else {
// future.return(res);
// }
// });
//
// printLabels({width, height, layout, title1, title2, ingredients, date}, boundCallback);
//
// return future.wait();
//}
async printLabels(width, height, layout, title1, title2, ingredients, date) {
let data = {width, height, layout, title1, title2, ingredients, date};
async printLabels(format, title1, title2, ingredients, date) {
let data = {format, title1, title2, ingredients, date};
let params = "";
let url = Meteor.absoluteUrl("/PrintLabel");
@@ -64,11 +25,8 @@ if(Meteor.isServer) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
//url = Meteor.absoluteUrl("/StaticTest.html");
//url = Meteor.absoluteUrl("/StaticTest.html");
console.log("Going to: " + url);
await page.goto(url, {waitUntil: 'networkidle0'}); //, {waitUntil: 'networkidle0'}
const pdf = await page.pdf({width: '3in', height: '2in'}); //path: 'C:\\Users\\Grumpy\\label.pdf',
const pdf = await page.pdf({width: LabelFormats[format].width, height: LabelFormats[format].height}); //path: 'C:\\Users\\Grumpy\\label.pdf',
//const pdf = await page.pdf({format: 'A4'});
//await page.pdf({path: 'C:\\Users\\Grumpy\\label.pdf', width: '6in', height: '4in'});
await browser.close();
@@ -85,7 +43,6 @@ if(Meteor.isServer) {
//Note: Price data looks like this: {XZ5Z3CM49NDrJNADA /* MeasureID */: {price: 10.5, effectiveDate: ISODate("2017-01-12T13:14:18.876-08:00"), previousPrice: 9}, ...}
//Measures is an array of MeasureIDs valid for this product.
let products = Meteor.collections.Products.find({}, {fields: {_id: 1, name: 1, measures: 1, prices: 1}, sort: {order: 1}}).fetch();
//let measuresById = measures.reduce((map, measure) => (map[measure._id] = measure), {});
let measuresById = {};
let barcodesByProductAndMeasureIds = {};
let result = {};
@@ -93,11 +50,6 @@ if(Meteor.isServer) {
for(measure of measures) measuresById[measure._id] = measure;
for(barcode of barcodes) barcodesByProductAndMeasureIds[barcode.productAndMeasureId] = barcode.barcodeId;
//console.log(measuresById);
//for(let measureId of Object.keys(measuresById)) {
// console.log(measureId + ":" + measuresById[measureId].name);
//}
for(let product of products) {
for(let measureId of product.measures) {

View File

@@ -14,7 +14,7 @@ import {SimpleSchema} from 'meteor/aldeed:simple-schema';
* A product that is hidden is one that exists in the system as a historical artifact due to there still being data attached to it (sales for example). It should not normally show in lists, and should show up with a red indicator if it is displayed.
*/
Products = new Mongo.Collection('Products');
let Products = new Mongo.Collection('Products');
const ProductsSchema = new SimpleSchema({
name: {

View File

@@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { check } from 'meteor/check';
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
import Batches from "./Batch";
/**
* Notes:
@@ -131,6 +132,10 @@ if(Meteor.isServer) {
if(!_.isNumber(skipCount) || skipCount < 0) skipCount = 0;
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
//console.log("dbQuery=" + JSON.stringify(dbQuery));
//console.log("Result Count: " + Batches.find(query).count());
return Meteor.collections.Sales.find(dbQuery, {limit: limit, sort, skip: skipCount});
});
Meteor.publish('duplicateSales', function(query, includeIgnoredDuplicates) {

View File

@@ -12,7 +12,7 @@ if(Meteor.isServer) {
"insertUser": function(user) {
check(user, {
username: String,
email: String,
emails: [{address: String, verified: Match.Maybe(Boolean)}],
roles: [String]
});
@@ -21,7 +21,8 @@ if(Meteor.isServer) {
//Verify the user name isn't already used.
if(Meteor.collections.Users.findOne({username: user.username}) === undefined) {
let pwd = Random.secret(20);
let id = Accounts.createUser({password: pwd, username: user.username, email: user.email});
console.log("Email: " + user.emails[0]);
let id = Accounts.createUser({password: pwd, username: user.username, email: user.emails[0].address});
//Requires the alanning:roles package.
Roles.addUsersToRoles(id, user.roles);

View File

@@ -2,45 +2,33 @@
<div id="labelMaker">
<div class="labelOptions">
<div>Label Size</div>
<div><label for="labelWidth">Width (mm):</label> <input type="number" name="labelWidth" class="labelWidth input" step="0.25" value="{{labelWidth}}"/></div>
<div><label for="labelHeight">Height (mm):</label> <input type="number" name="labelHeight" class="labelHeight input" step="0.25" value="{{labelHeight}}"/></div>
<div><label for="labelSpacing">Spacing (in):</label> <input type="number" name="labelSpacing" class="labelSpacing input" step="0.05" value="{{labelSpacing}}"/></div>
<div><label for="labelWidth">Width (mm):</label> <input disabled type="number" name="labelWidth" class="labelWidth input" step="0.25" value="{{labelWidth}}"/></div>
<div><label for="labelHeight">Height (mm):</label> <input disabled type="number" name="labelHeight" class="labelHeight input" step="0.25" value="{{labelHeight}}"/></div>
<div class="radioGroup"><input type="radio" name="labelType" value="oz8" checked><label for="labelType">8oz Label</label> <input type="radio" name="labelType" value="barcode"><label for="labelType">Barcode Only</label></div>
<div>Label Contents</div>
<!-- <label for="title1YOffset">Vertical Offset:</label> <input type="number" name="title1YOffset" class="title1YOffset input" value="{{title1YOffset}}"/>-->
<div><label for="title1">Title:</label> <input type="text" name="title1" class="title1 input" value="{{title1}}"/></div>
<div><label for="title2">Title:</label> <input type="text" name="title2" class="title2 input" value="{{title2}}"/></div>
<div><label for="ingredients" style="vertical-align: top">Ingredients:</label> <textarea name="ingredients" class="ingredients">{{ingredients}}</textarea></div>
<div><label for="date">Date:</label> <input type="number" name="date" class="date input" value="{{date}}"/></div>
<div class="labelTextControls"><label for="title1">Title:</label> <input type="text" name="title1" class="title1 input" value="{{title1}}"/></div>
<div class="labelTextControls"><label for="title2">Title:</label> <input type="text" name="title2" class="title2 input" value="{{title2}}"/></div>
<div class="labelTextControls"><label for="ingredients" style="vertical-align: top">Ingredients:</label> <textarea name="ingredients" class="ingredients">{{ingredients}}</textarea></div>
<div class="labelTextControls"><label for="date">Date:</label> <input type="number" name="date" class="date input" value="{{date}}"/></div>
<div><button name="print" class="print">Print</button></div>
<div><button name="preview" class="preview">Preview</button></div>
</div>
<div class="labelContainer">
<div class='label'>
<!-- /images/Logo_0.8x0.73_300ppi.png-->
<!-- <div class='barcodeContainer'><svg class='barcode' jsbarcode-format='upc' jsbarcode-value='123456789012' jsbarcode-textmargin='0' jsbarcode-fontoptions='bold' jsbarcode-margin='0' jsbarcode-width='1.5em' jsbarcode-height='10em'></svg></div>-->
<!-- <img class="qrcode" src="">-->
<div id="qrcode" class="qrcode"></div>
<img class='labelLogo' alt='logo' src='/images/3x2 Label Logo BW.svg'/>
<div class='title1'>{{title1}}</div>
<div class='title2'>{{title2}}</div>
<div class='ingredients'><span class='ingredientsPrefix'>Ingredients</span>: {{ingredients}}</div>
<div class='ingredientsEnding'>*<span style='font-style: oblique'>grown by us</span> <span class='size'></span> FD1951 (<span class="date">{{date}}</span>)</div>
<div class='instructions'>Refrigerate after opening; return jar when done</div>
<div class='address'>18601 Hwy 128, Yorkville, CA 95494</div>
<div class='website'>www.PetitTeton.com</div>
</div>
<div class="labelBackground">
{{>PrintLabel vars=printLabelVars}}
</div>
<!-- <div class="canvasContainer">-->
<!-- &lt;!&ndash; 3x2" == 76x50mm; 300ppi == 11.81ppmm; So 3x2" == 897 x 590x. &ndash;&gt;-->
<!--&lt;!&ndash; <canvas class="labelCanvas" width="{{labelPxWidthActual}}" height="{{labelPxHeightActual}}">&ndash;&gt;-->
<!--&lt;!&ndash; </canvas>&ndash;&gt;-->
<!-- <canvas class="labelCanvas" width="{{labelPxWidth}}" height="{{labelPxHeight}}">-->
<!-- </canvas>-->
<!-- <div class="labelContainer">-->
<!-- <div class='label'>-->
<!-- <div id="qrcode" class="qrcode"></div>-->
<!-- <img class='labelLogo' alt='logo' src='/images/3x2 Label Logo BW.svg'/>-->
<!-- <div class='title1 labelText'>{{title1}}</div>-->
<!-- <div class='title2 labelText'>{{title2}}</div>-->
<!-- <div class='ingredients labelText'><span class='ingredientsPrefix'>Ingredients</span>: {{ingredients}}</div>-->
<!-- <div class='ingredientsEnding labelText'>*<span style='font-style: oblique'>grown by us</span> <span class='size'></span> FD1951 (<span class="date">{{date}}</span>)</div>-->
<!-- <div class='instructions labelText'>Refrigerate after opening; return jar when done</div>-->
<!-- <div class='address labelText'>18601 Hwy 128, Yorkville, CA 95494</div>-->
<!-- <div class='website labelText'>www.PetitTeton.com</div>-->
<!-- </div>-->
<!-- </div>-->
<div class="testImage">
</div>
<div class="printableLabel"></div>
</div>
</template>

View File

@@ -7,6 +7,36 @@
@media not print
.labelOptions
.radioGroup
input[type='radio']
-webkit-appearance none
-moz-appearance none
appearance none
display inline-block
position relative
background-color #f1f1f1
color #666
height 30px
width 30px
border 0
border-radius 50px
cursor pointer
margin-right 7px
outline none
input[type='radio']:hover
background-color #f7f7f7
input[type='radio']:checked::before
position absolute
font 13px/1 'Open Sans', sans-serif
left 11px
top 7px
content '\02143'
transform rotate(40deg)
input[type='radio']:checked
background-color #f1f1f1
label
position relative
top -10px
label
font-family TimesNewRoman, Times New Roman, Times
font-weight 200
@@ -36,128 +66,10 @@
font-size 12px
font-weight 100
line-height 14px
.labelContainer
.labelBackground
text-align center
width 100%
width-min 3in
height-min 2in
width-min 5in
height-min 5in
background-color grey
padding 20px
.labels
display none
.printableLabel
display none
.label
display inline-block
width 3in
height 2in
.canvasContainer
padding 10px
background-color gray
@media all
.label
position relative
background-color white
color black
text-align center
font-family TimesNewRoman, Times New Roman, Times
//font-family Arial, Helvetica, sans-serif
font-size .1in
width 3in
height 2in
.barcodeContainer
position absolute
transform rotate(270deg) scale(0.7)
right -10em
top 7em
.qrcode
position absolute
left 3px
top 3px
//padding: 2px
//border: 2px solid black
.labelLogo
width 8em
padding 0
margin 0
padding-top .15em
margin-bottom .2em
.labelLogo3
width 14em
padding 0
margin 0
padding-top .15em
margin-bottom .8em
.labelTagline
font-size 1em
font-weight 100
line-height 1em
.title1
width 100%
font-size 2.5em
line-height .9em
font-weight 800
text-transform uppercase
.title2
width 100%
font-size 1.5em
line-height .9em
font-weight 800
padding-bottom .2em
.ingredients
width 100%
font-size 1.2em
font-weight 100
line-height 1em
min-height 2em
.ingredientsEnding
width 100%
font-size 1.2em
font-weight 100
.instructions
width 100%
font-size 1.2em
font-weight 800
.address
width 100%
font-size 1.2em
font-weight 100
.website
width 100%
font-size 1.2em
font-weight 100
@media print
@page
size 3in 2in
margin 0
padding 0
.labelOptions, .labelContainer, .canvasContainer, .labelCanvas
display none
.printableLabel
display block
margin 0
padding 0
//.printableLabels
// display inline-block
// margin 0
// padding 0
//#labelMaker
// display none
//.labels
// display block
//.label
// display block
// width 3in
// height 2in
// //width 100%
// //height 100%
// page-break-after always
// page-break-inside avoid
.canvasContainer
display none
@media print
.labelMaker
margin 0
padding 0
overflow visible

View File

@@ -8,6 +8,8 @@ import dragula from 'dragula';
import QRCode from '/imports/util/qrcode/qrcode';
//let QRCode = require('/imports/util/qrcode/qrcode.js');
import './PrintLabel.js';
console.log(QRCode);
//let {qrcode, svg2url} = require('pure-svg-code');
@@ -20,216 +22,11 @@ console.log(QRCode);
let PREFIX = "LabelMaker_";
let PX_PER_MM = 300 / 25.4;
let SCREEN_PX_PER_MM = 96 / 25.4;
let imagePath = "/images/3x2 Label Logo BW.svg";//"/images/Logo_0.8x0.73_300ppi.png";
function generateLabels(title1, title2, ingredients, date, count, topSpacing, bottomSpacing) {
//TODO: Allow logo to be removed or altered with an alternative logo for sizing fixes
let label = "<div class='label'>" +
"<div class='barcodeContainer'><svg class='barcode' jsbarcode-format='UPC' jsbarcode-value='123456789012' jsbarcode-textmargin='0' jsbarcode-fontoptions='bold' jsbarcode-margin='0' jsbarcode-width='2in' jsbarcode-height='10em'></svg></div>" +
//"<div style='height: " + (topSpacing) + "in'></div>" +
//"<img class='labelLogo' alt='logo' src='/images/PetitTetonLabelLogo_2in Width_v1.png'/>" +
"<img class='labelLogo' alt='logo' src='" + imagePath + "'/>" +
//"<div class='labelTagline'>We grow it. We can it.</div>" +
"<div class='title1'>" + title1 + "</div>" +
"<div class='title2'>" + (title2 === undefined ? "" : title2) + "</div>" +
"<div class='ingredients'><span class='ingredientsPrefix'>Ingredients</span>:" + ingredients + "</div>" +
"<div class='ingredientsEnding'>*<span style='font-style: oblique'>grown by us</span> <span class='size'>8oz</span> FD1951 (" + date + ")</div>" +
"<div class='instructions'>Refrigerate after opening; return jar when done</div>" +
"<div class='address'>18601 Hwy 128, Yorkville, CA 95494</div>" +
"<div class='website'>www.PetitTeton.com</div>" +
//"<div style='height: " + bottomSpacing + "in'></div>" +
"</div>";
let labels = "";
//TODO: Include bar code and identifying numbers.
for(let i = 0; i < count; i++) {
labels += label;
}
return labels;
}
function printImageOld(template, dataUrl) {
let img = new Image();
img.onload = function() {
let imageCanvas = $('.labelCanvas')[0];
let ctx = imageCanvas.getContext('2d');
//let threshold = 255 + 200 + 0;
let desiredContrast = 100;
let contrastCorrectionFactor = (259 * (desiredContrast + 255)) / (255 * (259 - desiredContrast));
imageCanvas.width = img.width;
imageCanvas.height = img.height;
//console.log("Generated image: " + img.width + ", " + img.height);
//ctx.scale(0.25, 0.25);
ctx.drawImage(img, 0, 0);
let imageData = ctx.getImageData(0, 0, imageCanvas.width, imageCanvas.height);
let data = imageData.data;
//Run three times
for(let c = 0; c < 3; c++) {
//Set each pixel to either black or white with the given threshold.
for(let i = 0; i < data.length; i += 4) {
data[i] = contrastCorrectionFactor * (data[i] - 128) + 128;
data[i + 1] = contrastCorrectionFactor * (data[i + 1] - 128) + 128;
data[i + 2] = contrastCorrectionFactor * (data[i + 2] - 128) + 128;
//if(data[i] + data[i + 1] + data[i + 2] < threshold) {
// data[i] = 0;
// data[i + 1] = 0;
// data[i + 2] = 0;
//}
//else {
// data[i] = 255;
// data[i + 1] = 255;
// data[i + 2] = 255;
//}
data[i + 3] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
//Convert the canvas content to an image for printing. (cannot print a canvas?)
//sendToPrinter(template, imageCanvas.toDataURL("image/png"));
//Save to disk.
//imageCanvas.toBlob(function(blob) {
// saveAs(blob, "label.png");
//}, "image/png", 1);
//imageCanvas.toBlob(function(blob) {
// let url = URL.createObjectURL(blob);
// window.open(url, "_blank");
//}, "image/png", 1);
//let imgData = imageCanvas.toDataURL('image/jpeg', 1.0);
imageCanvas.toBlob(function(blob) {
let pdf = new PDF();
let url = URL.createObjectURL(blob);
pdf.addImage(url, "image/png", 0, 0);
pdf.save("label.pdf");
}, "image/png", 1);
};
img.src = dataUrl;
}
function printImage(template, raw, width, height) {
let data = raw;
//Run three times
for(let c = 0; c < 3; c++) {
//Set each pixel to either black or white with the given threshold.
for(let i = 0; i < data.length; i += 4) {
data[i] = contrastCorrectionFactor * (data[i] - 128) + 128;
data[i + 1] = contrastCorrectionFactor * (data[i + 1] - 128) + 128;
data[i + 2] = contrastCorrectionFactor * (data[i + 2] - 128) + 128;
//if(data[i] + data[i + 1] + data[i + 2] < threshold) {
// data[i] = 0;
// data[i + 1] = 0;
// data[i + 2] = 0;
//}
//else {
// data[i] = 255;
// data[i + 1] = 255;
// data[i + 2] = 255;
//}
data[i + 3] = 255;
}
}
let url = URL.createObjectURL(new Blob(raw, {type: "image/png"}));
let test = new Image();
test.src = url;
$('.testImage').html(test);
}
// Note: Not working correctly. Output seems to be at 96dpi instead of 300+dpi. Using a large image scaled down in in an Image tag seems to not print well.
function sendToPrinter(template, dataUrl) {
let canvasImg = new Image();
canvasImg.onload = function() {
//window.print();
};
canvasImg.src = dataUrl;
canvasImg.style.height = template.labelHeight.get() + "mm";
canvasImg.style.width = template.labelWidth.get() + "mm";
$(".printableLabel").html(canvasImg);
//$('.printableLabel').html(img);
window.print();
}
function loadImage(url) {
return new Promise(r => { let i = new Image(); i.onload = (() => r(i)); i.src = url; });
}
async function refreshLabelCanvas(template) {
let mmWidth = template.labelWidth.get();
let mmHeight = template.labelHeight.get();
let title1 = template.title1.get();
let title1Font = template.title1Font.get();
let title1YOffset = template.title1YOffset.get();
let title2 = template.title2.get();
let title2Font = template.title2Font.get();
let title2YOffset = template.title2YOffset.get();
let ingredients = template.ingredients.get();
let ingredientsFont = template.ingredientsFont.get();
let ingredientsYOffset = template.ingredientsYOffset.get();
let date = template.date.get();
let $labelCanvas = $('.labelCanvas');
let ctx = $labelCanvas[0].getContext('2d');
let width = Math.floor(mmWidth * PX_PER_MM);
let height = Math.floor(mmHeight * PX_PER_MM);
let center = width / 2;
let img = await loadImage(imagePath);
let imageWidth = 241;
let imageHeight = 219;
let ingredientsY = 180;
let ingredientsEndingY = 240;
let instructionsY = 280;
let addressY = 320;
let websiteY = 380;
ctx.fillStyle = 'white';
ctx.fillRect(0,0, width, height);
ctx.fillStyle = 'black';
ctx.drawImage(img, center - (imageWidth / 2), 0);
ctx.font = title1Font;
ctx.textAlign = 'center';
ctx.fillText(title1, center, title1YOffset);
////TODO: Allow logo to be removed or altered with an alternative logo for sizing fixes
//let label = "<div class='label'>" +
// "<div style='height: " + topSpacing + "in'></div>" +
// //"<img class='labelLogo' alt='logo' src='/images/PetitTetonLabelLogo_2in Width_v1.png'/>" +
// "<img class='labelLogo' alt='logo' src='/images/Logo_0.8x0.73_300ppi.png'/>" +
// "<div class='labelTagline'>We grow it. We can it.</div>" +
// "<div class='title1'>" + title1 + "</div>" +
// "<div class='title2'>" + (title2 === undefined ? "" : title2) + "</div>" +
// "<div class='ingredients'><span class='ingredientsPrefix'>Ingredients</span>:" + ingredients + "</div>" +
// "<div class='ingredientsEnding'>*<span style='font-style: oblique'>grown by us</span> <span class='size'>8oz</span> FD1951 (" + date + ")</div>" +
// "<div class='instructions'>Refrigerate after opening; return jar when done</div>" +
// "<div class='address'>18601 Hwy 128, Yorkville, CA 95494</div>" +
// "<div class='website'>www.PetitTeton.com</div>" +
// "<div style='height: " + bottomSpacing + "in'></div>" +
// "</div>";
//let labels = "";
//
////TODO: Include bar code and identifying numbers.
//for(let i = 0; i < count; i++) {
// labels += label;
//}
//
//return labels;
}
function bufferToBase64(buf) {
var binstr = Array.prototype.map.call(buf, function (ch) {
return String.fromCharCode(ch);
}).join('');
return btoa(binstr);
}
//let formats = {
// "8oz Label": {logo: true, text: true, barcode: true, width: 76.2, height: 50.8, labelClass: '8oz'},
// "Barcode Only": {logo: false, text: false, barcode: true, width: 25, height: 25, labelClass: 'barcode'}
//};
Template.LabelMaker.onCreated(function() {
this.labelWidth = new ReactiveVar(76);
@@ -240,52 +37,29 @@ Template.LabelMaker.onCreated(function() {
this.ingredients = new ReactiveVar("*strawberry, sugar, *espelette");
this.date = new ReactiveVar(19001);
//Session.set(PREFIX + "title1", "Strawberry");
//Session.set(PREFIX + "title1Font", "50px Times New Roman");
//Session.set(PREFIX + "title1YOffset", 260);
//Session.set(PREFIX + "title2", "w/ Espelette");
//Session.set(PREFIX + "title2Font", "40px Times New Roman");
//Session.set(PREFIX + "title2YOffset", 340);
//Session.set(PREFIX + "ingredients", "*strawberry, sugar, *espelette");
//Session.set(PREFIX + "date", 19001);
//Session.set(PREFIX + "count", 3);
this.format = new ReactiveVar("oz8");
});
Template.LabelMaker.onRendered(function() {
let template = this;
//Re-run this routine when ever the session variables change.
//Tracker.autorun(function() {
// //refreshLabelCanvas(Session.get(PREFIX + "title1"), Session.get(PREFIX + "title2"), Session.get(PREFIX + "ingredients"), Session.get(PREFIX + "date"), 1, Session.get(PREFIX + "labelSpacing"), 0);
// refreshLabelCanvas(template);
//});
//
//template.$('.labelContainer').on('DOMSubtreeModified', function() {
// console.log("Initialized barcode");
// //
//});
//JsBarcode(".barcode").init();
//const svgString = qrcode({content: "1234567890", padding: 0, width: 60, height: 60, color: "#000000", background: "#FFFFFF", ecl: "L"});
//this.$('.qrcode').attr('src', svg2url(svgString));
//this.$('.qrcode').attr('src', svg2url(new QRCode({content: '1234567890', width: 80, height: 80, color: "#000000", background: "#FFFFFF"}).svg()));
new QRCode(document.getElementById("qrcode"), {text: "1234567890", width: 60, height: 60});
//new QRCode(document.getElementById("qrcode"), {text: "1234567890", width: 60, height: 60});
});
Template.LabelMaker.onDestroyed(function() {
});
Template.LabelMaker.events({
'change .labelWidth': function(e, t) {
let x = $(e.target).val();
//'change .labelWidth': function(e, t) {
// let x = $(e.target).val();
//
// t.labelWidth.set(!Number.isNaN(x) && x > 0 ? parseFloat(x) : 76);
//},
//'change .labelHeight': function(event, template) {
// let x = $(event.target).val();
//
// t.labelHeight.set(!Number.isNaN(x) && x > 0 ? parseFloat(x) : 50);
//},
t.labelWidth.set(!Number.isNaN(x) && x > 0 ? parseFloat(x) : 76);
},
'change .labelHeight': function(event, template) {
let x = $(event.target).val();
t.labelHeight.set(!Number.isNaN(x) && x > 0 ? parseFloat(x) : 50);
'change input[name="labelType"]': function(e, t) {
t.format.set($(e.target).val());
},
'change .title1': function(e, t) {t.title1.set($(e.target).val());},
@@ -302,25 +76,27 @@ Template.LabelMaker.events({
'change .date': function(e, t) {t.date.set(parseInt($(e.target).val()));},
'click .preview': function(event, template) {
let params = {};
let _this = template;
let format = _this.format.get();
let title1 =_this.title1.get();
let title2 =_this.title2.get();
let ingredients =_this.ingredients.get();
let date =_this.date.get();
let params = {format, title1, title2, ingredients, date};
params['title1'] = "Strawberry";
params['title2'] = "";
params['ingredients'] = "Fairies";
params['date'] = "1234";
window.open('/PrintLabel?' + $.param(params));
},
'click .print': function(event, template) {
let _this = template;
let node = $('.label')[0];
let width = _this.labelWidth.get();
let height =_this.labelHeight.get();
let format = _this.format.get();
let title1 =_this.title1.get();
let title2 =_this.title2.get();
let ingredients =_this.ingredients.get();
let date =_this.date.get();
Meteor.call('printLabels', width, height, "3x2Standard", title1, title2, ingredients, date, (error, result) => {
//console.log("Calling print with: " + JSON.stringify({format, title1, title2, ingredients, date}));
Meteor.call('printLabels', format, title1, title2, ingredients, date, (error, result) => {
if(error) {
console.log(error);
}
@@ -333,81 +109,37 @@ Template.LabelMaker.events({
}
});
//dti.toBlob(node, {bgcolor: 'white'}).then(function(blob) {
// printImage(template, blob);
//}).catch(function(err) {
// console.log(err);
//});
//dti.toPng(node, {bgcolor: 'white'}).then(function(dataUrl) {
// printImageOld(template, dataUrl);
//}).catch(function(err) {
// console.log(err);
//});
//let count = template.$('input[name="count"]').val();
//let spacing = Session.get(PREFIX + "labelSpacing");
//
////count = (count === undefined || Number.isNaN(count)) ? 1 : parseInt(count);
////
////if(count < 1) {
//// count = 1;
////}
////
////Session.set(PREFIX + "generatedLabels", generateLabels(Session.get(PREFIX + "title1"), Session.get(PREFIX + "title2"), Session.get(PREFIX + "ingredients"), Session.get(PREFIX + "date"), count, 0, spacing));
//
//let $label = $('.printableLabel');
//
//console.log($label);
//console.log($label.length);
//domtoimage.toPng($label).then(function(dataUrl) {
// console.log("A");
// let img = new Image();
// img.src = dataUrl;
// $('.printableLabel').html(img);
// //caman('.printableLabel img', function() {
// // this.contrast(100);
// // this.render();
// // window.print();
// //});
//}).catch(function(error) {
// console.error("failed to convert dom to image");
// console.error(error);
//});
}
});
Template.LabelMaker.helpers({
printLabelVars: function() { //Called to pass the values for rendering a sample label on the client. This mimics the same call to the same view when going to 'print' the label to PDF later.
let t = Template.instance();
return {
format: t.format.get(),
title1: t.title1.get(),
title2: t.title2.get(),
ingredients: t.ingredients.get(),
date: t.date.get()
}
},
title1: function() {return Template.instance().title1.get();},
title2: function() {return Template.instance().title2.get();},
ingredients: function() {return Template.instance().ingredients.get();},
date: function() {return Template.instance().date.get();},
labelWidth: function() {return Template.instance().labelWidth.get();},
labelHeight: function() {return Template.instance().labelHeight.get();},
sampleLabel: function() {
let t = Template.instance();
setTimeout(function() {JsBarcode(".barcode").init();}, 500);
return generateLabels(t.title1.get(), t.title2.get(), t.ingredients.get(), t.date.get(), 1, 0);
},
//canvasLabel: function() {
// return generateLabelCanvas(Session.get(PREFIX + "title1"), Session.get(PREFIX + "title2"), Session.get(PREFIX + "ingredients"), Session.get(PREFIX + "date"), 1, Session.get(PREFIX + "labelSpacing"), 0);
//},
labels: function() {
return Session.get(PREFIX + "generatedLabels");
},
labelPxWidth: function() {
//console.log("label width: " + Template.instance().labelWidth.get());
//console.log("px_per_mm: " + PX_PER_MM);
//console.log("labelPxWidth: " + (Template.instance().labelWidth.get() * PX_PER_MM));
return Math.floor(Template.instance().labelWidth.get() * PX_PER_MM);
},
labelPxHeight: function() {
return Math.floor(Template.instance().labelHeight.get() * PX_PER_MM);
},
labelPxWidthActual: function() {
//console.log("label width: " + Template.instance().labelWidth.get());
//console.log("px_per_mm: " + PX_PER_MM);
//console.log("labelPxWidth: " + (Template.instance().labelWidth.get() * PX_PER_MM));
return Math.floor(Template.instance().labelWidth.get() * SCREEN_PX_PER_MM);
},
labelPxHeightActual: function() {

View File

@@ -2,17 +2,15 @@
<div id="PrintLabel">
<div class="labelContainer">
<div class='label'>
<!-- /images/Logo_0.8x0.73_300ppi.png-->
<!-- <div class='barcodeContainer'><svg class='barcode' jsbarcode-format='upc' jsbarcode-value='123456789012' jsbarcode-textmargin='0' jsbarcode-fontoptions='bold' jsbarcode-margin='0' jsbarcode-width='1.5em' jsbarcode-height='10em'></svg></div>-->
<div id="qrcode" class="qrcode" src=""></div>
<div id="qrcode" class="qrcode"></div>
<img class='labelLogo' alt='logo' src='/images/3x2 Label Logo BW.svg'/>
<div class='title1'></div>
<div class='title2'></div>
<div class='ingredients'><span class='ingredientsPrefix'>Ingredients</span>: </div>
<div class='ingredientsEnding'>*<span style='font-style: oblique'>grown by us</span> <span class='size'></span> FD1951 (<span class="date"></span>)</div>
<div class='instructions'>Refrigerate after opening; return jar when done</div>
<div class='address'>18601 Hwy 128, Yorkville, CA 95494</div>
<div class='website'>www.PetitTeton.com</div>
<div class='title1 labelText'></div>
<div class='title2 labelText'></div>
<div class='ingredients labelText'><span class='ingredientsPrefix'>Ingredients</span>: <span class="ingredientsList"></span></div>
<div class='ingredientsEnding labelText'>*<span style='font-style: oblique'>grown by us</span> <span class='size'></span> FD1951 (<span class="date"></span>)</div>
<div class='instructions labelText'>Refrigerate after opening; return jar when done</div>
<div class='address labelText'>18601 Hwy 128, Yorkville, CA 95494</div>
<div class='website labelText'>www.PetitTeton.com</div>
</div>
</div>
</div>

View File

@@ -2,44 +2,19 @@
#PrintLabel
.labelContainer
text-align center
//width 100%
width-min 3in
width 3in
height-min 2in
height 2in
//background-color grey
//padding 20px
.labels
display none
.printableLabel
display none
.label
display inline-block
width 3in
height 2in
.canvasContainer
padding 10px
background-color gray
.label
position relative
background-color white
color black
text-align center
font-family TimesNewRoman, Times New Roman, Times
//font-family Arial, Helvetica, sans-serif
font-size .1in
width 3in
height 2in
.barcodeContainer
position absolute
transform rotate(270deg)
right -4.5em
top 5em
.qrcode
position absolute
left 10px
top 10px
width 60px
height 60px
.labelLogo
width 8em
padding 0
@@ -90,3 +65,17 @@
width 100%
font-size 1.2em
font-weight 100
.label.oz8
width 76.2mm
height 50.8mm
.label.barcode
width 30.5mm
height 30.5mm
.qrcode
position absolute
top 50%
left 50%
margin-top -30px
margin-left -30px
.labelText, .labelLogo
display none

View File

@@ -1,11 +1,11 @@
import './PrintLabel.html';
import JsBarcode from 'JsBarcode';
//import QRCode from "../util/qrcode/qrcode";
import QRCode from '/imports/util/qrcode/qrcode';
//let {qrcode, svg2url} = require('pure-svg-code');
import LabelFormats from '/imports/LabelFormats.js';
Template.PrintLabel.onCreated(function() {
});
Template.PrintLabel.onRendered(function() {
function getUrlVars() {
let vars = {};
let parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
@@ -13,20 +13,30 @@ Template.PrintLabel.onCreated(function() {
});
return vars;
}
function setupDisplay(vars) {
$('.label').removeClass().addClass("label " + vars.format);
$('.title1').html(vars['title1']);
$('.title2').html(vars['title2'] === undefined ? "" : vars['title2']);
$('.ingredientsList').html(vars['ingredients']);
$('.date').html(vars['date']);
$('.size').html(vars['size']);
}
this.vars = getUrlVars();
});
let _this = this;
Template.PrintLabel.onRendered(function() {
let vars = this.vars;
$('.title1').html(vars['title1']);
$('.title2').html(vars['title2'] === undefined ? "" : vars['title2']);
$('.ingredients').append(vars['ingredients']);
$('.date').html(vars['date']);
$('.size').html(vars['size']);
//JsBarcode(".barcode").init();
//Use the reactive variables if this is being rendered as part of the client's view (a preview of what will be printed). Otherwise take the URL parameters as the vars for rendering.
if(Blaze.getData(_this.view).vars) {
Tracker.autorun(function() {
let vars = Blaze.getData(_this.view).vars;
setupDisplay(vars);
});
}
else {
let vars = getUrlVars();
setupDisplay(vars);
}
//const svgString = qrcode({content: "1234567890", padding: 0, width: 50, height: 50, color: "#000000", background: "#FFFFFF", ecl: "L"});
//this.$('.qrcode').attr('src', svg2url(svgString));
new QRCode(document.getElementById("qrcode"), {text: "1234567890", width: 60, height: 60});
});

View File

@@ -11,7 +11,7 @@
<thead>
<tr>
<th class="hasLabels"></th>
<th class="name">Name {{>BatchSearch columnName='name'}}</th>
<th class="name">Name {{>BatchSearch columnName='productId' collectionQueryColumnName='name' collection='Products' collectionResultColumnName='_id' width="90%"}}</th>
<th class="date">Date {{>BatchDateRangeSearch columnName='date' width='90%'}}</th>
<th class="amount">Amount</th>
<th class="cook">Cook {{>BatchSearch columnName='cook' collectionQueryColumnName='name' collection='Workers' collectionResultColumnName='_id'}}</th>
@@ -50,7 +50,7 @@
{{else}}
<td class="hasLabels noselect left"><i class="fa fa-print clickable {{hasLabelsClass}}" aria-hidden="true"></i></td>
<td class="name noselect nonclickable left">{{name}}</td>
<td class="date noselect nonclickable left">{{date}}</td>
<td class="date noselect nonclickable left">{{date}} ({{jdate}})</td>
<td class="amount noselect nonclickable left">{{amount}}</td>
<td class="cook noselect nonclickable left">{{cook}}</td>
<td class="canner noselect nonclickable left">{{canner}}</td>

View File

@@ -44,19 +44,23 @@
width: 100%
> .date
//width: auto
min-width: 150px
width: 180px
min-width: 180px
max-width: 180px
> .amount
//width: auto
width: 100px
min-width: 100px
max-width: 100px
> .cook
//width: auto
min-width: 150px
width: 180px
min-width: 180px
max-width: 180px
> .canner
//width: auto
min-width: 150px
width: 180px
min-width: 180px
max-width: 180px
> .comment
width: 220px

View File

@@ -126,6 +126,9 @@ Template.Batch.helpers({
},
isDeleted: function() {
return this.deletedAt;
},
jdate: function() {
return moment(this.date, "YYYYMMDD").format("YYDDDD");
}
});
Template.Batch.events({
@@ -157,6 +160,8 @@ Template.Batch.events({
Template.BatchEditor.onCreated(function() {
});
Template.BatchEditor.onRendered(function() {
//Not working????
//this.$('.editorForm').validator();
});
Template.BatchEditor.helpers({
name: function() {
@@ -181,15 +186,30 @@ Template.BatchEditor.events({
'click .editorCancel': function(event, template) {
Session.set(PREFIX + "editedId", undefined);
},
'click input[type="submit"]': function(event, template) {
event.preventDefault();
template.$('.insertForm').data('bs.validator').validate(function(isValid) {
if(isValid) {
//Allow the user to edit the comment and the amount produced. Sometimes jars pop after the product cools and these things need to be recorded.
'click .editorApply': function(event, template) {
//template.$('.editorForm').data('bs.validator').validate(function(isValid) {
// if(isValid) {
let id = template.data._id;
let amount = parseInt(template.$('input.amount').val());
let comment = template.$('#batchEditorComment').val();
//TODO
}
});
console.log(id + " " + amount + " " + comment);
if(Number.isInteger(amount) && amount > 0) {
Meteor.call('updateBatch', id, amount, comment, function(error) {
if(error) sAlert.error("Failed to update the batch!\n" + error);
else {
sAlert.success("Production batch updated.");
Session.set(PREFIX + "editedId", undefined);
}
});
}
else {
sAlert.error("Amount must be a number greater than zero.");
}
// }
//});
}
});

View File

@@ -1,5 +1,6 @@
import './Products.html';
import Batches from "../api/Batch";
let QUERY_LIMIT = 100;
let QUERY_LIMIT_INCREMENT = 100;
@@ -57,6 +58,10 @@ Template.Products.helpers({
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
Session.set(PREFIX + 'productCount', Meteor.collections.Products.find(dbQuery).count()); //Always get a full count.
//console.log("dbQuery=" + JSON.stringify(dbQuery));
//console.log("Result Count: " + Meteor.collections.Products.find(dbQuery).count());
return Meteor.collections.Products.find(dbQuery, {limit: Session.get(PREFIX + "queryLimit"), skip: skipCount, sort: {name: 1}});
},
disableLoadMore: function() {

View File

@@ -1,6 +1,7 @@
import './UserManagement.html';
import '/imports/util/selectize/selectize.js'
import '/imports/util/selectize/selectize.js';
import Swal from 'sweetalert2';
let QUERY_LIMIT = 100;
let QUERY_LIMIT_INCREMENT = 100;
@@ -91,22 +92,36 @@ Template.User.events({
},
"click .userRemove": function(event, template) {
let _this = this;
bootbox.confirm({
message: "Delete the user?",
buttons: {confirm: {label: "Yes", className: 'btn-success'}, cancel: {label: "No", className: "btn-danger"}},
callback: function(result) {
if(result) {
Meteor.call('deleteUser', _this._id, function(error, result) {
if(error) {
sAlert.error(error);
}
else {
sAlert.success("User removed.");
}
});
}
Swal({title: "Delete User", text: "Delete the user?", type: 'warning', showCancelButton: true, confirmButtonColor: '#419c2b', cancelButtonColor: '#d33', confirmButtonText: "Yes, delete it!"}).then((isConfirm) => {
if(isConfirm) {
Meteor.call('deleteUser', _this._id, function(error, result) {
if(error) {
sAlert.error(error);
}
else {
sAlert.success("User removed.");
}
});
}
});
//bootbox.confirm({
// message: "Delete the user?",
// buttons: {confirm: {label: "Yes", className: 'btn-success'}, cancel: {label: "No", className: "btn-danger"}},
// callback: function(result) {
// if(result) {
// Meteor.call('deleteUser', _this._id, function(error, result) {
// if(error) {
// sAlert.error(error);
// }
// else {
// sAlert.success("User removed.");
// }
// });
// }
// }
//});
}
});
Template.User.helpers({

5
package-lock.json generated
View File

@@ -1667,11 +1667,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"nocache": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz",
"integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
},
"nwmatcher": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz",

View File

@@ -19,7 +19,6 @@
"jspdf": "^1.5.3",
"malihu-custom-scrollbar-plugin": "latest",
"meteor-node-stubs": "^0.4.1",
"nocache": "^2.1.0",
"properties-reader": "0.0.15",
"puppeteer": "^1.20.0",
"pure-svg-code": "^1.0.6",

View File

@@ -22,8 +22,3 @@ if (!process.env.MAIL_URL) {
// console.log("Mail settings: " + process.env.MAIL_URL);
if(Meteor.log) Meteor.log.info("Server Started");
WebApp.rawConnectHandlers.use('/', function(req, res, next) {
res.setHeader('cache-control', 'no-cache');
next();
});