diff --git a/.meteor/packages b/.meteor/packages index bea91c2..34df9ad 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -4,27 +4,27 @@ # 'meteor add' and 'meteor remove' will edit this file for you, # but you can also edit it by hand. -meteor-base@1.1.0 # Packages every Meteor app needs to have +meteor-base@1.2.0 # Packages every Meteor app needs to have mobile-experience@1.0.5 # Packages for a great mobile UX -mongo@1.2.2 # The database Meteor supports right now +mongo@1.3.1 # 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.1.9 # ??? +reactive-dict@1.2.0 # ??? tracker@1.1.3 # 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.1.2 # JS 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. poorvavyas:es6-shim -ecmascript@0.8.3 # Enable ECMAScript2015+ syntax in app code +ecmascript@0.9.0 # Enable ECMAScript2015+ syntax in app code #accounts-ui #accounts-base -accounts-password@1.4.0 +accounts-password@1.5.0 useraccounts:core -useraccounts:bootstrap +useraccounts:unstyled useraccounts:flow-routing # Configures email flows. Used for AccountsTemplates class. alanning:roles # Adds roles to the user mix. https://atmospherejs.com/alanning/roles && https://github.com/alanning/meteor-roles/blob/master/examples/flow-router/ @@ -33,9 +33,9 @@ arillo:flow-router-helpers # Provides various template helpers such as {{pathFo #tomwasd:flow-router-seo kadira:blaze-layout -shell-server@0.2.4 # ??? +shell-server@0.3.0 # ??? meteortoys:allthings -stylus@2.513.9 +stylus@2.513.13 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@1.2.5 # Allows for checking the structure and types of arguments passed to Meteor methods and publications. @@ -61,6 +61,6 @@ 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.1.3 +dynamic-import@0.2.0 markdown@1.0.12 wcrisman:jquery-custom-scrollbar diff --git a/.meteor/release b/.meteor/release index 099d5b9..56a7a07 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -METEOR@1.5.2.2 +METEOR@1.6.0.1 diff --git a/.meteor/versions b/.meteor/versions index 979e17b..aaee1f4 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -1,5 +1,5 @@ -accounts-base@1.3.4 -accounts-password@1.4.0 +accounts-base@1.4.0 +accounts-password@1.5.0 alanning:roles@1.2.16 aldeed:collection2@2.10.0 aldeed:collection2-core@1.2.0 @@ -7,35 +7,35 @@ aldeed:schema-deny@1.1.0 aldeed:schema-index@1.1.1 aldeed:simple-schema@1.5.3 aldeed:template-extension@4.1.0 -allow-deny@1.0.9 +allow-deny@1.1.0 arillo:flow-router-helpers@0.5.2 autoupdate@1.3.12 -babel-compiler@6.20.0 -babel-runtime@1.0.1 +babel-compiler@6.24.7 +babel-runtime@1.1.1 base64@1.0.10 binary-heap@1.0.10 blaze@2.3.2 blaze-html-templates@1.1.2 blaze-tools@1.0.10 -boilerplate-generator@1.2.0 +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 coffeescript@1.0.17 -ddp@1.3.1 -ddp-client@2.1.3 -ddp-common@1.2.9 +ddp@1.4.0 +ddp-client@2.2.0 +ddp-common@1.3.0 ddp-rate-limiter@1.0.7 -ddp-server@2.0.2 +ddp-server@2.1.1 deps@1.0.12 diff-sequence@1.0.7 -dynamic-import@0.1.3 -ecmascript@0.8.3 -ecmascript-runtime@0.4.1 -ecmascript-runtime-client@0.4.3 -ecmascript-runtime-server@0.4.1 -ejson@1.0.14 +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 +ejson@1.1.0 email@1.2.3 es5-shim@4.6.15 fortawesome:fontawesome@4.7.0 @@ -43,7 +43,7 @@ geojson-utils@1.0.10 hot-code-push@1.0.4 html-tools@1.0.11 htmljs@1.0.11 -http@1.2.12 +http@1.3.0 id-map@1.0.9 jcbernack:reactive-aggregate@0.7.0 jquery@1.11.10 @@ -52,12 +52,12 @@ kadira:blaze-layout@2.3.0 kadira:flow-router@2.12.1 launch-screen@1.1.1 livedata@1.0.18 -localstorage@1.1.1 -logging@1.1.17 +localstorage@1.2.0 +logging@1.1.19 markdown@1.0.12 mdg:validation-error@0.2.0 -meteor@1.7.2 -meteor-base@1.1.0 +meteor@1.8.2 +meteor-base@1.2.0 meteorhacks:aggregate@1.3.0 meteorhacks:collection-utils@1.2.0 meteortoys:allthings@4.0.0 @@ -78,32 +78,32 @@ meteortoys:throttle@4.0.0 meteortoys:toggle@4.0.0 meteortoys:toykit@4.0.1 minifier-css@1.2.16 -minifier-js@2.1.4 -minimongo@1.3.2 +minifier-js@2.2.2 +minimongo@1.4.3 mizzao:bootboxjs@4.4.0 mobile-experience@1.0.5 mobile-status-bar@1.0.14 -modules@0.10.0 -modules-runtime@0.8.0 -momentjs:moment@2.18.1 -mongo@1.2.2 -mongo-dev-server@1.0.1 +modules@0.11.1 +modules-runtime@0.9.1 +momentjs:moment@2.20.0 +mongo@1.3.1 +mongo-dev-server@1.1.0 mongo-id@1.0.6 mongo-livedata@1.0.12 msavin:jetsetter@4.0.0 msavin:mongol@4.0.1 npm-bcrypt@0.9.3 -npm-mongo@2.2.30 +npm-mongo@2.2.33 observe-sequence@1.0.16 ordered-dict@1.0.9 -ostrio:logger@2.0.3 -ostrio:loggermongo@2.0.1 +ostrio:logger@2.0.5 +ostrio:loggermongo@2.0.3 poorvavyas:es6-shim@0.21.1 -promise@0.9.0 +promise@0.10.0 raix:eventemitter@0.1.3 random@1.0.10 rate-limit@1.0.8 -reactive-dict@1.1.9 +reactive-dict@1.2.0 reactive-var@1.0.11 reload@1.1.11 retry@1.0.9 @@ -111,14 +111,14 @@ routepolicy@1.0.12 service-configuration@1.0.11 session@1.1.7 sha@1.0.9 -shell-server@0.2.4 +shell-server@0.3.1 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.1.2 -stylus@2.513.9 +standard-minifier-js@2.2.3 +stylus@2.513.13 templating@1.3.2 templating-compiler@1.3.3 templating-runtime@1.3.2 @@ -128,10 +128,10 @@ tracker@1.1.3 ui@1.0.13 underscore@1.0.10 url@1.1.0 -useraccounts:bootstrap@1.14.2 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.3.19 +webapp@1.4.0 webapp-hashing@1.0.9 zimme:active-route@2.3.2 diff --git a/client/client.js b/client/client.js index 8e33b86..b6c437b 100644 --- a/client/client.js +++ b/client/client.js @@ -13,7 +13,7 @@ import '/imports/util/de.combo.js'; import '/imports/util/resize/ResizeSensor.js'; import '/imports/util/resize/ElementQueries.js'; import '/imports/ui/layouts/Body.js'; -import '/imports/ui/layouts/Full.js'; +import '/imports/ui/layouts/Login.js'; import '/imports/ui/accounts/accounts.js'; import '/imports/util/select2/select2.css'; import '/imports/util/select2/select2.full.js'; diff --git a/client/main.styl b/client/main.styl index 001c556..d99e29a 100644 --- a/client/main.styl +++ b/client/main.styl @@ -169,7 +169,7 @@ body @import "../imports/util/bootstrap-like-btn.import.styl" @import "../imports/ui/layouts/Body.import.styl" -@import "../imports/ui/layouts/Full.import.styl" +@import "../imports/ui/layouts/Login.import.styl" @import "../imports/ui/UserManagement.import.styl" @import "../imports/ui/MiscManagement.import.styl" @@ -184,5 +184,6 @@ body @import "../imports/ui/SalesSheetEditor.import.styl" @import "../imports/ui/Pricing.import.styl" @import "../imports/ui/Production.import.styl" +@import "../imports/ui/Workers.import.styl" @import "../imports/ui/Graphs.import.styl" @import "../imports/ui/TestList.import.styl" \ No newline at end of file diff --git a/imports/api/Measure.js b/imports/api/Measure.js index 9ec89a2..847f104 100644 --- a/imports/api/Measure.js +++ b/imports/api/Measure.js @@ -113,7 +113,7 @@ if(Meteor.isServer) { check(order, Number); if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { - Products.update(id, {$set: {name, postfix, order, updatedAt: new Date()}}); + Measures.update(id, {$set: {name, postfix, order, updatedAt: new Date()}}); } else throw new Meteor.Error(403, "Not authorized."); } diff --git a/imports/api/Venue.js b/imports/api/Venue.js index 9e83c80..49557ff 100644 --- a/imports/api/Venue.js +++ b/imports/api/Venue.js @@ -3,6 +3,9 @@ import { Mongo } from 'meteor/mongo'; import { check } from 'meteor/check'; import {SimpleSchema} from 'meteor/aldeed:simple-schema'; +const TYPES = ['Retail', "Farmer's Market", "Restaurant", "Mail"]; +const FREQUENCIES = ['Daily', 'Weekly']; + Venues = new Mongo.Collection('Venues'); let VenuesSchema = new SimpleSchema({ name: { @@ -17,7 +20,15 @@ let VenuesSchema = new SimpleSchema({ type: String, label: "Type", optional: false, - trim: true + trim: true, + allowedValues: TYPES //If you change these values, also change Venues.js for the editor to include the new list when setting up the combo. + }, + frequency: { // How often the market is run. The exact day or week is not important, just that it is daily, weekly, bi-weekly, monthly, etc... Currently only supporting Daily and Weekly since all markets fit into these categories. + type: String, + label: "Frequency", + optional: false, + defaultValue: 'Daily', + allowedValues: FREQUENCIES //If you change these values, also change Venues.js for the editor to include the new list when setting up the combo. }, createdAt: { type: Date, @@ -40,6 +51,7 @@ let VenuesSchema = new SimpleSchema({ optional: true } }); +VenuesSchema.constants = {types: TYPES, frequencies: FREQUENCIES}; Venues.attachSchema(VenuesSchema); if(Meteor.isServer) Meteor.publish('venues', function() { @@ -58,12 +70,30 @@ if(Meteor.isServer) { //}); Meteor.methods({ - createVenue: function(name, type) { + createVenue: function(name, type, frequency) { check(name, String); check(type, String); + check(frequency, String); if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { - Venues.insert({name, type, createdAt: new Date()}); + Venues.insert({name, type, frequency, createdAt: new Date()}); + } + else throw new Meteor.Error(403, "Not authorized."); + }, + //deleteVenue: function(id) { + // if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + // Venues.remove(id); //TODO: If this is ever allowed, we should either remove or replace references to the deleted venue in the rest of the database. + // } + // else throw new Meteor.Error(403, "Not authorized."); + //}, + updateVenue: function(id, name, type, frequency) { + check(id, String); + check(name, String); + check(type, String); + check(frequency, String); + + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + Venues.update(id, {$set: {name, type, frequency, updatedAt: new Date()}}); } else throw new Meteor.Error(403, "Not authorized."); }, @@ -92,22 +122,6 @@ if(Meteor.isServer) { Venues.update(id, {$set: {hidden: false}}, {bypassCollection2: true}); } else throw new Meteor.Error(403, "Not authorized."); - }, - //deleteVenue: function(id) { - // if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { - // Venues.remove(id); //TODO: If this is ever allowed, we should either remove or replace references to the deleted venue in the rest of the database. - // } - // else throw new Meteor.Error(403, "Not authorized."); - //}, - updateVenue: function(id, name, type) { - check(id, String); - check(name, String); - check(type, String); - - if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { - Venues.update(id, {$set: {name, type, updatedAt: new Date()}}); - } - else throw new Meteor.Error(403, "Not authorized."); } }); } diff --git a/imports/api/Worker.js b/imports/api/Worker.js new file mode 100644 index 0000000..7660999 --- /dev/null +++ b/imports/api/Worker.js @@ -0,0 +1,125 @@ +import { Meteor } from 'meteor/meteor'; +import { Mongo } from 'meteor/mongo'; +import { check } from 'meteor/check'; +import {SimpleSchema} from 'meteor/aldeed:simple-schema'; + +Workers = new Mongo.Collection('Workers'); +let WORKER_ACTIVITIES = ['sales', 'prep', 'canning', 'farming']; +let workersSchema = new SimpleSchema({ + name: { + type: String, + label: "Name", + optional: false, + trim: true, + index: 1, + unique: true + }, + activities: { + type: [String], + label: "Activities", + optional: false, + trim: true + }, + hourlyRate: { + type: SimpleSchema.Integer, + label: "HourlyRate", + optional: false, + min: 0 + }, + createdAt: { //Force the value to the current date on the server. + type: Date, + label: "Created On", + // autoValue: function() { //The disadvantage of autoValue is that it sets the date after insertion, causing the UI to update twice - once where the item has no date, and then again where the date is set. Sorted lists will cause the item to bounce around. + // if(this.isInsert) return new Date(); + // else if(this.isUpsert) return {$setOnInsert: new Date()}; + // else this.unset(); + // }, + // denyUpdate: true, + optional: false + }, + updatedAt: { + type: Date, + label: "Updated On", + // autoValue: function() { + // if(this.isUpdate) return new Date(); + // }, + // denyInsert: true, + optional: true + }, + deactivated: { + type: Boolean, + label: "Deactivated", + optional: true + }, + hidden: { + type: Boolean, + label: "Hidden", + optional: true + } +}); +workersSchema.constants = {activities: WORKER_ACTIVITIES}; +Workers.attachSchema(workersSchema); + +if(Meteor.isServer) Meteor.publish('Workers', function() { + return Workers.find({}); +}); + +if(Meteor.isServer) { + Meteor.methods({ + createWorker: function(name, activities, hourlyRate) { + check(name, String); + check(activities, [String]); + check(hourlyRate, Number); + + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + Workers.insert({name, activities, hourlyRate, createdAt: new Date()}); + } + else throw new Meteor.Error(403, "Not authorized."); + }, + //deleteWorker: function(id) { + // if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + // //TODO: Should troll the database looking for references to remove or replace. This is currently not used. + // Workers.remove(id); + // } + // else throw new Meteor.Error(403, "Not authorized."); + //}, + updateWorker: function(id, name, activities, hourlyRate) { + check(id, String); + check(name, String); + check(activities, [String]); + check(hourlyRate, Number); + + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + Workers.update(id, {$set: {name, activities, hourlyRate, updatedAt: new Date()}}); + } + else throw new Meteor.Error(403, "Not authorized."); + }, + deactivateWorker: function(id) { + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + //Workers.remove(id); + Workers.update(id, {$set: {deactivated: true}}, {bypassCollection2: true}); + } + else throw new Meteor.Error(403, "Not authorized."); + }, + reactivateWorker: function(id) { + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + Workers.update(id, {$set: {deactivated: false}}, {bypassCollection2: true}); + } + else throw new Meteor.Error(403, "Not authorized."); + }, + hideWorker: function(id) { //One step past deactivated - will only show in the Workers list if hidden Workers are enabled. + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + Workers.update(id, {$set: {hidden: true}}, {bypassCollection2: true}); + } + else throw new Meteor.Error(403, "Not authorized."); + }, + showWorker: function(id) { //Returns the measure to being simply deactivated. Will again show in lists. + if(Roles.userIsInRole(this.userId, [Meteor.UserRoles.ROLE_UPDATE])) { + Workers.update(id, {$set: {hidden: false}}, {bypassCollection2: true}); + } + else throw new Meteor.Error(403, "Not authorized."); + } + }); +} + +export default Workers; \ No newline at end of file diff --git a/imports/api/index.js b/imports/api/index.js index 0821f1e..c46b4ea 100644 --- a/imports/api/index.js +++ b/imports/api/index.js @@ -7,9 +7,10 @@ import SalesSheets from "./SalesSheet.js"; import Logs from "./Logs.js"; import Users from "./User.js"; import UserRoles from "./Roles.js"; +import Workers from "./Worker.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}; +Meteor.collections = {Measures, Venues, Products, ProductTags, Sales, SalesSheets, Logs, Users, UserRoles, Workers}; //If this is the server then setup the default admin user if none exist. if(Meteor.isServer) { diff --git a/imports/startup/both/accounts.js b/imports/startup/both/accounts.js index 991b959..110eb42 100644 --- a/imports/startup/both/accounts.js +++ b/imports/startup/both/accounts.js @@ -1,16 +1,24 @@ import { AccountsTemplates } from 'meteor/useraccounts:core'; AccountsTemplates.configure({ - forbidClientAccountCreation: true, + forbidClientAccountCreation: true, //Turn off client side account creation. The app is expected to have a feature that will do this. showForgotPasswordLink: true, - defaultTemplate: 'atForm', - defaultLayout: 'Full', - defaultContentRegion: 'content', - defaultLayoutRegions: {} - // defaultTemplate: 'Auth_page', + defaultTemplate: 'OverrideAtForm', + //defaultTemplate: 'AuthorizationPage', //The template for all the forms related to logging in or out. + defaultLayout: 'Login', //What page template to place the defaultTemplate in. + defaultContentRegion: 'content', //The content region of the page template to place the defaultTemplate in. + defaultLayoutRegions: {}, // defaultLayout: 'Body', // defaultContentRegion: 'content', // defaultLayoutRegions: {} + texts: { + title: { + signIn: "" + }, + button: { + signIn: "Enter" + } + } }); // This removes the password field but returns it, @@ -29,6 +37,7 @@ AccountsTemplates.configure({ // pwd // ]); let pwd = AccountsTemplates.removeField('password'); + AccountsTemplates.removeField('email'); AccountsTemplates.addFields([ { @@ -46,6 +55,13 @@ AccountsTemplates.addFields([ re: /.+@(.+){2,}\.(.+){2,}/, errStr: 'Invalid email', }, + { + _id: 'username_and_email', + type: 'text', + required: true, + displayName: "Login", + placeholder: "Login / Email" + }, pwd ]); diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js index 28eefcf..929abff 100644 --- a/imports/startup/client/routes.js +++ b/imports/startup/client/routes.js @@ -88,6 +88,13 @@ pri.route('/venues', { BlazeLayout.render('Body', {content: 'Venues'}); } }); +pri.route('/workers', { + name: 'Workers', + action: function(params, queryParams) { + require("/imports/ui/Workers.js"); + BlazeLayout.render('Body', {content: 'Workers'}); + } +}); pri.route('/graphs', { name: 'Graphs', action: function(params, queryParams) { diff --git a/imports/ui/Measures.html b/imports/ui/Measures.html index 28d4ec1..125836c 100644 --- a/imports/ui/Measures.html +++ b/imports/ui/Measures.html @@ -71,7 +71,7 @@
-  /  +  /