diff --git a/.gitignore b/.gitignore
index 75fe283a..2a4f41ce 100755
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ client/js/nonprofits/donate/plugins-enabled
.DS_Store
+/postgres-data
# Ignore bundler config
/.bundle
@@ -62,4 +63,4 @@ javascripts/api
!public/css/donate-button.css
!public/css/donate-button.v2.css
!public/svgs
-!public/svgs/*
\ No newline at end of file
+!public/svgs/*
diff --git a/app/assets/stylesheets/campaigns/custom_layout/safety_around_water.css.scss b/app/assets/stylesheets/campaigns/custom_layout/safety_around_water.css.scss
new file mode 100644
index 00000000..0be0266f
--- /dev/null
+++ b/app/assets/stylesheets/campaigns/custom_layout/safety_around_water.css.scss
@@ -0,0 +1,78 @@
+@import 'mixins';
+@import 'common/fundraisers';
+
+button, a.js-contributeButton {
+ background: #01a490 !important;
+}
+
+main a.button {
+ background: #0089d0 !important;
+ color: white;
+}
+
+main .button.edit, main .button--tiny.edit {
+ color: white;
+}
+
+main {
+ width: 1200px;
+ margin: auto;
+}
+
+main > header {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin: auto;
+}
+
+body > .ymca-banner {
+ margin: auto;
+ width: 100vw;
+ height: 120px;
+ background-color: #01a490;
+}
+
+main > header div.fundraisingHeader--image-container {
+ background-position: 0 -80px;
+}
+
+img.fundraisingHeader--image-aspectRatio {
+ width: 1200px;
+ height: 500px;
+}
+
+main > .container {
+ max-width: none;
+ margin-top: 15px;
+}
+
+.campaigner-profile {
+ display: flex;
+ flex-wrap: nowrap;
+ align-items: baseline;
+}
+
+.campaigner-profile > figure {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-right: 20px;
+ align-self: flex-start;
+}
+
+.campaigner-profile > figure > .avatar {
+ flex-basis: 20%;
+}
+
+.avatar > img {
+ width: 150px;
+ height: 150px;
+ clip-path: circle(50% at center);
+}
+
+.campaigner-profile > figure > figcaption {
+ flex-basis: 55%;
+ padding: 15px;
+ text-align: left;
+}
diff --git a/app/controllers/campaigns_controller.rb b/app/controllers/campaigns_controller.rb
index 21c57919..121e40c8 100644
--- a/app/controllers/campaigns_controller.rb
+++ b/app/controllers/campaigns_controller.rb
@@ -38,8 +38,12 @@ class CampaignsController < ApplicationController
@campaign_background_image = FetchBackgroundImage.with_model(@campaign)
- respond_to do |format|
- format.html
+ if @nonprofit.custom_layout.blank?
+ respond_to do |format|
+ format.html
+ end
+ else
+ render template: "nonprofits/custom_campaign_layouts/" + @nonprofit.custom_layout
end
end
diff --git a/app/models/campaign.rb b/app/models/campaign.rb
index f19278a4..fbc09bb5 100644
--- a/app/models/campaign.rb
+++ b/app/models/campaign.rb
@@ -13,6 +13,8 @@ class Campaign < ActiveRecord::Base
:remove_main_image, # for carrierwave
:background_image,
:remove_background_image, #bool carrierwave
+ :custom_banner,
+ :remove_custom_banner,
:published,
:video_url, #str
:vimeo_video_id,
@@ -47,6 +49,7 @@ class Campaign < ActiveRecord::Base
mount_uploader :main_image, CampaignMainImageUploader
mount_uploader :background_image, CampaignBackgroundImageUploader
+ mount_uploader :custom_banner, CampaignCustomBannerUploader
has_many :donations
has_many :charges, through: :donations
@@ -60,6 +63,7 @@ class Campaign < ActiveRecord::Base
has_many :activities, as: :host, dependent: :destroy
belongs_to :profile
belongs_to :nonprofit
+ belongs_to :campaign_template
scope :published, -> {where(:published => true)}
scope :active, -> {where(:published => true).where("end_datetime IS NULL OR end_datetime >= ?", Date.today)}
diff --git a/app/models/campaign_template.rb b/app/models/campaign_template.rb
new file mode 100644
index 00000000..fcfe7d63
--- /dev/null
+++ b/app/models/campaign_template.rb
@@ -0,0 +1,24 @@
+class CampaignTemplate < ActiveRecord::Base
+ # these are very arbitrary names – some are attrs of campaign, some are not
+ # might be a good idea to get the default list from settings
+ CUSTOMIZABLE_ATTR = %i(goal_amount_dollars campaigner_photo reason_for_supporting)
+
+ attr_accessible \
+ :template_name,
+ :name, # refers to campaign name
+ :tagline,
+ :goal_amount,
+ :main_image,
+ :remove_main_image, # for carrierwave
+ :video_url,
+ :vimeo_video_id,
+ :youtube_video_id,
+ :summary,
+ :body
+
+ has_many :campaigns
+
+ def customizable_attribute?(attribute_name)
+ CUSTOMIZABLE_ATTR.include? attribute_name.to_sym
+ end
+end
diff --git a/app/uploaders/campaign_custom_banner_uploader.rb b/app/uploaders/campaign_custom_banner_uploader.rb
new file mode 100644
index 00000000..bfc2d652
--- /dev/null
+++ b/app/uploaders/campaign_custom_banner_uploader.rb
@@ -0,0 +1,39 @@
+class CampaignCustomBannerUploader < CarrierWave::Uploader::Base
+
+ # Include RMagick or MiniMagick support:
+ # include CarrierWave::RMagick
+ include CarrierWave::MiniMagick
+
+ # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
+ # include Sprockets::Helpers::RailsHelper
+ # include Sprockets::Helpers::IsolatedHelper
+
+ # Override the directory where uploaded files will be stored.
+ # This is a sensible default for uploaders that are meant to be mounted:
+ def store_dir
+ "uploads/campaigns/#{mounted_as}/#{model.id}"
+ end
+
+ # Process files as they are uploaded:
+ # process :scale => [200, 300]
+ #
+ # def scale(width, height)
+ # # do something
+ # end
+
+ # Add a white list of extensions which are allowed to be uploaded.
+ # For images you might use something like this:
+ def extension_white_list
+ %w(jpg jpeg png)
+ end
+
+ # Override the filename of the uploaded files:
+ # Avoid using model.id or version_name here, see uploader/store.rb for details.
+ # def filename
+ # "something.jpg" if original_filename
+ # end
+
+ def cache_dir
+ "#{Rails.root}/tmp/uploads"
+ end
+end
diff --git a/app/views/campaigns/_settings_modal.html.erb b/app/views/campaigns/_settings_modal.html.erb
index 51838193..199fb825 100644
--- a/app/views/campaigns/_settings_modal.html.erb
+++ b/app/views/campaigns/_settings_modal.html.erb
@@ -92,6 +92,21 @@
+ <% if @nonprofit.custom_layout %>
+
+
+
+ <% end %>
+
@@ -141,7 +156,7 @@
<% end %>