From 5ccb8e6a44a8d87323b5ab875f410893fe4a5581 Mon Sep 17 00:00:00 2001 From: Wynne Crisman Date: Tue, 1 Jan 2019 11:48:56 -0800 Subject: [PATCH] Added a reports page with a set of links to download CSV reports. --- .meteor/.finished-upgraders | 1 + .meteor/packages | 28 +- .meteor/release | 2 +- .meteor/versions | 123 +- README.md | 4 + client/main.styl | 1 + imports/api/Reports.js | 265 ++++ imports/api/Sale.js | 2 +- imports/api/index.js | 1 + imports/startup/client/routes.js | 7 + imports/ui/Reports.html | 7 + imports/ui/Reports.import.styl | 8 + imports/ui/Reports.js | 54 + imports/ui/layouts/Body.html | 7 + package-lock.json | 1986 +++++++----------------------- package.json | 2 +- 16 files changed, 910 insertions(+), 1588 deletions(-) create mode 100644 imports/api/Reports.js create mode 100644 imports/ui/Reports.html create mode 100644 imports/ui/Reports.import.styl create mode 100644 imports/ui/Reports.js diff --git a/.meteor/.finished-upgraders b/.meteor/.finished-upgraders index 910574c..4538749 100644 --- a/.meteor/.finished-upgraders +++ b/.meteor/.finished-upgraders @@ -15,3 +15,4 @@ notices-for-facebook-graph-api-2 1.4.1-add-shell-server-package 1.4.3-split-account-service-packages 1.5-add-dynamic-import-package +1.7-split-underscore-from-meteor-base diff --git a/.meteor/packages b/.meteor/packages index 34df9ad..425d535 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -4,25 +4,25 @@ # 'meteor add' and 'meteor remove' will edit this file for you, # but you can also edit it by hand. -meteor-base@1.2.0 # Packages every Meteor app needs to have +meteor-base@1.4.0 # Packages every Meteor app needs to have mobile-experience@1.0.5 # Packages for a great mobile UX -mongo@1.3.1 # The database Meteor supports right now +mongo@1.6.0 # The database Meteor supports right now blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views reactive-var@1.0.11 # Reactive variable for tracker -reactive-dict@1.2.0 # ??? -tracker@1.1.3 # Meteor's client-side reactive programming library +reactive-dict@1.2.1 # ??? +tracker@1.2.0 # Meteor's client-side reactive programming library tomwasd:history-polyfill # Adds IE 8/9 support for HTML5 history. email@1.2.3 # Adds the Meteor/Email package for sending lost password emails -standard-minifier-css@1.3.5 # CSS minifier run for production mode -standard-minifier-js@2.2.0 # JS minifier run for production mode -es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers. +standard-minifier-css@1.5.2 # CSS minifier run for production mode +standard-minifier-js@2.4.0 # JS minifier run for production mode +es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers. poorvavyas:es6-shim -ecmascript@0.9.0 # Enable ECMAScript2015+ syntax in app code +ecmascript@0.12.3 # Enable ECMAScript2015+ syntax in app code #accounts-ui #accounts-base -accounts-password@1.5.0 +accounts-password@1.5.1 useraccounts:core useraccounts:unstyled useraccounts:flow-routing # Configures email flows. Used for AccountsTemplates class. @@ -33,12 +33,12 @@ arillo:flow-router-helpers # Provides various template helpers such as {{pathFo #tomwasd:flow-router-seo kadira:blaze-layout -shell-server@0.3.0 # ??? +shell-server@0.4.0 # ??? meteortoys:allthings stylus@2.513.13 -session@1.1.7 +session@1.2.0 ##browser-policy # Adds support for specifying browser level security rules related to content and what's allowed to laod on the page. -check@1.2.5 # Allows for checking the structure and types of arguments passed to Meteor methods and publications. +check@1.3.1 # Allows for checking the structure and types of arguments passed to Meteor methods and publications. #audit-argument-checks # Used in combination with the Check package for checking the structure and types of arguments passed to Meteor methods and publications. Automatically alerts when a method or publication does not use a check() call. aldeed:simple-schema@1.5.3 @@ -61,6 +61,8 @@ juliancwirko:s-alert # Client error/alert handling jcbernack:reactive-aggregate # Allows us to create a new client collection (from the server) with the contents being an aggregate of server data. Note that aggregation can only be done on the server currently as mini-mongo does not support it. ostrio:logger ostrio:loggermongo -dynamic-import@0.2.0 +dynamic-import@0.5.0 markdown@1.0.12 wcrisman:jquery-custom-scrollbar +underscore +meteorhacks:aggregate # Allows databaseName.aggragate(pipeline) calls the exact same way you would on the command line in the mongo tool. diff --git a/.meteor/release b/.meteor/release index 56a7a07..2299ae7 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -METEOR@1.6.0.1 +METEOR@1.8.0.1 diff --git a/.meteor/versions b/.meteor/versions index aaee1f4..7a0cb6a 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -1,63 +1,65 @@ -accounts-base@1.4.0 -accounts-password@1.5.0 +accounts-base@1.4.3 +accounts-password@1.5.1 alanning:roles@1.2.16 aldeed:collection2@2.10.0 aldeed:collection2-core@1.2.0 aldeed:schema-deny@1.1.0 aldeed:schema-index@1.1.1 -aldeed:simple-schema@1.5.3 +aldeed:simple-schema@1.5.4 aldeed:template-extension@4.1.0 allow-deny@1.1.0 arillo:flow-router-helpers@0.5.2 -autoupdate@1.3.12 -babel-compiler@6.24.7 -babel-runtime@1.1.1 -base64@1.0.10 -binary-heap@1.0.10 -blaze@2.3.2 +autoupdate@1.5.0 +babel-compiler@7.2.4 +babel-runtime@1.3.0 +base64@1.0.11 +binary-heap@1.0.11 +blaze@2.3.3 blaze-html-templates@1.1.2 blaze-tools@1.0.10 -boilerplate-generator@1.3.1 -caching-compiler@1.1.9 -caching-html-compiler@1.1.2 -callback-hook@1.0.10 -check@1.2.5 +boilerplate-generator@1.6.0 +caching-compiler@1.2.1 +caching-html-compiler@1.1.3 +callback-hook@1.1.0 +check@1.3.1 coffeescript@1.0.17 ddp@1.4.0 -ddp-client@2.2.0 -ddp-common@1.3.0 +ddp-client@2.3.3 +ddp-common@1.4.0 ddp-rate-limiter@1.0.7 -ddp-server@2.1.1 +ddp-server@2.2.0 deps@1.0.12 -diff-sequence@1.0.7 -dynamic-import@0.2.1 -ecmascript@0.9.0 -ecmascript-runtime@0.5.0 -ecmascript-runtime-client@0.5.0 -ecmascript-runtime-server@0.5.0 +diff-sequence@1.1.1 +dynamic-import@0.5.1 +ecmascript@0.12.4 +ecmascript-runtime@0.7.0 +ecmascript-runtime-client@0.8.0 +ecmascript-runtime-server@0.7.1 ejson@1.1.0 email@1.2.3 -es5-shim@4.6.15 +es5-shim@4.8.0 +fetch@0.1.0 fortawesome:fontawesome@4.7.0 geojson-utils@1.0.10 hot-code-push@1.0.4 html-tools@1.0.11 htmljs@1.0.11 -http@1.3.0 -id-map@1.0.9 +http@1.4.2 +id-map@1.1.0 +inter-process-messaging@0.1.0 jcbernack:reactive-aggregate@0.7.0 -jquery@1.11.10 +jquery@1.11.11 juliancwirko:s-alert@3.2.0 kadira:blaze-layout@2.3.0 kadira:flow-router@2.12.1 launch-screen@1.1.1 livedata@1.0.18 localstorage@1.2.0 -logging@1.1.19 +logging@1.1.20 markdown@1.0.12 mdg:validation-error@0.2.0 -meteor@1.8.2 -meteor-base@1.2.0 +meteor@1.9.2 +meteor-base@1.4.0 meteorhacks:aggregate@1.3.0 meteorhacks:collection-utils@1.2.0 meteortoys:allthings@4.0.0 @@ -76,62 +78,65 @@ meteortoys:status@4.0.0 meteortoys:sub@4.0.0 meteortoys:throttle@4.0.0 meteortoys:toggle@4.0.0 -meteortoys:toykit@4.0.1 -minifier-css@1.2.16 -minifier-js@2.2.2 -minimongo@1.4.3 +meteortoys:toykit@4.0.2 +minifier-css@1.4.1 +minifier-js@2.4.0 +minimongo@1.4.5 mizzao:bootboxjs@4.4.0 mobile-experience@1.0.5 mobile-status-bar@1.0.14 -modules@0.11.1 -modules-runtime@0.9.1 -momentjs:moment@2.20.0 -mongo@1.3.1 +modern-browsers@0.1.3 +modules@0.13.0 +modules-runtime@0.10.3 +momentjs:moment@2.23.0 +mongo@1.6.0 +mongo-decimal@0.1.0 mongo-dev-server@1.1.0 -mongo-id@1.0.6 +mongo-id@1.0.7 mongo-livedata@1.0.12 msavin:jetsetter@4.0.0 msavin:mongol@4.0.1 npm-bcrypt@0.9.3 -npm-mongo@2.2.33 +npm-mongo@3.1.1 observe-sequence@1.0.16 -ordered-dict@1.0.9 -ostrio:logger@2.0.5 -ostrio:loggermongo@2.0.3 +ordered-dict@1.1.0 +ostrio:logger@2.0.7 +ostrio:loggermongo@2.0.4 poorvavyas:es6-shim@0.21.1 -promise@0.10.0 +promise@0.11.2 raix:eventemitter@0.1.3 -random@1.0.10 -rate-limit@1.0.8 -reactive-dict@1.2.0 +random@1.1.0 +rate-limit@1.0.9 +reactive-dict@1.2.1 reactive-var@1.0.11 -reload@1.1.11 -retry@1.0.9 -routepolicy@1.0.12 +reload@1.2.0 +retry@1.1.0 +routepolicy@1.1.0 service-configuration@1.0.11 -session@1.1.7 +session@1.2.0 sha@1.0.9 -shell-server@0.3.1 +shell-server@0.4.0 +socket-stream-client@0.2.2 softwarerero:accounts-t9n@1.3.11 spacebars@1.0.15 spacebars-compiler@1.1.3 -srp@1.0.10 -standard-minifier-css@1.3.5 -standard-minifier-js@2.2.3 -stylus@2.513.13 +srp@1.0.12 +standard-minifier-css@1.5.2 +standard-minifier-js@2.4.0 +stylus@2.513.14 templating@1.3.2 templating-compiler@1.3.3 templating-runtime@1.3.2 templating-tools@1.1.2 tomwasd:history-polyfill@0.0.1 -tracker@1.1.3 +tracker@1.2.0 ui@1.0.13 underscore@1.0.10 -url@1.1.0 +url@1.2.0 useraccounts:core@1.14.2 useraccounts:flow-routing@1.14.2 useraccounts:unstyled@1.14.2 wcrisman:jquery-custom-scrollbar@3.0.0 -webapp@1.4.0 +webapp@1.7.2 webapp-hashing@1.0.9 zimme:active-route@2.3.2 diff --git a/README.md b/README.md index daca794..6d2f85f 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,10 @@ NOTE: Use MongoBooster on a windows development machine to connect to the dev da 4. Look at the debug output by viewing the html files stored in `/tmp`. Use Samba to view them remotely. 5. Look at the Nginx logs (should be the same as the stuff in /tmp). +# Updating a Meteor Deployment *with* a NodeJS and Meteor version change. +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 ...}`} #Running Server Side Code diff --git a/client/main.styl b/client/main.styl index d99e29a..e027125 100644 --- a/client/main.styl +++ b/client/main.styl @@ -186,4 +186,5 @@ body @import "../imports/ui/Production.import.styl" @import "../imports/ui/Workers.import.styl" @import "../imports/ui/Graphs.import.styl" +@import "../imports/ui/Reports.import.styl" @import "../imports/ui/TestList.import.styl" \ No newline at end of file diff --git a/imports/api/Reports.js b/imports/api/Reports.js new file mode 100644 index 0000000..6aa4c80 --- /dev/null +++ b/imports/api/Reports.js @@ -0,0 +1,265 @@ +import { Meteor } from 'meteor/meteor'; + +if(Meteor.isServer) { + WebApp.connectHandlers.use("/reports/AnnualTotals", (req, res, next) => { + try { + let result = Meteor.collections.Sales.aggregate([{$group: {_id: {$substr: ['$date', 0, 4]}, total: {$sum: {$multiply: ["$price", "$amount"]}}}}]); + + result.toArray().then(function(result) { + res.writeHead(200, {'Content-Type': 'text/csv'}); + + res.write("Year,Sales Total\n"); + + for(let i = 0; i < result.length; i++) { + res.write(result[i]._id); + res.write(","); + res.write("" + result[i].total); + res.write("\n"); + } + + res.end(); + }); + } catch(err) { + console.log(err); + res.end(); + } + }); + WebApp.connectHandlers.use("/reports/MonthlyTotals", (req, res, next) => { + try { + let result = Meteor.collections.Sales.aggregate([{$group: {_id: {$substr: ['$date', 0, 6]}, total: {$sum: {$multiply: ["$price", "$amount"]}}}}]); + + result.toArray().then(function(result) { + res.writeHead(200, {'Content-Type': 'text/csv'}); + + res.write("Date,Sales Total\n"); + + result.sort(function(a, b) { + return parseInt(a._id) - parseInt(b._id); + }); + + for(let i = 0; i < result.length; i++) { + res.write(result[i]._id.substr(4, 2) + "/" + result[i]._id.substr(0, 4)); + res.write(","); + res.write("" + result[i].total); + res.write("\n"); + } + + res.end(); + }); + } catch(err) { + console.log(err); + res.end(); + } + }); + WebApp.connectHandlers.use("/reports/TagTotals", (req, res, next) => { + try { + //Aggregate all the sales by product id & year, then later create a map between products and tags to create tag totals. + let result = Meteor.collections.Sales.aggregate([{ + $group: { + _id: {$concat: ["$productId", "-", {$substr: ['$date', 0, 4]}]}, + productId: {$first: "$productId"}, + year: {$first: {$substr: ['$date', 0, 4]}}, + total: {$sum: {$multiply: ["$price", "$amount"]}} + } + }]); + + result.toArray().then(function(result) { + let productSalesTotalsMapByYear = {}; + + //Create a map of maps: year -> product id -> sales totals. + for(let next of result) { + let productSalesTotalsMap = productSalesTotalsMapByYear[next.year]; + + //Create the map if necessary. + if(productSalesTotalsMap === undefined) productSalesTotalsMap = productSalesTotalsMapByYear[next.year] = {}; + + productSalesTotalsMap[next.productId] = next.total; + } + + //Now create a mapping between the tag id's and tag names for later use. + let tagIdToTagNameMap = {}; + let tags = Meteor.collections.ProductTags.find({}, {fields: {_id: 1, name: 1}}).fetch(); + + for(let tag of tags) { + tagIdToTagNameMap[tag._id] = tag.name; + } + + //Now create a map between tag names -> [product ids] so that we can build a table below. + let tagProductIdsMap = {}; + let products = Meteor.collections.Products.find({}, {fields: {_id: 1, tags: 1}}).fetch(); + + for(let product of products) { + for(let tagId of product.tags) { + let tagName = tagIdToTagNameMap[tagId]; + let productIds = tagProductIdsMap[tagName]; + + //Initialize the array if undefined, and add to the mapping. + if(productIds === undefined) productIds = tagProductIdsMap[tagName] = []; + + productIds.push(product._id); + } + } + + //Collect the years in ascending oder. + let years = Object.keys(productSalesTotalsMapByYear).sort(function(a, b) {return parseInt(a) - parseInt(b);}); + + //Write the response table. + res.writeHead(200, {'Content-Type': 'text/csv'}); + + //Start with the table headers: Tag, Year1, Year2, .. + res.write("Tag"); + + //Iterate over the years and add them to the headers. + for(let year of years) { + res.write("," + year); + } + + res.write('\n'); + + //Now write the tag name, and the annual totals for each tag as a row. + for(let tagName in tagProductIdsMap) { + let productIds = tagProductIdsMap[tagName]; + + //console.log(result[i].name + "::" + result[i].total); + res.write(tagName); + + //Iterate over each year to add its total as a column. + for(let year of years) { + let productSalesTotalsMap = productSalesTotalsMapByYear[year]; + let annualTotal = 0; + + //Iterate over all the product id's for the tag and sum the annual totals for each product that is tagged. + for(productId of productIds) { + let productAnnualTotal = productSalesTotalsMap[productId]; + + if(productAnnualTotal) annualTotal += productAnnualTotal; + } + + res.write("," + annualTotal); + } + + res.write('\n'); + } + + res.end(); + + + //let tagSalesTotals = []; + //let tagIdToNameMap = []; + + ////Find all products and collect sales totals by tag id. + //let products = Meteor.collections.Products.find({}, {fields: {_id: 1, tags: 1}}).fetch(); + // + //for(let product of products) { + // for(let tag of product.tags) { + // let tagSalesTotal = tagSalesTotals[tag]; + // let productSalesTotal = productSalesTotalsMap[product._id]; + // + // if(tagSalesTotal === undefined) tagSalesTotal = 0; + // if(productSalesTotal === undefined) productSalesTotal = 0; + // + // tagSalesTotals[tag] = tagSalesTotal + productSalesTotal; + // } + //} + // + ////Find all tags and convert the tag id's to tag names. + //let tags = Meteor.collections.ProductTags.find({}, {fields: {_id: 1, name: 1}}).fetch(); + // + //for(let tag of tags) { + // tagIdToNameMap[tag._id] = tag.name; + //} + + ////Write the response table. + //res.writeHead(200, {'Content-Type': 'text/csv'}); + // + //res.write("Tag,Sales Total\n"); + // + ////result.sort(function(a, b) { + //// return a.name > b.name ? 1 : -1; + ////}); + // + //for(let tagId in tagSalesTotals) { + // let tagTotal = tagSalesTotals[tagId]; + // let tagName = tagIdToNameMap[tagId]; + // + // //console.log(result[i].name + "::" + result[i].total); + // res.write(tagName + ',' + tagTotal + '\n'); + //} + // + //res.end(); + }).catch((err) => { + console.log(err); + res.end(); + }); + + //Get all tags + //Get all products for each tag + //Total all sales for each product + //let tags = Meteor.collections.ProductTags.find({},{fields: {_id: 1, name: 1}}).fetch(); + //let result = []; + // + //for(let tag of tags) { + // let tagTotal = 0; + // let products = Meteor.collections.Products.find({tags: tag._id}, {fields: {_id: 1}}).fetch(); + // + // for(let product of products) { + // let sales = Meteor.collections.Sales.find({productId: product._id}, {fields: {amount: 1, price: 1, _id: 0}}).fetch(); + // + // for(let sale of sales) { + // tagTotal += sale.amount * sale.price; + // } + // } + // + // result.push({name: tag.name, total: tagTotal}); + //} + + //res.writeHead(200, {'Content-Type': 'text/csv'}); + // + //res.write("Tag,Sales Total\n"); + // + //result.sort(function(a, b) { + // return a.name > b.name ? 1 : -1; + //}); + // + //for(let i = 0; i < result.length; i++) { + // console.log(result[i].name + "::" + result[i].total); + // res.write(result[i].name); + // res.write(","); + // res.write("" + result[i].total); + // res.write("\n"); + //} + // + //res.end(); + } catch(err) { + console.log(err); + res.end(); + } + }); + WebApp.connectHandlers.use("/reports/WeekYearTable", (req, res, next) => { + try { + let result = Meteor.collections.Sales.aggregate([{$group: {_id: {$substr: ['$date', 0, 6]}, total: {$sum: {$multiply: ["$price", "$amount"]}}}}]); + + result.toArray().then(function(result) { + res.writeHead(200, {'Content-Type': 'text/csv'}); + + res.write("Date,Sales Total\n"); + + result.sort(function(a, b) { + return parseInt(a._id) - parseInt(b._id); + }); + + for(let i = 0; i < result.length; i++) { + res.write(result[i]._id.substr(4, 2) + "/" + result[i]._id.substr(0, 4)); + res.write(","); + res.write("" + result[i].total); + res.write("\n"); + } + + res.end(); + }); + } catch(err) { + console.log(err); + res.end(); + } + }); +} \ No newline at end of file diff --git a/imports/api/Sale.js b/imports/api/Sale.js index d3319e5..e757da8 100644 --- a/imports/api/Sale.js +++ b/imports/api/Sale.js @@ -349,7 +349,7 @@ if(Meteor.isServer) { 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 = sale.timestamp.getWeek().toString(); + let weekOfYear = timestamp.getWeek().toString(); if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { Sales.update(id, {$set: {date, venueId, price, amount, timestamp, weekOfYear}}, function(err, id) { diff --git a/imports/api/index.js b/imports/api/index.js index c46b4ea..65ed194 100644 --- a/imports/api/index.js +++ b/imports/api/index.js @@ -8,6 +8,7 @@ import Logs from "./Logs.js"; import Users from "./User.js"; import UserRoles from "./Roles.js"; import Workers from "./Worker.js"; +import './Reports.js'; //Save the collections in the Meteor.collections property for easy access without name conflicts. Meteor.collections = {Measures, Venues, Products, ProductTags, Sales, SalesSheets, Logs, Users, UserRoles, Workers}; diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js index 929abff..f566fca 100644 --- a/imports/startup/client/routes.js +++ b/imports/startup/client/routes.js @@ -102,6 +102,13 @@ pri.route('/graphs', { BlazeLayout.render('Body', {content: 'Graphs'}); } }); +pri.route('/reports', { + name: 'Reports', + action: function(params, queryParams) { + require("/imports/ui/Reports.js"); + BlazeLayout.render('Body', {content: 'Reports'}); + } +}); pri.route('/graphTest', { name: 'GraphTest', action: function(params, queryParams) { diff --git a/imports/ui/Reports.html b/imports/ui/Reports.html new file mode 100644 index 0000000..42591da --- /dev/null +++ b/imports/ui/Reports.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/imports/ui/Reports.import.styl b/imports/ui/Reports.import.styl new file mode 100644 index 0000000..7c76fb1 --- /dev/null +++ b/imports/ui/Reports.import.styl @@ -0,0 +1,8 @@ +#reports + display: table + content-box: border-box + padding: 10px 20px + height: 100% + width: 100% + text-align: left + margin-left:20px diff --git a/imports/ui/Reports.js b/imports/ui/Reports.js new file mode 100644 index 0000000..e27c44f --- /dev/null +++ b/imports/ui/Reports.js @@ -0,0 +1,54 @@ + +import './Reports.html'; + +let PREFIX = "reports."; + +//let SalesTotals = new Meteor.Collection("salesTotals"); +// +//Meteor.subscribe("venues"); +//Meteor.subscribe("productTags"); + +let salesTotalsSubscription; + + +Template.Reports.onCreated(function() { + //let template = Template.instance(); + + //Tracker.autorun(function() { + // salesTotalsSubscription = template.subscribe("salesTotals", Session.get(PREFIX + "time"), Session.get(PREFIX + "options")); + //}); +}); +Template.Reports.onRendered(function() { + //Template.instance() + //Tracker.autorun(function() { + // if(salesTotalsSubscription.ready()) { + // + // } + //}); +}); +//Template.Reports.helpers({ +// sales: function() { +// let sort = []; +// +// sort.push(['year', 'asc']);// year = 1; +// if(Session.get(PREFIX + "time") === 'weekly') sort.push(['week', 'asc']); // .week = 1; +// if(Session.get(PREFIX + "time") === 'monthly') sort.push(['month', 'asc']); // .month = 1; +// if(Session.get(PREFIX + "options") === 'markets') sort.push(['venue', 'asc']); // .month = 1; +// +// return SalesTotals.find({}, {sort: sort}); +// }, +// showTime: function(time) { +// return Session.get(PREFIX + "time") === time; +// }, +// showOption: function(option) { +// return Session.get(PREFIX + "options") === option; +// }, +// formatTotal: function(total) { +// return "$" + total.toFixed(2); +// } +//}); +//Template.Reports.events({ +// 'click annualNumbers': function(event, template) { +// +// } +//}); \ No newline at end of file diff --git a/imports/ui/layouts/Body.html b/imports/ui/layouts/Body.html index 7711fa4..bc4b1d9 100644 --- a/imports/ui/layouts/Body.html +++ b/imports/ui/layouts/Body.html @@ -51,6 +51,13 @@ +