diff --git a/.hound.yml b/.hound.yml index 489d9d661..d827f1aef 100644 --- a/.hound.yml +++ b/.hound.yml @@ -4,5 +4,6 @@ InlineComment: Enabled: false java_script: enabled: true + config_file: config/javascript.json coffee_script: enabled: true diff --git a/app/assets/javascripts/angular-libs/angular.openfarm.js b/app/assets/javascripts/angular-libs/angular.openfarm.js index beaf0304c..4b2f81135 100644 --- a/app/assets/javascripts/angular-libs/angular.openfarm.js +++ b/app/assets/javascripts/angular-libs/angular.openfarm.js @@ -1,4 +1,13 @@ -var openFarmModule = angular.module('openFarmModule', ['ngSanitize']); +var openFarmApp = angular.module('openFarmApp', [ + 'mm.foundation', + 'ng-rails-csrf', + 'ngS3upload', + 'openFarmModule', +]); + +var openFarmModule = angular.module('openFarmModule', [ + 'ngSanitize' +]); openFarmModule.factory('guideService', ['$http', function guideService($http) { @@ -11,7 +20,7 @@ openFarmModule.factory('guideService', ['$http', }).success(function (response) { return callback (true, response.guide); }).error(function (response, code) { - return callback(false, response, code) + return callback(false, response, code); }); }; return { @@ -30,7 +39,7 @@ openFarmModule.factory('userService', ['$http', }).success(function (response) { return callback (true, response.user); }).error(function (response, code) { - return callback(false, response, code) + return callback(false, response, code); }); }; return { @@ -42,19 +51,66 @@ openFarmModule.directive('markdown', ['$sanitize', function markdown($sanitize) { var converter = new Showdown.converter(); return { - restrict: 'A', - link: function (scope, element, attrs) { - function renderMarkdown() { - var htmlText = converter.makeHtml(scope.$eval(attrs.markdown) || ''); - element.html($sanitize(htmlText)); - } - scope.$watch(attrs.markdown, function(){ - renderMarkdown(); - }); - renderMarkdown(); + restrict: 'A', + link: function (scope, element, attrs) { + function renderMarkdown() { + var htmlText = converter.makeHtml(scope.$eval(attrs.markdown) || ''); + element.html($sanitize(htmlText)); } - } + scope.$watch(attrs.markdown, function(){ + renderMarkdown(); + }); + renderMarkdown(); + } + }; }]); +openFarmModule.directive('location', [ + function location() { + var geocoder = new google.maps.Geocoder(); + return { + restrict: 'A', + require: '?ngModel', + scope: true, + controller: ['$scope', '$element', '$attrs', + function ($scope, $element, $attrs) { + $scope.loadingText = $attrs.loadingText; + $scope.getLocation = function(val) { + if (geocoder) { + geocoder.geocode({ 'address': val }, function (results, status) { + if (status == google.maps.GeocoderStatus.OK) { + var addresses = []; + angular.forEach(results, function(item){ + addresses.push(item.formatted_address); + }); + $scope.addresses = addresses; + } + else { + console.log("Geocoding failed: " + status); + } + }); + } + }; + + $scope.addresses = []; + }], + template: ''+ + '', + }; +}]); + + + diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 5c86b3f29..ae39a9b7c 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -15,7 +15,6 @@ //= require foundation/foundation.topbar //= require foundation/mm-foundation-0.3.0.js //= require foundation/mm-foundation-tpls-0.3.0.js -//= require_tree ./guides //= require delete_me_later @@ -56,6 +55,6 @@ var getUrlVar = function(key) { }; var getIDFromURL = function(key) { - var result = new RegExp(key + "/([0-9a-f]*)", "i").exec(window.location.pathname); + var result = new RegExp(key + "/([0-9a-zA-Z\-]*)", "i").exec(window.location.pathname); return result && unescape(result[1]) || ""; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/app/assets/javascripts/foundation/mm-foundation-tpls-0.3.0.js b/app/assets/javascripts/foundation/mm-foundation-tpls-0.3.0.js index d478593d6..ad8dc0fab 100644 --- a/app/assets/javascripts/foundation/mm-foundation-tpls-0.3.0.js +++ b/app/assets/javascripts/foundation/mm-foundation-tpls-0.3.0.js @@ -3027,7 +3027,6 @@ angular.module('mm.foundation.typeahead', ['mm.foundation.position', 'mm.foundat var getMatchesAsync = function(inputValue) { var locals = {$viewValue: inputValue}; isLoadingSetter(originalScope, true); - console.log(originalScope.loadingCrops); $q.when(parserResult.source(originalScope, locals)).then(function(matches) { //it might happen that several async queries were in progress if a user were typing fast diff --git a/app/assets/javascripts/guides.js b/app/assets/javascripts/guides.js new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/javascripts/guides/edit.js b/app/assets/javascripts/guides/edit.js index 3a684d228..abf9f03c9 100644 --- a/app/assets/javascripts/guides/edit.js +++ b/app/assets/javascripts/guides/edit.js @@ -1,17 +1,18 @@ -var editGuidesApp = angular.module('editGuidesApp', [ - 'mm.foundation', - 'ngS3upload', - 'ng-rails-csrf', - 'openFarmModule' - ]); +// var editGuidesApp = angular.module('editGuidesApp', [ +// 'mm.foundation', +// 'ngS3upload', +// 'ng-rails-csrf', +// 'openFarmModule' +// ]); -editGuidesApp.controller('editGuideCtrl', ['$scope', '$http', 'guideService', - function editGuidesApp($scope, $http, guideService) { +openFarmApp.controller('editGuideCtrl', ['$scope', '$http', 'guideService', + function editGuideCtrl($scope, $http, guideService) { // setting this to true temporarily because // other wise the ajax loader doesn't load $scope.saving = true; - $scope.guide_id = getIDFromURL("guides"); + $scope.guide_id = getIDFromURL("guides") || GUIDE_ID; + console.log($scope.guide_id); $scope.alerts = []; @@ -236,7 +237,7 @@ editGuidesApp.controller('editGuideCtrl', ['$scope', '$http', 'guideService', }; }]); -editGuidesApp.directive('focusMe', function($timeout, $parse) { +openFarmApp.directive('focusMe', function($timeout, $parse) { return { //scope: true, // optionally create a child scope link: function(scope, element, attrs) { diff --git a/app/assets/javascripts/guides/new.js b/app/assets/javascripts/guides/new.js index 24bcc3b26..50444b3a0 100644 --- a/app/assets/javascripts/guides/new.js +++ b/app/assets/javascripts/guides/new.js @@ -1,10 +1,5 @@ -var guidesApp = angular.module('guidesApp', [ - 'mm.foundation', - 'ng-rails-csrf' - ]); - -guidesApp.controller('newGuideCtrl', ['$scope', '$http', - function guidesApp($scope, $http, $location) { +openFarmApp.controller('newGuideCtrl', ['$scope', '$http', + function newGuideCtrl($scope, $http) { $scope.alerts = []; $scope.crops = []; $scope.step = 1; @@ -20,7 +15,6 @@ guidesApp.controller('newGuideCtrl', ['$scope', '$http', if (getUrlVar("crop_id")){ $http.get('/api/crops/' + getUrlVar("crop_id")) .success(function(r){ - console.log(r); $scope.new_guide.crop = r.crop; $scope.query = r.crop.name; }) @@ -37,7 +31,7 @@ guidesApp.controller('newGuideCtrl', ['$scope', '$http', $scope.$watch('loadingCrops', function(){ // console.log($scope.loadingCrops); - }) + }); //Typeahead search for crops $scope.search = function () { @@ -74,22 +68,23 @@ guidesApp.controller('newGuideCtrl', ['$scope', '$http', $scope.createCrop = function(){ window.location.href = '/crops/new/?name=' + $scope.query; - } + }; $scope.nextStep = function(){ $scope.step += 1; - } + }; + $scope.previousStep = function(){ $scope.step -= 1; - } + }; $scope.submitForm = function () { var params = { - name: $scope.new_guide.name, - crop_id: $scope.new_guide.crop._id, - overview: $scope.new_guide.overview || null, - location: $scope.new_guide.location || null - } + name: $scope.new_guide.name, + crop_id: $scope.new_guide.crop._id, + overview: $scope.new_guide.overview || null, + location: $scope.new_guide.location || null + }; $http.post('/api/guides/', params) .success(function (r) { // console.log(r); @@ -104,33 +99,10 @@ guidesApp.controller('newGuideCtrl', ['$scope', '$http', }); }; - var geocoder = new google.maps.Geocoder(); - // Any function returning a promise object can be used to load values asynchronously - $scope.getLocation = function(val) { - console.log('val', val); - if (geocoder) { - geocoder.geocode({ 'address': val }, function (results, status) { - if (status == google.maps.GeocoderStatus.OK) { - var addresses = []; - angular.forEach(results, function(item){ - addresses.push(item.formatted_address); - }) - console.log('addresses'); - $scope.addresses = addresses; - } - else { - console.log("Geocoding failed: " + status); - } - - }); - } - }; $scope.cancel = function(path){ window.location.href = path || '/'; - } - - + }; }]); diff --git a/app/assets/javascripts/guides/show.js b/app/assets/javascripts/guides/show.js index 7add8404a..d506191b0 100644 --- a/app/assets/javascripts/guides/show.js +++ b/app/assets/javascripts/guides/show.js @@ -1,15 +1,8 @@ -var showGuidesApp = angular.module('showGuidesApp', [ - 'mm.foundation', - 'ngS3upload', - 'ng-rails-csrf', - 'openFarmModule' - ]); - -showGuidesApp.controller('showGuideCtrl', ['$scope', '$http', 'guideService', +openFarmApp.controller('showGuideCtrl', ['$scope', '$http', 'guideService', 'userService', - function showGuidesApp($scope, $http, guideService, userService) { - - $scope.guide_id = getIDFromURL('guides'); + function showGuideCtrl($scope, $http, guideService, userService) { + $scope.guide_id = getIDFromURL('guides') || GUIDE_ID; + $scope.alerts = []; $scope.setUser = function(success, object, code){ @@ -22,7 +15,7 @@ showGuidesApp.controller('showGuideCtrl', ['$scope', '$http', 'guideService', type: 'warning' }); } - } + }; $scope.setGuide = function(success, object, code){ if (success){ @@ -35,7 +28,7 @@ showGuidesApp.controller('showGuideCtrl', ['$scope', '$http', 'guideService', type: 'warning' }); } - } + }; guideService.getGuide($scope.guide_id, $scope.setGuide); }]); \ No newline at end of file diff --git a/app/assets/javascripts/search.js b/app/assets/javascripts/search.js index 41de6eb8c..8355d25aa 100644 --- a/app/assets/javascripts/search.js +++ b/app/assets/javascripts/search.js @@ -1,10 +1,5 @@ -var searchApp = angular.module('searchApp', [ - 'mm.foundation', - 'ng-rails-csrf' - ]); - -searchApp.controller('searchCtrl', ['$scope', '$http', '$location', - function searchApp($scope, $http, $location) { +openFarmApp.controller('searchCtrl', ['$scope', '$http', + function searchCtrl($scope, $http) { $scope.crops = []; //Typeahead search for crops @@ -22,7 +17,7 @@ searchApp.controller('searchCtrl', ['$scope', '$http', '$location', if (response.crops.length){ $scope.crops = response.crops; } - }) + }); } }; }]); diff --git a/app/assets/javascripts/users.js b/app/assets/javascripts/users.js new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/javascripts/users/finish.js b/app/assets/javascripts/users/finish.js new file mode 100644 index 000000000..f89cae797 --- /dev/null +++ b/app/assets/javascripts/users/finish.js @@ -0,0 +1,4 @@ +openFarmApp.controller('finishCtrl', ['$scope', '$http', + function finishCtrl($scope, $http) { + +}]); \ No newline at end of file diff --git a/app/assets/stylesheets/presets.css.scss b/app/assets/stylesheets/_presets.css.scss similarity index 96% rename from app/assets/stylesheets/presets.css.scss rename to app/assets/stylesheets/_presets.css.scss index 621b17d28..7cace6098 100644 --- a/app/assets/stylesheets/presets.css.scss +++ b/app/assets/stylesheets/_presets.css.scss @@ -77,9 +77,13 @@ small.error{ } .button{ - @include background-gradient(#A2BD6A, #A2BF6B); + @include background-gradient(#A2BD6A, #83A544); border-radius: 3px; - /*font-family: SourceSansPro-Bold;*/ + transition: .2s background-image; +} + +.button:hover{ + @include background-gradient(#8FAB54, #7A9841); } .button[disabled=disabled].loading, .button[disabled].loading, .button[disabled].loading:hover{ @@ -113,7 +117,6 @@ small.error{ h2, h5 { display: inline-block; - color: white; font-weight: 600; } diff --git a/app/assets/stylesheets/requirement.css.scss b/app/assets/stylesheets/requirement.css.scss deleted file mode 100644 index 7a647ac48..000000000 --- a/app/assets/stylesheets/requirement.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Requirement controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/stages.css.scss b/app/assets/stylesheets/stages.css.scss deleted file mode 100644 index c361eb512..000000000 --- a/app/assets/stylesheets/stages.css.scss +++ /dev/null @@ -1,3 +0,0 @@ -// Place all the styles related to the Stage controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/users.css.scss b/app/assets/stylesheets/users.css.scss new file mode 100644 index 000000000..e69de29bb diff --git a/app/assets/stylesheets/users/_finish.css.scss b/app/assets/stylesheets/users/_finish.css.scss new file mode 100644 index 000000000..45660e69f --- /dev/null +++ b/app/assets/stylesheets/users/_finish.css.scss @@ -0,0 +1,17 @@ +.title{ + text-align: center; + margin-bottom: 2rem; + + h2{ + font-size: 1.6rem; + color: #222; + } +} + +.row.submit{ + margin: 2rem auto 4rem; +} + +.finish .row{ + max-width: 640px; +} \ No newline at end of file diff --git a/app/assets/stylesheets/sign_up.css.scss b/app/assets/stylesheets/users/_sign_up.css.scss similarity index 100% rename from app/assets/stylesheets/sign_up.css.scss rename to app/assets/stylesheets/users/_sign_up.css.scss diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb new file mode 100644 index 000000000..6892358ec --- /dev/null +++ b/app/controllers/gardens_controller.rb @@ -0,0 +1,2 @@ +class GardensController < ApplicationController +end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 0026f51ba..581d1f730 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -1,6 +1,18 @@ class RegistrationsController < Devise::RegistrationsController + def create + super + @outcome = Gardens::CreateGarden.run( + params, + user: current_user, + name: "Your First Garden", + description: "We created this garden automatically to get you started" + + ". You can edit it to better suit your needs!") + +# # session[:omniauth] = nil unless @user.new_record? + end + protected - + # https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a- # specific-page-on-successful-sign-up-(registration) def after_sign_up_path_for(resource) @@ -9,7 +21,8 @@ def after_sign_up_path_for(resource) if go_to go_to || request.referer || root_path else - edit_user_registration_path + url_for(controller: 'users', + action: 'finish') end end end diff --git a/app/controllers/requirements_controller.rb b/app/controllers/requirements_controller.rb index 82a5d5171..868171453 100644 --- a/app/controllers/requirements_controller.rb +++ b/app/controllers/requirements_controller.rb @@ -6,13 +6,13 @@ def create #TODO: Assign a slug if none has been given. if @requirement.save - redirect_to(:controller => 'guides', - :action => 'edit', - :id => @requirement.guide.id) + redirect_to(controller: 'guides', + action: 'edit', + id: @requirement.guide.id) else - redirect_to(:controller => 'guides', - :action => 'edit', - :id => @requirement.guide.id) + redirect_to(controller: 'guides', + action: 'edit', + id: @requirement.guide.id) end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 000000000..f19aa2f90 --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,14 @@ +class UsersController < ApplicationController + def update + @outcome = Users::UpdateUser.run( + params, + user: current_user) + if @outcome.errors + flash[:alert] = @outcome.errors.message_list + redirect_to(controller: 'users', + action: 'finish') + else + redirect_to :gardens + end + end +end diff --git a/app/models/garden.rb b/app/models/garden.rb index 2a2c66c9f..a32cf15c9 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -6,10 +6,11 @@ class Garden # TODO: information about the plants in the garden: placement, dates planted, guides used, etc field :name + field :description validates_presence_of :user field :location # users can have gardens in different locations - field :garden_type # outdoor, indoor, hydroponic, etc + field :type # outdoor, indoor, hydroponic, etc field :average_sun # full, partial, etc field :soil_type # clay, high organic, etc field :ph # 0-14 diff --git a/app/models/user.rb b/app/models/user.rb index 17de4037a..1ae7547cf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -26,11 +26,13 @@ class User validates_presence_of :display_name field :location, type: String field :years_experience, type: Integer - field :admin, :type => Boolean, default: false + field :units, type: String + field :mailing_list, type: Mongoid::Boolean, default: false + + field :admin, type: Mongoid::Boolean, default: false # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable # , :omniauthable - field :mailing_list, type: Mongoid::Boolean, default: false end diff --git a/app/mutations/gardens/create_garden.rb b/app/mutations/gardens/create_garden.rb new file mode 100644 index 000000000..23dec3a4f --- /dev/null +++ b/app/mutations/gardens/create_garden.rb @@ -0,0 +1,41 @@ +module Gardens + class CreateGarden < Mutations::Command + required do + model :user + string :name + end + + optional do + string :location + string :description + string :type + string :average_sun + string :soil_type + integer :ph + Array :growing_practices + end + + def garden + @garden ||= Garden.new + end + + def execute + set_params + garden + end + + def set_params + garden.user = user + # TODO: validate that the stage name is one + # of stage options, or should we? + garden.name = name + garden.location = location if location + garden.description = description if description + garden.type = type if type + garden.average_sun = average_sun if average_sun + garden.soil_type = soil_type if soil_type + garden.ph = ph if ph + garden.save + end + end +end diff --git a/app/mutations/users/update_user.rb b/app/mutations/users/update_user.rb new file mode 100644 index 000000000..42967e0ba --- /dev/null +++ b/app/mutations/users/update_user.rb @@ -0,0 +1,29 @@ +module Users + class UpdateUser < Mutations::Command + + required do + model :user + end + + optional do + string :display_name + string :location + string :years_experience + string :mailing_list + string :units + end + + def execute + set_valid_params + end + + def set_valid_params + # TODO: Probably a DRYer way of doing this. + user.location = location if location.present? + user.display_name = display_name if display_name.present? + user.mailing_list = mailing_list if mailing_list.present? + user.units = units if units.present? + user.save + end + end +end diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index 89b21c5e5..1909f4f32 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,7 +1,10 @@ +<% content_for(:banner) do %>
+ +<% end %>