From b99f7959ce545af0d94225e9702d99eec3878fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasia=20Jarmo=C5=82kowicz?= Date: Wed, 11 Apr 2018 22:36:23 +0200 Subject: [PATCH] Add CampaignTemplate Read S3 bucket name and AWS region from env Add /postgres-data to .gitignore Custom campaign layout Adjust custom layout wip fix wizard init on campaign page wip adjust design adjust campaigner profile section wider banner, fix button colours Fix custom layout Add custom_layout to nonprofit and render, if exists Fallback profile picture wip --- .gitignore | 3 +- .../safety_around_water.css.scss | 78 ++++++++ app/controllers/campaigns_controller.rb | 8 +- app/models/campaign.rb | 4 + app/models/campaign_template.rb | 24 +++ .../campaign_custom_banner_uploader.rb | 39 ++++ app/views/campaigns/_settings_modal.html.erb | 17 +- app/views/campaigns/show.html.erb | 3 +- .../safety_around_water.html.erb | 169 ++++++++++++++++++ client/js/nonprofits/donate/wizard.js | 27 +-- config/routes.rb | 3 + config/settings.yml | 2 +- .../201810202124316_add_campaign_templates.rb | 22 +++ ...02124317_add_custom_layout_to_nonprofit.rb | 5 + .../201810202124318_add_banner_to_campaign.rb | 5 + db/structure.sql | 70 +++++++- 16 files changed, 458 insertions(+), 21 deletions(-) create mode 100644 app/assets/stylesheets/campaigns/custom_layout/safety_around_water.css.scss create mode 100644 app/models/campaign_template.rb create mode 100644 app/uploaders/campaign_custom_banner_uploader.rb create mode 100644 app/views/nonprofits/custom_campaign_layouts/safety_around_water.html.erb create mode 100644 db/migrate/201810202124316_add_campaign_templates.rb create mode 100644 db/migrate/201810202124317_add_custom_layout_to_nonprofit.rb create mode 100644 db/migrate/201810202124318_add_banner_to_campaign.rb 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 %> +
+ +
+
+ +

Custom image at the very top of the campaign page

+
+ Edit + +
+
+
+ <% end %> +
@@ -141,7 +156,7 @@ <% end %>
- + > diff --git a/app/views/campaigns/show.html.erb b/app/views/campaigns/show.html.erb index 0fb8f954..6218ffa3 100644 --- a/app/views/campaigns/show.html.erb +++ b/app/views/campaigns/show.html.erb @@ -84,7 +84,7 @@ Manage Gift Options <% end %> - +
@@ -141,4 +141,3 @@ <%= render 'components/share_modal', name: @campaign.name, type: 'campaign' %> <%= render 'common/email_share_modal', fundraiser: @campaign.name, fundraiser_url: @url %> - diff --git a/app/views/nonprofits/custom_campaign_layouts/safety_around_water.html.erb b/app/views/nonprofits/custom_campaign_layouts/safety_around_water.html.erb new file mode 100644 index 00000000..078fc99f --- /dev/null +++ b/app/views/nonprofits/custom_campaign_layouts/safety_around_water.html.erb @@ -0,0 +1,169 @@ +<%= content_for(:title_prefix) { "#{@campaign.name} - #{@campaign.nonprofit.name} | ".html_safe } %> +<% content_for(:fixed_position_cta_hidden) {'hidden'} %> +<%= content_for(:meta_description) {raw @campaign.summary} %> +<% @brand_color = @nonprofit.brand_color ? @nonprofit.brand_color : nil %> + +<%= content_for :javascripts do %> + + <%= render 'schema', campaign: @campaign, url: @url %> + <%= render 'common/froala' if current_campaign_editor? %> + + <%= IncludeAsset.js '/client/js/campaigns/show/page.js' %> +<% end %> + +<%= content_for :stylesheets do %> + <%= stylesheet_link_tag 'campaigns/show/page' %> + <%= stylesheet_link_tag 'campaigns/edit/page' %> + <%= stylesheet_link_tag 'campaigns/custom_layout/safety_around_water' %> + +<% end %> + +<% content_for :head do %> + +<% end %> + +<%= content_for :facebook_tags do %> + + + +<% end %> + +<%= content_for :twitter_tags do %> + + + +<% end %> + +<% if current_campaign_editor? %> + <%= render 'admin_top_nav' %> +<% end %> + +<%= render '/components/trial_bar' if QueryBillingSubscriptions.currently_in_trial?(@nonprofit.id) %> + +<% hide_title = @campaign.hide_title && @campaign_background_image ? true : false %> +<% css_style = current_campaign_editor? ? "style='margin-top: 0'" : '' %> + +
+ +
+ + <%= render 'components/fundraising_pages/header', + image_url: @campaign_background_image, + is_editor: current_campaign_editor?, + hide_title: @campaign.hide_title && @campaign_background_image, + header_content_partial: 'header_content' %> + + <%= render 'components/preview_mode_notification' %> + +
+
+ <%= render 'campaign_media' %> +
+ +
+ + <% if current_campaign_editor? %> + + + <% end %> + + +
+ + + +
+ +
+ +
+
+
+ /> +
+
+

<%= @campaign.profile.name %>

+

<%= @campaign.profile.city %>

+
+
+ +
+
I am supporting the Y because…
+
+ (customizable reason) +
+ + <% unless current_campaign_editor? %> + + Start Your Own Campaign for <%= @nonprofit.name %> + + <% end %> +
+
+
+ +
+

<%= @campaign.name %>

+ +
+ <%= raw @campaign.body %> +
+ + <% unless @campaign.hide_activity_feed %> +
+ <%= render 'components/activity_feed' %> +
+ <% end %> +
+
+
+ +<% if current_campaign_editor? %> + <%= render 'settings_modal' %> + <%= render 'video_modal' %> + <%= render 'donations/campaign_new_offline_modal' %> + <%= render 'campaign_gift_options/manage_modal'%> + <%= render 'campaign_gift_options/form_modal'%> + <%= render 'components/upload_background_image', + end_point: "/nonprofits/#{@nonprofit.id}/campaigns/#{@campaign.id}", + image_url: @campaign_background_image, + input_name: 'campaign[background_image]' %> + <%= render 'components/custom_receipt_modal', + title: 'Campaign Receipt Message', + type: 'campaign', + path: nonprofit_campaign_path(@nonprofit, @campaign), + key: 'campaign[receipt_message]', + text: @campaign.receipt_message %> + <%= render 'components/duplicate_fundraiser_modal', type: 'campaign' %> +<% end %> + +<%= render 'components/share_modal', name: @campaign.name, type: 'campaign' %> +<%= render 'common/email_share_modal', fundraiser: @campaign.name, fundraiser_url: @url %> diff --git a/client/js/nonprofits/donate/wizard.js b/client/js/nonprofits/donate/wizard.js index 1d4a547f..59c945bd 100644 --- a/client/js/nonprofits/donate/wizard.js +++ b/client/js/nonprofits/donate/wizard.js @@ -27,6 +27,7 @@ renderStyles()(brandedWizard(null)) // pass in a stream of configuration parameters const init = params$ => { + console.log(params$()) var state = { error$: flyd.stream() , loading$: flyd.stream() @@ -99,10 +100,10 @@ const init = params$ => { (ev, params) => { if(!parent) return if(params.redirect) parent.postMessage(`commitchange:redirect:${params.redirect}`, '*') - else if(params.mode !== 'embedded'){ + else if(params.mode !== 'embedded'){ parent.postMessage('commitchange:close', '*'); } else { - if (window.parent) {window.parent.postMessage('commitchange:close', '*');}; + if (window.parent) {window.parent.postMessage('commitchange:close', '*');}; } } , state.clickFinish$, state.params$ ) @@ -193,16 +194,18 @@ const headerDesignation = state => { } const wizardWrapper = state => { - return h('div.wizard-steps.donation-steps', [ - wizard.view(R.merge(state.wizard, { - steps: [ - {name: I18n.t('nonprofits.donate.amount.label'), body: amountStep.view(state.amountStep)} - , {name: I18n.t('nonprofits.donate.info.label'), body: infoStep.view(state.infoStep)} - , {name: I18n.t('nonprofits.donate.payment.label'), body: paymentStep.view(state.paymentStep)} - ] - , followup: followupStep.view(state) - })) - ]) + // return h('div.wizard-steps.donation-steps', [ + // wizard.view(R.merge(state.wizard, { + // steps: [ + // {name: I18n.t('nonprofits.donate.amount.label'), body: amountStep.view(state.amountStep)} + // , {name: I18n.t('nonprofits.donate.info.label'), body: infoStep.view(state.infoStep)} + // , {name: I18n.t('nonprofits.donate.payment.label'), body: paymentStep.view(state.paymentStep)} + // ] + // , followup: followupStep.view(state) + // })) + // ]) + + return h('div.wizard-steps.donation-steps', 'Donation widget should be here.') } module.exports = {view, init} diff --git a/config/routes.rb b/config/routes.rb index a9520158..39f0f3e5 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -147,6 +147,8 @@ Commitchange::Application.routes.draw do resources(:campaign_gift_options, {only: [:index, :show, :create, :update, :destroy]}) do put(:update_order, {on: :collection}) end + + get 'custom_layout', controller: 'campaigns', action: 'custom_layout' end resource(:billing_subscription, {only: [:create]}) do @@ -224,6 +226,7 @@ Commitchange::Application.routes.draw do # Campaigns match ':state_code/:city/:name/campaigns' => 'campaigns#index' match ':state_code/:city/:name/campaigns/:campaign_slug' => 'campaigns#show', :as => :campaign_loc + match ':state_code/:city/:name/campaigns/:campaign_slug/custom_layout' => 'campaigns#custom_layout', :as => :campaign_loc match ':state_code/:city/:name/campaigns/:campaign_slug/supporters' => 'campaigns/supporters#index', :as => :campaign_loc match '/peer-to-peer' => 'campaigns#peer_to_peer' diff --git a/config/settings.yml b/config/settings.yml index c465193b..f657c967 100644 --- a/config/settings.yml +++ b/config/settings.yml @@ -20,7 +20,7 @@ default: aws: access_key_id: <%= ENV['AWS_ACCESS_KEY'] %> secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> - region: test + region: <%= ENV['AWS_REGION'] %> bucket: <%= ENV['S3_BUCKET_NAME'] %> mailer: diff --git a/db/migrate/201810202124316_add_campaign_templates.rb b/db/migrate/201810202124316_add_campaign_templates.rb new file mode 100644 index 00000000..062f37b2 --- /dev/null +++ b/db/migrate/201810202124316_add_campaign_templates.rb @@ -0,0 +1,22 @@ +class AddCampaignTemplates < ActiveRecord::Migration + def change + create_table :campaign_templates do |t| + t.string :template_name, null: false + t.string :name + t.string :tagline + t.integer :goal_amount + t.string :main_image + t.text :video_url + t.string :vimeo_video_id + t.string :youtube_video_id + t.text :summary + t.text :body + + t.timestamps + end + + change_table :campaigns do |t| + t.references :campaign_template + end + end +end diff --git a/db/migrate/201810202124317_add_custom_layout_to_nonprofit.rb b/db/migrate/201810202124317_add_custom_layout_to_nonprofit.rb new file mode 100644 index 00000000..db58866a --- /dev/null +++ b/db/migrate/201810202124317_add_custom_layout_to_nonprofit.rb @@ -0,0 +1,5 @@ +class AddCustomLayoutToNonprofit < ActiveRecord::Migration + def change + add_column :nonprofits, :custom_layout, :string + end +end diff --git a/db/migrate/201810202124318_add_banner_to_campaign.rb b/db/migrate/201810202124318_add_banner_to_campaign.rb new file mode 100644 index 00000000..c1fe6406 --- /dev/null +++ b/db/migrate/201810202124318_add_banner_to_campaign.rb @@ -0,0 +1,5 @@ +class AddBannerToCampaign < ActiveRecord::Migration + def change + add_column :campaigns, :custom_banner, :string + end +end diff --git a/db/structure.sql b/db/structure.sql index 0844371c..b146ebc2 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -2,8 +2,13 @@ -- PostgreSQL database dump -- +<<<<<<< HEAD -- Dumped from database version 9.6.5 -- Dumped by pg_dump version 9.6.10 +======= +-- Dumped from database version 9.6.8 +-- Dumped by pg_dump version 9.6.8 +>>>>>>> Add CampaignTemplate SET statement_timeout = 0; SET lock_timeout = 0; @@ -355,6 +360,46 @@ CREATE SEQUENCE public.campaign_gifts_id_seq ALTER SEQUENCE public.campaign_gifts_id_seq OWNED BY public.campaign_gifts.id; +-- +-- Name: campaign_templates; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.campaign_templates ( + id integer NOT NULL, + template_name character varying(255) NOT NULL, + name character varying(255), + tagline character varying(255), + goal_amount integer, + main_image character varying(255), + video_url text, + vimeo_video_id character varying(255), + youtube_video_id character varying(255), + summary text, + body text, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL +); + + +-- +-- Name: campaign_templates_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.campaign_templates_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: campaign_templates_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.campaign_templates_id_seq OWNED BY public.campaign_templates.id; + + -- -- Name: campaigns; Type: TABLE; Schema: public; Owner: - -- @@ -392,7 +437,8 @@ CREATE TABLE public.campaigns ( hide_custom_amounts boolean, show_recurring_amount boolean DEFAULT false, end_datetime timestamp without time zone, - external_identifier character varying(255) + external_identifier character varying(255), + campaign_template_id integer ); @@ -1412,7 +1458,8 @@ CREATE TABLE public.nonprofits ( card_failure_message_bottom text, fields_needed text, autocomplete_supporter_address boolean DEFAULT false, - currency character varying(255) DEFAULT 'usd'::character varying + currency character varying(255) DEFAULT 'usd'::character varying, + custom_layout character varying(255) ); @@ -2305,6 +2352,13 @@ ALTER TABLE ONLY public.campaign_gift_options ALTER COLUMN id SET DEFAULT nextva ALTER TABLE ONLY public.campaign_gifts ALTER COLUMN id SET DEFAULT nextval('public.campaign_gifts_id_seq'::regclass); +-- +-- Name: campaign_templates id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.campaign_templates ALTER COLUMN id SET DEFAULT nextval('public.campaign_templates_id_seq'::regclass); + + -- -- Name: campaigns id; Type: DEFAULT; Schema: public; Owner: - -- @@ -2690,6 +2744,14 @@ ALTER TABLE ONLY public.campaign_gifts ADD CONSTRAINT campaign_gifts_pkey PRIMARY KEY (id); +-- +-- Name: campaign_templates campaign_templates_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.campaign_templates + ADD CONSTRAINT campaign_templates_pkey PRIMARY KEY (id); + + -- -- Name: campaigns campaigns_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -4347,3 +4409,7 @@ INSERT INTO schema_migrations (version) VALUES ('20181002160627'); INSERT INTO schema_migrations (version) VALUES ('20181003212559'); +INSERT INTO schema_migrations (version) VALUES ('201810202124316'); + +INSERT INTO schema_migrations (version) VALUES ('201810202124317'); +