From e1b0b19589d6ec074243e566d22896ca4a287feb Mon Sep 17 00:00:00 2001 From: Wynne Crisman Date: Tue, 9 May 2017 13:51:26 -0700 Subject: [PATCH] Added a Sales Sheet page along with other changes. --- .../meteor_packages_auto_import_browser.xml | 20 - .../meteor_packages_auto_import_npm.xml | 4520 ----------------- .idea/workspace.xml | 1107 ++-- .meteor/packages | 18 +- .meteor/release | 2 +- .meteor/versions | 3 - README.md | 186 +- client/client.js | 4 + client/main.styl | 154 +- imports/api/Sale.js | 62 +- imports/api/SalesSheet.js | 160 + imports/api/Venue.js | 18 +- imports/api/index.js | 8 +- imports/startup/client/routes.js | 9 + imports/ui/Products.js | 1 - imports/ui/Sales.html | 157 +- imports/ui/Sales.import.styl | 177 +- imports/ui/Sales.js | 283 +- imports/ui/SalesSheetEditor.html | 76 + imports/ui/SalesSheetEditor.import.styl | 149 + imports/ui/SalesSheetEditor.js | 419 ++ imports/ui/SalesSheetForm.html | 70 + imports/ui/SalesSheetForm.import.styl | 109 + imports/ui/SalesSheetForm.js | 372 ++ imports/ui/SalesSheets.html | 34 + imports/ui/SalesSheets.import.styl | 98 + imports/ui/SalesSheets.js | 160 + imports/ui/layouts/Body.html | 134 +- imports/ui/layouts/Body.import.styl | 156 +- imports/ui/styles/buttons.import.styl | 52 + imports/ui/styles/effects.import.styl | 34 + imports/ui/styles/forms.import.styl | 117 + imports/ui/styles/maxHeightLayout.import.styl | 133 + imports/ui/styles/tabs.import.styl | 61 + imports/util/de.combo.js | 32 +- imports/util/polyfills/array.js | 70 +- imports/util/polyfills/blaze.js | 2 +- imports/util/validator.js | 18 +- package.json | 6 +- 39 files changed, 3581 insertions(+), 5610 deletions(-) create mode 100644 imports/api/SalesSheet.js create mode 100644 imports/ui/SalesSheetEditor.html create mode 100644 imports/ui/SalesSheetEditor.import.styl create mode 100644 imports/ui/SalesSheetEditor.js create mode 100644 imports/ui/SalesSheetForm.html create mode 100644 imports/ui/SalesSheetForm.import.styl create mode 100644 imports/ui/SalesSheetForm.js create mode 100644 imports/ui/SalesSheets.html create mode 100644 imports/ui/SalesSheets.import.styl create mode 100644 imports/ui/SalesSheets.js create mode 100644 imports/ui/styles/buttons.import.styl create mode 100644 imports/ui/styles/effects.import.styl create mode 100644 imports/ui/styles/forms.import.styl create mode 100644 imports/ui/styles/maxHeightLayout.import.styl create mode 100644 imports/ui/styles/tabs.import.styl diff --git a/.idea/libraries/meteor_packages_auto_import_browser.xml b/.idea/libraries/meteor_packages_auto_import_browser.xml index 1f6ad38..ee521af 100644 --- a/.idea/libraries/meteor_packages_auto_import_browser.xml +++ b/.idea/libraries/meteor_packages_auto_import_browser.xml @@ -303,16 +303,8 @@ - - - - - - - - @@ -334,8 +326,6 @@ - - @@ -715,16 +705,8 @@ - - - - - - - - @@ -746,8 +728,6 @@ - - diff --git a/.idea/libraries/meteor_packages_auto_import_npm.xml b/.idea/libraries/meteor_packages_auto_import_npm.xml index a40aae0..ca9e561 100644 --- a/.idea/libraries/meteor_packages_auto_import_npm.xml +++ b/.idea/libraries/meteor_packages_auto_import_npm.xml @@ -5565,2266 +5565,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -13391,2266 +11131,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.idea/workspace.xml b/.idea/workspace.xml index b87498a..2acada6 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,33 +2,30 @@ - - + + - + + - - - + - - - - - - + + + + + - @@ -51,149 +48,105 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -210,36 +163,36 @@ - setPrevious - productTags - table - PricingFo - $or - InsertSaleMeasure - selectedProduct - id= - insertSale - class="insertSale - #insertSale - #InsertSale - # - $ - InsertSaleProduct - var - x - Template. - find - _id - xdomain - Product - Session.set(PREFIX + "editedMeasure", undefined) - Session - product + tabContent + SalesSheetFormProduct + ReactiveDict + Number + console.log + salesSheet .name - measure - Measure - postfix - Postfix + _. + productsDepe + odd + text-shad + sheetHeader + salesSheetProducts + salesSheetEditorControls + salesSheetFormProducts + salesSheetFormMeasures + resetAmounts + resetPrices + resetAmount + oddProductIds + currentData + previousAutoSetPrice + amount + input[name="amount"] + salesSheet.get().products + shadow + text-shadow + text- + text-sha + transition firstRow @@ -258,7 +211,6 @@ saleCount prevButton input[name="product"] - let x0Scale measure Measure @@ -266,6 +218,10 @@ Venue Type type + let + salesSheetFormElements + measureTemplates + autoSetPrice @@ -274,57 +230,57 @@ @@ -346,10 +302,10 @@ - @@ -398,7 +354,6 @@ - @@ -438,6 +393,32 @@ + + + + + + + + + + + @@ -457,6 +438,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + - @@ -546,6 +571,7 @@ + @@ -559,6 +585,7 @@ + @@ -730,12 +757,13 @@ - + + - @@ -747,27 +775,27 @@ - - + + - + - + - + + - + + - - @@ -789,7 +817,7 @@ - @@ -799,302 +827,77 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1102,7 +905,121 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1110,78 +1027,210 @@ - + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.meteor/packages b/.meteor/packages index 1a3146e..c2a08fb 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -13,17 +13,17 @@ reactive-dict@1.1.8 # ??? jquery@1.11.10 # Helpful client-side library tracker@1.1.1 # Meteor's client-side reactive programming library tomwasd:history-polyfill # Adds IE 8/9 support for HTML5 history. -email # Adds the Meteor/Email package for sending lost password emails +email@1.1.18 # Adds the Meteor/Email package for sending lost password emails standard-minifier-css@1.3.2 # CSS minifier run for production mode standard-minifier-js@1.2.1 # JS minifier run for production mode es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers. poorvavyas:es6-shim -ecmascript # Enable ECMAScript2015+ syntax in app code +ecmascript@0.6.1 # Enable ECMAScript2015+ syntax in app code #accounts-ui #accounts-base -accounts-password +accounts-password@1.3.3 useraccounts:core useraccounts:bootstrap useraccounts:flow-routing # Configures email flows. Used for AccountsTemplates class. @@ -34,18 +34,18 @@ arillo:flow-router-helpers # Provides various template helpers such as {{pathFo #tomwasd:flow-router-seo kadira:blaze-layout -shell-server # ??? +shell-server@0.2.1 # ??? meteortoys:allthings -stylus -session +stylus@2.513.8 +session@1.1.7 ##browser-policy # Adds support for specifying browser level security rules related to content and what's allowed to laod on the page. -check # Allows for checking the structure and types of arguments passed to Meteor methods and publications. +check@1.2.4 # 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 aldeed:collection2@2.10.0 -matb33:collection-hooks # Allows the collections to register handlers that run before or after database interactions. -zimme:collection-softremovable +#matb33:collection-hooks # Allows the collections to register handlers that run before or after database interactions. +#zimme:collection-softremovable #aldeed:autoform@5.8.1 #aldeed:collection2-core@2.0.0 diff --git a/.meteor/release b/.meteor/release index 61f6c67..cb1ecb2 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -METEOR@1.4.2.3 +METEOR@1.4.2.7 diff --git a/.meteor/versions b/.meteor/versions index 19a4a72..7e2cad9 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -52,7 +52,6 @@ launch-screen@1.0.12 livedata@1.0.18 localstorage@1.0.12 logging@1.1.16 -matb33:collection-hooks@0.8.4 mdg:validation-error@0.2.0 meteor@1.6.0 meteor-base@1.0.4 @@ -127,5 +126,3 @@ useraccounts:flow-routing@1.14.2 webapp@1.3.12 webapp-hashing@1.0.9 zimme:active-route@2.3.2 -zimme:collection-behaviours@1.0.4 -zimme:collection-softremovable@1.0.5 diff --git a/README.md b/README.md index 4487b35..daca794 100644 --- a/README.md +++ b/README.md @@ -8,82 +8,116 @@ These can be changed in development mode by setting environment variables. At runtime (production environment), the application should be deployed on a linux machine. Package this application by running 'npm run build' from the command line in the project base directory, or double click the npm "build" script in the development environment. -1. Install MongoDB on the linux machine. - 1. `sudo apt-get update` - 1. `sudo apt-get install -y mongodb` (installs 2.6.10 on Ubuntu LTS 16.04 - that is the minimum version of mongo required for Meteor 1.4 - you should install the latest mongo: 3.2 per the meteor install instructions) +1. Install MongoDB on the linux machine. +2. `sudo apt-get update` +3. `sudo apt-get install -y mongodb` (installs 2.6.10 on Ubuntu LTS 16.04 - that is the minimum version of mongo required for Meteor 1.4 - you should install the latest mongo: 3.2 per the meteor install instructions) - **OR** + **OR** - See [instructions](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/) for installing newer versions of MongoDB (RECOMMENDED) - 1. Get the version of the mongo command line tool: `sudo mongo --version` - 1. Get the version of the mongo server: `sudo mongod --version` - 1. Start/stop/restart the mongo service: `sudo service mongod stop/start/restart` - 1. View logs: `/var/log/mongodb/mongod.log` - 1. Edit config: `/etc/mongod.conf` (see [docs](https://docs.mongodb.com/manual/reference/configuration-options/)) - 1. Run tools: (see [descriptions](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/#packages)) - - mongod (the mongo database server) - - mongo (command line shell for interacting with a running db) - - mongoimport (imports data from: Extended JSON, CSV, or TSV formats created by mongoexport or 3rd party tools) - - bsondump (converts bson file formats [binary] into human readable formats [JSON] - use with mongodump files) - - mongodump (produces binary output for backups - not for use with shared clusters and replica sets) - - mongoexport (produces JSON or CSV data) - - mongofiles (command line gridfs integration - for manipulating files) - - mongooplog (replication & polling - ?) - - mongoperf - - mongorestore - - mongostat - - mongotop (stats) -1. Install nodejs & npm - 1. `sudo apt-get install nodejs` - 1. `sudo apt-get install npm` -1. Install n - 1. `sudo npm install -g n` -1. Update nodejs to 4.7.0 (for use with meteor 1.4 - may be another nodejs version for newer meteor versions): `n bin 4.7.0` (may need to first download 4.7.0 - see other docs on linux & nodejs) - 1. `sudo n 4.7.0` - 1. `sudo npm install -g npm` (updates npm?) -1. Install nginx on the linux machine. -1. Install samba on the linux machine. (`sudo nano /etc/samba/smb.conf` & `sudo service smbd restart`) - 1. Share the /var/www directory using the www-data user. - 1. Share the /etc/nginx directory using the root user (optional & security risk - makes configuring /etc/nginx/sites-available easier). - 1. Share the nginx logs directory /var/logs/nginx using a standard user with read only access (maybe www-data?). -1. Install passenger which will glue the nginx web server to one or more instances of nodejs/meteor running on the machine. (See passenger site for updated install instructions - these are specific to Ubuntu) - 1. `sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7` - 1. `sudo apt-get install -y apt-transport-https ca-certificates` - 1. `sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger xenial main > /etc/apt/sources.list.d/passenger.list'` - 1. `sudo apt-get update` - 1. `sudo apt-get install -y nginx-extras passenger` - 1. Configure the nginx sites-available file ("PTapp") to link nginx to passenger, and provide passenger the settings to startup meteor. Example: (replace {{xxxx}} with your own content) (NOTE: setting the mail_url fails, I used a release.properties file in the app's private directory instead, with code to use the properties file first in the server.js file in meteor.) - ``` - server { - listen 80; - listen [::]:80; - server_name app.petitteton.com; - root /var/www/PTApp/bundle/public; - # Turn on Passenger - passenger_enabled on; - # Tell Passenger that your app is a Meteor app - passenger_app_type node; - passenger_startup_file main.js; - # Tell your app where MongoDB is - passenger_env_var MONGO_URL {{your mongodb address/port/dbname. Example: mongodb://localhost:27017/PTApp}}; - # Tell your app what its root URL is - passenger_env_var ROOT_URL http://app.petitteton.com; - #passenger_env_var MAIL_URL smtp://{{your email. example: administrator%40declarativeengineering.com}}:{{smtp password here - don't use symbols like # or $ etc}}@{{your email server. Example: secure.emailsrvr.com}}; - passenger_nodejs /usr/local/n/versions/node/4.7.0/bin/node; - } - ``` - 1. Restart nginx: `sudo service nginx restart` - 1. Get status with `sudo passenger-status` - 1. Stop passenger & nginx: `sudo service nginx stop` (use start or restart or reload also) -1. Create an app folder in /var/www (example: PTApp) -1. Unpack the packaged application into this new folder (easily done via the samba share on the windows development machine by drag and dropping the contents of the archive created in step 1). - 1. Install the app with npm (navigate to /var/www/PTApp/bundle/programs/server): `npm install --production` - 1. **Restart the passenger app each time the application is updated**: `sudo passenger-config restart-app /var/www/PTApp` -1. Use RDP to connect to the GUI for the linux server -1. Install Mongo Chef (free version) to connect to the db on localhost:27017 - 1. Download the archive. - 1. Move the unpacked archive into /opt - 1. Modify the ~/.bashrc to include: `PATH=$PATH:/opt/mongochef-3.5.0-linux-x86-dist/bin` at the end (not sure if this is necessary). - 1. Run Mongo Chef from the GUI environment (how? - probably use the start menu -> Run, then pass the path like above + the executable name) + See [instructions](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/) for installing newer versions of MongoDB (RECOMMENDED) +4. Get the version of the mongo command line tool: `sudo mongo --version` +5. Get the version of the mongo server: `sudo mongod --version` +6. Start/stop/restart the mongo service: `sudo service mongod stop/start/restart` +7. View logs: `/var/log/mongodb/mongod.log` +8. Edit config: `/etc/mongod.conf` (see [docs](https://docs.mongodb.com/manual/reference/configuration-options/)) +9. Make the mongo service run all the time. (SystemCtl) + 1. Edit the Mongo Service file: `sudo nano mongod.service` See docs for options. + 2. Reload the SystemCtl daemon: `sudo systemctl daemon-reload` + 3. Start the Mongod process: `sudo systemctl start mongod` + 4. Modify the system to always start Mongod: `sudo systemctl enable mongod` +10. Run tools: (see [descriptions](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/#packages)) + - mongod (the mongo database server) + - mongo (command line shell for interacting with a running db) + - mongoimport (imports data from: Extended JSON, CSV, or TSV formats created by mongoexport or 3rd party tools) + - bsondump (converts bson file formats [binary] into human readable formats [JSON] - use with mongodump files) + - mongodump (produces binary output for backups - not for use with shared clusters and replica sets) + - mongoexport (produces JSON or CSV data) + - mongofiles (command line gridfs integration - for manipulating files) + - mongooplog (replication & polling - ?) + - mongoperf + - mongorestore + - mongostat + - mongotop (stats) +11. Install nodejs & npm + 1. `sudo apt-get install nodejs` + 2. `sudo apt-get install npm` +12. Install n + 1. `sudo npm install -g n` +13. Update nodejs to 4.7.0 (for use with meteor 1.4 - may be another nodejs version for newer meteor versions): `n bin 4.7.0` (may need to first download 4.7.0 - see other docs on linux & nodejs) + 1. `sudo n 4.7.0` + 2. `sudo npm install -g npm` (updates npm?) +14. Install nginx on the linux machine. +15. Install samba on the linux machine. (`sudo nano /etc/samba/smb.conf` & `sudo service smbd restart`) + 1. Share the /var/www directory using the www-data user. + 2. Share the /etc/nginx directory using the root user (optional & security risk - makes configuring /etc/nginx/sites-available easier). + 3. Share the nginx logs directory /var/logs/nginx using a standard user with read only access (maybe www-data?). +16. Install passenger which will glue the nginx web server to one or more instances of nodejs/meteor running on the machine. (See passenger site for updated install instructions - these are specific to Ubuntu) + 1. `sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7` + 2. `sudo apt-get install -y apt-transport-https ca-certificates` + 3. `sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger xenial main > /etc/apt/sources.list.d/passenger.list'` + 4. `sudo apt-get update` + 5. `sudo apt-get install -y nginx-extras passenger` + 6. Configure the nginx sites-available file ("PTapp") to link nginx to passenger, and provide passenger the settings to startup meteor. Example: (replace {{xxxx}} with your own content) (NOTE: setting the mail_url fails, I used a release.properties file in the app's private directory instead, with code to use the properties file first in the server.js file in meteor.) + ``` + server { + listen 80; + listen [::]:80; + server_name app.petitteton.com; + root /var/www/PTApp/bundle/public; + # Turn on Passenger + passenger_enabled on; + # Tell Passenger that your app is a Meteor app + passenger_app_type node; + passenger_startup_file main.js; + # Tell your app where MongoDB is + passenger_env_var MONGO_URL {{your mongodb address/port/dbname. Example: mongodb://localhost:27017/PTApp}}; + # Tell your app what its root URL is + passenger_env_var ROOT_URL http://app.petitteton.com; + #passenger_env_var MAIL_URL smtp://{{your email. example: administrator%40declarativeengineering.com}}:{{smtp password here - don't use symbols like # or $ etc}}@{{your email server. Example: secure.emailsrvr.com}}; + passenger_nodejs /usr/local/n/versions/node/4.7.0/bin/node; + } + ``` + 1. Restart nginx: `sudo service nginx restart` + 2. Get status with `sudo passenger-status` + 3. Stop passenger & nginx: `sudo service nginx stop` (use start or restart or reload also) +17. Create an app folder in /var/www (example: PTApp) +18. Unpack the packaged application into this new folder (easily done via the samba share on the windows development machine by drag and dropping the contents of the archive created in step 1). + 1. Install the app with npm (navigate to /var/www/PTApp/bundle/programs/server): `npm install --production` + 2. **Restart the passenger app each time the application is updated**: `sudo passenger-config restart-app /var/www/PTApp` +19. Use RDP to connect to the GUI for the linux server +20. Install Mongo Chef (free version) to connect to the db on localhost:27017 + 1. Download the archive. + 2. Move the unpacked archive into /opt + 3. Modify the ~/.bashrc to include: `PATH=$PATH:/opt/mongochef-3.5.0-linux-x86-dist/bin` at the end (not sure if this is necessary). + 4. Run Mongo Chef from the GUI environment (how? - probably use the start menu -> Run, then pass the path like above + the executable name) -NOTE: Use MongoBooster on a windows development machine to connect to the dev database (localhost:3001) and to export. \ No newline at end of file +NOTE: Use MongoBooster on a windows development machine to connect to the dev database (localhost:3001) and to export. + +#Updating a Meteor Deployment +1. Run the NPM script for building the app. This can be done either from Webstorm by viewing the NPM display (shows a list of scripts in the package.json file), or typing `npm run build` from the command line. Alternatively you can simply type the build command in the command line: `meteor build --server-only ../` to build it. The command should exit with code zero for success. +2. Find the archive file: it should be in the parent directory if you ran the above script exactly, otherwise it is where ever you specified (path at the end of the command). It should be called "PetitTetonMeteor.tar.gz" as of the writing of this documentation. +3. Copy the archive to the server. Use what ever tools you want for this, samba and drag and drop works great. Otherwise sftp, or other method also works. +4. Navigate to /var/www/PTApp (or what ever the folder is). +5. Use `sudo tar -xvzf PetitTetonMeteor.tar.gz` to unpack it. +6. Delete the archive (optional): `sudo rm PetitTetonMeteor.tar.gz` +7. Modify the owner of the app: `sudo chown -R www-data bundle` Run this from inside the project directory /var/www/PTApp. +8. Modify the permissions of the app: `sudo chmod -R 777 bundle` Run this from inside the project directory /var/www/PTApp. +9. Optional: Run NPM's install to update the dependancies (if they changed): `cd /var/www/PTApp/bundle/programs/server && npm install && cd /var/www/PTApp` +10. Restart the meteor app: `sudo passenger-config restart-app /var/www/PTApp` + +# Updating a Meteor Deployment #2 + +1. Run the NPM script for building the app `npm run build` which will package the app for the selected platform (in the package.json definition for the build script). Can double click the build script in WebStorm's UI for NPM alternatively. Can also manually run the script: `npm install --product && meteor build --architecture os.linux.x86_64 --server-only ../`. This will generate an archive file for the project that is production ready. +2. Copy the archive to the deployment server. Can use Samba for this. I place it in the web folder for the app. +3. Run the deploy.sh script `sudo ./deploy.sh` which exists in the web directory for the app: `/var/www/PTApp`. This will unpack the archive, remove the archive, change file permissions, run NPM's install on the app, and restart the app in Phusion Passenger. +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). + + + +#Running Server Side Code +This is useful for importing data or running scripts that might perform some one time task. +1. Open a console and enter the server shell for meteor. + +#Server Error Handling +Errors are generated in meteor, but handled by passenger. Passenger will log the error on the client screen with a code, and will log the same message in the nginx error logs. The error will be findable in the tmp folder as an html file starting with passenger and ending with the code. This is the place to look for the real error output. \ No newline at end of file diff --git a/client/client.js b/client/client.js index d240237..9295e8e 100644 --- a/client/client.js +++ b/client/client.js @@ -6,6 +6,7 @@ import '/imports/ui/helpers.js'; // import '/imports/util/normalize.css'; import '/imports/util/validator.js'; import '/imports/util/polyfills/blaze.js'; +import '/imports/util/polyfills/regex.js'; import '/imports/util/polyfills/date.js'; import '/imports/util/polyfills/array.js'; import '/imports/util/de.combo.js'; @@ -16,7 +17,10 @@ import '/imports/ui/layouts/Full.js'; import '/imports/ui/accounts/accounts.js'; import '/imports/util/select2/select2.css'; import '/imports/util/select2/select2.full.js'; +//The SweetAlert2 NPM package is where this is being pulled from. The js file that actually wants to use it should import it (see Sales.js). +import 'sweetalert2/dist/sweetalert2.min.css'; import '/imports/util/simplegrid.css'; +import 'dragula/dist/dragula.css'; Blaze._allowJavascriptUrls(); diff --git a/client/main.styl b/client/main.styl index ae15df1..7222f10 100644 --- a/client/main.styl +++ b/client/main.styl @@ -17,32 +17,14 @@ html scrollbar-arrow-color: #ffffff scrollbar-track-color: #505050 height: 100% - -html, body, #archives ul, #overall-footer, #content ul - margin: 0 0 0 0 - padding: 0 0 0 0 - + min-height: 100% body font-family: verdana, arial, helvetica, sans-serif font-size: 12px height: 100% - + min-height: 100% #__blaze-root - //max-width: 950px //Use if the width should be limited. - //min-width: 250px - //margin: 0 auto //Use if the width should be limited. - //min-height: 100% //Used with a full height layout. - - //Flex container. - //display: flex - //flex-direction: row - //flex-wrap: nowrap - //align-items: stretch - //align-content: stretch - height: 100%; - //width: 100%; - //min-height: 100%; - //min-width: 100%; + height: 100% //Standard Stylings .noselect @@ -69,7 +51,6 @@ body //Table Styles .table - border: 0 padding: 0 margin: 0 border-collapse: collapse @@ -108,123 +89,6 @@ body .table-hover > tbody > tr:hover background-color: #ded -//Form Styles -.select2-container - font-size: 10px -.select2-selection - font-size: 13px //Make the font small enough the control can have a height similar to a standard input field. - margin-bottom: 0px - min-height: 10px !important //This is what really sets the height of the box containing the selection(s) - padding-bottom: 2px //Add a little space below the selections to balance it all out. -input - padding: 6px - border-radius: 4px - border-width: 1px - border-style: solid - border-color: #ccc -//input[type='button'].btn-success, input[type='submit'].btn-success -// background-color: #5cb85c -// :hover -// background-color: -//input[type='button'].btn-danger, input[type='submit'].btn-danger -// background-color: #e55b46 -.form-control, .select2-selection //? - font-size: 14px - margin-bottom: 0px -.form-group - margin: 4px 0 -.has-error .form-control - border-color: #a94442 - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) - -@media screen and (-webkit-min-device-pixel-ratio: 0) - input[type="date"].form-control, input[type="time"].form-control, input[type="datetime-local"].form-control, input[type="month"].form-control - line-height: 34px - -.form-control - display: block - width: 100% - height: 34px - padding: 6px 12px - font-size: 14px - line-height: 1.42857143 - color: #555 - background-color: #fff - background-image: none - border: 1px solid #ccc - border-radius: 4px - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075) - -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s -input[type="date" i], input[type="datetime-local" i], input[type="month" i], input[type="time" i], input[type="week" i] - align-items: center - -webkit-padding-start: 1px - overflow: hidden - padding-left: 10px -input - -webkit-appearance: textfield - background-color: white - -webkit-rtl-ordering: logical - user-select: text - cursor: auto - padding: 1px - border-width: 2px - border-style: inset - border-color: initial - border-image: initial -.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control - background-color: #eee - opacity: 1 -input, textarea, keygen, select, button - text-rendering: auto - color: initial - letter-spacing: normal - word-spacing: normal - text-transform: none - text-indent: 0px - text-shadow: none - display: inline-block - text-align: start - margin: 0em 0em 0em 0em - font: 13.3333px Arial -input, textarea, keygen, select, button, meter, progress - -webkit-writing-mode: horizontal-tb -//.btn.disabled, .btn[disabled], fieldset[disabled] .btn -// cursor: not-allowed -// filter: unquote("alpha(opacity=65)") -// -webkit-box-shadow: none -// box-shadow: none -// opacity: .65 -//button, html input[type="button"], input[type="reset"], input[type="submit"] -// -webkit-appearance: button -// cursor: pointer -//button, html input[type="button"], input[type="reset"], input[type="submit"] -// -webkit-appearance: button -// cursor: pointer -//.btn -// display: inline-block; -// padding: 6px 12px; -// margin-bottom: 0; -// font-size: 14px; -// font-weight: normal; -// line-height: 1.42857143; -// text-align: center; -// white-space: nowrap; -// vertical-align: middle; -// -ms-touch-action: manipulation; -// touch-action: manipulation; -// cursor: pointer; -// -webkit-user-select: none; -// -moz-user-select: none; -// -ms-user-select: none; -// user-select: none; -// background-image: none; -// border: 1px solid transparent; -// border-radius: 4px; - .pagination text-align: right font-size: 15px @@ -232,7 +96,8 @@ input, textarea, keygen, select, button, meter, progress font-family: "Arial Black", "Arial Bold", Gadget, sans-serif margin: 0 0 10px 0 overflow: visible - whitespace: nowrap + white-space: nowrap + display: inline-block span padding: 2px 8px 3px 8px margin: 0 8px @@ -288,6 +153,12 @@ input, textarea, keygen, select, button, meter, progress overflow: visible !important max-width: none !important +@import "../imports/ui/styles/effects.import.styl" +@import "../imports/ui/styles/buttons.import.styl" +@import "../imports/ui/styles/maxHeightLayout.import.styl" +@import "../imports/ui/styles/tabs.import.styl" +@import "../imports/ui/styles/forms.import.styl" + //@import "../imports/util/selectize/selectize.default.import.styl" //@import "../imports/util/selectize/selectize.import.styl" @import "../imports/util/de.combo.import.styl" @@ -302,6 +173,9 @@ input, textarea, keygen, select, button, meter, progress @import "../imports/ui/Products.import.styl" @import "../imports/ui/ProductTags.import.styl" @import "../imports/ui/Sales.import.styl" +@import "../imports/ui/SalesSheets.import.styl" +@import "../imports/ui/SalesSheetForm.import.styl" +@import "../imports/ui/SalesSheetEditor.import.styl" @import "../imports/ui/Pricing.import.styl" @import "../imports/ui/Production.import.styl" @import "../imports/ui/Graphs.import.styl" \ No newline at end of file diff --git a/imports/api/Sale.js b/imports/api/Sale.js index 64cd3f2..8da59ca 100644 --- a/imports/api/Sale.js +++ b/imports/api/Sale.js @@ -53,6 +53,11 @@ let SalesSchema = new SimpleSchema({ // } // } }, + comment: { + type: String, + trim: false, + optional: true + }, createdAt: { type: Date, label: "Created On", @@ -62,7 +67,7 @@ let SalesSchema = new SimpleSchema({ Sales.attachSchema(SalesSchema); if(Meteor.isServer) { - Meteor.publish('sales', function(query, limit = 100, skipCount) { + Meteor.publish('sales', function(query, sort, limit = 100, skipCount) { let dbQuery = []; if(query) { @@ -90,7 +95,7 @@ if(Meteor.isServer) { if(!_.isNumber(skipCount) || skipCount < 0) skipCount = 0; dbQuery = dbQuery.length > 0 ? {$and: dbQuery} : {}; - return Meteor.collections.Sales.find(dbQuery, {limit: limit, sort: {date: -1, createdAt: -1}, skip: skipCount}); + return Meteor.collections.Sales.find(dbQuery, {limit: limit, sort, skip: skipCount}); }); // time: expects either undefined, 'weekly', or 'monthly' // options: expects either undefined, 'markets', or 'types' @@ -179,6 +184,21 @@ if(Meteor.isServer) { return Sales.find(query).count(); }, insertSale: function(sale) { + check(sale, { + date: Date, + amount: Match.Where(function(x) { + check(x, Number); + return x > 0; + }), + price: Match.Where(function(x) { + check(x, Number); + return x > 0; + }), + measureId: String, + productId: String, + venueId: String, + comment: Match.Optional(String) + }); //TODO: Check the structure of sale. Use: check(sale, {name: String, ...}); sale.createdAt = new Date(); @@ -193,9 +213,45 @@ if(Meteor.isServer) { check(id, String); if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { - Sales.remove(id, {bypassCollection2: true}); + Sales.remove(id); } else throw new Meteor.Error(403, "Not authorized."); + }, + editSaleComment: 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) { + Sales.update(id, {$set: {comment}}, function(error, count) { + if(error) throw new Meteor.Error(400, "Unexpected database error: " + error); + }); + } + else { + Sales.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."); + }, + updateSale: function(id, date, venueId, price, amount) { + check(id, String); + check(date, Date); + check(venueId, String); + check(price, Number); + check(amount, Number); + + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + Sales.update(id, {$set: {date, venueId, price, amount}}, function(err, id) { + if(err) console.log(err); + }, {bypassCollection2: true}); + } } }); } diff --git a/imports/api/SalesSheet.js b/imports/api/SalesSheet.js new file mode 100644 index 0000000..0891492 --- /dev/null +++ b/imports/api/SalesSheet.js @@ -0,0 +1,160 @@ +import { Meteor } from 'meteor/meteor'; +import { Mongo } from 'meteor/mongo'; +import { check } from 'meteor/check'; +import {SimpleSchema} from 'meteor/aldeed:simple-schema'; + +SalesSheets = new Mongo.Collection('SalesSheets'); + +const SalesSheetSchema = new SimpleSchema({ + name: { + type: String, + label: "Name", + optional: false, + trim: true, + index: 1, + unique: false + }, + products: { //An ordered array of product id's included on the sheet. + type: Array, + label: "products", + optional: false, + defaultValue: [] + }, + 'products.$': { + type: new SimpleSchema({ + name: { + type: String, + label: "Name", + optional: false, + trim: true, + unique: false + }, + productId: { //Note: Will be non-existent for headings. + type: String, + label: "Product ID", + trim: false, + regEx: SimpleSchema.RegEx.Id, + optional: true + }, + measureIds: { //Note: Will be non-existent for headings. + type: [String], + label: "Measure IDs", + optional: true + } + //measureIds: { + // type: Array, + // label: "Measure IDs", + // optional: true + //}, + //'measureIds.$': { + // type: String, + // label: "Measure ID", + // trim: false, + // regEx: SimpleSchema.RegEx.Id, + // optional: false + //} + }) + }, + createdAt: { + type: Date, + label: "Created On", + optional: false + }, + updatedAt: { + type: Date, + label: "Updated On", + optional: true + } +}); +SalesSheets.attachSchema(SalesSheetSchema); + +if(Meteor.isServer) { + Meteor.publish('salesSheets', function() { + return SalesSheets.find({}); + }); + + Meteor.methods({ + createSalesSheet: function(name) { + check(name, String); + + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + return SalesSheets.insert({name, products: [], createdAt: new Date()}); + } + else throw new Meteor.Error(403, "Not authorized."); + }, + // This gets ridiculous. What would be required, along with a ton of code to micro manage each change. + //updateSalesSheet_addProduct: function(id, productId, productName, productMeasures) { + // + //}, + //updateSalesSheet_removeProduct: function(id, productId) { + // + //}, + //updateSalesSheet_updateProduct: function(id, productId, productName) { + // + //}, + //updateSalesSheet_updateProduct_addMeasure: function(id, productId, productName, productMeasures) { + // + //}, + //updateSalesSheet_updateProduct_removeMeasure: function(id, productId, productName, productMeasures) { + // + //}, + updateSalesSheet: function(id, name, products) { + check(id, String); + check(name, String); + check(products, [{ + productId: Match.Maybe(String), + name: String, + measureIds: Match.Maybe([String]) + }]); + + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + try { + // Generates some queries for testing. + //console.log("db.SalesSheet.update({_id: " + id + "}, {{name: " + name + ", products: " + products + ", updatedAt: " + new Date() + "}})"); + //let productList = ""; + //let firstProduct = true; + //for(next of products) { + // if(firstProduct) firstProduct = false; + // else productList += ','; + // productList += '{id:"' + next.id + '",name:"' + next.name + '",measureIds:['; + // let firstMeasure = true; + // for(measureId of next.measureIds) { + // if(firstMeasure) firstMeasure = false; + // else productList += ','; + // productList += '"' + measureId + '"'; + // } + // productList += ']}'; + //} + //console.log("db.SalesSheet.update({_id: '" + id + "'}, {$set: {name: '" + name + "', updatedAt: " + new Date() + "}, $pull: {$exists: true}, $pushAll: [" + productList + "]})"); + + // Forces the object to be re-written, versus piecemeal updated. + SalesSheets.update({_id: id}, {$set: {name: name, products: products, updatedAt: new Date()}}, {validate: false}, function(err, count) { + if(err) console.log(err); + }); + + // Attempts to remove all products and re-add them. Note: Does not work! + //SalesSheet.update({_id: id}, {$set: {name: name, updatedAt: new Date()}, $pull: {products: {$exists: true}}}, {bypassCollection2: true}, function(err, count) { + // if(err) console.log(err); + //}); + //SalesSheet.update({_id: id}, {$push: {products: {$each: [products]}}}, {bypassCollection2: true}, function(err, count) { + // if(err) console.log(err); + //}); + } + catch(err) { + console.log(err); + } + } + else throw new Meteor.Error(403, "Not authorized."); + }, + removeSalesSheet: function(id) { + check(id, String); + + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + SalesSheets.remove(id); + } + else throw new Meteor.Error(403, "Not authorized."); + } + }); +} + +export default SalesSheets; \ No newline at end of file diff --git a/imports/api/Venue.js b/imports/api/Venue.js index d576f54..9e83c80 100644 --- a/imports/api/Venue.js +++ b/imports/api/Venue.js @@ -46,16 +46,16 @@ if(Meteor.isServer) Meteor.publish('venues', function() { return Venues.find({}); }); -// //Requires: meteor add matb33:collection-hooks if(Meteor.isServer) { - Venues.before.insert(function(userId, doc) { - // check(userId, String); - doc.createdAt = new Date(); - }); - Venues.before.update(function(userId, doc, fieldNames, modifier, options) { - modifier.$set = modifier.$set || {}; //Make sure there is an object. - modifier.$set.updatedAt = new Date(); - }); +// //Requires: meteor add matb33:collection-hooks + //Venues.before.insert(function(userId, doc) { + // // check(userId, String); + // doc.createdAt = new Date(); + //}); + //Venues.before.update(function(userId, doc, fieldNames, modifier, options) { + // modifier.$set = modifier.$set || {}; //Make sure there is an object. + // modifier.$set.updatedAt = new Date(); + //}); Meteor.methods({ createVenue: function(name, type) { diff --git a/imports/api/index.js b/imports/api/index.js index b5a97d4..ac79af3 100644 --- a/imports/api/index.js +++ b/imports/api/index.js @@ -1,14 +1,16 @@ -//import Categories from "./Category.js"; -//import Subcategories from "./Subcategory.js"; import Measures from "./Measure.js"; import Venues from "./Venue.js"; import Products from "./Product.js"; import ProductTags from "./ProductTag.js"; import Sales from "./Sale.js"; +import SalesSheets from "./SalesSheet.js"; import Users from "./User.js"; import UserRoles from "./Roles.js"; -Meteor.collections = {Measures, Venues, Products, ProductTags, Sales, Users, UserRoles}; +//Save the collections in the Meteor.collections property for easy access without name conflicts. +Meteor.collections = {Measures, Venues, Products, ProductTags, Sales, SalesSheets, Users, UserRoles}; + +//If this is the server then setup the default admin user if none exist. if(Meteor.isServer) { //Change this to find admin users, create a default admin user if none exists. if(Users.find({}).count() == 0) { diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js index 18e7028..a4faffa 100644 --- a/imports/startup/client/routes.js +++ b/imports/startup/client/routes.js @@ -40,9 +40,18 @@ pri.route('/sales', { name: 'Sales', action: function(params, queryParams) { require("/imports/ui/Sales.js"); + BlazeLayout.render('Body', {content: 'Sales'}); } }); +pri.route('/salesSheets', { + name: 'SalesSheets', + action: function(params, queryParams) { + require("/imports/ui/SalesSheets.js"); + + BlazeLayout.render('Body', {content: 'SalesSheets'}); + } +}); pri.route('/production', { name: 'Production', action: function(params, queryParams) { diff --git a/imports/ui/Products.js b/imports/ui/Products.js index da3c38e..6424111 100644 --- a/imports/ui/Products.js +++ b/imports/ui/Products.js @@ -267,6 +267,5 @@ Template.ProductEditor.events({ } }); } - } }); \ No newline at end of file diff --git a/imports/ui/Sales.html b/imports/ui/Sales.html index e5eb631..023c09e 100644 --- a/imports/ui/Sales.html +++ b/imports/ui/Sales.html @@ -1,43 +1,47 @@ + + @@ -61,33 +88,37 @@