diff --git a/.DS_Store b/.DS_Store index 861ce21..797e7a7 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Gemfile b/Gemfile index b7d7aab..b5edc6e 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,16 @@ source 'https://rubygems.org' +group :development, :test do + gem 'sqlite3' +end +group :production do + gem 'pg', '~> 0.18' +end +gem 'jquery-rails' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '5.0.2' # Use sqlite3 as the database for Active Record -gem 'sqlite3' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets @@ -41,7 +47,6 @@ gem 'cancan' # or cancancan gem 'draper' gem 'pundit' - # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' diff --git a/Gemfile.lock b/Gemfile.lock index 1ef8616..50aa96c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -24,15 +24,15 @@ GEM erubis (~> 2.7.0) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activeadmin (1.1.0) + activeadmin (1.3.0) arbre (>= 1.1.1) coffee-rails formtastic (~> 3.1) formtastic_i18n - inherited_resources (~> 1.7) - jquery-rails - kaminari (>= 0.15, < 2.0) - railties (>= 4.2, < 5.2) + inherited_resources (>= 1.7.0) + jquery-rails (>= 4.2.0) + kaminari (>= 0.15) + railties (>= 4.2, < 5.3) ransack (~> 1.3) sass (~> 3.1) sprockets (< 4.1) @@ -58,10 +58,11 @@ GEM activesupport (>= 3.0.0) arel (7.1.4) bcrypt (3.1.11) - binding_of_caller (0.7.2) + bcrypt (3.1.11-x86-mingw32) + binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) builder (3.2.3) - byebug (9.1.0) + byebug (10.0.2) cancan (1.6.10) coffee-rails (4.1.1) coffee-script (>= 2.2.0) @@ -71,12 +72,12 @@ GEM execjs coffee-script-source (1.12.2) concurrent-ruby (1.0.5) - crass (1.0.2) + crass (1.0.4) debug_inspector (0.0.3) - devise (4.3.0) + devise (4.4.3) bcrypt (~> 3.0) orm_adapter (~> 0.1) - railties (>= 4.1.0, < 5.2) + railties (>= 4.1.0, < 6.0) responders warden (~> 1.2.3) draper (3.0.1) @@ -87,7 +88,8 @@ GEM request_store (~> 1.0) erubis (2.7.0) execjs (2.7.0) - ffi (1.9.18) + ffi (1.9.23) + ffi (1.9.23-x86-mingw32) formtastic (3.1.5) actionpack (>= 3.2.13) formtastic_i18n (0.6.0) @@ -96,20 +98,20 @@ GEM haml (5.0.4) temple (>= 0.8.0) tilt - has_scope (0.7.1) - actionpack (>= 4.1, < 5.2) - activesupport (>= 4.1, < 5.2) - i18n (0.9.1) + has_scope (0.7.2) + actionpack (>= 4.1) + activesupport (>= 4.1) + i18n (0.9.5) concurrent-ruby (~> 1.0) - inherited_resources (1.7.2) - actionpack (>= 3.2, < 5.2.x) + inherited_resources (1.8.0) + actionpack (>= 4.2, <= 5.2) has_scope (~> 0.6) - railties (>= 3.2, < 5.2.x) + railties (>= 4.2, <= 5.2) responders jbuilder (2.7.0) activesupport (>= 4.2.0) multi_json (>= 1.2) - jquery-rails (4.3.1) + jquery-rails (4.3.3) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) @@ -126,25 +128,28 @@ GEM activerecord kaminari-core (= 1.1.1) kaminari-core (1.1.1) - loofah (2.1.1) + loofah (2.2.2) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.0) mini_mime (>= 0.1.1) method_source (0.9.0) - mini_mime (0.1.4) + mini_mime (1.0.0) mini_portile2 (2.3.0) - minitest (5.10.3) - multi_json (1.12.1) - nio4r (2.1.0) - nokogiri (1.8.1) + minitest (5.11.3) + multi_json (1.13.1) + nio4r (2.3.0) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + nokogiri (1.8.2-x86-mingw32) mini_portile2 (~> 2.3.0) orm_adapter (0.5.0) - polyamorous (1.3.1) + pg (0.21.0) + polyamorous (1.3.3) activerecord (>= 3.0) pundit (1.1.0) activesupport (>= 3.0.0) - rack (2.0.3) + rack (2.0.5) rack-cors (0.3.1) rack-test (0.6.3) rack (>= 1.0) @@ -163,35 +168,36 @@ GEM rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.0.3) - loofah (~> 2.0) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) railties (5.0.2) actionpack (= 5.0.2) activesupport (= 5.0.2) method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rake (12.2.1) - ransack (1.8.4) + rake (12.3.1) + ransack (1.8.8) actionpack (>= 3.0) activerecord (>= 3.0) activesupport (>= 3.0) i18n - polyamorous (~> 1.3) - rb-fsevent (0.10.2) + polyamorous (~> 1.3.2) + rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) rdoc (4.3.0) - request_store (1.3.2) + request_store (1.4.1) + rack (>= 1.4) responders (2.4.0) actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) - sass (3.5.1) + sass (3.5.6) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sass-rails (5.0.6) + sass-rails (5.0.7) railties (>= 4.0.0, < 6) sass (~> 3.1) sprockets (>= 2.8, < 4.0) @@ -200,9 +206,9 @@ GEM sdoc (0.4.2) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) - simple_form (3.5.0) - actionpack (> 4, < 5.2) - activemodel (> 4, < 5.2) + simple_form (4.0.0) + actionpack (> 4) + activemodel (> 4) spring (2.0.2) activesupport (>= 4.2) sprockets (3.7.1) @@ -213,16 +219,17 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.3.13) + sqlite3 (1.3.13-x86-mingw32) temple (0.8.0) thor (0.20.0) thread_safe (0.3.6) tilt (2.0.8) - turbolinks (5.0.1) - turbolinks-source (~> 5) - turbolinks-source (5.0.3) - tzinfo (1.2.4) + turbolinks (5.1.1) + turbolinks-source (~> 5.1) + turbolinks-source (5.1.0) + tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (3.2.0) + uglifier (4.1.10) execjs (>= 0.3.0, < 3) warden (1.2.7) rack (>= 1.0) @@ -233,10 +240,11 @@ GEM sprockets-rails (>= 2.0, < 4.0) websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.2) + websocket-extensions (0.1.3) PLATFORMS ruby + x86-mingw32 DEPENDENCIES activeadmin @@ -248,6 +256,7 @@ DEPENDENCIES haml jbuilder (~> 2.0) jquery-rails + pg (~> 0.18) pundit rack-cors (~> 0.3.1) rails (= 5.0.2) @@ -261,4 +270,4 @@ DEPENDENCIES web-console (~> 2.0) BUNDLED WITH - 1.16.0 + 1.16.1 diff --git a/README.md b/README.md index 792b0dd..820cdaf 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,54 @@ # LFC_Features +### Local Food Connection Application +LFC is a Grinnell farm directory service. It contains basic information of farms that are connected to Local Food Connection Organization. The goal of the app is to allow user to easily search for Grinnell's sustainable food system. + +You can obtain the source with the following command: +```shell +git clone https://github.com/CSC322-Grinnell/LFC_Features.git +``` + +## Authors and Contributors + +### Current Builds + +- [Sara Marku](https://github.com/saramarku) +- [Linh Pham](https://github.com/linhpha) +- [Pratik Karki](https://github.com/karkipra) +- [Elise Brod](https://github.com/brodelis) +- [James Msekela]() + +### Previous Builds + +- Matt Murphy +- Thu Nguyen +- Minh Tran +- Alexandar Hrusanov +- Nick Roberson + + +### Project Structure + + +### How to build + + + +### Things to do + + +## License +``` +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +``` diff --git a/app/admin/farm.rb b/app/admin/farm.rb index d7dfc50..a0cce77 100644 --- a/app/admin/farm.rb +++ b/app/admin/farm.rb @@ -1,17 +1,4 @@ ActiveAdmin.register Farm do - # See permitted parameters documentation: - # https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters - # - # permit_params :list, :of, :attributes, :on, :model - # - # or - # - # permit_params do - # permitted = [:permitted, :attributes] - # permitted << :other if params[:action] == 'create' && current_user.admin? - # permitted - # end - controller do before_filter :authorize_index, only: :index def authorize_index @@ -26,13 +13,9 @@ def authorize_index end # scope_to :current_farm, unless: proc{ :current_farm } - - permit_params do - permitted = [:name, :address, :phone, :email, :url, :facebook, :instagram, - :password, :password_confirmation, :twitter] - permitted << :approved if current_farm.admin? - permitted - end + ## Add strong parameters for admin to be able to edit these fields + permit_params :name, :address, :phone, :email, :url, :facebook, :instagram, :password, :password_confirmation, :primary_operation, :growth_promoter, :antibiotic, :why_farm, :fav_activity, :twitter, :approved, + operation_ids: [], selling_method_ids: [], growing_method_ids: [], market_ids: [] index do selectable_column @@ -69,15 +52,13 @@ def authorize_index f.input :twitter f.input :other_media - @ops = ['Fruit', 'Vegetables', 'Dairy', 'Pork', 'Chicken', 'Turkey', 'Lamb', 'Duck', 'Agitourism', 'Hay', 'Row Crop'] - @grow = ['Certified Natural Grown', 'USDA Certified Organic', '100% Grass Fed', 'Grass Finished', 'Non-GMO', 'Regenerative Organic Certified', 'Integrated Pest Management', 'Pasture Raised', 'Corn Fed', 'Conventional'] - @sell = ['CSA', 'Farmers Market', 'Wholesale', 'Grocery Stores', 'Grinnell Area Local Food Source', 'On-Farm', 'Iowa Food Coop', 'Institutions', 'Restaurants'] - @market = ['Grinnell-Thursday', 'Grinnell-Saturday', "Des Moines Downtown-Saturday", "Cedar Rapids Downtown-Select Saturdays", "Iowa City-Saturday", "Tama-Toledo", "Brooklyn"] - f.input :operations, as: :check_boxes, collection: @ops - f.input :growing_methods, as: :check_boxes, collection: @grow + + f.input :operations, as: :check_boxes, collection: Operation.all + f.input :primary_operation, as: :check_boxes, collection: PrimaryOperation.all + f.input :growing_methods, as: :check_boxes, collection: GrowingMethod.all f.input :link_to_cert - f.input :selling_methods, as: :check_boxes, collection: @sell - f.input :markets, as: :check_boxes, collection: @market + f.input :selling_methods, as: :check_boxes, collection: SellingMethod.all + f.input :markets, as: :check_boxes, collection: Market.all f.input :growth_promoter, as: :boolean, checked_value: true, unchecked_value: false f.input :antibiotic, as: :boolean, checked_value: true, unchecked_value: false diff --git a/app/assets/icons/24apple.png b/app/assets/icons/24apple.png new file mode 100644 index 0000000..a4b7099 Binary files /dev/null and b/app/assets/icons/24apple.png differ diff --git a/app/assets/icons/24broccoli.png b/app/assets/icons/24broccoli.png new file mode 100644 index 0000000..cb057ef Binary files /dev/null and b/app/assets/icons/24broccoli.png differ diff --git a/app/assets/icons/24chicken.png b/app/assets/icons/24chicken.png new file mode 100644 index 0000000..d462e90 Binary files /dev/null and b/app/assets/icons/24chicken.png differ diff --git a/app/assets/icons/24cow.png b/app/assets/icons/24cow.png new file mode 100644 index 0000000..f13173f Binary files /dev/null and b/app/assets/icons/24cow.png differ diff --git a/app/assets/icons/24dairy.png b/app/assets/icons/24dairy.png new file mode 100644 index 0000000..6927072 Binary files /dev/null and b/app/assets/icons/24dairy.png differ diff --git a/app/assets/icons/24pig.png b/app/assets/icons/24pig.png new file mode 100644 index 0000000..7c81a0e Binary files /dev/null and b/app/assets/icons/24pig.png differ diff --git a/app/assets/icons/24sheep.png b/app/assets/icons/24sheep.png new file mode 100644 index 0000000..1bdce28 Binary files /dev/null and b/app/assets/icons/24sheep.png differ diff --git a/app/assets/icons/64cow.png b/app/assets/icons/64cow.png new file mode 100644 index 0000000..c448c32 Binary files /dev/null and b/app/assets/icons/64cow.png differ diff --git a/app/assets/icons/agricultural.png b/app/assets/icons/agricultural.png new file mode 100644 index 0000000..a151cff Binary files /dev/null and b/app/assets/icons/agricultural.png differ diff --git a/app/assets/icons/carrot.png b/app/assets/icons/carrot.png new file mode 100644 index 0000000..6b1b1d2 Binary files /dev/null and b/app/assets/icons/carrot.png differ diff --git a/app/assets/icons/dairy_free.png b/app/assets/icons/dairy_free.png new file mode 100644 index 0000000..43c9bde Binary files /dev/null and b/app/assets/icons/dairy_free.png differ diff --git a/app/assets/icons/farm2.jpg b/app/assets/icons/farm2.jpg new file mode 100644 index 0000000..c5f19f2 Binary files /dev/null and b/app/assets/icons/farm2.jpg differ diff --git a/app/assets/icons/gluten_free.png b/app/assets/icons/gluten_free.png new file mode 100644 index 0000000..558d955 Binary files /dev/null and b/app/assets/icons/gluten_free.png differ diff --git a/app/assets/icons/kosher.png b/app/assets/icons/kosher.png new file mode 100644 index 0000000..30b07b7 Binary files /dev/null and b/app/assets/icons/kosher.png differ diff --git a/app/assets/icons/peanut_free.jpg b/app/assets/icons/peanut_free.jpg new file mode 100644 index 0000000..ca38b82 Binary files /dev/null and b/app/assets/icons/peanut_free.jpg differ diff --git a/app/assets/icons/steak-512.png b/app/assets/icons/steak-512.png new file mode 100644 index 0000000..c5182d0 Binary files /dev/null and b/app/assets/icons/steak-512.png differ diff --git a/app/assets/icons/tree_nut_free.jpg b/app/assets/icons/tree_nut_free.jpg new file mode 100644 index 0000000..5eda7af Binary files /dev/null and b/app/assets/icons/tree_nut_free.jpg differ diff --git a/app/assets/icons/vegetarian.jpg b/app/assets/icons/vegetarian.jpg new file mode 100644 index 0000000..e78c81c Binary files /dev/null and b/app/assets/icons/vegetarian.jpg differ diff --git a/app/assets/images/logo.png b/app/assets/images/logo.png new file mode 100644 index 0000000..640bc00 Binary files /dev/null and b/app/assets/images/logo.png differ diff --git a/app/assets/javascripts/active_admin.js.coffee b/app/assets/javascripts/active_admin.js.coffee new file mode 100644 index 0000000..3752dce --- /dev/null +++ b/app/assets/javascripts/active_admin.js.coffee @@ -0,0 +1 @@ +#= require active_admin/base diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index e07c5a8..a8670ea 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -1,16 +1,631 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, -// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. -// -// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details -// about supported directives. -// +// To enable jquery for rails //= require jquery -//= require jquery_ujs -//= require turbolinks -//= require_tree . +var map; +var geocoder; +var farms = {}; +var recipes = {}; +/*********** + * API_KEYS * + ***********/ +var edemam_app_id = "0649d198"; +var edemam_app_key = "77bd12dd099e7f2c02338006ef659724"; +var lfc_key = "YAS0sY2rbi"; +$(document).ready(function() { + $(".dropdown-menu li a").click(function() { + $("#category_button").text($(this).text()); + }); +}); +/******** + * INIT * + ********/ +$(window).load(function() { + init(); +}); +/** +Set up on_click for search farm and search recipe +**/ +function init() { + // set up recipe search + document.getElementById("search_recipes").onclick = function() { + // Get checked values for dietary choises + var checkedDietaryOptionsList = []; + $('input[name=recipeCheckboxList]:checked').each(function() { + checkedDietaryOptionsList.push($(this).val()); + }); + var text = $('#recipe_search_text').val(); + text = text.split(' ').join('%20') + if (text != "") { + callFood2Fork(text, checkedDietaryOptionsList); + } + }; + // set up farm search + document.getElementById("search_farm").onclick = function() { + // Delete old markers on map + DeleteMarkers(); + // Get checked values for operations + var checkedOperations = []; + $('input[name=checkboxList]:checked').each(function() { + if ($(this).val() == "meat") + checkedOperations.push("lamb", "beef", "chicken", "pork"); + else if ($(this).val() == "agritourism") + checkedOperations.push("agritourism", "hay", "row crop"); + else + checkedOperations.push($(this).val()); + }); + // Get farm by filtered operation + callIndexApi2(checkedOperations); + // Get searech option + var text = $('#search_farm_text').val(); + var search_by = $('#category_button').text(); + // Search by Address + if (search_by == "Address") { + // Set up map positions + if (text != "") { + geocoder.geocode({ + 'address': text + }, function(results, status) { + if (status == 'OK') { + map.setCenter(results[0].geometry.location); + map.setZoom(17); + //map.panTo(curmarker.position); + var marker = new google.maps.Marker({ + map: map, + position: results[0].geometry.location + }); + } else { + alert('Geocode was not successful for the following reason: ' + status); + } + }); + + } + // Search by Farm's Name + } else if (search_by == "Farm's Name") { + var farms = []; + var call_url = "/farms/farm_json"; + // Get all farms + $.ajax({ + type: "GET", + url: call_url, + headers: { + 'X-Auth-Token': lfc_key + }, + dataType: 'json', + contentType: 'application/json', + crossDomain: true, + async: false, + success: function(result) { + if (result != null || result.length > 0) { + farms = handleAddressCall(result, text); + handleIndexCall3(farms); + // text += "Iowa, 50112"; // this is temporary + } else { + alert("Your search query returned no results . . . ") + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown) { + console.log("Status: " + textStatus); + console.log("Error: " + errorThrown); + } + }); + if (text != "") { + geocoder.geocode({ + 'address': text + }, function(results, status) { + if (status == 'OK') { + map.setCenter(results[0].geometry.location); + map.setZoom(17); + //map.panTo(curmarker.position); ?? + var marker = new google.maps.Marker({ + map: map, + position: results[0].geometry.location + }); + } else { + alert('Geocode was not successful for the following reason: ' + status); + } + }); + } + } else { + document.getElementById("search_farm_text").text = "Please enter your query"; + } + } +} +/************* + * INIT MAP * + * ***********/ +function initMap() { + // set location set to grinnell as center of map + var grinnell = { + lat: 41.7434, + lng: -92.7232 + }; + // init map + map = new google.maps.Map(document.getElementById('map'), { + zoom: 13.7, + center: grinnell + }); + // init geocoder + geocoder = new google.maps.Geocoder(); + // call index function for API to load all farms + callIndexApi(); +} +/**************************************** + * GEOCODING AND ADDING MARKERS FUNCTIONS + * **************************************/ +function geocodeAddressAndAddMarker(farm) { + var address = farm.address + ", Iowa, 50112" + geocoder.geocode({ + 'address': address + }, function(results, status) { + // if OK/200 status, add marker to map, else throw alert. + if (status === 'OK') { + addMarker(farm, results); + } else { + alert('Geocode was not successful for the following reason: ' + status); + } + }); +} +var markers = [] + +function addMarker(farm, results) { + if (farm.operations.length == 0) { + operation_icon = '/assets/64cow.png'; + } else { + var primary_operation = farm.operations[0].food; + if (primary_operation == "cow" || primary_operation == "pork" || primary_operation == "chicken" || + primary_operation == "turkey" || primary_operation == "lamb" || primary_operation == "duck") { + operation_icon = '/assets/steak-512.png'; + } else if (primary_operation == "fruit") { + console.log("HERE"); + operation_icon = '/assets/24apple.png'; + } else if (primary_operation == "vegetables") { + operation_icon = '/assets/24broccoli.png'; + } else if (primary_operation == "dairy") { + operation_icon = '/assets/24dairy.png'; + } else if (primary_operation == "agritourism" || primary_operation == "hay" || primary_operation == "row crop") { + operation_icon = '/assets/agricultural.png'; + } else if (primary_operation == "") {} + } + var iconCow = '/assets/64cow.png' + var iconPig = '/assets/24pig.png' + // create marker object + var marker = new google.maps.Marker({ + map: map, + animation: google.maps.Animation.BOUNCE, + position: results[0].geometry.location, + title: farm.name, + icon: operation_icon + }); + // data string for display tooltip + var data = farm.name; + // info window for tooltip, contains data + var infowindow = new google.maps.InfoWindow({ + content: data + }); + // add listener to map for marker to display info window + google.maps.event.addListener(marker, 'click', function() { + // open info window + infowindow.open(map, marker); + }); + markers.push(marker); +} +/*********************** + * DELETE MARKERS ON MAP * + * *********************/ +function DeleteMarkers() { + //Loop through all the markers and remove + for (var i = 0; i < markers.length; i++) { + markers[i].setMap(null); + } + markers = []; +}; +/*********************** + * FARM API FUNCTIONS * + * *********************/ +function callIndexApi() { + document.getElementById("farmList").innerHTML = ""; + var call_url = "/farms/farm_json"; + $.ajax({ + type: "GET", + url: call_url, + headers: { + 'X-Auth-Token': lfc_key + }, + dataType: 'json', + contentType: 'application/json', + crossDomain: true, + async: false, + success: function(result) { + if (result != null || result.length > 0) { + handleIndexCall(result); + } else { + alert("Your search query returned no results . . . ") + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown) { + console.log("Status: " + textStatus); + console.log("Error: " + errorThrown); + } + }); +} + +function handleIndexCall(result) { + // set to new map + farms = {}; + for (var i = 0; i < result.length; i++) { + // create id + var id = "farm_" + result[i].id; + // add to map + farms[id] = result[i]; + // append card + $('#farmList').append('
  • ' + + '

    ' + result[i].name + '

    ' + + '
    ' + result[i].address + '
    ' + + '

    CSA, Wholesale, and Farmers Market

    ' + + '' + result[i].url + ' | ' + + '' + result[i].phone + '' + + '
  • ' + ); + // on click to show modal + $('#' + id).on('click', function() { + var new_id = this.getAttribute('id'); + console.log("new id" + new_id); + // alter html in modal + setAndShowFarmModal(farms[new_id]); + }); + // add marker at proper placec + geocodeAddressAndAddMarker(result[i]); + } +} + +function handleAddressCall(result, addressSearch) { + farms = []; + for (var i = 0; i < result.length; i++) { + // create id + var name = result[i].name; + var id = "farm_" + result[i].id; + // add to map + //farms[id] = result[i]; + console.log("name is " + name); + if ((name.toLowerCase()).includes(addressSearch.toLowerCase())) { + console.log("name is " + name); + // return result[i].address; + farms.push(result[i]); + } + } + console.log("Address call to farms"); + console.log(farms); + return farms; +} +/************************* + * RECIPE API FUNCTIONS * + * ***********************/ +function callFood2Fork(food_string, checkRecipeValues) { + // clear the html to get rid of old recipes + $("#recipe_grid").html(""); + // set new url to access + // var call_url = "https://api.edamam.com/search?q=${food_string}&app_id=${edemam_app_id}&app_key=${edemam_app_key}" + var call_url = "https://api.edamam.com/search?q=" + food_string + "&app_id=" + edemam_app_id + "&app_key=" + edemam_app_key; + var health_query = ""; + console.log(checkRecipeValues); + for (var i = 0; i < checkRecipeValues.length; i++) { + console.log(checkRecipeValues[i]); + if (i != checkRecipeValues.length - 1) { + health_query += checkRecipeValues[i] + ',%20'; + } + } + if (checkRecipeValues.length > 0) { + call_url += "&healthLabels=" + health_query; + } + // make call + $.ajax({ + type: "GET", + url: call_url, + headers: { + "more": true, + }, + dataType: 'json', + crossDomain: true, + success: function(result) { + if (result != null && result.hits.length > 0) { + console.log(result); + handleRecipeAPICall(result.hits); + } else { + alert("Your search query returned no results . . . ") + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown) { + console.log("Status: " + textStatus); + console.log("Error: " + errorThrown); + } + }); +} + +function handleRecipeAPICall(recipe_list) { + // reset recipe list + recipes = {}; + // iterate through + for (var i = 0; i < recipe_list.length; i++) { + // get current recipe and id + var current_recipe = recipe_list[i].recipe; + var id = "recipe_" + (i + 1); + // put in recipe list + recipes[id] = current_recipe; + // add html + $('#recipe_grid').append( + '
    ' + + '' + + '
    ' + + '

    ' + current_recipe.label + '

    ' + + '
    ' + current_recipe.source + '
    ' + + 'Go to recipe' + + '' + ); + // on click to show modal + $('#' + id).on('click', function() { + var new_id = this.getAttribute('id'); + // alter html in modal + setAndShowRecipeModal(recipes[new_id]); + }); + } +} +/******************** + * MODAL FUNCTIONS * + * ******************/ +function capitalize_words(str) { + return str.replace(/\w\S*/g, function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); +} + +function getOperation(farm) { + var result = ""; + if (!farm.operations) { + farm = farm[0]; + } + for (var i = 0; i < farm.operations.length; i++) { + result += capitalize_words(farm.operations[i].food); + if (i != farm.operations.length - 1) { + result += ', '; + } + } + if (result == "") { + return "N/A" + } + return result; +} + +function getGrowingMethod(farm) { + var result = ""; + if (!farm.growing_methods) { + farm = farm[0]; + } + for (var i = 0; i < farm.growing_methods.length; i++) { + result += capitalize_words(farm.growing_methods[i].grow_method); + if (i != farm.growing_methods.length - 1) { + result += ', '; + } + } + if (result == "") { + return "N/A" + } + return result +} + +function getSellingMethod(farm) { + var result = ""; + if (!farm.selling_methods) { + farm = farm[0]; + } + for (var i = 0; i < farm.selling_methods.length; i++) { + result += capitalize_words(farm.selling_methods[i].sell_method); + if (i != farm.selling_methods.length - 1) { + result += ', '; + } + } + if (result == "") { + return "N/A" + } + return result; +} + +function setAndShowFarmModal(farm) { + // set modal header html + if (!farm.name) { + farm = farm[0]; + } + console.log(farm); + $('#modal_header').html('

    ' + farm.name + '

    '); + // set modal tab 1 html + $('#tab_1_title').html('Home'); + $('#tab_1').html( + '

    Basic Information:' + '

    ' + + '

    Growing Method: ' + getGrowingMethod(farm) + '

    ' + + '

    Operation: ' + getOperation(farm) + '

    ' + + '

    Selling Method: ' + getSellingMethod(farm) + '

    ' + ); + // set modal tab 2 html + $('#tab_2_title').html('Contact'); + $('#tab_2').html( + '

    ' + farm.address + '

    ' + + '

    ' + farm.phone + '

    ' + + '
    ' + + ' Visit our webpage | ' + + 'Facebook | ' + + 'Twitter' + + '
    ' + ); + // set modal tab 3 html + $('#tab_3_title').html('Menu 1'); + $('#tab_3').html( + '

    MENU1

    ' + + '

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    ' + ); + // set modal tab 4 html + $('#tab_4_title').html('Menu 2'); + $('#tab_4').html( + '

    MENU2

    ' + + '

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    ' + ); + // show button + $('#contact_button').show(); + $('#recipe_link_button').hide(); + // show modal + $("#generic_modal").modal() +} + +function setAndShowRecipeModal(recipe) { + // set modal header html + $('#modal_header').html( + '

    ' + recipe.label + '

    ' + + '

    ' + recipe.source + '

    ' + ); + // compile tab 1 data + var ingredient_list = '
      '; + for (var i = 0; i < recipe.ingredients.length; i++) { + ingredient_list += "
    • " + recipe.ingredients[i].text + "
    • "; + } + ingredient_list += "
    "; + // compile tab 2 data + var health_list = '
      '; + for (var i = 0; i < recipe.digest.length; i++) { + health_list += "
    • " + + recipe.digest[i].label + + '' + + Math.round(recipe.digest[i].total * 10) / 10 + + recipe.digest[i].unit + + "
    • "; + } + health_list += "
    "; + // compile tab 3 data + var nutrient_list = '
      '; + for (var key in recipe.totalDaily) { + //if (!recipe.totalDaily.hasOwnProperty(key)) continue; + nutrient_list += '
    • ' + + recipe.totalDaily[key].label + + '' + + Math.round(recipe.totalNutrients[key].quantity * 10) / 10 + + recipe.totalNutrients[key].unit + ' (' + + Math.round(recipe.totalDaily[key].quantity * 10) / 10 + + recipe.totalDaily[key].unit + + ")
    • "; + } + nutrient_list += "
    "; + // compile tab 4 data + // set all modal tabs html content + $('#tab_1_title').html('Ingredients'); + $('#tab_1').html(ingredient_list); + $('#tab_2_title').html('Health Information'); + $('#tab_2').html(health_list); + $('#tab_3_title').html("Nutrients"); + $('#tab_3').html(nutrient_list); + // hide button + $('#contact_button').hide(); + $('#recipe_link_button').show(); + $('#recipe_link_tag').attr("href", recipe.url); + // show modal + $("#generic_modal").modal() +} + +function callIndexApi2(operations) { + document.getElementById("farmList").innerHTML = ""; + var call_url = "/api/v1/farms/farm_by_operation"; + $.ajax({ + type: "POST", + url: call_url, + data: JSON.stringify({ + "farms": { + "operations": operations + } + }), + headers: { + 'X-Auth-Token': lfc_key + }, + dataType: 'json', + contentType: 'application/json', + crossDomain: true, + async: false, + success: function(result) { + if (result != null || result.length > 0) { + console.log("LENGTH" + result.length); + handleIndexCall2(result); + } else { + alert("Your search query returned no results . . . ") + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown) { + console.log("Status: " + textStatus); + console.log("Error: " + errorThrown); + } + }); +} + +function handleIndexCall2(result) { + // set to new map + farms = {}; + var farm; + for (var i = 0; i < result.length; i++) { + console.log("In index call 2"); + console.log(result[i][0]); + var farm = result[i][0]; + + // create id + if (!farm) { + continue; + } + var id = "farm_" + farm.id; + console.log(farm.id); + // add to map + farms[id] = result[i]; + // append card + $('#farmList').append('
  • ' + + '

    ' + farm.name + '

    ' + + '
    ' + farm.address + '
    ' + + '

    CSA, Wholesale, and Farmers Market

    ' + + '' + farm.url + ' | ' + + '' + farm.phone + '' + + '
  • ' + ); + // on click to show modal + $('#' + id).on('click', function() { + var new_id = this.getAttribute('id'); + console.log("HERE" + new_id); + setAndShowFarmModal(farms[new_id]); + }); + // add marker at proper placec + geocodeAddressAndAddMarker(farm); + } +} + +function handleIndexCall3(result) { + // set to new map + farms = {}; + var farm; + console.log("In IndexCall3"); + for (var i = 0; i < result.length; i++) { + farm = result[i]; + // create id + if (!farm) { + continue; + } + var id = "farm_" + farm.id; + // add to map + farms[id] = result[i]; + // append card + $('#farmList').append('
  • ' + + '

    ' + farm.name + '

    ' + + '
    ' + farm.address + '
    ' + + '

    CSA, Wholesale, and Farmers Market

    ' + + '' + farm.url + ' | ' + + '' + farm.phone + '' + + '
  • ' + ); + // // on click to show modal + $('#' + id).on('click', function() { + var new_id = this.getAttribute('id'); + setAndShowFarmModal(farms[new_id]); + }); + // // add marker at proper placec + geocodeAddressAndAddMarker(farm); + } +} \ No newline at end of file diff --git a/app/assets/javascripts/ui.coffee b/app/assets/javascripts/ui.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/ui.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/active_admin.scss b/app/assets/stylesheets/active_admin.scss new file mode 100644 index 0000000..d3c61f3 --- /dev/null +++ b/app/assets/stylesheets/active_admin.scss @@ -0,0 +1,17 @@ +// SASS variable overrides must be declared before loading up Active Admin's styles. +// +// To view the variables that Active Admin provides, take a look at +// `app/assets/stylesheets/active_admin/mixins/_variables.scss` in the +// Active Admin source. +// +// For example, to change the sidebar width: +// $sidebar-width: 242px; + +// Active Admin's got SASS! +@import "active_admin/mixins"; +@import "active_admin/base"; + +// Overriding any non-variable SASS must be done after the fact. +// For example, to change the default status-tag color: +// +// .status_tag { background: #6090DB; } diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index f9cd5b3..aa44569 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -1,15 +1,260 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any styles - * defined in the other CSS/SCSS files in this directory. It is generally better to create a new - * file per style scope. - * - *= require_tree . - *= require_self - */ +* { + + font-family: proxima-nova; + font-family: proxima-nova; + +} + + + +.checkbox { + font-size: 20px; +} + +.col-sm-12 search-container{ + padding-top: 50px; + padding-right: 100px; + padding-bottom: 50px; + padding-left: 80px; +} + + +nav { + width: 100%; + height: 100px; + color: #eee; +} + +#button_list ul { +float: right; +margin-right: 60px; +} + +.logo{ + float: left; + line-height: 100px; + padding-left: 20px; +} + +#button_list ul li { +list-style: none; +display: inline-block; +line-height: 100px; +} + +#button_list ul li a { +text-decoration: none; + font-family: proxima-nova; + font-weight: 600; + font-style: normal; + font-size: 13px; + letter-spacing: 2px; + text-transform: uppercase; + text-decoration: none; + line-height: 1em; + padding: 0 20px; + color: black; +} + +#button_list ul li a:hover { +color: green; +} + + + +.wrap { + width: 100%; +} +.image { + width: 100%; + background-image: url(/assets/farm2.jpg); + background-repeat: no-repeat; + background-position: center center; + background-size: cover; + height: 435px; +} +.image:before{ + content: ''; + position: relative; + top: 0; + right: 0; + left: 0; + bottom: 0; + + background: rgba(0.8,0,0,0); +} + +.text { + position: relative; + top: 40%; + left: 30%; + right: 30%; + /* transform: translate(-50%, -50%); */ + font-family: "proxima-nova","Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 60px; + font-weight: bold; + color: white; + +} + + +#map { + border-radius: .1cm; + height: 70vh; + width: 100%; +} + + + +#logoImage: { + + +} + + + +#header { + padding: 0 20px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 1000; + top: 0; + left: 0; + width: 100%; + line-height: 1em; + background-color: #fff; + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: subpixel-antialiased; + position: relative; +} + + +.section-title { + margin: 0px !important; +} + +.jumbotron { + padding-top: 5px !important; + padding-bottom: 5px !important; +} +.search { + margin: 0cm 0cm .25cm 0cm; + width: 100%; +} + +.search-recipes { + margin: 0px !important; + width: 100%; +} +.category-button { + margin: 0cm 0cm .25cm 0cm !important; +} +.list-group-item { + width: 90%; + margin: 5% 5% 5% 5% !important; + padding: 10px 15px 10px 15px; + border-radius: 10px !important; + -webkit-box-shadow: 5px 5px 15px rgba(0,0,0,0.4); + -moz-box-shadow: 5px 5px 15px rgba(0,0,0,0.4); +} +.list-group-item:hover { + background-color: #eeeeee; +} + +.list-group { + height: 70vh; + overflow: hidden; + -webkit-animation: autoScrolling 5s linear infinite; + overflow-y: scroll !important; +} +/*.col-md-4 { + padding: 0% 5% 0% 5%; +} + +.col-md-8 { + padding: 0% 5% 0% 5%; +}*/ + +.search-container { + padding: 2%; +} + +.content-container { + padding: 2% !important; +} + +.scrollmenu { + background-color: #ffffff; + overflow: auto; + white-space: nowrap; +} + +.scrollmenu-item { + display: inline-block; + margin: 10px; + border-radius: 15px; + width: 22vw; + -webkit-box-shadow: 5px 5px 15px rgba(0,0,0,0.4); + -moz-box-shadow: 5px 5px 15px rgba(0,0,0,0.4); + + -webkit-animation: fadein 2s; /* Safari, Chrome and Opera > 12.1 */ + -moz-animation: fadein 2s; /* Firefox < 16 */ + -ms-animation: fadein 2s; /* Internet Explorer */ + -o-animation: fadein 2s; /* Opera < 12.1 */ + animation: fadein 2s; +} +.scrollmenu-item-section { + padding: 10px; +} + +.scrollmenu-item:hover { + background-color: #eeeeee; +} + +.recipe_image { + border-top-left-radius: 15px; + border-top-right-radius: 15px; +} + +@keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Firefox < 16 */ +@-moz-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Safari, Chrome and Opera > 12.1 */ +@-webkit-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +/* Internet Explorer */ +@-ms-keyframes fadein { + from { opacity: 0; } + to { opacity: 1; } +} + +.modal-image { + width: 40vw; + padding: 15px; +} + +.modal-style { + margin: 15px !important; +} + +.tab-pane { + height: 35vh !important; + overflow-y: scroll !important; +} + + + +/* Position of Logo */ +#locator { position: absolute; visibility: visible; right: 0px ; top: 20px; z-index: 200; } diff --git a/app/assets/stylesheets/ui.scss b/app/assets/stylesheets/ui.scss new file mode 100644 index 0000000..6a009fa --- /dev/null +++ b/app/assets/stylesheets/ui.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the UI controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/farms_controller.rb b/app/controllers/farms_controller.rb index 8aa7ae6..ae1d37a 100644 --- a/app/controllers/farms_controller.rb +++ b/app/controllers/farms_controller.rb @@ -2,13 +2,12 @@ class FarmsController < ApplicationController before_filter :skip_authorization before_action :authenticate + skip_before_action :verify_authenticity_token #disable security check? # before_action :authenticate_farm! def show # @farm = Farm.find(parmas[:id]) # authorize @farm - - @show_farms = Farm.where(approved: true) @invalid_farms = Farm.where(approved: false) if params[:id] == "farm_json" @@ -26,6 +25,7 @@ def index @show_farms = Farm.where(approved: true) + # @operation_farms = Farm.where(operation: beef) # @farms_json = buildJson @show_farms # puts @farms_json end @@ -75,13 +75,27 @@ def approved end def farm_json - @show_farms = Farm.where(approved: true) - @farms_json = buildJson @show_farms + show_farms = Farm.where(approved: true).includes([:operations, :growing_methods, :selling_methods]) + render json: show_farms.as_json(include: [:operations, :growing_methods, :selling_methods]) + end + + def farm_by_operation + show_farms = [] + Operation.all.each do |o| + if params[:farms][:operations].include? o.food + show_farm = o.farms + if (!show_farms.include? show_farm) + show_farms.push(show_farm) + end + end + end + render json: show_farms.as_json(include: [:operations, :growing_methods, :selling_methods]) end + - def buildJson farms - render :json => farms - end + # def buildJson farms + # render :json => farms + # end def approve id = params[:item_id] @@ -121,7 +135,7 @@ def authenticate #private def farm_params - params.require(:farm).permit(:name, :address, :url, :phone, :facebook, :instagram, :twitter, :email, :contact_name, :year, :statement, :other_media, :link_to_cert, :growth_promoter, :antibiotic, :fav_activity, :why_farm) + params.require(:farm).permit(:name, :address, :url, :phone, :facebook, :instagram, :twitter, :email, :contact_name, :year, :statement, :other_media, :link_to_cert, :growth_promoter, :antibiotic, :fav_activity, :why_farm, :operations, :primary_operation) end private diff --git a/app/controllers/ui_controller.rb b/app/controllers/ui_controller.rb new file mode 100644 index 0000000..f7ffda4 --- /dev/null +++ b/app/controllers/ui_controller.rb @@ -0,0 +1,4 @@ +class UiController < ApplicationController + def home + end +end diff --git a/app/decorators/ui_decorator.rb b/app/decorators/ui_decorator.rb new file mode 100644 index 0000000..19876eb --- /dev/null +++ b/app/decorators/ui_decorator.rb @@ -0,0 +1,13 @@ +class UiDecorator < Draper::Decorator + delegate_all + + # Define presentation-specific methods here. Helpers are accessed through + # `helpers` (aka `h`). You can override attributes, for example: + # + # def created_at + # helpers.content_tag :span, class: 'time' do + # object.created_at.strftime("%a %m/%d/%y") + # end + # end + +end diff --git a/app/helpers/ui_helper.rb b/app/helpers/ui_helper.rb new file mode 100644 index 0000000..8b831d8 --- /dev/null +++ b/app/helpers/ui_helper.rb @@ -0,0 +1,2 @@ +module UiHelper +end diff --git a/app/models/farm.rb b/app/models/farm.rb index 04de6e4..04aaea3 100644 --- a/app/models/farm.rb +++ b/app/models/farm.rb @@ -4,8 +4,8 @@ class Farm < ActiveRecord::Base # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable - - has_and_belongs_to_many :operations + has_many :farms_operations + has_many :operations, through: :farms_operations has_and_belongs_to_many :growing_methods has_and_belongs_to_many :selling_methods has_and_belongs_to_many :markets diff --git a/app/models/farms_operation.rb b/app/models/farms_operation.rb new file mode 100644 index 0000000..04d429d --- /dev/null +++ b/app/models/farms_operation.rb @@ -0,0 +1,4 @@ +class FarmsOperation < ApplicationRecord + belongs_to :farm + belongs_to :operation +end diff --git a/app/models/growing_method.rb b/app/models/growing_method.rb index e2505e6..682bbed 100644 --- a/app/models/growing_method.rb +++ b/app/models/growing_method.rb @@ -1,3 +1,8 @@ class GrowingMethod < ApplicationRecord has_and_belongs_to_many :farms + +# To display name of growing_method in admin page +def display_name + grow_method +end end diff --git a/app/models/operation.rb b/app/models/operation.rb index 058d659..8a6f692 100644 --- a/app/models/operation.rb +++ b/app/models/operation.rb @@ -1,3 +1,9 @@ class Operation < ApplicationRecord - has_and_belongs_to_many :farms + has_many :farms_operations + has_many :farms, through: :farms_operations + + #To display name of the operation in the admin page +def display_name + food +end end diff --git a/app/models/primary_operation.rb b/app/models/primary_operation.rb new file mode 100644 index 0000000..76bbb7a --- /dev/null +++ b/app/models/primary_operation.rb @@ -0,0 +1,6 @@ +class PrimaryOperation < ApplicationRecord + has_one :operation +def display_name + food +end +end diff --git a/app/models/selling_method.rb b/app/models/selling_method.rb index d087b01..bfcf641 100644 --- a/app/models/selling_method.rb +++ b/app/models/selling_method.rb @@ -1,3 +1,7 @@ class SellingMethod < ApplicationRecord has_and_belongs_to_many :farms +# To display selling_method in admin page +def display_name + sell_method +end end diff --git a/app/views/ui/home.html.erb b/app/views/ui/home.html.erb new file mode 100644 index 0000000..cf0a47c --- /dev/null +++ b/app/views/ui/home.html.erb @@ -0,0 +1,148 @@ + + + + + + + + + + + <%= stylesheet_link_tag "application", media: "all" %> + + + + + +
    +
    +
    +

    Explore our farms

    +
    +
    +
    + +
    +

    Search Local Farms

    + + +
    + + + + + + +
    + +
    + +
    +
    +
    + +
    +
      +
    +
    +
    +
    + +
    +
    +

    Search Recipes

    +
    + +
    + + + + +
    +
    + + + + + + + +
    +
    + +
    +
    +
    + + + + + \ No newline at end of file diff --git a/bundle-log b/bundle-log new file mode 100644 index 0000000..22a151f --- /dev/null +++ b/bundle-log @@ -0,0 +1,87 @@ +Using rake 12.3.1 +Using concurrent-ruby 1.0.5 +Using i18n 0.9.5 +Using minitest 5.11.3 +Using thread_safe 0.3.6 +Using tzinfo 1.2.5 +Using activesupport 5.0.2 +Using builder 3.2.3 +Using erubis 2.7.0 +Using mini_portile2 2.3.0 +Using nokogiri 1.8.2 +Using rails-dom-testing 2.0.3 +Using crass 1.0.4 +Using loofah 2.2.2 +Using rails-html-sanitizer 1.0.4 +Using actionview 5.0.2 +Using rack 2.0.4 +Using rack-test 0.6.3 +Using actionpack 5.0.2 +Using nio4r 2.3.0 +Using websocket-extensions 0.1.3 +Using websocket-driver 0.6.5 +Using actioncable 5.0.2 +Using globalid 0.4.1 +Using activejob 5.0.2 +Using mini_mime 1.0.0 +Using mail 2.7.0 +Using actionmailer 5.0.2 +Using arbre 1.1.1 +Using coffee-script-source 1.12.2 +Using execjs 2.7.0 +Using coffee-script 2.4.1 +Using method_source 0.9.0 +Using thor 0.20.0 +Using railties 5.0.2 +Using coffee-rails 4.1.1 +Using formtastic 3.1.5 +Using formtastic_i18n 0.6.0 +Using has_scope 0.7.2 +Using responders 2.4.0 +Using inherited_resources 1.8.0 +Using jquery-rails 4.3.3 +Using kaminari-core 1.1.1 +Using kaminari-actionview 1.1.1 +Using activemodel 5.0.2 +Using arel 7.1.4 +Using activerecord 5.0.2 +Using kaminari-activerecord 1.1.1 +Using kaminari 1.1.1 +Using polyamorous 1.3.3 +Using ransack 1.8.8 +Using rb-fsevent 0.10.3 +Using ffi 1.9.23 +Using rb-inotify 0.9.10 +Using sass-listen 4.0.0 +Using sass 3.5.6 +Using sprockets 3.7.1 +Using activeadmin 1.2.1 +Using activemodel-serializers-xml 1.0.2 +Using bcrypt 3.1.11 +Using bundler 1.16.1 +Using cancan 1.6.10 +Using orm_adapter 0.5.0 +Using warden 1.2.7 +Using devise 4.4.3 +Using request_store 1.4.1 +Using draper 3.0.1 +Using temple 0.8.0 +Using tilt 2.0.8 +Using haml 5.0.4 +Using multi_json 1.13.1 +Using jbuilder 2.7.0 +Using json 1.8.6 +Using pundit 1.1.0 +Using rack-cors 0.3.1 +Using sprockets-rails 3.2.1 +Using rails 5.0.2 +Using rdoc 4.3.0 +Using sass-rails 5.0.7 +Using sdoc 0.4.2 +Using simple_form 4.0.0 +Using turbolinks-source 5.1.0 +Using turbolinks 5.1.1 +Using uglifier 4.1.9 +Bundle complete! 21 Gemfile dependencies, 84 gems now installed. +Gems in the groups production, development and test were not installed. +Use `bundle info [gemname]` to see where a bundled gem is installed. diff --git a/config/application.rb b/config/application.rb index c270c61..4080c5a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -33,8 +33,10 @@ class Application < Rails::Application origins '*' resource '*', :headers => :any, :methods => [:get, :post, :options] end + end + config.assets.paths << Rails.root.join("assets", "icons") end - end + end diff --git a/config/database.yml b/config/database.yml index 1c1a37c..d6366a2 100644 --- a/config/database.yml +++ b/config/database.yml @@ -5,21 +5,34 @@ # gem 'sqlite3' # default: &default - adapter: sqlite3 + adapter: postgresql pool: 5 timeout: 5000 development: - <<: *default - database: db/development.sqlite3 + adapter: sqlite3 + pool: 5 + #username: local_foods + # password: + database: lfc_development.sqlite3 + timeout: 5000 + # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: - <<: *default - database: db/test.sqlite3 + adapter: sqlite3 + pool: 5 + #username: local_foods + #password: + database: lfc_test.sqlite3 + timeout: 5000 production: - <<: *default - database: db/production.sqlite3 + adapter: postgresql + pool: 5 + username: local_foods + password: + database: lfc_production + timeout: 5000 diff --git a/config/routes.rb b/config/routes.rb index 01c6ff7..4fc9c15 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,7 @@ Rails.application.routes.draw do + get 'ui/home' + devise_for :farms, ActiveAdmin::Devise.config ActiveAdmin.routes(self) resources :farms @@ -9,10 +11,20 @@ scope '/v1' do scope '/farms' do post '/' => 'farms#farm_json' + + end + end + end + + scope '/api' do + scope '/v1' do + scope '/farms' do + post '/farm_by_operation' => 'farms#farm_by_operation' end end end + root :to => redirect('/admin') get 'farms/review' diff --git a/db/migrate/20171012170351_create_farms.rb b/db/migrate/20171012170351_create_farms.rb index 251ad76..fdc0881 100644 --- a/db/migrate/20171012170351_create_farms.rb +++ b/db/migrate/20171012170351_create_farms.rb @@ -8,7 +8,7 @@ def change t.string :facebook t.string :instagram t.string :twitter - + t.string :type_of_farm t.timestamps null: false end end diff --git a/db/migrate/20180228195837_add_new_column_to_my_table.rb b/db/migrate/20180228195837_add_new_column_to_my_table.rb new file mode 100644 index 0000000..d34e833 --- /dev/null +++ b/db/migrate/20180228195837_add_new_column_to_my_table.rb @@ -0,0 +1,5 @@ +class AddNewColumnToMyTable < ActiveRecord::Migration[5.0] + def change + add_column :farms, :farm_type, :string + end +end diff --git a/db/migrate/20180425200411_create_primary_operations.rb b/db/migrate/20180425200411_create_primary_operations.rb new file mode 100644 index 0000000..f53eccc --- /dev/null +++ b/db/migrate/20180425200411_create_primary_operations.rb @@ -0,0 +1,9 @@ +class CreatePrimaryOperations < ActiveRecord::Migration[5.0] + def change + create_table :primary_operations do |t| + t.string :food + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 0d59914..6a83ad6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171205061024) do +ActiveRecord::Schema.define(version: 20180425200411) do create_table "active_admin_comments", force: :cascade do |t| t.string "namespace" @@ -34,6 +34,7 @@ t.string "facebook" t.string "instagram" t.string "twitter" + t.string "type_of_farm" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.boolean "approved", default: false @@ -58,6 +59,7 @@ t.text "fav_activity" t.text "why_farm" t.integer "role" + t.string "farm_type" t.index ["email"], name: "index_farms_on_email", unique: true t.index ["reset_password_token"], name: "index_farms_on_reset_password_token", unique: true end @@ -108,6 +110,12 @@ t.string "food" end + create_table "primary_operations", force: :cascade do |t| + t.string "food" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "selling_methods", force: :cascade do |t| t.datetime "created_at", null: false t.datetime "updated_at", null: false diff --git a/db/seeds/seed_farm.rb b/db/seeds/seed_farm.rb index cf3bd92..ecd837a 100644 --- a/db/seeds/seed_farm.rb +++ b/db/seeds/seed_farm.rb @@ -19,7 +19,11 @@ "ujpassword", 0], ["Aunt Maria's Farm", "1641 Park St.", "auntmaria.com", "5150009999", \ "Aunt Maria's Farm", "auntmaria_farm", "auntmaria_farm", false, \ - "auntmaria@example.com", "awpassword", "awpassword", 0] + "auntmaria@example.com", "awpassword", "awpassword", 0], + ["Aunt Maria's Farm", "1641 Park St.", "auntmaria.com", "5150009999", \ + "Aunt Maria's Farm", "auntmaria_farm", "auntmaria_farm", true, \ + "auntmaria1@example.com", "awpassword", "awpassword", 0] + ] farm_list.each do |name, address, url, phone, facebook, instagram, twitter, approved, email, password, password_confirmation| diff --git a/db/seeds/seed_operation.rb b/db/seeds/seed_operation.rb index 9d62009..edaf035 100644 --- a/db/seeds/seed_operation.rb +++ b/db/seeds/seed_operation.rb @@ -1,4 +1,4 @@ -operation_list = ["fruit", "vegetables", "dairy", "pork", "chicken", "turkey", "lamb", "duck", "agritourism", "hay", "row crop"] +operation_list = ["fruit", "vegetables", "dairy", "pork", "chicken", "turkey", "lamb", "duck", "agritourism", "hay", "row crop", "food pantry"] operation_list.each do |food| Operation.create!(food: food) diff --git a/db/seeds/seed_primary_operation.rb b/db/seeds/seed_primary_operation.rb new file mode 100644 index 0000000..ab8aed2 --- /dev/null +++ b/db/seeds/seed_primary_operation.rb @@ -0,0 +1,6 @@ + +operation_list = ["fruit", "vegetables", "dairy", "pork", "chicken", "turkey", "lamb", "duck", "agritourism", "hay", "row crop", "food pantry"] + +operation_list.each do |food| + PrimaryOperation.create!(food: food) +end \ No newline at end of file diff --git a/javascript_app/.DS_Store b/javascript_app/.DS_Store new file mode 100644 index 0000000..76de8e2 Binary files /dev/null and b/javascript_app/.DS_Store differ diff --git a/javascript_app/carrot.png b/javascript_app/carrot.png new file mode 100644 index 0000000..6b1b1d2 Binary files /dev/null and b/javascript_app/carrot.png differ diff --git a/javascript_app/farm2.JPG b/javascript_app/farm2.JPG new file mode 100644 index 0000000..2ab092f Binary files /dev/null and b/javascript_app/farm2.JPG differ diff --git a/javascript_app/farm2.jpg b/javascript_app/farm2.jpg new file mode 100644 index 0000000..c5f19f2 Binary files /dev/null and b/javascript_app/farm2.jpg differ diff --git a/javascript_app/icons/agricultural.png b/javascript_app/icons/agricultural.png new file mode 100644 index 0000000..a151cff Binary files /dev/null and b/javascript_app/icons/agricultural.png differ diff --git a/javascript_app/icons/dairy_free.png b/javascript_app/icons/dairy_free.png new file mode 100644 index 0000000..43c9bde Binary files /dev/null and b/javascript_app/icons/dairy_free.png differ diff --git a/javascript_app/icons/gluten_free.png b/javascript_app/icons/gluten_free.png new file mode 100644 index 0000000..558d955 Binary files /dev/null and b/javascript_app/icons/gluten_free.png differ diff --git a/javascript_app/icons/kosher.png b/javascript_app/icons/kosher.png new file mode 100644 index 0000000..30b07b7 Binary files /dev/null and b/javascript_app/icons/kosher.png differ diff --git a/javascript_app/icons/peanut_free.jpg b/javascript_app/icons/peanut_free.jpg new file mode 100644 index 0000000..ca38b82 Binary files /dev/null and b/javascript_app/icons/peanut_free.jpg differ diff --git a/javascript_app/icons/steak-512.png b/javascript_app/icons/steak-512.png new file mode 100644 index 0000000..c5182d0 Binary files /dev/null and b/javascript_app/icons/steak-512.png differ diff --git a/javascript_app/icons/tree_nut_free.jpg b/javascript_app/icons/tree_nut_free.jpg new file mode 100644 index 0000000..5eda7af Binary files /dev/null and b/javascript_app/icons/tree_nut_free.jpg differ diff --git a/javascript_app/icons/vegetarian.jpg b/javascript_app/icons/vegetarian.jpg new file mode 100644 index 0000000..e78c81c Binary files /dev/null and b/javascript_app/icons/vegetarian.jpg differ diff --git a/javascript_app/index.css b/javascript_app/index.css index b9a293b..c81cad6 100644 --- a/javascript_app/index.css +++ b/javascript_app/index.css @@ -1,16 +1,141 @@ +* { + + font-family: proxima-nova; + font-family: proxima-nova; + +} + + +.checkbox { + font-size: 16px; +} + +.col-sm-12 search-container{ + padding-top: 50px; + padding-right: 100px; + padding-bottom: 50px; + padding-left: 80px; +} + + +nav { + width: 100%; + height: 100px; + color: #eee; +} + +#button_list ul { +float: right; +margin-right: 60px; +} + +.logo{ + float: left; + line-height: 100px; + padding-left: 20px; +} + +#button_list ul li { +list-style: none; +display: inline-block; +line-height: 100px; +} + +#button_list ul li a { +text-decoration: none; + font-family: proxima-nova; + font-weight: 600; + font-style: normal; + font-size: 13px; + letter-spacing: 2px; + text-transform: uppercase; + text-decoration: none; + line-height: 1em; + padding: 0 20px; + color: black; +} + +#button_list ul li a:hover { +color: green; +} + + + +.wrap { + width: 100%; +} +.image { + width: 100%; + background-image: url(../javascript_app/farm2.jpg); + background-repeat: no-repeat; + background-position: center center; + background-size: cover; + height: 435px; +} +.image:before{ + content: ''; + position: relative; + top: 0; + right: 0; + left: 0; + bottom: 0; + + background: rgba(0.8,0,0,0); +} + +.text { + position: relative; + top: 40%; + left: 30%; + right: 30%; + /* transform: translate(-50%, -50%); */ + font-family: "proxima-nova","Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 60px; + font-weight: bold; + color: white; + +} + + #map { border-radius: .1cm; height: 70vh; width: 100%; } + + +#logoImage: { + + +} + + + +#header { + padding: 0 20px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 1000; + top: 0; + left: 0; + width: 100%; + line-height: 1em; + background-color: #fff; + -moz-osx-font-smoothing: auto; + -webkit-font-smoothing: subpixel-antialiased; + position: relative; +} + + .section-title { margin: 0px !important; } .jumbotron { padding-top: 5px !important; - padding-bottom: 5px !important; + padding-bottom: 5px !important; } .search { margin: 0cm 0cm .25cm 0cm; @@ -88,7 +213,7 @@ .recipe_image { border-top-left-radius: 15px; - border-top-right-radius: 15px; + border-top-right-radius: 15px; } @keyframes fadein { @@ -127,3 +252,8 @@ height: 35vh !important; overflow-y: scroll !important; } + + + +/* Position of Logo */ +#locator { position: absolute; visibility: visible; right: 0px ; top: 20px; z-index: 200; } diff --git a/javascript_app/index.html b/javascript_app/index.html index 10b12f6..ed99420 100644 --- a/javascript_app/index.html +++ b/javascript_app/index.html @@ -1,5 +1,5 @@ - + @@ -8,64 +8,66 @@ + + - - - -
    -
    -

    Local Foods Connection

    -

    Explore farms in the Poweshiek County area!

    + +
    +
    +
    +

    Explore our farms

    +
    - -
    -

    Explore Local Farms

    - +
    +

    Search Local Farms

    - -
    - - - - - - - +
    + + + + + +
    -
    -
    -
      @@ -73,13 +75,11 @@

      Explore Local Farms

    -
    -

    Search Recipes

    +

    Search Recipes

    -
    @@ -87,25 +87,30 @@

    Search Recipes

    - +
    + + + + + + + +
    -
    - - + \ No newline at end of file diff --git a/javascript_app/index.js b/javascript_app/index.js index 3a3044e..9998b39 100644 --- a/javascript_app/index.js +++ b/javascript_app/index.js @@ -3,9 +3,10 @@ var geocoder; var farms = {}; var recipes = {}; // api keys -var edemam_app_id = "c1a85afb"; -var edemam_app_key = "0bf8d80e45004f66c8d4a9e6a523f14f"; +var edemam_app_id = "0649d198"; +var edemam_app_key = "77bd12dd099e7f2c02338006ef659724"; var lfc_key = "YAS0sY2rbi"; +var base_url = "http://localhost:3000"; init(); @@ -13,41 +14,132 @@ init(); * INIT * ********/ +$(document).ready(function() { + $(".dropdown-menu li a").click(function() { + $("#category_button").text($(this).text()); + }); +}); + + function init() { // set up recipe search document.getElementById("search_recipes").onclick = function() { + var checkRecipeValues = []; + $('input[name=recipeCheckboxList]:checked').each(function() { + console.log("HERE" + $(this).val()); + checkRecipeValues.push($(this).val()); + }); var text = $('#recipe_search_text').val(); text = text.split(' ').join('%20') if (text != "") { - callFood2Fork(text); + callFood2Fork(text, checkRecipeValues); } - } + }; // set up farm search document.getElementById("search_farm").onclick = function() { + DeleteMarkers(); + var checkValues = []; + $('input[name=checkboxList]:checked').each(function() { + console.log($(this).val()); + if ($(this).val() == "meat") + checkValues.push("lamb", "beef", "chicken", "pork"); + else if ($(this).val() == "agritourism") + checkValues.push("agritourism", "hay", "row crop"); + else + checkValues.push($(this).val()); + + }); + callIndexApi2(checkValues); + var text = $('#search_farm_text').val(); - if (text != "") { - // call search api here + var search_by = $('#category_button').text(); + // Search by Address + if (search_by == "Address") { + if (text != "") { + geocoder.geocode({ + 'address': text + }, function(results, status) { + if (status == 'OK') { + map.setCenter(results[0].geometry.location); + map.setZoom(17); + //map.panTo(curmarker.position); + var marker = new google.maps.Marker({ + map: map, + position: results[0].geometry.location + }); + } else { + alert('Geocode was not successful for the following reason: ' + status); + } + }); + } + // Search by Farm's Name + } else if (search_by == "Farm's Name") { + + var farms = []; + + var call_url = base_url + "/farms/farm_json"; + $.ajax({ + type: "GET", + url: call_url, + headers: { + 'X-Auth-Token': lfc_key + }, + dataType: 'json', + contentType: 'application/json', + crossDomain: true, + async: false, + success: function(result) { + if (result != null || result.length > 0) { + farms = handleAddressCall(result, text); + handleIndexCall3(farms); + // text += "Iowa, 50112"; // this is temporary + } else { + alert("Your search query returned no results . . . ") + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown) { + console.log("Status: " + textStatus); + console.log("Error: " + errorThrown); + } + }); + if (text != "") { + geocoder.geocode({ + 'address': text + }, function(results, status) { + if (status == 'OK') { + map.setCenter(results[0].geometry.location); + map.setZoom(17); + //map.panTo(curmarker.position); ?? + var marker = new google.maps.Marker({ + map: map, + position: results[0].geometry.location + }); + } else { + alert('Geocode was not successful for the following reason: ' + status); + } + }); + } + } else { + document.getElementById("search_farm_text").text = "You must enter a username"; } } - - // callFood2Fork(["peas","carrots"]); } /************* * INIT MAP * * ***********/ - function initMap() { // set location set to grinnell as center of map var grinnell = { lat: 41.7434, - lng: -92.7232 }; + lng: -92.7232 + }; // init map map = new google.maps.Map(document.getElementById('map'), { - zoom: 10, + zoom: 13.7, center: grinnell }); @@ -64,7 +156,9 @@ function initMap() { function geocodeAddressAndAddMarker(farm) { var address = farm.address + ", Iowa, 50112" - geocoder.geocode({'address': address}, function(results, status) { + geocoder.geocode({ + 'address': address + }, function(results, status) { // if OK/200 status, add marker to map, else throw alert. if (status === 'OK') { addMarker(farm, results); @@ -74,20 +168,55 @@ function geocodeAddressAndAddMarker(farm) { }); } +var markers = [] +// "fruit", "vegetables", "dairy", "pork", "chicken", "turkey", "lamb", "duck", "agritourism", "hay", "row crop", "food pantry"] function addMarker(farm, results) { + console.log("NAme " + farm.name); + console.log( "Length" + farm.operations.length); + var operation_icon; + if (farm.operations.length == 0) { + operation_icon = '../javascript_app/icons/64cow.png'; + } else { + var primary_operation = farm.operations[0].food; + console.log(primary_operation.food); + if (primary_operation == "cow" || primary_operation == "pork" || primary_operation == "chicken" || + primary_operation == "turkey" || primary_operation == "lamb" || primary_operation == "duck") { + operation_icon = '../javascript_app/icons/steak-512.png'; + } else if (primary_operation == "fruit") { + console.log("HERE"); + operation_icon = '../javascript_app/icons/24apple.png'; + } else if (primary_operation == "vegetables") { + operation_icon = '../javascript_app/icons/24broccoli.png'; + } else if (primary_operation == "dairy") { + operation_icon = '../javascript_app/icons/24dairy.png'; + } else if (primary_operation == "agritourism" || primary_operation == "hay" || primary_operation == "row crop") { + operation_icon = '../javascript_app/icons/agricultural.png'; + } else if (primary_operation == "") { - var iconCow = '../icons/64cow.png' + } + } + var iconCow = '../javascript_app/icons/64cow.png' + var iconPig = '../javascript_app/icons/24pig.png' -// create marker object + + // create marker object var marker = new google.maps.Marker({ map: map, animation: google.maps.Animation.BOUNCE, position: results[0].geometry.location, title: farm.name, - icon: iconCow + icon: operation_icon }); + // var marker = new google.maps.Marker({ + // map: map, + // animation: google.maps.Animation.BOUNCE, + // position: results[0].geometry.location, + // title: farm.name, + // icon: iconPig + // }); + // data string for display tooltip var data = farm.name; // info window for tooltip, contains data @@ -97,10 +226,19 @@ function addMarker(farm, results) { // add listener to map for marker to display info window google.maps.event.addListener(marker, 'click', function() { // open info window - infowindow.open(map,marker); + infowindow.open(map, marker); }); + markers.push(marker); } +function DeleteMarkers() { + //Loop through all the markers and remove + for (var i = 0; i < markers.length; i++) { + markers[i].setMap(null); + } + markers = []; +}; + /*********************** * FARM API FUNCTIONS * * *********************/ @@ -108,12 +246,13 @@ function addMarker(farm, results) { function callIndexApi() { document.getElementById("farmList").innerHTML = ""; - var call_url = "http://localhost:3000/farms/farm_json"; + + var call_url = base_url + "/farms/farm_json"; $.ajax({ type: "GET", url: call_url, headers: { - 'X-Auth-Token' : lfc_key + 'X-Auth-Token': lfc_key }, dataType: 'json', contentType: 'application/json', @@ -131,16 +270,17 @@ function callIndexApi() { console.log("Error: " + errorThrown); } }); + } -function handleIndexCall(result) { +function handleIndexCall(result) { // set to new map farms = {}; - for (var i = 0; i < result.length; i++) { // create id var id = "farm_" + result[i].id; + // add to map farms[id] = result[i]; // append card @@ -155,7 +295,7 @@ function handleIndexCall(result) { // on click to show modal $('#' + id).on('click', function() { var new_id = this.getAttribute('id'); - console.log(new_id); + // console.log(new_id); // alter html in modal setAndShowFarmModal(farms[new_id]); }); @@ -165,27 +305,66 @@ function handleIndexCall(result) { } } +function handleAddressCall(result, addressSearch) { + farms = []; + + + for (var i = 0; i < result.length; i++) { + // create id + var name = result[i].name; + var id = "farm_" + result[i].id; + // add to map + //farms[id] = result[i]; + console.log("name is " + name); + if ((name.toLowerCase()).includes(addressSearch.toLowerCase())) { + console.log("name is " + name); + // return result[i].address; + farms.push(result[i]); + } + + + } + console.log("Address call to farms"); + console.log(farms); + + + return farms; + + +} + /************************* * RECIPE API FUNCTIONS * * ***********************/ -function callFood2Fork(food_string) { - +function callFood2Fork(food_string, checkRecipeValues) { // clear the html to get rid of old recipes $("#recipe_grid").html(""); // set new url to access - var call_url = "https://api.edamam.com/search?q=" + food_string - + "&app_id=" + edemam_app_id - + "&app_key=" + edemam_app_key; + // var call_url = "https://api.edamam.com/search?q=${food_string}&app_id=${edemam_app_id}&app_key=${edemam_app_key}" + var call_url = "https://api.edamam.com/search?q=" + food_string + "&app_id=" + edemam_app_id + "&app_key=" + edemam_app_key; + var health_query = ""; + console.log(checkRecipeValues); + for (var i = 0; i < checkRecipeValues.length; i++) { + console.log(checkRecipeValues[i]); + if (i != checkRecipeValues.length - 1) { + health_query += checkRecipeValues[i] + ',%20'; + } + } + if (checkRecipeValues.length > 0) { + call_url += "&healthLabels=" + health_query; + } + // call_url += &ingr= [] once we make a max-ingredients button + // call_url += &time= [] once we have a max-time option // make call $.ajax({ type: "GET", url: call_url, headers: { - // "Access-Control-Allow-Origin":"*" - "more" : true, + // "Access-Control-Allow-Origin":"*" + "more": true, }, dataType: 'json', //contentType: 'text/plain;charset=UTF-8', @@ -224,12 +403,12 @@ function handleRecipeAPICall(recipe_list) { // add html $('#recipe_grid').append( '
    ' + - '' + - '
    ' + - '

    ' + current_recipe.label + '

    ' + - '
    ' + current_recipe.source + '
    ' + - 'Go to recipe' + - '' + + '
    ' + + '

    ' + current_recipe.label + '

    ' + + '
    ' + current_recipe.source + '
    ' + + 'Go to recipe' + + '' ); @@ -245,29 +424,90 @@ function handleRecipeAPICall(recipe_list) { /******************** * MODAL FUNCTIONS * * ******************/ +function capitalize_words(str) { + return str.replace(/\w\S*/g, function(txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); +} + +function getOperation(farm) { + var result = ""; + if (!farm.operations) { + farm = farm[0]; + } + for (var i = 0; i < farm.operations.length; i++) { + result += capitalize_words(farm.operations[i].food); + if (i != farm.operations.length - 1) { + result += ', '; + } + } + + if (result == "") { + return "N/A" + } + return result; +} + +function getGrowingMethod(farm) { + var result = ""; + if (!farm.growing_methods) { + farm = farm[0]; + } + for (var i = 0; i < farm.growing_methods.length; i++) { + result += capitalize_words(farm.growing_methods[i].grow_method); + if (i != farm.growing_methods.length - 1) { + result += ', '; + } + } + if (result == "") { + return "N/A" + } + return result +} + +function getSellingMethod(farm) { + var result = ""; + if (!farm.selling_methods) { + farm = farm[0]; + } + for (var i = 0; i < farm.selling_methods.length; i++) { + result += capitalize_words(farm.selling_methods[i].sell_method); + if (i != farm.selling_methods.length - 1) { + result += ', '; + } + } + + if (result == "") { + return "N/A" + } + return result; +} function setAndShowFarmModal(farm) { // set modal header html + console.log(farm); $('#modal_header').html('

    ' + farm.name + '

    '); // set modal tab 1 html $('#tab_1_title').html('Home'); $('#tab_1').html( - '

    HOME

    ' + - '

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

    ' + '

    Basic Information:' + '

    ' + + '

    Growing Method: ' + getGrowingMethod(farm) + '

    ' + + '

    Operation: ' + getOperation(farm) + '

    ' + + '

    Selling Method: ' + getSellingMethod(farm) + '

    ' ); // set modal tab 2 html $('#tab_2_title').html('Contact'); $('#tab_2').html( - '

    ' + farm.address + '

    ' + - '

    ' + farm.phone + '

    ' + - '
    ' + - ' Visit our webpage | ' + - 'Facebook | ' + - 'Twitter' + - '
    ' + '

    ' + farm.address + '

    ' + + '

    ' + farm.phone + '

    ' + + '
    ' + + ' Visit our webpage | ' + + 'Facebook | ' + + 'Twitter' + + '
    ' ); // set modal tab 3 html @@ -293,49 +533,43 @@ function setAndShowFarmModal(farm) { } function setAndShowRecipeModal(recipe) { - // set modal header html $('#modal_header').html( '

    ' + recipe.label + '

    ' + '

    ' + recipe.source + '

    ' ); - // compile tab 1 data var ingredient_list = '
      '; - for(var i = 0; i < recipe.ingredients.length; i++) { + for (var i = 0; i < recipe.ingredients.length; i++) { ingredient_list += "
    • " + recipe.ingredients[i].text + "
    • "; } ingredient_list += "
    "; - // compile tab 2 data var health_list = '
      '; - for(var i = 0; i < recipe.digest.length; i++) { - health_list += "
    • " - + recipe.digest[i].label - + '' - + Math.round(recipe.digest[i].total * 10) / 10 - + recipe.digest[i].unit - + "
    • "; + for (var i = 0; i < recipe.digest.length; i++) { + health_list += "
    • " + + recipe.digest[i].label + + '' + + Math.round(recipe.digest[i].total * 10) / 10 + + recipe.digest[i].unit + + "
    • "; } health_list += "
    "; - // compile tab 3 data var nutrient_list = '
      '; - for(var key in recipe.totalDaily) { + for (var key in recipe.totalDaily) { //if (!recipe.totalDaily.hasOwnProperty(key)) continue; - - nutrient_list += '
    • ' - + recipe.totalDaily[key].label - + '' - + Math.round(recipe.totalNutrients[key].quantity * 10) / 10 - + recipe.totalNutrients[key].unit + ' (' - + Math.round(recipe.totalDaily[key].quantity * 10) / 10 - + recipe.totalDaily[key].unit - + ")
    • "; + nutrient_list += '
    • ' + + recipe.totalDaily[key].label + + '' + + Math.round(recipe.totalNutrients[key].quantity * 10) / 10 + + recipe.totalNutrients[key].unit + ' (' + + Math.round(recipe.totalDaily[key].quantity * 10) / 10 + + recipe.totalDaily[key].unit + + ")
    • "; } nutrient_list += "
    "; // compile tab 4 data - // set all modal tabs html content $('#tab_1_title').html('Ingredients'); $('#tab_1').html(ingredient_list); @@ -343,13 +577,121 @@ function setAndShowRecipeModal(recipe) { $('#tab_2').html(health_list); $('#tab_3_title').html("Nutrients"); $('#tab_3').html(nutrient_list); - // hide button $('#contact_button').hide(); $('#recipe_link_button').show(); $('#recipe_link_tag').attr("href", recipe.url); - - // show modal $("#generic_modal").modal() } + +function callIndexApi2(operations) { + document.getElementById("farmList").innerHTML = ""; + // var test = ["lamb", "duck"]; + var call_url = base_url + "/api/v1/farms/farm_by_operation"; + $.ajax({ + type: "POST", + url: call_url, + data: JSON.stringify({ + "farms": { + "operations": operations + } + }), + headers: { + 'X-Auth-Token': lfc_key + }, + dataType: 'json', + contentType: 'application/json', + crossDomain: true, + async: false, + success: function(result) { + if (result != null || result.length > 0) { + console.log("LENGTH" + result.length); + handleIndexCall2(result); + } else { + alert("Your search query returned no results . . . ") + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown) { + console.log("Status: " + textStatus); + console.log("Error: " + errorThrown); + + + } + }); + +} + +function handleIndexCall2(result) { + // set to new map + farms = {}; + var farm; + for (var i = 0; i < result.length; i++) { + console.log(result[i]); + farm = result[i][0]; + // create id + if (!farm) { + continue; + } + var id = "farm_" + farm.id; + console.log(farm.id); + + // add to map + farms[id] = result[i]; + // // append card + $('#farmList').append('
  • ' + + '

    ' + farm.name + '

    ' + + '
    ' + farm.address + '
    ' + + '

    CSA, Wholesale, and Farmers Market

    ' + + '' + farm.url + ' | ' + + '' + farm.phone + '' + + '
  • ' + ); + // // on click to show modal + $('#' + id).on('click', function() { + var new_id = this.getAttribute('id'); + setAndShowFarmModal(farms[new_id]); + }); + + // // add marker at proper placec + geocodeAddressAndAddMarker(farm); + } +} + + +function handleIndexCall3(result) { + // set to new map + farms = {}; + var farm; + console.log("In IndexCall3"); + for (var i = 0; i < result.length; i++) { + console.log(result[i]); + farm = result[i]; + // create id + if (!farm) { + continue; + } + var id = "farm_" + farm.id; + console.log("ID" + farm.id); + + // add to map + farms[id] = result[i]; + // // append card + $('#farmList').append('
  • ' + + '

    ' + farm.name + '

    ' + + '
    ' + farm.address + '
    ' + + '

    CSA, Wholesale, and Farmers Market

    ' + + '' + farm.url + ' | ' + + '' + farm.phone + '' + + '
  • ' + ); + // // on click to show modal + $('#' + id).on('click', function() { + var new_id = this.getAttribute('id'); + setAndShowFarmModal(farms[new_id]); + }); + + // // add marker at proper placec + geocodeAddressAndAddMarker(farm); + } +} \ No newline at end of file diff --git a/javascript_app/index.zip b/javascript_app/index.zip new file mode 100644 index 0000000..1e070e5 Binary files /dev/null and b/javascript_app/index.zip differ diff --git a/javascript_app/logo.png b/javascript_app/logo.png new file mode 100644 index 0000000..640bc00 Binary files /dev/null and b/javascript_app/logo.png differ diff --git a/lfc_development.sqlite3 b/lfc_development.sqlite3 new file mode 100644 index 0000000..a09b895 Binary files /dev/null and b/lfc_development.sqlite3 differ diff --git a/lfc_test.sqlite3 b/lfc_test.sqlite3 new file mode 100644 index 0000000..321f966 Binary files /dev/null and b/lfc_test.sqlite3 differ diff --git a/test/controllers/ui_controller_test.rb b/test/controllers/ui_controller_test.rb new file mode 100644 index 0000000..929924f --- /dev/null +++ b/test/controllers/ui_controller_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' + +class UiControllerTest < ActionDispatch::IntegrationTest + test "should get home" do + get ui_home_url + assert_response :success + end + +end diff --git a/test/decorators/ui_decorator_test.rb b/test/decorators/ui_decorator_test.rb new file mode 100644 index 0000000..5d71bea --- /dev/null +++ b/test/decorators/ui_decorator_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class UiDecoratorTest < Draper::TestCase +end diff --git a/test/fixtures/farms_operations.yml b/test/fixtures/farms_operations.yml new file mode 100644 index 0000000..80aed36 --- /dev/null +++ b/test/fixtures/farms_operations.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/fixtures/primary_operations.yml b/test/fixtures/primary_operations.yml new file mode 100644 index 0000000..87b1ade --- /dev/null +++ b/test/fixtures/primary_operations.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + food: MyString + +two: + food: MyString diff --git a/test/models/farms_operation_test.rb b/test/models/farms_operation_test.rb new file mode 100644 index 0000000..332be27 --- /dev/null +++ b/test/models/farms_operation_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class FarmsOperationTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/primary_operation_test.rb b/test/models/primary_operation_test.rb new file mode 100644 index 0000000..01be4c7 --- /dev/null +++ b/test/models/primary_operation_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class PrimaryOperationTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end