Material design changes

This commit is contained in:
Brenda Wallace
2019-02-15 21:06:37 +13:00
parent 3967e68038
commit 3ed173ebcd
64 changed files with 1170 additions and 567 deletions

View File

@@ -17,6 +17,9 @@ gem 'jsonapi-resources'
# CSS framework
gem 'bootstrap-sass'
gem 'bootstrap', '4.1.1'
gem 'material-sass', '4.1.1'
gem 'material_icons'
gem 'font-awesome-sass'
gem 'uglifier' # JavaScript compressor

View File

@@ -66,6 +66,10 @@ GEM
bonsai-elasticsearch-rails (7.0.1)
elasticsearch-model (< 8)
elasticsearch-rails (< 8)
bootstrap (4.1.1)
autoprefixer-rails (>= 6.0.3)
popper_js (>= 1.12.9, < 2)
sass (>= 3.5.2)
bootstrap-datepicker-rails (1.8.0.1)
railties (>= 3.0)
bootstrap-kaminari-views (0.0.5)
@@ -280,6 +284,11 @@ GEM
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
material-sass (4.1.1)
autoprefixer-rails (>= 6.0.3)
sass (>= 3.5.2)
material_icons (2.2.1)
railties (>= 3.2)
memcachier (0.0.2)
method_source (0.9.2)
mime-types (3.2.2)
@@ -336,6 +345,7 @@ GEM
capybara (>= 2.1, < 4)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
popper_js (1.14.5)
powerpack (0.1.2)
public_suffix (3.0.3)
puma (3.12.0)
@@ -510,6 +520,7 @@ DEPENDENCIES
better_errors
bluecloth
bonsai-elasticsearch-rails
bootstrap (= 4.1.1)
bootstrap-datepicker-rails
bootstrap-kaminari-views
bootstrap-sass
@@ -556,6 +567,8 @@ DEPENDENCIES
letter_opener
listen
loofah (>= 2.2.1)
material-sass (= 4.1.1)
material_icons
memcachier
newrelic_rpm
omniauth (~> 1.3)

View File

@@ -18,4 +18,8 @@
// = require jquery-ui/widgets/autocomplete
// = require bootstrap-sprockets
// = require bootstrap-datepicker
// = require jquery
// = require popper
// = require bootstrap
// = require material
// = require_tree .

212
app/assets/javascripts/jquery-roadmap.js vendored Normal file
View File

@@ -0,0 +1,212 @@
;(function(factory) {
"use strict";
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports !== 'undefined') {
module.exports = factory(require('jquery'), window, document);
} else {
factory(jQuery, window, document);
}
}(function($, window, document, undefined ) {
"use strict";
// undefined is used here as the undefined global variable in ECMAScript 3 is
// mutable (ie. it can be changed by someone else). undefined isn't really being
// passed in so we can ensure the value of it is truly undefined. In ES5, undefined
// can no longer be modified.
// window and document are passed through as local variables rather than global
// as this (slightly) quickens the resolution process and can be more efficiently
// minified (especially when both are regularly referenced in your plugin).
/**
* jQuery custom plugin implement the roadmap functionality
*/
$.fn.roadmap = function(events, opts) {
if ( !events instanceof Array ) {
events = [];
}
var defaults = {
slide: 1,
eventsPerSlide: 6,
rootClass: 'roadmap',
prevArrow: 'prev',
nextArrow: 'next',
orientation: 'auto',
eventTemplate: '<div class="event">' +
'<div class="event__date">####DATE###</div>' +
'<div class="event__content">####CONTENT###</div>' +
'</div>'
};
var settings = $.extend({}, defaults, opts);
var buildEvent = function(event, key) {
var html = '<li class="' + settings.rootClass + '__events__event">' + settings.eventTemplate + '</li>';
html = html.replace('####DATE###', event.date);
html = html.replace('####CONTENT###', event.content);
var left = (100/(settings.eventsPerSlide-1))*key;
return $(html).css('left', left + '%');
}
return this.each(function() {
var _this = this;
var $this = $(this);
var currentSlide = settings.slide - 1;
/**
* Store events and settings
*/
$this.data({
events: events,
settings: settings,
currentSlide: currentSlide
}).addClass(settings.rootClass);
var clear = function() {
$this.removeClass(settings.rootClass + '--initialized');
$this.find('.' + settings.rootClass + '__events').remove();
$this.find('.' + settings.rootClass + '__navigation').remove();
}
var buildEvents = function() {
var currentSlide = $this.data('currentSlide');
var settings = $this.data('settings');
var events = $this.data('events');
$('<ol/>', {class: settings.rootClass + '__events'}).append(events.slice((currentSlide*settings.eventsPerSlide), ((currentSlide+1)*settings.eventsPerSlide)).map(buildEvent)).appendTo(_this);
}
var buildNavigation = function() {
var currentSlide = $this.data('currentSlide');
var buildNav = function(nav) {
switch (nav) {
case 'prev':
if ( currentSlide > 0 ) {
return $('<li><a href="#" class="' + nav + '">' + settings.prevArrow + '</a></li>');
}
break;
case 'next':
if ( (currentSlide+1)*settings.eventsPerSlide < events.length ) {
return $('<li><a href="#" class="' + nav + '">' + settings.nextArrow + '</a></li>');
}
break;
}
return $('<li></li>');
}
$('<ul/>', {class: settings.rootClass + '__navigation'}).append(['prev', 'next'].map(buildNav)).appendTo(_this);
}
var setOrientation = function() {
var getOrientation = function() {
switch (settings.orientation) {
case 'horizontal':
case 'vertical':
case 'auto':
return settings.orientation;
break;
}
return 'auto';
}
$this.addClass(settings.rootClass + '--orientation-' + getOrientation());
}
var build = function() {
clear();
/**
* Init events
*/
buildEvents();
/**
* Init navigation
*/
buildNavigation();
/**
* Set orientation
*/
setOrientation();
/**
* Initialize
*/
setTimeout(function() {
$this.addClass(settings.rootClass + '--initialized');
}, 100);
}
/**
* Build roadmap
*/
build();
/**
* Event Listeners
*/
$('body').on('click', '.' + settings.rootClass + ' .' + settings.rootClass + '__navigation li > *', function(e) {
e.preventDefault();
/**
* Handle prev click
*/
if ( $(this).hasClass('prev') ) {
var currentSlide = $this.data('currentSlide');
if ( currentSlide < 1 ) {
return false;
}
$this.data({
events: events,
settings: settings,
currentSlide: currentSlide-1
});
build();
}
/**
* Handle next click
*/
else {
var currentSlide = $this.data('currentSlide');
if ( (currentSlide+1)*settings.eventsPerSlide >= events.length ) {
return false;
}
$this.data({
events: events,
settings: settings,
currentSlide: currentSlide+1
});
build();
}
});
$(window).on('resize', function () {
$this.removeClass(settings.rootClass + '--initialized');
build();
});
});
};
}));

View File

@@ -1,9 +1,19 @@
@import 'material'
@import 'material_icons'
@import 'variables'
@import 'overrides'
@import 'jquery-ui/autocomplete'
@import 'bootstrap-datepicker'
@import 'leaflet'
@import 'leaflet.markercluster'
@import 'custom_bootstrap/custom_bootstrap'
@import 'overrides'
@import 'graphs'
@import 'predictions'
@import 'plantings'
@import 'plantings'
@import 'members'
@import 'homepage'
// Font Awesome
@import 'font-awesome-sprockets'
@import 'font-awesome'

View File

@@ -1,82 +0,0 @@
.btn:focus {
outline: dotted 2px #000;
}
div.active:focus {
outline: dotted 1px #000;
}
a:focus {
outline: dotted 1px #000;
}
.close:hover,
.close:focus {
outline: dotted 1px #000;
}
.nav > li > a:hover,
.nav > li > a:focus {
outline: dotted 1px #000;
}
.carousel-indicators li,
.carousel-indicators li.active {
height: 18px;
width: 18px;
border-width: 2px;
position: relative;
box-shadow: 0px 0px 0px 1px #808080;
}
.carousel-indicators.active li {
background-color: rgba(100, 149, 253, 0.6);
}
.carousel-indicators.active li.active {
background-color: white;
}
.carousel-tablist-highlight {
display: block;
position: absolute;
outline: 2px solid transparent;
background-color: transparent;
box-shadow: 0px 0px 0px 1px transparent;
}
.carousel-tablist-highlight.focus {
outline: 2px solid #6495ed;
background-color: rgba(0, 0, 0, 0.4);
}
a.carousel-control:focus {
outline: 2px solid #6495ed;
background-image: linear-gradient(
to right,
transparent 0px,
rgba(0, 0, 0, 0.5) 100%
);
box-shadow: 0px 0px 0px 1px #000000;
}
.carousel-pause-button {
position: absolute;
top: -30em;
left: -300em;
display: block;
}
.carousel-pause-button.focus {
top: 0.5em;
left: 0.5em;
}
.carousel:hover .carousel-caption,
.carousel.contrast .carousel-caption {
background-color: rgba(0, 0, 0, 0.5);
z-index: 10;
}
.alert-success {
color: #2d4821;
}
.alert-info {
color: #214c62;
}
.alert-warning {
color: #6c4a00;
background-color: #f9f1c6;
}
.alert-danger {
color: #d2322d;
}
.alert-danger:hover {
color: #a82824;
}

View File

@@ -1,59 +0,0 @@
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! AUTOMATICALLY GENERATED FILE. DO NOT MODIFY !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Core variables and mixins
@import "bootstrap-sprockets"
@import "bootstrap/variables"
// Modify this for custom colors, font-sizes, etc
@import "custom_bootstrap/variables"
@import "bootstrap/mixins"
// Modify this for custom mixins
@import "custom_bootstrap/mixins"
// Reset and dependencies
@import "bootstrap/normalize"
@import "bootstrap/print"
@import "bootstrap/glyphicons"
// Core CSS
@import "bootstrap/scaffolding"
@import "bootstrap/type"
@import "bootstrap/code"
@import "bootstrap/grid"
@import "bootstrap/tables"
@import "bootstrap/forms"
@import "bootstrap/buttons"
// Components
@import "bootstrap/component-animations"
@import "bootstrap/dropdowns"
@import "bootstrap/button-groups"
@import "bootstrap/input-groups"
@import "bootstrap/navs"
@import "bootstrap/navbar"
@import "bootstrap/breadcrumbs"
@import "bootstrap/pagination"
@import "bootstrap/pager"
@import "bootstrap/labels"
@import "bootstrap/badges"
@import "bootstrap/jumbotron"
@import "bootstrap/thumbnails"
@import "bootstrap/alerts"
@import "bootstrap/progress-bars"
@import "bootstrap/media"
@import "bootstrap/list-group"
@import "bootstrap/panels"
@import "bootstrap/responsive-embed"
@import "bootstrap/wells"
@import "bootstrap/close"
// Components w/ JavaScript
@import "bootstrap/modals"
@import "bootstrap/tooltip"
@import "bootstrap/popovers"
@import "bootstrap/carousel"
// Utility classes
@import "bootstrap/utilities"
@import "bootstrap/responsive-utilities"

View File

@@ -1 +0,0 @@
// Use this file to override Twitter Bootstrap mixins or define own mixins.

View File

@@ -0,0 +1,17 @@
// let's condense the hero unit a little
.jumbotron
//padding-top: 30px
//padding-bottom: 30px
// info under the main heading on homepage
.jumbotron .info
// padding-top: 15px
// signup widget on homepage
.jumbotron .signup
background-color: lighten($green, 40%)
border: 1px solid lighten($green, 20%)
border-radius: 6px
line-height: 200%
padding: 15px
text-align: center

View File

@@ -0,0 +1,381 @@
// Config
@import 'base/variables';
@import 'base/mixins';
@mixin roadmap-default {
position: relative;
width: 95%;
margin: 0 auto;
.roadmap__events {
position: relative;
width: calc(100% - 200px);
margin: 0 auto;
padding: 200px 0;
&:after {
position: absolute;
top: 50%;
left: 0;
display: block;
content: "";
width: 0%;
height: 4px;
background-color: $primary-color;
// box-shadow: 0 0 30px -1px rgba($primary-color, 0.2);
border-radius: 2px;
transition: all 0.5s linear;
}
&__event {
position: absolute;
width: 280px;
height: 200px;
margin-left: -140px;
list-style: none;
font-size: 16px;
&:before,
&:after {
position: absolute;
content: "";
display: block;
background-color: $primary-color;
// box-shadow: 0 0 30px -1px rgba($primary-color, 0.2);
transition: all 0.3s $transition-function;
}
&:before {
width: 20px;
height: 20px;
border-radius: 20px;
left: 50%;
transform: translateX(-50%);
transform: scale(0);
}
&:after {
width: 4px;
// height: 62px;
height: 0;
border-radius: 2px;
left: 50%;
transform: translateX(-50%);
}
.event {
position: absolute;
display: block;
text-align: center;
width: 100%;
transition: all 0.3s $transition-function;
transform: scale(0);
.event__date {
font-weight: 600;
}
.event__content {
small {
display: block;
}
}
}
/**
* Events showing on the bottom of the timeline
*/
&:nth-child(odd) {
bottom: 0;
&:before {
top: -8px;
}
&:after {
top: 0;
}
.event {
top: 80px;
}
}
/**
* Events showing on the top of the timeline
*/
&:nth-child(even) {
top: 0;
&:before {
bottom: -12px;
}
&:after {
bottom: -4px;
}
.event {
bottom: 80px;
}
}
@for $i from 1 through 15 {
&:nth-child(#{$i}n) {
&:before,
&:after,
.event {
transition-delay: #{$i * 0.13}s;
}
}
}
}
}
.roadmap__navigation {
margin: 0;
&>* {
position: absolute;
top: 50%;
transform: translateY(-46%);
z-index: 100;
list-style: none;
a {
display: block;
color: #000;
line-height: 0;
i {
font-size: 44px;
}
&:hover {
text-decoration: none;
box-shadow: none;
}
}
&:first-child {
left: 40px;
}
&:last-child {
right: 40px;
}
}
.prev {}
.next {}
}
&.roadmap--initialized {
.roadmap__events {
&:after {
width: 100%;
}
.roadmap__events__event {
/**
* Dot
*/
&:before {
transform: scale(1) translateX(-50%);
}
/**
* Line
*/
&:after {
height: 62px;
}
.event {
transform: scale(1);
}
}
}
}
}
@mixin roadmap-vertical {
margin: $gap*2 auto;
.roadmap__events {
padding: 0;
width: 80%;
max-width: 640px;
min-height: 400px;
&:after {
left: 50%;
top: 0;
width: 4px;
height: calc(0% - 0px);
transform: translateX(-50%);
}
&__event {
position: relative;
left: auto !important;
top: auto;
bottom: auto;
margin-left: 0;
width: auto;
height: auto;
min-height: 120px;
&:before {
top: -8px;
bottom: auto;
}
&:after {
top: 0;
bottom: auto;
// width: 48px;
width: 0;
height: 4px !important;
}
.event {
top: -15px;
bottom: auto;
width: 40%;
@include sm-down {
width: 50%;
}
}
/**
* Events showing on the left of the timeline
*/
&:nth-child(odd) {
&:before {}
&:after {
transform: translateX(-100%);
}
.event {
@include sm-down {
margin-left: -10%;
}
}
}
/**
* Events showing on the right of the timeline
*/
&:nth-child(even) {
&:before {
// margin-left: -12px;
}
&:after {
transform: translateX(0%);
}
.event {
right: 0;
@include sm-down {
margin-right: -10%;
}
}
}
}
}
&.roadmap--initialized {
.roadmap__events {
&:after {
width: 4px;
height: calc(100% - 120px);
}
.roadmap__events__event {
/**
* Dot
*/
&:before {}
/**
* Line
*/
&:after {
width: 48px;
@include sm-down {
width: 32px;
}
}
.event {}
/**
* Events showing on the left of the timeline
*/
&:nth-child(odd) {
&:before {}
&:after {
transform: translateX(-100%);
}
.event {}
}
/**
* Events showing on the right of the timeline
*/
&:nth-child(even) {
&:before {}
&:after {
transform: translateX(0%);
}
.event {}
}
}
}
}
}
.roadmap {
&.roadmap--orientation-auto {
@include roadmap-default;
@include md-down {
@include roadmap-vertical;
}
}
&.roadmap--orientation-horizontal {
@include roadmap-default;
}
&.roadmap--orientation-vertical {
@include roadmap-default;
@include roadmap-vertical;
}
}

View File

@@ -0,0 +1,19 @@
.member-cards
display: flex
flex: none
flex-wrap: wrap
.member-thumbnail
padding: .25em
margin: 1em
border-radius: 12px
height: 200px
div
width: 5em
display: inline-block
vertical-align: top
.member-thumbnail div~div
padding-left: 1em
width: 15em

View File

@@ -1,6 +1,5 @@
@import "bootstrap-sprockets"
@import "bootstrap"
@import "custom_bootstrap/variables"
// this padding needs to be done before the responsive stuff is imported
body
padding-top: $navbar-height
@@ -72,7 +71,13 @@ h3
// info under the main heading on homepage
.jumbotron .info
padding-top: 15px
//padding-top: 15px
padding: 0.5em
text-align: center
p
// signup widget on homepage
.jumbotron .signup
@@ -87,29 +92,12 @@ h3
p.stats
font-weight: bold
.member-cards
display: flex
flex: none
flex-wrap: wrap
.card-row
display: grid
grid-template-columns: 50% 50%
grid-gap: 25px
grid-row-gap: 5px
.member-thumbnail
padding: .25em
margin: 1em
div
width: 5em
display: inline-block
vertical-align: top
.member-thumbnail div~div
padding-left: 1em
width: 15em
.progress
border-radius: 0
@@ -117,7 +105,6 @@ p.stats
text-align: center
.layout-actions
width: 100%
#placesmap, #cropmap
height: 500px
@@ -141,6 +128,8 @@ p.stats
.member-location a
color: $brown
.associations
list-style-type: none
.photo-thumbnail
padding: 0
@@ -168,11 +157,20 @@ p.stats
display: block
.thumbnail
border: none
// border: 1px solid lighten($green, 20%)
text-align: center
margin-bottom: 1.5em
max-width: 160px
max-height: 200px
//max-height: 220px
//height: 180px
.seed-thumbnail
height: 220px
.seedinfo
.seed-name
font-size: 120%
overflow: hidden
.member-thumbnail
text-align: left
@@ -182,8 +180,8 @@ p.stats
max-width: 85px
.crop-thumbnail
height: 220px
.cropinfo
margin-top: 0.5em
display: inline-block
max-width: 100%
white-space: nowrap
@@ -193,15 +191,21 @@ p.stats
.cropname
overflow: hidden
text-overflow: ellipsis
font-size: 120%
.scientificname
font-size: small
font-style: italic
overflow: hidden
text-overflow: ellipsis
font-size: 70%
.plantingcount
font-size: small
.planting-lifespan
font-size: 70%
.crop-name a
padding-top: 2px
@@ -257,11 +261,9 @@ html, body
height: 100%
.crop-image, .member-image
width: 100%
height: 100%
border-radius: 50%
// Autosuggest
.ui-autocomplete
background: white
z-index: $zindex-tooltip
@@ -363,8 +365,6 @@ ul.thumbnail-buttons
.homepage
.thumbnail
height: 180px
.seed-thumbnail
height: 220px
#maincontainer
padding: 10px

View File

@@ -26,8 +26,9 @@
top: -0.5em
.planting-quick-actions
position: absolute
left: 142px
top: 6px
top: 0px
left: 130px
.planting-thumbnail-photo
height: 150px

View File

@@ -1,11 +1,10 @@
.predictions
.prediction-metric
text-align: center
height: 180px
border: 1px solid lighten($green, 20%)
border-radius: 5%
background: $white
margin: 4px
margin: 1em
strong
font-size: 4em
font-align: center

View File

@@ -1,10 +1,10 @@
// Use this file to override Twitter Bootstrap variables or define own variables.
// Import original variables so they can be used in overrides
@import 'bootstrap/variables.scss'
//@import 'bootstrap/variables.scss'
//$screen-md-min: 1028px
// Base colours
$beige: #f3f1ee
$brown: #413f3b
@@ -22,7 +22,7 @@ $graph-hover: $orange
$brand-primary: $green
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif
$font-family-serif: Georgia, "Times New Roman", Times, serif
$font-family-mono: Monaco, Menlo, Consolas, "Courier New", monospace
@@ -33,7 +33,7 @@ $alt-font-family: $font-family-serif
$headings-font-family: $font-family-sans-serif
$headings-font-weight: bold // instead of browser default, bold
$headings-color: inherit // empty to use BS default, $textColor
$headings-color: inherit // empty to use BS default, $textColor
// Hero unit
$jumbotron-bg: darken($body-bg, 10%)
@@ -48,9 +48,10 @@ $navbar-default-link-active-color: darken($beige,80%)
$navbar-default-brand-color: lighten($green, 20%)
// Top nav collapse threshold
$grid-float-breakpoint: $screen-md-min
//$grid-float-breakpoint: $screen-md-min
$dropdown-bg: lighten($beige, 10%)
$dropdown-link-color: $brown
$dropdown-link-hover-color: $brown
$dropdown-link-hover-bg: lighten($green, 50%)

View File

@@ -27,11 +27,9 @@ module ApplicationHelper
end
def required_field_help_text
# rubocop:disable Rails/OutputSafety
asterisk = content_tag :span, '*', class: ['red']
text = content_tag :em, 'denotes a required field'
content_tag :div, asterisk + ' '.html_safe + text, class: ['margin-bottom']
# rubocop:enable Rails/OutputSafety
end
#

View File

@@ -1,7 +1,7 @@
module ButtonsHelper
include IconsHelper
def garden_plant_something_button(garden)
link_to new_planting_path(garden_id: garden.id), class: "btn btn-default btn-xs btn-primary" do
link_to new_planting_path(garden_id: garden.id), class: "btn btn-default" do
planting_icon + ' ' + t('buttons.plant_something_here')
end
end
@@ -9,13 +9,13 @@ module ButtonsHelper
def garden_mark_active_button(garden)
link_to t('buttons.mark_as_active'),
garden_path(garden, garden: { active: 1 }),
method: :put, class: 'btn btn-default btn-xs'
method: :put, class: 'btn'
end
def garden_mark_inactive_button(garden)
link_to t('buttons.mark_as_inactive'),
garden_path(garden, garden: { active: 0 }),
method: :put, class: 'btn btn-default btn-xs',
method: :put, class: 'btn',
data: { confirm: 'All plantings associated with this garden will be marked as finished. Are you sure?' }
end
@@ -43,7 +43,15 @@ module ButtonsHelper
return unless can?(:edit, planting) || planting.finished
link_to planting_path(planting, planting: { finished: 1 }),
method: :put, class: 'btn btn-default btn-xs append-date' do
method: :put, class: 'btn btn-default btn-secondary append-date' do
finished_icon + ' ' + t('buttons.mark_as_finished')
end
end
def seed_finish_button(seed)
return unless can?(:create, Planting) && seed.active?
link_to seed_path(seed, seed: { finished: 1 }), method: :put, class: 'btn btn-default append-date' do
finished_icon + ' ' + t('buttons.mark_as_finished')
end
end
@@ -51,7 +59,7 @@ module ButtonsHelper
def planting_harvest_button(planting)
return unless planting.active? && can?(:create, Harvest) && can?(:edit, planting)
link_to new_planting_harvest_path(planting), class: "btn btn-default btn-xs" do
link_to new_planting_harvest_path(planting), class: "btn btn-default" do
harvest_icon + ' ' + t('buttons.harvest')
end
end
@@ -59,7 +67,7 @@ module ButtonsHelper
def planting_save_seeds_button(planting)
return unless can?(:edit, planting)
link_to new_planting_seed_path(planting), class: "btn btn-default btn-xs" do
link_to new_planting_seed_path(planting), class: "btn btn-default" do
seed_icon + ' ' + t('buttons.save_seeds')
end
end
@@ -68,13 +76,13 @@ module ButtonsHelper
return unless can?(:edit, model) && can?(:create, Photo)
link_to new_photo_path(id: model.id, type: model_type_for_photo(model)),
class: "btn btn-default btn-xs" do
class: "btn btn-default" do
photo_icon + ' ' + t('buttons.add_photo')
end
end
def edit_button(path)
link_to path, class: "btn btn-default btn-xs" do
link_to path, class: "btn btn-raised btn-info" do
edit_icon + ' ' + t('buttons.edit')
end
end
@@ -82,7 +90,7 @@ module ButtonsHelper
def delete_button(model, message: 'are_you_sure')
return unless can? :destroy, model
link_to model, method: :delete, data: { confirm: t(message) }, class: 'btn btn-default btn-xs' do
link_to model, method: :delete, data: { confirm: t(message) }, class: 'btn btn-danger' do
delete_icon + ' ' + t('buttons.delete')
end
end

View File

@@ -15,9 +15,10 @@ module PhotosHelper
end
end
def planting_image_path(planting)
def planting_image_path(planting, full_size: false)
if planting.photos.present?
planting.photos.order(date_taken: :desc).first.thumbnail_url
photo = planting.photos.order(date_taken: :desc).first
full_size ? photo.fullsize_url : photo.thumbnail_url
else
placeholder_image
end
@@ -33,11 +34,13 @@ module PhotosHelper
end
end
def seed_image_path(seed)
def seed_image_path(seed, full_size: false)
if seed.default_photo.present?
seed.default_photo.thumbnail_url
photo = seed.default_photo
full_size ? photo.fullsize_url : photo.thumbnail_url
elsif seed.crop.default_photo.present?
seed.crop.default_photo.thumbnail_url
photo = seed.crop.default_photo
full_size ? photo.fullsize_url : photo.thumbnail_url
else
placeholder_image
end

View File

@@ -23,7 +23,7 @@ class Planting < ApplicationRecord
# Ancestry of food
belongs_to :parent_seed, class_name: 'Seed', # parent
foreign_key: 'parent_seed_id',
required: false,
optional: true,
inverse_of: :child_plantings
has_many :child_seeds, class_name: 'Seed', # children
foreign_key: 'parent_planting_id',

View File

@@ -14,7 +14,7 @@ class Seed < ApplicationRecord
# Relationships
belongs_to :crop
belongs_to :parent_planting, class_name: 'Planting', foreign_key: 'parent_planting_id',
required: false, inverse_of: :child_seeds # parent
optional: true, inverse_of: :child_seeds # parent
has_many :child_plantings, class_name: 'Planting',
foreign_key: 'parent_seed_id', dependent: :nullify,
inverse_of: :parent_seed # children

View File

@@ -1,16 +1,18 @@
.crop-actions
.btn-group
- if can? :create, Planting
= link_to new_planting_path(crop_id: crop.id), class: 'btn btn-default' do
= planting_icon
= t('buttons.plant_crop', crop_name: crop.name)
- if signed_in?
- if can? :create, Harvest
= link_to new_harvest_path(crop_id: crop.id), class: 'btn btn-default' do
= harvest_icon
= t('buttons.harvest_crop', crop_name: crop.name)
- if can? :create, Seed
= link_to new_seed_path(crop_id: crop.id), class: 'btn btn-default' do
= seed_icon
= t('buttons.add_seed_to_stash', crop_name: crop.name)
.crop-actions
.btn-group
- if can? :create, Planting
= link_to new_planting_path(crop_id: crop.id), class: 'btn btn-default' do
= planting_icon
= t('buttons.plant_crop', crop_name: crop.name)
- if can? :create, Harvest
= link_to new_harvest_path(crop_id: crop.id), class: 'btn btn-default' do
= harvest_icon
= t('buttons.harvest_crop', crop_name: crop.name)
- if can? :create, Seed
= link_to new_seed_path(crop_id: crop.id), class: 'btn btn-default' do
= seed_icon
= t('buttons.add_seed_to_stash', crop_name: crop.name)

View File

@@ -1,10 +1,11 @@
- [Planting, Harvest, Seed].each do |model_name|
.row
.col-md-12
%h3
= @crop.name
= t("activerecord.models.#{model_name.to_s.downcase}.other")
.row
- photos.by_model(model_name).limit(6).each do |photo|
.col-md-2.six-across
.thumbnail= link_to image_tag(photo.thumbnail_url, alt: photo.title, class: 'img'), photo
- if @crop.photos.size.positive?
%h2 Photos
- [Planting, Harvest, Seed].each do |model_name|
- if photos.by_model(model_name).size.positive?
%h3 #{@crop.name} #{t("activerecord.models.#{model_name.to_s.downcase}.other")}
.row
- photos.by_model(model_name).limit(6).each do |photo|
.col-md-2.six-across
.thumbnail= link_to image_tag(photo.thumbnail_url, alt: photo.title, class: 'img'), photo
%p.text-right= link_to 'more photos »', crop_photos_path(@crop), class: 'btn'

View File

@@ -1,32 +1,51 @@
%h3 Predictions
.predictions
- unless crop.perennial.nil?
.row
.col-md-12
%p
#{crop.name} is
- if crop.perennial == true
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
a perennial crop
(living more than two years)
- elsif crop.perennial == false
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
an annual crop
(living and reproducing in a single year or less)
.row
- unless crop.perennial.nil?
.col-md-3.col-xs-5
.card
.card-body.text-center
%h3
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
- if crop.perennial == true
Perennial
- elsif crop.perennial == false
Annual
.d-flex.justify-content-between
%p.display-1
%i.far.fa-calendar
- if crop.perennial == true
%small living more than two years
- elsif crop.perennial == false
%small living and reproducing in a single year or less
- if crop.annual? && crop.median_lifespan.present?
.prediction-metric.col-md-3.col-xs-5
%h3 Median lifespan
%strong= crop.median_lifespan
%span days
.col-md-3.col-xs-5
.card
.card-body.text-center
%h3 Median lifespan
.d-flex.justify-content-between
%p.display-1= crop.median_lifespan
%i.fas.fa-sun-o.fa-5x.pt-3.amber-text
%span days
- if crop.median_days_to_first_harvest.present?
.prediction-metric.col-md-3.col-xs-5
%h3 First harvest expected
%strong= crop.median_days_to_first_harvest
%span days after planting
.col-md-3.col-xs-5
.card
.card-body.text-center
%h3 First harvest expected
%p.display-1= crop.median_days_to_first_harvest
%span days after planting
- if crop.annual? && crop.median_days_to_last_harvest.present?
.prediction-metric.col-md-3.col-xs-5
%h3 Last harvest expected
%strong= crop.median_days_to_last_harvest
%span days after planting
.col-md-3.col-xs-5
.card
.card-body.text-center
%h3 Last harvest expected
%p.display-1= crop.median_days_to_last_harvest
%span days after planting

View File

@@ -1,4 +1,5 @@
= form_tag search_crops_path, method: :get, id: 'navbar-search' do
= form_tag 'search' do
-# , method: :get, id: 'navbar-search' do
= label_tag :term, "Search crop database:", class: 'sr-only'
.input
.input-group

View File

@@ -1,18 +1,17 @@
- cache cache_key_for(Crop, crop.id) do
.thumbnail
.crop-thumbnail
- if crop
= link_to image_tag(crop_image_path(crop),
alt: crop.name, class: 'img'),
crop
.cropinfo
.cropname
= link_to crop.name, crop
- unless crop.scientific_names.empty?
.scientificname
= crop.scientific_names.first.name
- if crop.annual? && crop.median_lifespan.present?
.planting-lifespan
lifespan
%strong= crop.median_lifespan
days
= link_to image_tag(crop_image_path(crop),
alt: crop.name, class: 'img'),
crop
.cropinfo
.cropname
= link_to crop.name, crop
- unless crop.scientific_names.empty?
.scientificname
= crop.scientific_names.first.name
- if crop.annual? && crop.median_lifespan.present?
.planting-lifespan
lifespan
%strong= crop.median_lifespan
days

View File

@@ -1,8 +1,12 @@
- content_for :title, t('.title')
- content_for :subtitle, t('.subtitle', crops_size: @crops.size)
- if can? :wrangle, Crop
= link_to 'Wrangle Crops', wrangle_crops_path, class: 'btn btn-primary'
- content_for :buttonbar do
- if can? :wrangle, Crop
= link_to 'Wrangle Crops', wrangle_crops_path, class: 'btn btn-secondary'
- if can? :create, Crop
= link_to 'Add new Crop', new_crop_path, class: 'btn btn-primary'
- if @num_requested_crops && @num_requested_crops.positive?
= link_to(I18n.t('crops.requested.link', number_crops: @num_requested_crops), requested_crops_path)
@@ -30,9 +34,6 @@
.col-md-2.six-across
= render partial: "thumbnail", locals: { crop: crop }
- if can? :create, Crop
%div
= link_to 'New Crop', new_crop_path, class: 'btn btn-primary'
.pagination
= will_paginate @crops

View File

@@ -21,34 +21,35 @@
.col-md-9
%h2
- if !@crop.plantings.empty?
= @crop.name.titleize
has been planted
#{@crop.name.titleize} has been planted
= pluralize(@crop.plantings.size, "time")
by #{ENV['GROWSTUFF_SITE_NAME']} members.
- else
Nobody is growing this yet. You could be the first!
%hr/
%h3 Predictions
= render 'predictions', crop: @crop
%hr/
= render 'crops/photos', photos: @photos
%hr/
%h2 Photos
%p= render 'crops/photos', photos: @photos
%p= link_to 'more photos', crop_photos_path(@crop)
.row
.col-md-3
%h3 Sunniness
= pie_chart crop_sunniness_path(@crop, format: :json), legend: "bottom"
.col-md-3
%h3 Planted from
= pie_chart crop_planted_from_path(@crop, format: :json), legend: "bottom"
.col-md-3
%h3 Harvested for
= pie_chart crop_harvested_for_path(@crop, format: :json), legend: "bottom"
.row.text-center
.col-md-4
.card
.card-body
%h3.section-heading.h3.pt-4 Sunniness
= pie_chart crop_sunniness_path(@crop, format: :json), legend: "bottom"
.col-md-4
.card
.card-body
%h3.section-heading.h3.pt-4 Planted from
= pie_chart crop_planted_from_path(@crop, format: :json), legend: "bottom"
.col-md-4
.card
.card-body
%h3.section-heading.h3.pt-4 Harvested for
= pie_chart crop_harvested_for_path(@crop, format: :json), legend: "bottom"
= render 'varieties', crop: @crop
@@ -59,27 +60,18 @@
= link_to "Set your location.", edit_member_registration_path
#cropmap
.row
.col-md-12
= render 'crops/posts', crop: @crop
= render 'crops/posts', crop: @crop
.col-md-3
= render partial: 'wrangle', locals: { crop: @crop }
%p
%li
= link_to crop_seeds_path(@crop) do
View all #{@crop.name} seeds
(#{@crop.seeds.size})
%li
= link_to crop_plantings_path(@crop) do
View all #{@crop.name} plantings
(#{@crop.plantings.size})
%li
= link_to crop_harvests_path(@crop) do
View all #{@crop.name} harvests
(#{@crop.harvests.size})
= link_to crop_plantings_path(@crop) do
View all #{@crop.name} plantings
(#{@crop.plantings.size})
%p
= link_to crop_harvests_path(@crop) do
View all #{@crop.name} harvests
(#{@crop.harvests.size})
- if member_signed_in?
%p
= link_to member_seeds_path(current_member, crop_slug: @crop.slug) do

View File

@@ -7,6 +7,9 @@
.col-md-2.col-xs-12.garden-info
%p= render 'gardens/photo', garden: garden
%p= display_garden_description(garden)
- if can?(:edit, garden)
= render 'gardens/actions', garden: garden
.col-md-10
- if garden.plantings.current.size.positive?
.row
@@ -15,5 +18,3 @@
= render "plantings/thumbnail", planting: planting
- else
no plantings
- if can?(:edit, garden)
.panel-footer= render 'gardens/actions', garden: garden

View File

@@ -100,6 +100,7 @@
- if can?(:edit, @garden) && can?(:create, Photo)
%p
=
= link_to new_photo_path(type: "garden", id: @garden.id),
class: 'btn btn-primary' do
%span.glyphicon.glyphicon-camera{ title: "Add photo" }
@@ -108,5 +109,4 @@
%h3= localize_plural(@garden.photos, Photo)
.row
- @garden.photos.includes(:owner).each do |photo|
.col-xs-6
= render partial: 'photos/thumbnail', locals: { photo: photo }
.col-xs-6= render partial: 'photos/thumbnail', locals: { photo: photo }

View File

@@ -1,10 +1,12 @@
- harvests.each do |h|
- cache h do
.row
.col-lg-6.col-md-3.col-xs-4.homepage-listing
= render 'harvests/image_with_popover', harvest: h
.col-lg-3.col-md-9.col-xs-4
= link_to h.crop, crop_path(h.crop)
%br/
- harvests.each do |harvest|
- cache harvest do
.card
.view.overlay
= link_to harvest do
%img.card-img-top.img-responsive{alt: harvest, src: harvest.default_photo.fullsize_url}/
.card-body.p-3
%h5.card-title.font-weight-bold.fuchsia-rose-text.mb-0
= link_to harvest, harvest
%small
%i= h.owner.location
%i= harvest.owner.location
%hr/

View File

@@ -1,11 +1,10 @@
.container
.row
.col-md-12
%h1= ENV['GROWSTUFF_SITE_NAME']
.col-md-8.info
%p= t('.intro', site_name: ENV['GROWSTUFF_SITE_NAME'])
= render partial: 'stats'
.col-md-4.signup
.row
.col-md-8.info
%h1= ENV['GROWSTUFF_SITE_NAME']
%p= t('.intro', site_name: ENV['GROWSTUFF_SITE_NAME'])
= render partial: 'stats'
.col-md-4
.signup
%p= t('.perks')
%p= link_to(t('.sign_up'), new_member_registration_path, class: 'btn btn-primary btn-lg')
%p

View File

@@ -1,6 +1,9 @@
- cache cache_key_for(Crop, 'interesting'), expires_in: 1.day do
%h2.section-heading.h1.pt-4= t('.our_crops')
.row
%h2= t('.our_crops')
- Crop.interesting.includes(:scientific_names, :photos).shuffle.first(12).each do |c|
- Crop.interesting.includes(:scientific_names, :photos).shuffle.first(36).each do |c|
.col-lg-2.col-md-4.col-sm-3.col-xs-6
= render 'crops/thumbnail', crop: c
.align-bottom
%p.text-right= link_to "#{t('home.crops.view_all')} »", crops_path, class: 'btn'

View File

@@ -1,17 +1,34 @@
%h2= t('.discussion')
- posts = Post.order(created_at: :desc).limit(6)
- if posts
= render "posts/summary", posts: posts, howmany: 6
-# - Post.order(created_at: :desc).limit(6).each do |post|
- cache cache_key_for(Forum) do
- forums = Forum.all.order(:name)
- if forums
%ul.list-inline
%li
%strong #{t('.forums')}:
- forums.each do |f|
%li= link_to f.name, f
-# = link_to truncate(strip_tags(post.subject), length: 40, separator: ' '), post
-# by
-# = link_to post.author, post.author
-# - cache cache_key_for(Forum) do
-# - forums = Forum.all.order(:name)
-# - if forums
-# %ul.list-inline
-# %li
-# %strong #{t('.forums')}:
-# - forums.each do |f|
-# %li= link_to f.name, f
.list-group
- Post.order(created_at: :desc).limit(3).each do |post|
%a.list-group-item.list-group-item-action.flex-column.align-items-start{:href => post_path(post)}
.d-flex.w-100.justify-content-between
%h5.mb-2.h5= truncate(strip_tags(post.subject))
%small
= time_ago_in_words(post.created_at)
ago
%p.mb-2
= truncate(strip_tags(post.body), length: 200)
%small
= post.comments.size
comments
%p.text-right
= link_to "#{t('.view_all')} »", posts_path
= link_to "#{t('.view_all')} »", posts_path, class: 'btn'

View File

@@ -1,3 +1,3 @@
- cache cache_key_for(Harvest) do
%h2 Recently Harvested
= render 'harvests/list', harvests: Harvest.includes(:crop, :owner, :photos).has_photos.recent.first(6)
%h2.section-heading.h1.pt-4 Recently Harvested
= render 'harvests/list', harvests: Harvest.includes(:crop, :owner, :photos).has_photos.recent.first(3)

View File

@@ -1,13 +1,12 @@
- cache cache_key_for(Member) do
.hidden-xs
- members = Member.includes(plantings: :crop).interesting.first(6)
- if members.present?
%section
%h2= t('.title')
%section.section.pb-3.text-center
- members = Member.includes(plantings: :crop).interesting.first(6)
- if members.present?
%h2.section-heading.h1.pt-4= t('.title')
.row.member-cards
- members.each do |m|
.col-md-3.col.sm-2= render "members/thumbnail", member: m
.member-cards
- members.each do |m|
= render "members/thumbnail", member: m
%p.text-right
= link_to "#{t('.view_all')} »", members_path
%p.text-right
= link_to "#{t('.view_all')} »", members_path, class: 'btn'

View File

@@ -1,3 +1,3 @@
- cache cache_key_for(Planting, 'home'), expires_in: 1.day do
%h2= t('.recently_planted')
= render 'plantings/list', plantings: Planting.includes(:crop, garden: :owner).has_photos.recent.limit(6)
%h2.section-heading.h2.pt-4= t('.recently_planted')
= render 'plantings/list', plantings: Planting.includes(:crop, garden: :owner).has_photos.recent.limit(3)

View File

@@ -1,22 +1,5 @@
- cache cache_key_for(Seed, 'interesting'), expires_in: 1.day do
%h2= t('.title')
.row
- Seed.current.tradable.includes(:owner, :crop).order(created_at: :desc).limit(6).each do |seed|
.col-md-2.col-sm-2.col-xs-6
.thumbnail.seed-thumbnail
- cache cache_key_for(Crop, seed.id) do
= link_to image_tag(seed_image_path(seed),
alt: seed.crop.name, class: 'img'),
seed
.seedinfo
= link_to seed.crop.name, seed
.trade-to
%p= seed.owner.location
%p
%small
Will trade to:
%br/
%em= seed.tradable_to
%p.text-right
= link_to "#{t('.view_all')} »", seeds_path
- cache cache_key_for(Seed) do
- seeds = Seed.current.tradable.includes(:owner, :crop).order(created_at: :desc).limit(6)
- if seeds.size.positive?
%h2.section-heading.h1.pt-4.text-center= t('.title')
= render 'seeds/list', seeds: seeds

View File

@@ -1,36 +1,32 @@
.homepage.row
.col-md-12
- if member_signed_in?
- content_for :title, t('.welcome', site_name: ENV['GROWSTUFF_SITE_NAME'], member_name: current_member)
.homepage
.row
.col-md-12
- if member_signed_in?
- content_for :title, t('.welcome', site_name: ENV['GROWSTUFF_SITE_NAME'], member_name: current_member)
= render 'stats'
- else
.hidden-xs
.jumbotron
= render 'blurb'
.visible-xs
= render 'blurb'
= render 'stats'
- else
.hidden-xs
.jumbotron= render 'blurb'
-# .visible-xs= render 'blurb'
.row
.col-lg-8.col-md-6.col-sm-12
= render 'crops'
.col-lg-2.col-md-3.col-sm-6
= render 'plantings'
.col-lg-2.col-md-3.col-sm-6
= render 'harvests'
.col-md-12
- cache cache_key_for(Crop, 'recent') do
%p{ style: 'margin-top: 11.25px' }
%strong
#{t('.recently_added')}:
!= Crop.recent.limit(30).map { |c| link_to(c, c) }.join(", ")
.row
.col-lg-8.col-md-6.col-sm-12.well
= render 'crops'
.col-lg-2.col-md-3.col-sm-6
= render 'plantings'
.col-lg-2.col-md-3.col-sm-6
= render 'harvests'
.col-md-12
- cache cache_key_for(Crop, 'recent') do
%p{ style: 'margin-top: 11.25px' }
%strong
#{t('.recently_added')}:
!= Crop.recent.limit(30).map { |c| link_to(c, c) }.join(", ")
%p.text-right
= link_to "#{t('home.crops.view_all')} »", crops_path
.row
.col-md-12
= render 'seeds'
= render 'members'
.row
.col-md-12
= render 'discuss'
.row
.col-lg-8.col-md-6.col-sm-12
= render 'seeds'
.col-lg-4.col-md-6.col-sm-12
= render 'discuss'
= render 'members'

View File

@@ -1,10 +1,9 @@
.sr-only
= link_to t(".skip"), "#skipnav"
.navbar.navbar-default.navbar-fixed-top{ role: "navigation" }
.container
.container-fluid
.navbar-header
%button.navbar-toggle{ 'data-target': "#navbar-collapse", 'data-toggle': "collapse" }
%span.sr-only= t('.toggle_navigation')
%button.navbar-toggle{"data-target" => ".navbar-responsive-collapse", "data-toggle" => "collapse", type: "button"}
%span.icon-bar
%span.icon-bar
%span.icon-bar
@@ -16,15 +15,36 @@
class: "img-responsive",
alt: ENV['GROWSTUFF_SITE_NAME'])
.form.navbar-form.pull-left
.navbar-collapse.collapse.navbar-responsive-collapse
-# %ul.nav.navbar-nav
-# %li.active
-# %a{href: "javascript:void(0)"} Active
-# %li
-# %a{href: "javascript:void(0)"} Link
-# %li.dropdown
-# %a.dropdown-toggle{"data-target" => "#", "data-toggle" => "dropdown", href: "http://fezvrasta.github.io/bootstrap-material-design/bootstrap-elements.html"}
-# Dropdown
-# %b.caret
-# %ul.dropdown-menu
-# %li
-# %a{href: "javascript:void(0)"} Action
-# %li
-# %a{href: "javascript:void(0)"} Another action
-# %li
-# %a{href: "javascript:void(0)"} Something else here
-# %li.divider
-# %li.dropdown-header Dropdown header
-# %li
-# %a{href: "javascript:void(0)"} Separated link
-# %li
-# %a{href: "javascript:void(0)"} One more separated link
%form.navbar-form.navbar-left
= render 'crops/search_bar'
.navbar-collapse.collapse#navbar-collapse
-# .form-group
-# %input.form-control.col-sm-8{placeholder: "Search", type: "text"}/
%ul.nav.navbar-nav.navbar-right
%li.dropdown<
%a.dropdown-toggle{ 'data-toggle': 'dropdown', href: crops_path }
= t('.crops')
%b.caret
%a.dropdown-toggle{ 'data-toggle': 'dropdown', href: crops_path }= t('.crops')
%ul.dropdown-menu
%li= link_to t('.browse_crops'), crops_path
%li= link_to t('.seeds'), seeds_path
@@ -33,13 +53,11 @@
%li.dropdown<
%a.dropdown-toggle{ 'data-toggle': 'dropdown', href: members_path }
= t('.community')
%b.caret
%ul.dropdown-menu
%li= link_to t('.community_map'), places_path
%li= link_to t('.browse_members'), members_path
%li= link_to t('.posts'), posts_path
%li= link_to t('.forums'), forums_path
- if member_signed_in?
%li.dropdown<
%a.dropdown-toggle{ 'data-toggle': 'dropdown', href: root_path }
@@ -47,7 +65,6 @@
= t('.your_stuff', unread_count: current_member.notifications.unread_count)
- else
= t('.current_memberlogin_name', current_memberlogin_name: current_member.login_name)
%b.caret
%ul.dropdown-menu
%li= link_to t('.profile'), member_path(current_member)
%li= link_to t('.gardens'), member_gardens_path(current_member)
@@ -68,13 +85,11 @@
- if current_member.role?(:admin)
%li= link_to t('.admin'), admin_path
%li= link_to t('.sign_out'), destroy_member_session_path, method: :delete
- else
%li= link_to t('.sign_in'), new_member_session_path, id: 'navbar-signin'
%li= link_to t('.sign_up'), new_member_registration_path, id: 'navbar-signup'
-# anchor tag for accessibility link to skip the navigation menu
%a{ name: 'skipnav' }
%a{ name: 'skipnav' }

View File

@@ -1,13 +1,13 @@
- content_for :buttonbar do
- if current_member.present?
= link_to url_for([current_member, model]), class: 'btn btn-default' do
= link_to url_for([current_member, model]), class: 'btn' do
My #{model.model_name.human.pluralize}
= link_to model, class: 'btn btn-default' do
= link_to model, class: 'btn' do
Everyone's #{model.model_name.human.pluralize}
- if can?(:create, model)
= link_to url_for([model, action: :new]), class: 'btn btn-default' do
= link_to url_for([model, action: :new]), class: 'btn' do
Add a #{model.model_name.human}
- unless current_member

View File

@@ -8,15 +8,15 @@
#maincontainer
.row
.col-md-6
- if content_for?(:buttonbar)
= yield(:buttonbar)
- if content_for?(:title)
%h1#title
= yield(:title)
- if content_for?(:subtitle)
%small= yield(:subtitle)
- if content_for?(:buttonbar)
.btn-group.layout-actions
= yield(:buttonbar)
.col-md-6
= render 'shared/global_actions'

View File

@@ -1,5 +1,4 @@
- if member
= link_to image_tag(avatar_uri(member, 150),
alt: '',
class: 'img img-responsive avatar'),
member_path(member)
= link_to image_tag(avatar_uri(member, 150),
alt: member,
class: 'img img-responsive avatar mr-3'),
member_path(member)

View File

@@ -1,26 +1,38 @@
-# .member-thumbnail.well
-# %div
-# = render "members/avatar", member: member
-# %div
-# %p.login-name
-# = link_to member.login_name, member
-# - unless member.location.blank?
-# %small
-# %br/
-# %i= member.location
-# - unless member.plantings.empty?
-# %small
-# %br/
-# Recently planted:
-# != member.plantings.order(created_at: :desc).first(3).map { |p| link_to p.crop_name, p }.join(", ")
- cache member do
.member-thumbnail.panel
%div
= render partial: "members/avatar", locals: { member: member }
%div
%p.login-name
= link_to member.login_name, member
- unless member.location.blank?
%small
%br/
%i= member.location
- unless member.plantings.empty?
%small
%br/
Recently planted:
!= member.plantings.order(created_at: :desc).first(3).map { |p| link_to p.crop_name, p }.join(", ")
.card.text-center
/ Background color
.card-up.teal.lighten-2
/ Avatar
.avatar.mx-auto.white
= link_to member do
= image_tag(avatar_uri(member, 150), class: 'rounded-circle img-fluid', alt: member)
.card-body
/ Name
%h4.card-title
= link_to member, member
%hr/
%p
%small
Joined
= distance_of_time_in_words(member.created_at, Time.zone.now)
ago.
%p
%small
= [localize_plural(member.gardens, Garden),
localize_plural(member.plantings, Planting),
localize_plural(member.seeds, Seed)].join(", ")
%ul.nav.md-pills.nav-justified.pills-pink.small
%li.nav-item= link_to localize_plural(member.plantings, Planting), member_plantings_path(member)
%li.nav-item= link_to localize_plural(member.harvests, Harvest), member_harvests_path(member)
%li.nav-item= link_to localize_plural(member.seeds, Seed), member_seeds_path(member)

View File

@@ -2,6 +2,6 @@
- if can?(:edit, @photo) && can?(:destroy, @photo)
%p
- if can?(:edit, @photo)
= edit_button(@photo)
= edit_button(edit_photo_path(@photo))
- if can?(:destroy, @photo)
= delete_button(@photo)

View File

@@ -8,7 +8,4 @@
- photos.each do |photo|
.col-xs-6.col-md-3.six-across= render 'photos/thumbnail', photo: photo
- if can?(:create, Photo) && can?(:edit, item)
= link_to new_photo_path(type: type, id: item.id), class: 'btn btn-primary' do
%span.glyphicon.glyphicon-camera{ title: "Add photo" }
Add photo
= add_photo_button(item)

View File

@@ -1,4 +1,5 @@
- if can? :edit, photo
= link_to photo_associations_path(photo_id: photo.id, type: type, id: thing.id),
method: 'delete', class: 'btn btn-default btn-xs' do
= delete_icon
method: 'delete', class: 'btn btn-danger btn-xs' do
%i.fas.fa-backspace

View File

@@ -1,21 +1,26 @@
%h4 This photo depicts:
%ul
- @photo.plantings.each do |planting|
%li
= link_to t('photos.show.planting', planting: planting.to_s, owner: planting.owner.to_s), planting_path(planting)
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'planting', thing: planting }
%p
%ul.associations
- @photo.plantings.each do |planting|
%li
= planting_icon
= link_to t('photos.show.planting', planting: planting.to_s, owner: planting.owner.to_s), planting_path(planting)
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'planting', thing: planting }
- @photo.harvests.each do |harvest|
%li
= link_to t('photos.show.harvest', crop: harvest.crop.name, owner: harvest.owner.to_s), harvest_path(harvest)
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'harvest', thing: harvest }
- @photo.harvests.each do |harvest|
%li
= harvest_icon
= link_to t('photos.show.harvest', crop: harvest.crop.name, owner: harvest.owner.to_s), harvest_path(harvest)
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'harvest', thing: harvest }
- @photo.gardens.each do |garden|
%li
= link_to t('photos.show.garden', garden: garden.to_s, owner: garden.owner.to_s), garden_path(garden)
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'garden', thing: garden }
- @photo.gardens.each do |garden|
%li
= garden_icon
= link_to t('photos.show.garden', garden: garden.to_s, owner: garden.owner.to_s), garden_path(garden)
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'garden', thing: garden }
- @photo.seeds.each do |seed|
%li
= link_to t('photos.show.seed', seed: seed.to_s, owner: seed.owner.to_s), seed_path(seed)
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'seed', thing: seed }
- @photo.seeds.each do |seed|
%li
= seed_icon
= link_to t('photos.show.seed', seed: seed.to_s, owner: seed.owner.to_s), seed_path(seed)
= render partial: "photo_association_delete", locals: { photo: @photo, type: 'seed', thing: seed }

View File

@@ -1,5 +1,10 @@
- content_for :title, "Edit Photo"
= form_for(@photo) do |f|
= f.label :title
= f.text_field :title, placeholder: "title"
= f.submit
.rol
.col-md-2= render 'photos/thumbnail', photo: @photo
.col-md-10
- content_for :title, "Edit Photo"
= form_for(@photo) do |f|
.form-group
= f.label :title
= f.text_field :title, placeholder: "title"
.form-group
.form-actions= f.submit 'Save', class: 'btn'

View File

@@ -8,13 +8,13 @@
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
.row
.col-md-8
%p= image_tag(@photo.fullsize_url, alt: @photo.title, class: 'img img-responsive')
.col-md-4
= render 'photos/actions', photo: @photo
.col-md-5
- if @crops.size.positive?
- @crops.each do |crop|
= render 'crops/index_card', crop: crop
%p
%strong Posted by:
%i.fas.fa-camera-retro
%strong Photo by
= link_to @photo.owner, @photo.owner
%p
%strong License:
@@ -22,13 +22,13 @@
= link_to @photo.license_name, @photo.license_url
- else
= succeed "." do
= @photo.license_name
%p= link_to "View on Flickr", @photo.link_url
= @photo.license_name
- if @photo.associations?
= render "photo_associations", locals: { photo: @photo }
- if @crops.size.positive?
- @crops.each do |crop|
= render 'crops/index_card', crop: crop
= render 'photos/actions', photo: @photo
.col-md-7
//%img.img-fluid.z-depth-1{:alt => "1", :src => "https://mdbootstrap.com/img/Photos/Slides/img%20(54).jpg"}/
%p= image_tag(@photo.fullsize_url, alt: @photo.title, class: 'rounded img-fluid z-depth-1 float-right ')
%p= link_to "View on Flickr", @photo.link_url, class: 'btn'

View File

@@ -8,7 +8,4 @@
- else
%p No seeds saved
- if planting.active? && can?(:create, Seed) && can?(:edit, planting)
= link_to new_planting_seed_path(planting), class: 'btn btn-primary' do
%span.glyphicon.glyphicon-heart{ title: "Add photo" }
Save seeds
= planting_save_seeds_button(planting)

View File

@@ -7,7 +7,4 @@
.col-xs-6.col-sm-4.col-md-3
= render 'harvests/thumbnail', harvest: harvest
- if planting.active? && can?(:edit, planting)
= link_to new_planting_harvest_path(planting), class: 'btn btn-primary' do
%span.glyphicon.glyphicon-leaf{ title: "Harvest" }
Harvest
= planting_harvest_button(planting)

View File

@@ -1,7 +1,7 @@
- cache planting do
= link_to image_tag(planting_image_path(planting),
alt: planting.to_s,
class: 'image-responsive crop-image'),
class: 'image-responsive'),
planting,
rel: "popover",
'data-trigger': 'hover',

View File

@@ -1,10 +1,14 @@
- plantings.each do |p|
- cache p do
.row
.col-lg-6.col-md-3.col-xs-4.homepage-listing
= render 'plantings/image_with_popover', planting: p
.col-lg-3.col-md-9.col-xs-4
= link_to p.crop, p.crop
%br/
%small
%i= p.location
- plantings.each do |planting|
- cache planting do
.card
.view.overlay
= link_to planting do
%img.card-img-top.img-responsive{alt: planting, src: planting_image_path(planting, full_size: true)}/
.card-body.p-3
%h5.card-title.font-weight-bold.fuchsia-rose-text.mb-0
= link_to planting, planting
%p.float-right
= link_to planting.owner do
= image_tag(avatar_uri(planting.owner, 50), alt: '', class: 'img img-responsive avatar rounded-circle')
%hr/

View File

@@ -1,13 +1,16 @@
- if can?(:edit, planting)
.planting-quick-actions.pull-right
%a.btn.btn-default.btn-xs#actionsMenu.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#"}
=icon('fas', 'bars')
%ul.dropdown-menu{"aria-labelledby" => "actionsMenu"}
- if can?(:edit, planting)
%li= planting_edit_button(planting)
%li= add_photo_button(planting)
%a.btn#actionsMenu.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#"}
-# =icon('fas', 'ellipsis-v')
%ul.dropdown-menu.dropdown-menu-left{"aria-labelledby" => "actionsMenu"}
%li.btn-xs
= link_to t('view'), planting, class: 'btn'
%li.btn-xs= planting_edit_button(planting)
%li.btn-xs= add_photo_button(planting)
- if planting.active?
%li.btn-xs= planting_finish_button(planting)
%li.btn-xs= planting_harvest_button(planting)
%li.btn-xs= planting_save_seeds_button(planting)
- if planting.active?
%li= planting_finish_button(planting)
%li= planting_harvest_button(planting)
%li= planting_save_seeds_button(planting)

View File

@@ -0,0 +1,13 @@
.planting-stats
%span.badge.harvest-count{'data-toggle': "tooltip", 'data-placement': "top", title: 'Harvests'}
= harvest_icon
= planting.harvests.size
%span.badge.child-seeds-count{'data-toggle': "tooltip", 'data-placement': "top", title: 'Seeds saved'}
= seed_icon
= planting.child_seeds.size
%span.badge.photos-count{'data-toggle': "tooltip", 'data-placement': "top", title: 'Photos'}
= photo_icon
= planting.photos.size
%span.badge.photos-count{'data-toggle': "tooltip", 'data-placement': "top", title: 'Age in days'}
= planting_icon
= planting.age_in_days

View File

@@ -73,7 +73,7 @@
%dd= render 'plantings/progress', planting: @planting, show_explanation: true
.col-xs-12.col-sm-6
= render partial: "crops/index_card", locals: { crop: @planting.crop }
= render "crops/index_card", crop: @planting.crop
- if @planting.owner.location
%p
%small

View File

@@ -5,10 +5,10 @@
= add_photo_button(seed)
- if can?(:create, Planting) && seed.active?
= link_to new_planting_path(seed_id: seed), class: 'btn btn-default btn-xs' do
= link_to new_planting_path(seed_id: seed), class: 'btn btn-default' do
%span.glyphicon.glyphicon-grain{ title: "Plant seeds" }
Plant seeds
= render 'shared/buttons/finish_seeds', seed: seed
= seed_finish_button(seed)
= delete_button(seed) if can? :destroy, seed

View File

@@ -0,0 +1,16 @@
- seeds.each do |seed|
- cache seed do
.col-lg-3.col-md-4.col-sm-3.col-xs-6
.card
.view.overlay
= link_to seed do
= image_tag(seed_image_path(seed, full_size: true), alt: seed, class: 'card-img-top img-responsive')
.card-body.p-3
%h5.card-title.font-weight-bold.fuchsia-rose-text.mb-0
= link_to seed, seed
%p
%i #{seed.owner.location}
%p Will trade #{seed.tradable_to}
%p.float-right
= link_to seed.owner do
= image_tag(avatar_uri(seed.owner, 50), alt: '', class: 'img img-responsive avatar rounded')

View File

@@ -1,14 +1,12 @@
.thumbnail
.seed-thumbnail
= link_to image_tag(seed_image_path(seed),
alt: seed.crop.name, class: 'img'),
seed_path(seed)
.seedinfo
.seed-name
= link_to seed, seed_path(seed)
.trade-to
%p= seed.owner.location
%p
Will trade to:
%br/
= seed.tradable_to
- cache cache_key_for(Seed, seed.id) do
.thumbnail
.seed-thumbnail
= link_to image_tag(seed_image_path(seed),
alt: seed.name, class: 'img'),
seed
.seedinfo
.seedname
= link_to seed.name, seed
%small.trade-to
%p #{seed.owner.location}
%p Will trade #{seed.tradable_to}

View File

@@ -1,22 +1,24 @@
- if signed_in?
.global-actions.pull-right
.btn-group
= link_to member_gardens_path(current_member), class: 'btn btn-default' do
= garden_icon
= t('links.my_gardens')
.btn-group
= link_to new_planting_path, class: 'btn btn-default' do
= link_to new_planting_path, class: "btn #{current_page?(new_planting_path) ? 'btn-primary' : ''}" do
= planting_icon
= t('plantings.plant_something')
= link_to new_harvest_path, class: 'btn btn-default' do
= link_to new_harvest_path, class: "btn #{current_page?(new_harvest_path) ? 'btn-primary' : ''}" do
= harvest_icon
= t('harvests.harvest_something')
= link_to new_seed_path, class: 'btn btn-default' do
= link_to new_seed_path, class: "btn #{current_page?(new_seed_path) ? 'btn-primary' : ''}" do
= seed_icon
= t('buttons.save_seeds')
.btn-group
= link_to t('posts.write_blog_post'), new_post_path, class: 'btn btn-default'
-# .btn-group
-# = link_to t('posts.write_blog_post'), new_post_path, class: 'btn'
- unless current_page?(member_gardens_path(current_member))
.btn-group
= link_to member_gardens_path(current_member), class: "btn" do
= garden_icon
= t('links.my_gardens')

View File

@@ -1,5 +0,0 @@
- unless seed.finished
= link_to seed_path(seed, seed: { finished: 1 }),
method: :put, class: 'btn btn-default btn-xs append-date' do
= render 'shared/glyphicon', icon: 'ok', title: 'buttons.finished'
=t('buttons.mark_as_finished')

View File

@@ -79,6 +79,6 @@ Rails.application.configure do
config.after_initialize do
Bullet.enable = true
Bullet.rails_logger = true
Bullet.add_footer = true
# Bullet.add_footer = true
end
end

View File

@@ -118,4 +118,6 @@ Rails.application.configure do
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
config.bot_email = 'cropbot@growstuff.org'
end

View File

@@ -145,12 +145,12 @@ describe Photo do
seed.photos << seed_photo
end
it { expect(Photo.by_model(Harvest)).to eq([ harvest_photo ]) }
it { expect(Photo.by_model(Planting)).to eq([ planting_photo ]) }
it { expect(Photo.by_model(Seed)).to eq([ seed_photo ]) }
it { expect(Photo.by_model(Harvest)).to eq([harvest_photo]) }
it { expect(Photo.by_model(Planting)).to eq([planting_photo]) }
it { expect(Photo.by_model(Seed)).to eq([seed_photo]) }
it { expect(Photo.by_crop(harvest_crop)).to eq([ harvest_photo ]) }
it { expect(Photo.by_crop(planting_crop)).to eq([ planting_photo ]) }
it { expect(Photo.by_crop(seed_crop)).to eq([ seed_photo ]) }
it { expect(Photo.by_crop(harvest_crop)).to eq([harvest_photo]) }
it { expect(Photo.by_crop(planting_crop)).to eq([planting_photo]) }
it { expect(Photo.by_crop(seed_crop)).to eq([seed_photo]) }
end
end