Fixes and updates.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
node_modules
|
node_modules
|
||||||
.idea
|
.idea
|
||||||
private
|
private
|
||||||
|
.meteor/local
|
||||||
@@ -66,4 +66,4 @@ markdown@1.0.12
|
|||||||
wcrisman:jquery-custom-scrollbar
|
wcrisman:jquery-custom-scrollbar
|
||||||
underscore@1.0.10
|
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.
|
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.
|
||||||
|
|||||||
@@ -12,9 +12,6 @@ arillo:flow-router-helpers@0.5.2
|
|||||||
autoupdate@1.6.0
|
autoupdate@1.6.0
|
||||||
babel-compiler@7.3.4
|
babel-compiler@7.3.4
|
||||||
babel-runtime@1.3.0
|
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
|
base64@1.0.12
|
||||||
binary-heap@1.0.11
|
binary-heap@1.0.11
|
||||||
blaze@2.3.3
|
blaze@2.3.3
|
||||||
@@ -26,14 +23,6 @@ caching-html-compiler@1.1.3
|
|||||||
callback-hook@1.1.0
|
callback-hook@1.1.0
|
||||||
check@1.3.1
|
check@1.3.1
|
||||||
coffeescript@1.0.17
|
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@1.4.0
|
||||||
ddp-client@2.3.3
|
ddp-client@2.3.3
|
||||||
ddp-common@1.4.0
|
ddp-common@1.4.0
|
||||||
@@ -52,8 +41,6 @@ es5-shim@4.8.0
|
|||||||
fetch@0.1.1
|
fetch@0.1.1
|
||||||
fortawesome:fontawesome@4.7.0
|
fortawesome:fontawesome@4.7.0
|
||||||
geojson-utils@1.0.10
|
geojson-utils@1.0.10
|
||||||
gwendall:body-events@0.1.6
|
|
||||||
gwendall:session-json@0.1.7
|
|
||||||
hot-code-push@1.0.4
|
hot-code-push@1.0.4
|
||||||
html-tools@1.0.11
|
html-tools@1.0.11
|
||||||
htmljs@1.0.11
|
htmljs@1.0.11
|
||||||
@@ -65,7 +52,6 @@ jquery@1.11.11
|
|||||||
juliancwirko:s-alert@3.2.0
|
juliancwirko:s-alert@3.2.0
|
||||||
kadira:blaze-layout@2.3.0
|
kadira:blaze-layout@2.3.0
|
||||||
kadira:flow-router@2.12.1
|
kadira:flow-router@2.12.1
|
||||||
lai:collection-extensions@0.2.1_1
|
|
||||||
launch-screen@1.1.1
|
launch-screen@1.1.1
|
||||||
livedata@1.0.18
|
livedata@1.0.18
|
||||||
localstorage@1.2.0
|
localstorage@1.2.0
|
||||||
|
|||||||
@@ -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).
|
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.
|
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 ...}`}
|
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
|
## Running Server Side Code
|
||||||
|
|
||||||
|
|||||||
224
client/main.css
224
client/main.css
@@ -3507,22 +3507,26 @@ input[type="button"].btn-block {
|
|||||||
}
|
}
|
||||||
#production .table thead > tr > .date,
|
#production .table thead > tr > .date,
|
||||||
#production .table tbody > tr > .date {
|
#production .table tbody > tr > .date {
|
||||||
min-width: 150px;
|
width: 180px;
|
||||||
|
min-width: 180px;
|
||||||
max-width: 180px;
|
max-width: 180px;
|
||||||
}
|
}
|
||||||
#production .table thead > tr > .amount,
|
#production .table thead > tr > .amount,
|
||||||
#production .table tbody > tr > .amount {
|
#production .table tbody > tr > .amount {
|
||||||
|
width: 100px;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
max-width: 100px;
|
max-width: 100px;
|
||||||
}
|
}
|
||||||
#production .table thead > tr > .cook,
|
#production .table thead > tr > .cook,
|
||||||
#production .table tbody > tr > .cook {
|
#production .table tbody > tr > .cook {
|
||||||
min-width: 150px;
|
width: 180px;
|
||||||
|
min-width: 180px;
|
||||||
max-width: 180px;
|
max-width: 180px;
|
||||||
}
|
}
|
||||||
#production .table thead > tr > .canner,
|
#production .table thead > tr > .canner,
|
||||||
#production .table tbody > tr > .canner {
|
#production .table tbody > tr > .canner {
|
||||||
min-width: 150px;
|
width: 180px;
|
||||||
|
min-width: 180px;
|
||||||
max-width: 180px;
|
max-width: 180px;
|
||||||
}
|
}
|
||||||
#production .table thead > tr > .comment,
|
#production .table thead > tr > .comment,
|
||||||
@@ -3917,6 +3921,40 @@ input[type="button"].btn-block {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
@media not print {
|
@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 {
|
#labelMaker .labelOptions label {
|
||||||
font-family: TimesNewRoman, Times New Roman, Times;
|
font-family: TimesNewRoman, Times New Roman, Times;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
@@ -3951,140 +3989,14 @@ input[type="button"].btn-block {
|
|||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
}
|
}
|
||||||
#labelMaker .labelContainer {
|
#labelMaker .labelBackground {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
width-min: 3in;
|
width-min: 5in;
|
||||||
height-min: 2in;
|
height-min: 5in;
|
||||||
background-color: #808080;
|
background-color: #808080;
|
||||||
padding: 20px;
|
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 {
|
#testList {
|
||||||
margin: 10px 20px;
|
margin: 10px 20px;
|
||||||
@@ -4092,25 +4004,6 @@ input[type="button"].btn-block {
|
|||||||
}
|
}
|
||||||
#PrintLabel .labelContainer {
|
#PrintLabel .labelContainer {
|
||||||
text-align: center;
|
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 {
|
#PrintLabel .label {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -4119,19 +4012,13 @@ input[type="button"].btn-block {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
font-family: TimesNewRoman, Times New Roman, Times;
|
font-family: TimesNewRoman, Times New Roman, Times;
|
||||||
font-size: 0.1in;
|
font-size: 0.1in;
|
||||||
width: 3in;
|
|
||||||
height: 2in;
|
|
||||||
}
|
|
||||||
#PrintLabel .label .barcodeContainer {
|
|
||||||
position: absolute;
|
|
||||||
transform: rotate(270deg);
|
|
||||||
right: -4.5em;
|
|
||||||
top: 5em;
|
|
||||||
}
|
}
|
||||||
#PrintLabel .label .qrcode {
|
#PrintLabel .label .qrcode {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
}
|
}
|
||||||
#PrintLabel .label .labelLogo {
|
#PrintLabel .label .labelLogo {
|
||||||
width: 8em;
|
width: 8em;
|
||||||
@@ -4193,3 +4080,22 @@ input[type="button"].btn-block {
|
|||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
font-weight: 100;
|
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
6
imports/LabelFormats.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
let formats = {
|
||||||
|
"oz8": {width: "76.2mm", height: "50.8mmm"},
|
||||||
|
"barcode": {width: "30.5mm", height: "30.5mm"}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default formats;
|
||||||
@@ -128,13 +128,15 @@ if(Meteor.isServer) {
|
|||||||
if(!_.isNumber(skipCount) || skipCount < 0) skipCount = 0;
|
if(!_.isNumber(skipCount) || skipCount < 0) skipCount = 0;
|
||||||
|
|
||||||
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
|
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({
|
Meteor.methods({
|
||||||
getBatchCount: function(query) {
|
getBatchCount: function(query) {
|
||||||
//TODO: Validate the 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).
|
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])) {
|
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
||||||
@@ -198,40 +200,44 @@ if(Meteor.isServer) {
|
|||||||
}
|
}
|
||||||
else throw new Meteor.Error(403, "Not authorized.");
|
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(id, String);
|
||||||
check(comment, String);
|
check(amount, Number);
|
||||||
|
check(comment, Match.OneOf(String, undefined));
|
||||||
|
|
||||||
//Trim and convert empty comment to undefined.
|
//Trim and convert empty comment to undefined.
|
||||||
comment = comment ? comment.trim() : undefined;
|
comment = comment ? comment.trim() : undefined;
|
||||||
comment = comment && comment.length > 0 ? comment : undefined;
|
comment = comment && comment.length > 0 ? comment : undefined;
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
//let dateString = date.toString();
|
||||||
console.log("Changed comment of " + id + " to: " + comment);
|
//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(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();
|
|
||||||
|
|
||||||
if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) {
|
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);
|
if(err) console.log(err);
|
||||||
}, {bypassCollection2: true});
|
}, {bypassCollection2: true});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,54 +2,15 @@ import { Meteor } from 'meteor/meteor';
|
|||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
||||||
|
import LabelFormats from '/imports/LabelFormats.js';
|
||||||
|
|
||||||
|
|
||||||
if(Meteor.isServer) {
|
if(Meteor.isServer) {
|
||||||
const puppeteer = require('puppeteer');
|
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({
|
Meteor.methods({
|
||||||
//printLabels: function(width, height, layout, title1, title2, ingredients, date) {
|
async printLabels(format, title1, title2, ingredients, date) {
|
||||||
// console.log("Loaded Label");
|
let data = {format, title1, title2, ingredients, date};
|
||||||
// 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};
|
|
||||||
let params = "";
|
let params = "";
|
||||||
let url = Meteor.absoluteUrl("/PrintLabel");
|
let url = Meteor.absoluteUrl("/PrintLabel");
|
||||||
|
|
||||||
@@ -64,11 +25,8 @@ if(Meteor.isServer) {
|
|||||||
|
|
||||||
const browser = await puppeteer.launch();
|
const browser = await puppeteer.launch();
|
||||||
const page = await browser.newPage();
|
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'}
|
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'});
|
//const pdf = await page.pdf({format: 'A4'});
|
||||||
//await page.pdf({path: 'C:\\Users\\Grumpy\\label.pdf', width: '6in', height: '4in'});
|
//await page.pdf({path: 'C:\\Users\\Grumpy\\label.pdf', width: '6in', height: '4in'});
|
||||||
await browser.close();
|
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}, ...}
|
//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.
|
//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 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 measuresById = {};
|
||||||
let barcodesByProductAndMeasureIds = {};
|
let barcodesByProductAndMeasureIds = {};
|
||||||
let result = {};
|
let result = {};
|
||||||
@@ -93,11 +50,6 @@ if(Meteor.isServer) {
|
|||||||
|
|
||||||
for(measure of measures) measuresById[measure._id] = measure;
|
for(measure of measures) measuresById[measure._id] = measure;
|
||||||
for(barcode of barcodes) barcodesByProductAndMeasureIds[barcode.productAndMeasureId] = barcode.barcodeId;
|
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 product of products) {
|
||||||
for(let measureId of product.measures) {
|
for(let measureId of product.measures) {
|
||||||
|
|||||||
@@ -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.
|
* 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({
|
const ProductsSchema = new SimpleSchema({
|
||||||
name: {
|
name: {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor';
|
|||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { check } from 'meteor/check';
|
import { check } from 'meteor/check';
|
||||||
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
import {SimpleSchema} from 'meteor/aldeed:simple-schema';
|
||||||
|
import Batches from "./Batch";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notes:
|
* Notes:
|
||||||
@@ -131,6 +132,10 @@ if(Meteor.isServer) {
|
|||||||
if(!_.isNumber(skipCount) || skipCount < 0) skipCount = 0;
|
if(!_.isNumber(skipCount) || skipCount < 0) skipCount = 0;
|
||||||
|
|
||||||
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
|
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});
|
return Meteor.collections.Sales.find(dbQuery, {limit: limit, sort, skip: skipCount});
|
||||||
});
|
});
|
||||||
Meteor.publish('duplicateSales', function(query, includeIgnoredDuplicates) {
|
Meteor.publish('duplicateSales', function(query, includeIgnoredDuplicates) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ if(Meteor.isServer) {
|
|||||||
"insertUser": function(user) {
|
"insertUser": function(user) {
|
||||||
check(user, {
|
check(user, {
|
||||||
username: String,
|
username: String,
|
||||||
email: String,
|
emails: [{address: String, verified: Match.Maybe(Boolean)}],
|
||||||
roles: [String]
|
roles: [String]
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -21,7 +21,8 @@ if(Meteor.isServer) {
|
|||||||
//Verify the user name isn't already used.
|
//Verify the user name isn't already used.
|
||||||
if(Meteor.collections.Users.findOne({username: user.username}) === undefined) {
|
if(Meteor.collections.Users.findOne({username: user.username}) === undefined) {
|
||||||
let pwd = Random.secret(20);
|
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.
|
//Requires the alanning:roles package.
|
||||||
Roles.addUsersToRoles(id, user.roles);
|
Roles.addUsersToRoles(id, user.roles);
|
||||||
|
|||||||
@@ -2,45 +2,33 @@
|
|||||||
<div id="labelMaker">
|
<div id="labelMaker">
|
||||||
<div class="labelOptions">
|
<div class="labelOptions">
|
||||||
<div>Label Size</div>
|
<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="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 type="number" name="labelHeight" class="labelHeight input" step="0.25" value="{{labelHeight}}"/></div>
|
<div><label for="labelHeight">Height (mm):</label> <input disabled 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 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>
|
<div>Label Contents</div>
|
||||||
<!-- <label for="title1YOffset">Vertical Offset:</label> <input type="number" name="title1YOffset" class="title1YOffset input" value="{{title1YOffset}}"/>-->
|
<div class="labelTextControls"><label for="title1">Title:</label> <input type="text" name="title1" class="title1 input" value="{{title1}}"/></div>
|
||||||
<div><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><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><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><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="print" class="print">Print</button></div>
|
||||||
<div><button name="preview" class="preview">Preview</button></div>
|
<div><button name="preview" class="preview">Preview</button></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="labelContainer">
|
<div class="labelBackground">
|
||||||
<div class='label'>
|
{{>PrintLabel vars=printLabelVars}}
|
||||||
<!-- /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>
|
</div>
|
||||||
<!-- <div class="canvasContainer">-->
|
<!-- <div class="labelContainer">-->
|
||||||
<!-- <!– 3x2" == 76x50mm; 300ppi == 11.81ppmm; So 3x2" == 897 x 590x. –>-->
|
<!-- <div class='label'>-->
|
||||||
<!--<!– <canvas class="labelCanvas" width="{{labelPxWidthActual}}" height="{{labelPxHeightActual}}">–>-->
|
<!-- <div id="qrcode" class="qrcode"></div>-->
|
||||||
<!--<!– </canvas>–>-->
|
<!-- <img class='labelLogo' alt='logo' src='/images/3x2 Label Logo BW.svg'/>-->
|
||||||
<!-- <canvas class="labelCanvas" width="{{labelPxWidth}}" height="{{labelPxHeight}}">-->
|
<!-- <div class='title1 labelText'>{{title1}}</div>-->
|
||||||
<!-- </canvas>-->
|
<!-- <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>-->
|
||||||
<div class="testImage">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="printableLabel"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
154
imports/ui/Label.import.styl
vendored
154
imports/ui/Label.import.styl
vendored
@@ -7,6 +7,36 @@
|
|||||||
|
|
||||||
@media not print
|
@media not print
|
||||||
.labelOptions
|
.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
|
label
|
||||||
font-family TimesNewRoman, Times New Roman, Times
|
font-family TimesNewRoman, Times New Roman, Times
|
||||||
font-weight 200
|
font-weight 200
|
||||||
@@ -36,128 +66,10 @@
|
|||||||
font-size 12px
|
font-size 12px
|
||||||
font-weight 100
|
font-weight 100
|
||||||
line-height 14px
|
line-height 14px
|
||||||
.labelContainer
|
.labelBackground
|
||||||
text-align center
|
text-align center
|
||||||
width 100%
|
width 100%
|
||||||
width-min 3in
|
width-min 5in
|
||||||
height-min 2in
|
height-min 5in
|
||||||
background-color grey
|
background-color grey
|
||||||
padding 20px
|
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
|
|
||||||
@@ -8,6 +8,8 @@ import dragula from 'dragula';
|
|||||||
import QRCode from '/imports/util/qrcode/qrcode';
|
import QRCode from '/imports/util/qrcode/qrcode';
|
||||||
//let QRCode = require('/imports/util/qrcode/qrcode.js');
|
//let QRCode = require('/imports/util/qrcode/qrcode.js');
|
||||||
|
|
||||||
|
import './PrintLabel.js';
|
||||||
|
|
||||||
console.log(QRCode);
|
console.log(QRCode);
|
||||||
|
|
||||||
//let {qrcode, svg2url} = require('pure-svg-code');
|
//let {qrcode, svg2url} = require('pure-svg-code');
|
||||||
@@ -20,216 +22,11 @@ console.log(QRCode);
|
|||||||
let PREFIX = "LabelMaker_";
|
let PREFIX = "LabelMaker_";
|
||||||
let PX_PER_MM = 300 / 25.4;
|
let PX_PER_MM = 300 / 25.4;
|
||||||
let SCREEN_PX_PER_MM = 96 / 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) {
|
//let formats = {
|
||||||
//TODO: Allow logo to be removed or altered with an alternative logo for sizing fixes
|
// "8oz Label": {logo: true, text: true, barcode: true, width: 76.2, height: 50.8, labelClass: '8oz'},
|
||||||
let label = "<div class='label'>" +
|
// "Barcode Only": {logo: false, text: false, barcode: true, width: 25, height: 25, labelClass: 'barcode'}
|
||||||
"<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);
|
|
||||||
}
|
|
||||||
|
|
||||||
Template.LabelMaker.onCreated(function() {
|
Template.LabelMaker.onCreated(function() {
|
||||||
this.labelWidth = new ReactiveVar(76);
|
this.labelWidth = new ReactiveVar(76);
|
||||||
@@ -240,52 +37,29 @@ Template.LabelMaker.onCreated(function() {
|
|||||||
this.ingredients = new ReactiveVar("*strawberry, sugar, *espelette");
|
this.ingredients = new ReactiveVar("*strawberry, sugar, *espelette");
|
||||||
|
|
||||||
this.date = new ReactiveVar(19001);
|
this.date = new ReactiveVar(19001);
|
||||||
|
this.format = new ReactiveVar("oz8");
|
||||||
//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);
|
|
||||||
});
|
});
|
||||||
Template.LabelMaker.onRendered(function() {
|
Template.LabelMaker.onRendered(function() {
|
||||||
let template = this;
|
let template = this;
|
||||||
|
|
||||||
//Re-run this routine when ever the session variables change.
|
//new QRCode(document.getElementById("qrcode"), {text: "1234567890", width: 60, height: 60});
|
||||||
//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});
|
|
||||||
});
|
});
|
||||||
Template.LabelMaker.onDestroyed(function() {
|
Template.LabelMaker.onDestroyed(function() {
|
||||||
});
|
});
|
||||||
Template.LabelMaker.events({
|
Template.LabelMaker.events({
|
||||||
'change .labelWidth': function(e, t) {
|
//'change .labelWidth': function(e, t) {
|
||||||
let x = $(e.target).val();
|
// 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 input[name="labelType"]': function(e, t) {
|
||||||
},
|
t.format.set($(e.target).val());
|
||||||
'change .labelHeight': function(event, template) {
|
|
||||||
let x = $(event.target).val();
|
|
||||||
|
|
||||||
t.labelHeight.set(!Number.isNaN(x) && x > 0 ? parseFloat(x) : 50);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'change .title1': function(e, t) {t.title1.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()));},
|
'change .date': function(e, t) {t.date.set(parseInt($(e.target).val()));},
|
||||||
'click .preview': function(event, template) {
|
'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));
|
window.open('/PrintLabel?' + $.param(params));
|
||||||
},
|
},
|
||||||
'click .print': function(event, template) {
|
'click .print': function(event, template) {
|
||||||
let _this = template;
|
let _this = template;
|
||||||
let node = $('.label')[0];
|
let format = _this.format.get();
|
||||||
let width = _this.labelWidth.get();
|
|
||||||
let height =_this.labelHeight.get();
|
|
||||||
let title1 =_this.title1.get();
|
let title1 =_this.title1.get();
|
||||||
let title2 =_this.title2.get();
|
let title2 =_this.title2.get();
|
||||||
let ingredients =_this.ingredients.get();
|
let ingredients =_this.ingredients.get();
|
||||||
let date =_this.date.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) {
|
if(error) {
|
||||||
console.log(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({
|
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();},
|
title1: function() {return Template.instance().title1.get();},
|
||||||
title2: function() {return Template.instance().title2.get();},
|
title2: function() {return Template.instance().title2.get();},
|
||||||
ingredients: function() {return Template.instance().ingredients.get();},
|
ingredients: function() {return Template.instance().ingredients.get();},
|
||||||
date: function() {return Template.instance().date.get();},
|
date: function() {return Template.instance().date.get();},
|
||||||
labelWidth: function() {return Template.instance().labelWidth.get();},
|
labelWidth: function() {return Template.instance().labelWidth.get();},
|
||||||
labelHeight: function() {return Template.instance().labelHeight.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() {
|
labels: function() {
|
||||||
return Session.get(PREFIX + "generatedLabels");
|
return Session.get(PREFIX + "generatedLabels");
|
||||||
},
|
},
|
||||||
labelPxWidth: function() {
|
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);
|
return Math.floor(Template.instance().labelWidth.get() * PX_PER_MM);
|
||||||
},
|
},
|
||||||
labelPxHeight: function() {
|
labelPxHeight: function() {
|
||||||
return Math.floor(Template.instance().labelHeight.get() * PX_PER_MM);
|
return Math.floor(Template.instance().labelHeight.get() * PX_PER_MM);
|
||||||
},
|
},
|
||||||
labelPxWidthActual: function() {
|
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);
|
return Math.floor(Template.instance().labelWidth.get() * SCREEN_PX_PER_MM);
|
||||||
},
|
},
|
||||||
labelPxHeightActual: function() {
|
labelPxHeightActual: function() {
|
||||||
|
|||||||
@@ -2,17 +2,15 @@
|
|||||||
<div id="PrintLabel">
|
<div id="PrintLabel">
|
||||||
<div class="labelContainer">
|
<div class="labelContainer">
|
||||||
<div class='label'>
|
<div class='label'>
|
||||||
<!-- /images/Logo_0.8x0.73_300ppi.png-->
|
<div id="qrcode" class="qrcode"></div>
|
||||||
<!-- <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>
|
|
||||||
<img class='labelLogo' alt='logo' src='/images/3x2 Label Logo BW.svg'/>
|
<img class='labelLogo' alt='logo' src='/images/3x2 Label Logo BW.svg'/>
|
||||||
<div class='title1'></div>
|
<div class='title1 labelText'></div>
|
||||||
<div class='title2'></div>
|
<div class='title2 labelText'></div>
|
||||||
<div class='ingredients'><span class='ingredientsPrefix'>Ingredients</span>: </div>
|
<div class='ingredients labelText'><span class='ingredientsPrefix'>Ingredients</span>: <span class="ingredientsList"></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='ingredientsEnding labelText'>*<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='instructions labelText'>Refrigerate after opening; return jar when done</div>
|
||||||
<div class='address'>18601 Hwy 128, Yorkville, CA 95494</div>
|
<div class='address labelText'>18601 Hwy 128, Yorkville, CA 95494</div>
|
||||||
<div class='website'>www.PetitTeton.com</div>
|
<div class='website labelText'>www.PetitTeton.com</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
43
imports/ui/PrintLabel.import.styl
vendored
43
imports/ui/PrintLabel.import.styl
vendored
@@ -2,44 +2,19 @@
|
|||||||
#PrintLabel
|
#PrintLabel
|
||||||
.labelContainer
|
.labelContainer
|
||||||
text-align center
|
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
|
.label
|
||||||
position relative
|
position relative
|
||||||
background-color white
|
background-color white
|
||||||
color black
|
color black
|
||||||
text-align center
|
text-align center
|
||||||
font-family TimesNewRoman, Times New Roman, Times
|
font-family TimesNewRoman, Times New Roman, Times
|
||||||
//font-family Arial, Helvetica, sans-serif
|
|
||||||
font-size .1in
|
font-size .1in
|
||||||
width 3in
|
|
||||||
height 2in
|
|
||||||
.barcodeContainer
|
|
||||||
position absolute
|
|
||||||
transform rotate(270deg)
|
|
||||||
right -4.5em
|
|
||||||
top 5em
|
|
||||||
.qrcode
|
.qrcode
|
||||||
position absolute
|
position absolute
|
||||||
left 10px
|
left 10px
|
||||||
top 10px
|
top 10px
|
||||||
|
width 60px
|
||||||
|
height 60px
|
||||||
.labelLogo
|
.labelLogo
|
||||||
width 8em
|
width 8em
|
||||||
padding 0
|
padding 0
|
||||||
@@ -90,3 +65,17 @@
|
|||||||
width 100%
|
width 100%
|
||||||
font-size 1.2em
|
font-size 1.2em
|
||||||
font-weight 100
|
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
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import './PrintLabel.html';
|
import './PrintLabel.html';
|
||||||
import JsBarcode from 'JsBarcode';
|
|
||||||
//import QRCode from "../util/qrcode/qrcode";
|
|
||||||
import QRCode from '/imports/util/qrcode/qrcode';
|
import QRCode from '/imports/util/qrcode/qrcode';
|
||||||
|
import LabelFormats from '/imports/LabelFormats.js';
|
||||||
//let {qrcode, svg2url} = require('pure-svg-code');
|
|
||||||
|
|
||||||
Template.PrintLabel.onCreated(function() {
|
Template.PrintLabel.onCreated(function() {
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.PrintLabel.onRendered(function() {
|
||||||
function getUrlVars() {
|
function getUrlVars() {
|
||||||
let vars = {};
|
let vars = {};
|
||||||
let parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
|
let parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
|
||||||
@@ -13,20 +13,30 @@ Template.PrintLabel.onCreated(function() {
|
|||||||
});
|
});
|
||||||
return vars;
|
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() {
|
//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.
|
||||||
let vars = this.vars;
|
if(Blaze.getData(_this.view).vars) {
|
||||||
$('.title1').html(vars['title1']);
|
Tracker.autorun(function() {
|
||||||
$('.title2').html(vars['title2'] === undefined ? "" : vars['title2']);
|
let vars = Blaze.getData(_this.view).vars;
|
||||||
$('.ingredients').append(vars['ingredients']);
|
|
||||||
$('.date').html(vars['date']);
|
setupDisplay(vars);
|
||||||
$('.size').html(vars['size']);
|
});
|
||||||
//JsBarcode(".barcode").init();
|
}
|
||||||
|
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});
|
new QRCode(document.getElementById("qrcode"), {text: "1234567890", width: 60, height: 60});
|
||||||
});
|
});
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="hasLabels"></th>
|
<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="date">Date {{>BatchDateRangeSearch columnName='date' width='90%'}}</th>
|
||||||
<th class="amount">Amount</th>
|
<th class="amount">Amount</th>
|
||||||
<th class="cook">Cook {{>BatchSearch columnName='cook' collectionQueryColumnName='name' collection='Workers' collectionResultColumnName='_id'}}</th>
|
<th class="cook">Cook {{>BatchSearch columnName='cook' collectionQueryColumnName='name' collection='Workers' collectionResultColumnName='_id'}}</th>
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
{{else}}
|
{{else}}
|
||||||
<td class="hasLabels noselect left"><i class="fa fa-print clickable {{hasLabelsClass}}" aria-hidden="true"></i></td>
|
<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="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="amount noselect nonclickable left">{{amount}}</td>
|
||||||
<td class="cook noselect nonclickable left">{{cook}}</td>
|
<td class="cook noselect nonclickable left">{{cook}}</td>
|
||||||
<td class="canner noselect nonclickable left">{{canner}}</td>
|
<td class="canner noselect nonclickable left">{{canner}}</td>
|
||||||
|
|||||||
10
imports/ui/Production.import.styl
vendored
10
imports/ui/Production.import.styl
vendored
@@ -44,19 +44,23 @@
|
|||||||
width: 100%
|
width: 100%
|
||||||
> .date
|
> .date
|
||||||
//width: auto
|
//width: auto
|
||||||
min-width: 150px
|
width: 180px
|
||||||
|
min-width: 180px
|
||||||
max-width: 180px
|
max-width: 180px
|
||||||
> .amount
|
> .amount
|
||||||
//width: auto
|
//width: auto
|
||||||
|
width: 100px
|
||||||
min-width: 100px
|
min-width: 100px
|
||||||
max-width: 100px
|
max-width: 100px
|
||||||
> .cook
|
> .cook
|
||||||
//width: auto
|
//width: auto
|
||||||
min-width: 150px
|
width: 180px
|
||||||
|
min-width: 180px
|
||||||
max-width: 180px
|
max-width: 180px
|
||||||
> .canner
|
> .canner
|
||||||
//width: auto
|
//width: auto
|
||||||
min-width: 150px
|
width: 180px
|
||||||
|
min-width: 180px
|
||||||
max-width: 180px
|
max-width: 180px
|
||||||
> .comment
|
> .comment
|
||||||
width: 220px
|
width: 220px
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ Template.Batch.helpers({
|
|||||||
},
|
},
|
||||||
isDeleted: function() {
|
isDeleted: function() {
|
||||||
return this.deletedAt;
|
return this.deletedAt;
|
||||||
|
},
|
||||||
|
jdate: function() {
|
||||||
|
return moment(this.date, "YYYYMMDD").format("YYDDDD");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Template.Batch.events({
|
Template.Batch.events({
|
||||||
@@ -157,6 +160,8 @@ Template.Batch.events({
|
|||||||
Template.BatchEditor.onCreated(function() {
|
Template.BatchEditor.onCreated(function() {
|
||||||
});
|
});
|
||||||
Template.BatchEditor.onRendered(function() {
|
Template.BatchEditor.onRendered(function() {
|
||||||
|
//Not working????
|
||||||
|
//this.$('.editorForm').validator();
|
||||||
});
|
});
|
||||||
Template.BatchEditor.helpers({
|
Template.BatchEditor.helpers({
|
||||||
name: function() {
|
name: function() {
|
||||||
@@ -181,15 +186,30 @@ Template.BatchEditor.events({
|
|||||||
'click .editorCancel': function(event, template) {
|
'click .editorCancel': function(event, template) {
|
||||||
Session.set(PREFIX + "editedId", undefined);
|
Session.set(PREFIX + "editedId", undefined);
|
||||||
},
|
},
|
||||||
'click input[type="submit"]': function(event, template) {
|
'click .editorApply': function(event, template) {
|
||||||
event.preventDefault();
|
//template.$('.editorForm').data('bs.validator').validate(function(isValid) {
|
||||||
template.$('.insertForm').data('bs.validator').validate(function(isValid) {
|
// if(isValid) {
|
||||||
if(isValid) {
|
let id = template.data._id;
|
||||||
//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.
|
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.");
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
//});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
import './Products.html';
|
import './Products.html';
|
||||||
|
import Batches from "../api/Batch";
|
||||||
|
|
||||||
let QUERY_LIMIT = 100;
|
let QUERY_LIMIT = 100;
|
||||||
let QUERY_LIMIT_INCREMENT = 100;
|
let QUERY_LIMIT_INCREMENT = 100;
|
||||||
@@ -57,6 +58,10 @@ Template.Products.helpers({
|
|||||||
|
|
||||||
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
|
dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {};
|
||||||
Session.set(PREFIX + 'productCount', Meteor.collections.Products.find(dbQuery).count()); //Always get a full count.
|
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}});
|
return Meteor.collections.Products.find(dbQuery, {limit: Session.get(PREFIX + "queryLimit"), skip: skipCount, sort: {name: 1}});
|
||||||
},
|
},
|
||||||
disableLoadMore: function() {
|
disableLoadMore: function() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
import './UserManagement.html';
|
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 = 100;
|
||||||
let QUERY_LIMIT_INCREMENT = 100;
|
let QUERY_LIMIT_INCREMENT = 100;
|
||||||
@@ -91,22 +92,36 @@ Template.User.events({
|
|||||||
},
|
},
|
||||||
"click .userRemove": function(event, template) {
|
"click .userRemove": function(event, template) {
|
||||||
let _this = this;
|
let _this = this;
|
||||||
bootbox.confirm({
|
Swal({title: "Delete User", text: "Delete the user?", type: 'warning', showCancelButton: true, confirmButtonColor: '#419c2b', cancelButtonColor: '#d33', confirmButtonText: "Yes, delete it!"}).then((isConfirm) => {
|
||||||
message: "Delete the user?",
|
if(isConfirm) {
|
||||||
buttons: {confirm: {label: "Yes", className: 'btn-success'}, cancel: {label: "No", className: "btn-danger"}},
|
Meteor.call('deleteUser', _this._id, function(error, result) {
|
||||||
callback: function(result) {
|
if(error) {
|
||||||
if(result) {
|
sAlert.error(error);
|
||||||
Meteor.call('deleteUser', _this._id, function(error, result) {
|
}
|
||||||
if(error) {
|
else {
|
||||||
sAlert.error(error);
|
sAlert.success("User removed.");
|
||||||
}
|
}
|
||||||
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({
|
Template.User.helpers({
|
||||||
|
|||||||
5
package-lock.json
generated
5
package-lock.json
generated
@@ -1667,11 +1667,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
"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": {
|
"nwmatcher": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz",
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
"jspdf": "^1.5.3",
|
"jspdf": "^1.5.3",
|
||||||
"malihu-custom-scrollbar-plugin": "latest",
|
"malihu-custom-scrollbar-plugin": "latest",
|
||||||
"meteor-node-stubs": "^0.4.1",
|
"meteor-node-stubs": "^0.4.1",
|
||||||
"nocache": "^2.1.0",
|
|
||||||
"properties-reader": "0.0.15",
|
"properties-reader": "0.0.15",
|
||||||
"puppeteer": "^1.20.0",
|
"puppeteer": "^1.20.0",
|
||||||
"pure-svg-code": "^1.0.6",
|
"pure-svg-code": "^1.0.6",
|
||||||
|
|||||||
@@ -22,8 +22,3 @@ if (!process.env.MAIL_URL) {
|
|||||||
// console.log("Mail settings: " + process.env.MAIL_URL);
|
// console.log("Mail settings: " + process.env.MAIL_URL);
|
||||||
|
|
||||||
if(Meteor.log) Meteor.log.info("Server Started");
|
if(Meteor.log) Meteor.log.info("Server Started");
|
||||||
|
|
||||||
WebApp.rawConnectHandlers.use('/', function(req, res, next) {
|
|
||||||
res.setHeader('cache-control', 'no-cache');
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
|
|||||||
Reference in New Issue
Block a user