Merge branch 'master' into docker-improvement-latest

This commit is contained in:
Eric Schultz 2018-11-30 20:47:50 -06:00 committed by GitHub
commit f8874f49f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
70 changed files with 1625 additions and 1103 deletions

1
.gitignore vendored
View file

@ -7,6 +7,7 @@ client/js/nonprofits/donate/plugins-enabled
.DS_Store .DS_Store
/postgres-data
# Ignore bundler config # Ignore bundler config
/.bundle /.bundle

View file

@ -0,0 +1,9 @@
/* License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later */
body .campaign-banner {
margin: auto;
width: 980px;
max-height: 120px;
text-align: center;
overflow: hidden;
}

View file

@ -6,11 +6,14 @@
@import 'components/simple_tabs'; @import 'components/simple_tabs';
@import 'pikaday'; @import 'pikaday';
@import 'common/image_uploader'; @import 'common/image_uploader';
@import '../common';
body { body {
padding: 0; padding: 0;
background: $fog; background: $fog;
} }
main { main {
display: block; display: block;
padding: 60px 0 50px 0; padding: 60px 0 50px 0;

View file

@ -13,6 +13,7 @@
@import 'components/draggable'; @import 'components/draggable';
@import 'gift_levels'; @import 'gift_levels';
@import '../../nonprofits/donation_form/form'; @import '../../nonprofits/donation_form/form';
@import '../common';
.button--gift { .button--gift {
font-size: 17px; font-size: 17px;
@ -103,6 +104,43 @@
margin-right: 1px; margin-right: 1px;
} }
.campaigner-profile {
display: flex;
flex-wrap: nowrap;
align-items: baseline;
}
.campaigner-profile > figure {
display: flex;
flex-direction: column;
align-items: center;
margin: auto 10px;
align-self: flex-start;
}
.campaigner-profile > figure > .avatar {
flex-basis: 20%;
min-width: 100px;
height: auto;
}
.avatar > img {
clip-path: circle(50% at center);
}
.campaigner-profile > figure > figcaption {
flex-basis: 40%;
padding: 15px;
text-align: left;
}
.campaigner-profile .reason {
flex-basis: 60%;
}
.campaigner-profile .pastelBox-body {
min-height: 100px;
}
@media screen and (max-width: 1000px) { @media screen and (max-width: 1000px) {
.box, .box,

View file

@ -19,6 +19,11 @@
width: 192px; width: 192px;
} }
.image-upload--banner {
width: 100%;
height: auto;
}
.image-upload span { .image-upload span {
margin-top: 30px; margin-top: 30px;
padding: 5px; padding: 5px;
@ -28,6 +33,11 @@
@include basicShadow; @include basicShadow;
} }
.image-upload--banner span {
margin-top: 30px;
margin-bottom: 30px;
}
.image-upload--large span { .image-upload--large span {
margin-top: 60px; margin-top: 60px;
} }

View file

@ -36,23 +36,34 @@ class CampaignsController < ApplicationController
@nonprofit = current_nonprofit @nonprofit = current_nonprofit
@url = Format::Url.concat(root_url, @campaign.url) @url = Format::Url.concat(root_url, @campaign.url)
@campaign_background_image = FetchBackgroundImage.with_model(@campaign) if @campaign.child_campaign?
@parent_campaign = @campaign.parent_campaign
respond_to do |format| @peer_to_peer_campaign_param = @parent_campaign.id
format.html else
@peer_to_peer_campaign_param = @campaign.id
end end
@campaign_background_image = FetchBackgroundImage.with_model(@campaign)
end end
def activities def activities
render json: QueryDonations.for_campaign_activities(params[:id]) @campaign = current_campaign
render json: QueryDonations.for_campaign_activities(@campaign.id)
end end
def create def create
Time.use_zone(current_nonprofit.timezone || 'UTC') do Time.use_zone(current_nonprofit.timezone || 'UTC') do
params[:campaign][:end_datetime] = Chronic.parse(params[:campaign][:end_datetime]) if params[:campaign][:end_datetime].present? params[:campaign][:end_datetime] = Chronic.parse(params[:campaign][:end_datetime]) if params[:campaign][:end_datetime].present?
end end
campaign = current_nonprofit.campaigns.create params[:campaign]
json_saved campaign, 'Campaign created! Well done.' if !params[:campaign][:parent_campaign_id]
campaign = current_nonprofit.campaigns.create params[:campaign]
json_saved campaign, 'Campaign created! Well done.'
else
profile_id = params[:campaign][:profile_id]
Profile.find(profile_id).update_attributes params[:profile]
render json: CreatePeerToPeerCampaign.create(params[:campaign], profile_id)
end
end end
def update def update
@ -63,7 +74,6 @@ class CampaignsController < ApplicationController
json_saved current_campaign, 'Successfully updated!' json_saved current_campaign, 'Successfully updated!'
end end
# post 'nonprofits/:np_id/campaigns/:campaign_id/duplicate' # post 'nonprofits/:np_id/campaigns/:campaign_id/duplicate'
def duplicate def duplicate
@ -98,7 +108,22 @@ class CampaignsController < ApplicationController
def peer_to_peer def peer_to_peer
session[:donor_signup_url] = request.env["REQUEST_URI"] session[:donor_signup_url] = request.env["REQUEST_URI"]
@npo = Nonprofit.find_by_id(params[:npo_id]) @nonprofit = Nonprofit.find_by_id(params[:npo_id])
@parent_campaign = Campaign.find_by_id(params[:campaign_id])
if params[:campaign_id].present? && !@parent_campaign
raise ActionController::RoutingError.new('Not Found')
end
if current_user
@profile = current_user.profile
if (@parent_campaign)
@child_campaign = Campaign.where(
profile_id: @profile.id,
parent_campaign_id: @parent_campaign.id
).first
end
end
end end
private private
@ -108,5 +133,4 @@ class CampaignsController < ApplicationController
raise ActionController::RoutingError.new('Not Found') raise ActionController::RoutingError.new('Not Found')
end end
end end
end end

View file

@ -13,6 +13,8 @@ class Campaign < ActiveRecord::Base
:remove_main_image, # for carrierwave :remove_main_image, # for carrierwave
:background_image, :background_image,
:remove_background_image, #bool carrierwave :remove_background_image, #bool carrierwave
:banner_image,
:remove_banner_image,
:published, :published,
:video_url, #str :video_url, #str
:vimeo_video_id, :vimeo_video_id,
@ -30,7 +32,10 @@ class Campaign < ActiveRecord::Base
:hide_thermometer, #bool :hide_thermometer, #bool
:hide_title, # bool :hide_title, # bool
:receipt_message, # text :receipt_message, # text
:hide_custom_amounts # boolean :hide_custom_amounts, # boolean
:parent_campaign_id,
:reason_for_supporting,
:default_reason_for_supporting
validate :end_datetime_cannot_be_in_past, :on => :create validate :end_datetime_cannot_be_in_past, :on => :create
validates :profile, :presence => true validates :profile, :presence => true
@ -47,6 +52,7 @@ class Campaign < ActiveRecord::Base
mount_uploader :main_image, CampaignMainImageUploader mount_uploader :main_image, CampaignMainImageUploader
mount_uploader :background_image, CampaignBackgroundImageUploader mount_uploader :background_image, CampaignBackgroundImageUploader
mount_uploader :banner_image, CampaignBannerImageUploader
has_many :donations has_many :donations
has_many :charges, through: :donations has_many :charges, through: :donations
@ -61,6 +67,9 @@ class Campaign < ActiveRecord::Base
belongs_to :profile belongs_to :profile
belongs_to :nonprofit belongs_to :nonprofit
belongs_to :parent_campaign, class_name: 'Campaign'
has_many :children_campaigns, class_name: 'Campaign', foreign_key: 'parent_campaign_id'
scope :published, -> {where(:published => true)} scope :published, -> {where(:published => true)}
scope :active, -> {where(:published => true).where("end_datetime IS NULL OR end_datetime >= ?", Date.today)} scope :active, -> {where(:published => true).where("end_datetime IS NULL OR end_datetime >= ?", Date.today)}
scope :past, -> {where(:published => true).where("end_datetime < ?", Date.today)} scope :past, -> {where(:published => true).where("end_datetime < ?", Date.today)}
@ -155,4 +164,24 @@ class Campaign < ActiveRecord::Base
(self.end_datetime.to_date - Date.today).to_i (self.end_datetime.to_date - Date.today).to_i
end end
def finished?
self.end_datetime && self.end_datetime < Time.now
end
def child_params
excluded_for_peer_to_peer = %w(
id created_at updated_at slug profile_id url
total_raised show_recurring_amount external_identifier parent_campaign_id
reason_for_supporting metadata
)
attributes.except(*excluded_for_peer_to_peer)
end
def child_campaign?
parent_campaign.present?
end
def parent_campaign?
!child_campaign?
end
end end

View file

@ -1,3 +1,4 @@
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
class EmailList < ActiveRecord::Base class EmailList < ActiveRecord::Base
attr_accessible :list_name, :mailchimp_list_id, :nonprofit, :tag_master attr_accessible :list_name, :mailchimp_list_id, :nonprofit, :tag_master
belongs_to :nonprofit belongs_to :nonprofit

View file

@ -0,0 +1,16 @@
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
class CampaignBannerImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
def store_dir
"uploads/campaigns/#{mounted_as}/#{model.id}"
end
def extension_white_list
%w(jpg jpeg png)
end
def cache_dir
"#{Rails.root}/tmp/uploads"
end
end

View file

@ -5,39 +5,42 @@
<p><strong>Manage Campaign</strong></p> <p><strong>Manage Campaign</strong></p>
<a class='button--tiny edit'>
<!--= on 'click' (open_modal 'campaignSettings') -->
<i class='fa fa-gear'></i> Settings
</a>
<a class='button--tiny edit' target='_blank' href="<%= @campaign.url + '/supporters' %>">
<i class='fa fa-th-list'></i> Dashboard
</a>
<a class='button--tiny edit'>
<!--= on 'click' (open_modal 'offlineCampaignDonation') -->
<i class='fa fa-plus'></i> Offsite Donation
</a>
<a class='button--tiny edit'> <a class='button--tiny edit'>
<!--= on 'click' (open_modal 'manageGiftOptionsModal') --> <!--= on 'click' (open_modal 'campaignSettings') -->
<i class='fa fa-gift'></i> Gift Options <i class='fa fa-gear'></i> Settings
</a> </a>
<a class='button--tiny edit'> <% if @campaign.parent_campaign? %>
<!--= on 'click' (open_modal 'customReceiptModal') --> <a class='button--tiny edit' target='_blank' href="<%= @campaign.url + '/supporters' %>">
<i class='fa fa-pencil'></i> Custom Receipt <i class='fa fa-th-list'></i> Dashboard
</a> </a>
<a class='button--tiny edit'>
<!--= on 'click' (open_modal 'offlineCampaignDonation') -->
<i class='fa fa-plus'></i> Offsite Donation
</a>
<a class='button--tiny edit'>
<!--= on 'click' (open_modal 'manageGiftOptionsModal') -->
<i class='fa fa-gift'></i> Gift Options
</a>
<a class='button--tiny edit'>
<!--= on 'click' (open_modal 'customReceiptModal') -->
<i class='fa fa-pencil'></i> Custom Receipt
</a>
<% end %>
<a class='button--tiny edit' href='?preview=t'> <a class='button--tiny edit' href='?preview=t'>
<i class='fa fa-eye'></i> Preview Mode <i class='fa fa-eye'></i> Preview Mode
</a> </a>
<a class='button--tiny edit'> <% if @campaign.parent_campaign? %>
<!--= on 'click' (open_modal 'duplicateFundraiserModal') --> <a class='button--tiny edit'>
<i class='fa fa-copy'></i> Copy Campaign <!--= on 'click' (open_modal 'duplicateFundraiserModal') -->
</a> <i class='fa fa-copy'></i> Copy Campaign
</a>
<% end %>
<%= render 'components/messages/deleted_campaign_or_event', type: 'campaign' %> <%= render 'components/messages/deleted_campaign_or_event', type: 'campaign' %>

View file

@ -1,7 +0,0 @@
<%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%>
<% selector ||= nil %>
<div class='progressBar--medium-fill' if-branded='background-color, light'>
<!--= style 'width' (cat metrics.percentage_funded '%') -->
</div>

View file

@ -1,6 +1,8 @@
<%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%> <%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%>
<table class='table--striped u-marginBottom--0'> <table class='table--striped u-marginBottom--0'>
<% campaigns.each do |campaign |%> <% campaigns.each do |campaign|%>
<% metric = QueryCampaignMetrics.on_donations(campaign.id) %>
<tr> <tr>
<td class='u-padding--0 u-width--200 u-hideIf--400'> <td class='u-padding--0 u-width--200 u-hideIf--400'>
<img src='<%= campaign.main_image_url(:normal) %>'> <img src='<%= campaign.main_image_url(:normal) %>'>
@ -18,11 +20,11 @@
<small><%= campaign.summary ? strip_tags(campaign.summary) : strip_tags(campaign.tagline) %></small> <small><%= campaign.summary ? strip_tags(campaign.summary) : strip_tags(campaign.tagline) %></small>
</p> </p>
<% if campaign.show_total_count %> <% if campaign.show_total_count %>
<span class='pastelBox--white u-padding--3'><%= campaign.donations.count %> <small>supporters</small></span> <span class='pastelBox--white u-padding--3'><%= metric['supporters_count'] %> <small>supporters</small></span>
<% end %> <% end %>
<% if campaign.show_total_raised %> <% if campaign.show_total_raised %>
<span class='pastelBox--white u-padding--3'> <span class='pastelBox--white u-padding--3'>
<%= print_currency campaign.total_raised, campaign.nonprofit.currency_symbol %> <small>raised</small> <%= print_currency metric['total_raised'], campaign.nonprofit.currency_symbol %> <small>raised</small>
</span> </span>
<% end %> <% end %>
</td> </td>

View file

@ -1,39 +0,0 @@
<%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%>
<!-- partial start: campaigns/fixed_top_actions -->
<div class='fixedTopAction fixedTopAction--campaign' <%= current_campaign_editor? ? "style='padding-left: 60px'".html_safe : "" %>>
<div class='container'>
<table class='fixedTopAction-table'>
<tr>
<td class='fixedTopAction-left'>
<h1 class='fixedTopAction-title'><%= @campaign.name %></h1><br>
<span class='fixedTopAction-metrics'>
<a if-branded='color, darker' href='<%= @nonprofit.url %>'> <%= @nonprofit.name %></a>
<span class='u-capitalize'><%= Format::Address.city_and_state(@nonprofit.city, @nonprofit.state_code) %></span>
<span>
<!--= show_if campaign_time_remaining -->
<!--= put campaign_time_remaining --> left
</span>
</span>
</td>
<td class='fixedTopAction-right'>
<% if !@campaign.hide_thermometer %>
<div class='fixedTopAction-hideWhenMobile progressBar--medium'>
<%= render 'campaign_progress_bar_inner', selector: 'u-width--full' %>
</div>
<% end %>
<a class='u-marginRight--10 fixedTopAction-promote' title='Promote' if-branded='color, darker'>
<!--= on 'click' (open_modal 'shareModal') -->
Promote</a>
<button class='button' id='js-contribute' title='Contribute' if-branded='background, dark'>
Contribute
</button>
</td>
</tr>
</table>
</div>
</div>
<!-- partial end: campaigns/fixed_top_actions -->

View file

@ -0,0 +1,77 @@
<!-- partial campaigns/new-modal -->
<!-- include 'campaigns/new/index' -->
<div class='modal' id='newPeerToPeerCampaign'>
<%= render 'common/modal_header', title: @parent_campaign.name %>
<div class='wizard-steps' style='display:none;'>
<!--= wizard.init 'new_p2p_campaign_wiz' -->
<%= render 'components/wizard/step_index', wizard_name: 'new_p2p_campaign_wiz' %>
<div class='modal-body' style='display: table;'>
<div class='wizard-step reason-step'>
<!--= wizard.set_step 'new_p2p_campaign_wiz' 'About you' -->
<form parsley-validate>
<!--= on 'submit' (def 'new_p2p_campaign' form_object) (wizard.advance 'new_p2p_campaign_wiz') -->
<input type='hidden' name='campaign[profile_id]' value='<%= current_user.profile.id %>'>
<input type='hidden' name='campaign[parent_campaign_id]' value='<%= @parent_campaign.id %>'>
<p>Personalize your campaign page with your name and photo to greatly increase the success of your campaign.</p>
<div class='layout--three'>
<fieldset>
<label>Name</label>
<input type='text' name='profile[name]' placeholder='Your Name' value='<%= @profile.name %>' required>
</fieldset>
<fieldset>
<label>City</label>
<input type='text' name='profile[city]' placeholder='City' value='<%= @profile.city %>'>
</fieldset>
<fieldset>
<label>State</label>
<%= render 'common/states_dropdown', name: 'profile[state_code]', default: @profile.state_code %>
</fieldset>
</div>
<%= render 'components/forms/submit_button', button_text: 'Next', scope: 'new_p2p_campaign_wiz', branded: true %>
</form>
</div>
<div class='wizard-step amount-step'>
<!--= wizard.set_step 'new_p2p_campaign_wiz' 'Customize' -->
<form parsley-validate>
<!--= on 'submit' create_p2p_campaign -->
<!--= log new_p2p_campaign -->
<div class='u-margin--auto'>
<fieldset class='col-right-12'>
<label>What's your reason for supporting <%= @parent_campaign.name %>?</label>
<p>Your passion is contagious! Inspire giving by telling your network why youre getting involved in this campaign.</p>
<textarea class='u-marginTop--15' rows='4' name='campaign[reason_for_supporting]' required><%= @parent_campaign.default_reason_for_supporting %></textarea>
</fieldset>
<fieldset class='group u-marginBottom--0'>
<label class='u-paddingTop--5'>Goal Amount</label>
<div class='prepend--dollar'>
<input class='input--100 u-marginBottom--5' value='1000' type='number' name='campaign[goal_amount_dollars]' required min='1'>
</div>
</fieldset>
</div>
<%= render 'components/forms/submit_button', button_text: 'Preview Campaign!', scope: 'new_p2p_campaign_wiz', branded: true %>
</form>
</div>
</div>
</div>
</div>
<!-- end partial campaigns/new-modal -->

View file

@ -4,160 +4,205 @@
<%= render 'common/modal_header', title: 'Campaign Settings' %> <%= render 'common/modal_header', title: 'Campaign Settings' %>
<form class='form--flatFields' autosubmit action='/nonprofits/<%=@nonprofit.id%>/campaigns/<%=@campaign.id%>' method='put' data-reload parsley-validate> <form class='form--flatFields' autosubmit action='/nonprofits/<%=@nonprofit.id%>/campaigns/<%=@campaign.id%>' method='put' data-reload parsley-validate>
<% if @campaign.child_campaign? %>
<div class='modal-body'>
<section class='layout--three'>
<fieldset>
<label>Goal</label>
<div class='prepend--dollar u-inlineBlock'>
<input type='number' parsley-type='number' class='input--150' name='campaign[goal_amount_dollars]' value='<%= sprintf("%.2f", @campaign.goal_amount / 100.0) %>'>
</div>
</fieldset>
</section>
</div>
<% else %>
<div class='modal-body'> <div class='modal-body'>
<section class='layout--two'> <section class='layout--two'>
<fieldset> <fieldset>
<label>Title </label> <label>Title </label>
<input type='text' class='u-marginBottom--0' name='campaign[name]' value='<%= @campaign.name %>'> <input type='text' class='u-marginBottom--0' name='campaign[name]' value='<%= @campaign.name %>'>
</fieldset> </fieldset>
<fieldset> <fieldset>
<label class='u-block'>Tagline</label> <label class='u-block'>Tagline</label>
<input type='text' name='campaign[tagline]' value='<%= @campaign.tagline %>'> <input type='text' name='campaign[tagline]' value='<%= @campaign.tagline %>'>
</fieldset> </fieldset>
</section> </section>
<hr> <hr>
<section class='layout--three'> <section class='layout--three'>
<fieldset> <fieldset>
<label>Goal</label> <label>Goal</label>
<div class='prepend--dollar u-inlineBlock'> <div class='prepend--dollar u-inlineBlock'>
<input type='number' parsley-type='number' class='input--150' name='campaign[goal_amount_dollars]' value='<%= sprintf("%.2f", @campaign.goal_amount / 100.0) %>'> <input type='number' parsley-type='number' class='input--150' name='campaign[goal_amount_dollars]' value='<%= sprintf("%.2f", @campaign.goal_amount / 100.0) %>'>
</div> </div>
</fieldset> </fieldset>
</fieldset>
<fieldset>
<label>End Date & Time</label>
<div pikaday-timepicker='MM/DD/YYYY hh:mm a'>
<input class='u-width--200 u-bold u-inlineBlock' type='text' name='campaign[end_datetime]' required parsley-trigger='change' placeholder='MM/DD/YYYY HH:MM' value='<%= Format::Date.full(@campaign.end_datetime, @nonprofit.timezone) %>'>
<a class='button edit u-inlineBlock'>Set</a>
</div>
</fieldset>
</section>
<hr>
<%= render 'components/forms/slug_field', fundraiser: @campaign, url: @nonprofit.url + '/campaigns' %>
<hr>
<section class='layout--three u-overflow--hidden'>
<fieldset>
<label>Main Image <small>(at least 500x400)</small></label>
<p><small>Used for previews and social media</small></p>
<div class='image-upload u-inlineBlock' style='background-image: url("<%= @campaign.main_image_url(:thumb) %>");'>
<span><i class='fa fa-pencil'></i> Edit</span>
<input type='file' name='campaign[main_image]'>
</div>
</fieldset>
<fieldset>
<label>Header Image <small>(1000x600)</small></label>
<p><small>Used at top of campaign page</small></p>
<% if @campaign_background_image %>
<div class='image-upload u-inlineBlock' style='background-image:url(<%= @campaign_background_image %>)'>
<!--= on 'click' (open_modal 'uploadBackgroundImage') -->
<span><i class='fa fa-pencil'></i> Edit</span>
</div>
<% else %>
<a class='button edit'>
<!--= on 'click' (open_modal 'uploadBackgroundImage') -->
<i class='fa fa-plus'></i> Add Image </i>
</a>
<% end %>
</fieldset>
<fieldset>
<label>Campaign Video </label>
<p><small>Videos are optional but recommended</small></p>
<% if @campaign.vimeo_video_id || @campaign.youtube_video_id%>
<% if @campaign.vimeo_video_id %>
<div class='image-upload u-inlineBlock'>
<!--= set_attr 'style' vimeo_image_url -->
<!--= on 'click' (open_modal 'videoModal') -->
<span> <i class='fa fa-pencil'></i> Edit</span>
</div>
<% else%>
<div class='image-upload u-inlineBlock' style="background-image:url('http://img.youtube.com/vi/<%=@campaign.youtube_video_id%>/0.jpg')">
<!--= on 'click' (open_modal 'videoModal') -->
<span> <i class='fa fa-pencil'></i> Edit</span>
</div>
<% end %>
<% else %>
<a class='button edit'><i class='fa fa-plus'></i> Add Video</a>
<!--= on 'click' (open_modal 'videoModal') -->
<% end %>
</fieldset>
</section>
<hr>
<section class='layout--two'>
<fieldset>
<input type='hidden' name='campaign[published]' value='false'>
<input id='campaign-published-input' type='checkbox' name='campaign[published]' <%= @campaign.published ? "checked='checked'" : '' %>>
<label class='u-marginBottom--10' for='campaign-published-input'>Published?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[show_total_raised]'>
<input id='show_total_raised-checkbox' type='checkbox' name='campaign[show_total_raised]' <%= @campaign.show_total_raised ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='show_total_raised-checkbox'>Show total dollars raised?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[show_total_count]'>
<input id='show_total_count-checkbox' type='checkbox' name='campaign[show_total_count]' <%= @campaign.show_total_count ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='show_total_count-checkbox'>Show total supporters?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[hide_goal]'>
<input id='hide_goal-checkbox' type='checkbox' name='campaign[hide_goal]' <%= @campaign.hide_goal ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='hide_goal-checkbox'>Hide goal amount?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[hide_thermometer]'>
<input id='hide_thermometer-checkbox' type='checkbox' name='campaign[hide_thermometer]' <%= @campaign.hide_thermometer ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='hide_thermometer-checkbox'>Hide thermometer?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[hide_activity_feed]'>
<input id='hide_activity_feed-checkbox' type='checkbox' name='campaign[hide_activity_feed]' <%= @campaign.hide_activity_feed ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='hide_activity_feed-checkbox'>Hide activity feed?</label>
</fieldset>
<% if @campaign_background_image %>
<fieldset> <fieldset>
<input type='hidden' value='false' name='campaign[hide_title]'> <label>End Date & Time</label>
<input id='hide_title-checkbox' type='checkbox' name='campaign[hide_title]' <%= @campaign.hide_title ? 'checked="checked"' : '' %>> <div pikaday-timepicker='MM/DD/YYYY hh:mm a'>
<label for='hide_title-checkbox'>Hide main title?</label> <input class='u-width--200 u-bold u-inlineBlock' type='text' name='campaign[end_datetime]' required parsley-trigger='change' placeholder='MM/DD/YYYY HH:MM' value='<%= Format::Date.full(@campaign.end_datetime, @nonprofit.timezone) %>'>
<a class='button edit u-inlineBlock'>Set</a>
</div>
</fieldset>
</section>
<hr>
<%= render 'components/forms/slug_field', fundraiser: @campaign, url: @nonprofit.url + '/campaigns' %>
<hr>
<section class='layout--three u-overflow--hidden'>
<fieldset>
<label>Main Image <small>(at least 500x400)</small></label>
<p><small>Used for previews and social media</small></p>
<div class='image-upload u-inlineBlock' style='background-image: url("<%= @campaign.main_image_url(:thumb) %>");'>
<span><i class='fa fa-pencil'></i> Edit</span>
<input type='file' name='campaign[main_image]'>
</div>
</fieldset> </fieldset>
<fieldset>
<label>Header Image <small>(1000x600)</small></label>
<p><small>Used at top of campaign page</small></p>
<% if @campaign_background_image %>
<div class='image-upload u-inlineBlock' style='background-image:url(<%= @campaign_background_image %>)'>
<!--= on 'click' (open_modal 'uploadBackgroundImage') -->
<span><i class='fa fa-pencil'></i> Edit</span>
</div>
<% else %>
<a class='button edit'>
<!--= on 'click' (open_modal 'uploadBackgroundImage') -->
<i class='fa fa-plus'></i> Add Image </i>
</a>
<% end %>
</fieldset>
<fieldset>
<label>Campaign Video </label>
<p><small>Videos are optional but recommended</small></p>
<% if @campaign.vimeo_video_id || @campaign.youtube_video_id%>
<% if @campaign.vimeo_video_id %>
<div class='image-upload u-inlineBlock'>
<!--= set_attr 'style' vimeo_image_url -->
<!--= on 'click' (open_modal 'videoModal') -->
<span> <i class='fa fa-pencil'></i> Edit</span>
</div>
<% else%>
<div class='image-upload u-inlineBlock' style="background-image:url('http://img.youtube.com/vi/<%=@campaign.youtube_video_id%>/0.jpg')">
<!--= on 'click' (open_modal 'videoModal') -->
<span> <i class='fa fa-pencil'></i> Edit</span>
</div>
<% end %>
<% else %>
<a class='button edit'><i class='fa fa-plus'></i> Add Video</a>
<!--= on 'click' (open_modal 'videoModal') -->
<% end %>
</fieldset>
</section>
<hr>
<section class='layout--one'>
<fieldset>
<label>Banner <small>(1000x120)</small></label>
<p><small>Custom image at the very top of the campaign page</small></p>
<% if @campaign.banner_image_url.present? %>
<div class='image-upload image-upload--banner u-inlineBlock u-marginBottom--15' style='background-image:url(<%= @campaign.banner_image_url %>)'>
<!--= on 'click' (open_modal 'uploadBannerImage') -->
<span><i class='fa fa-pencil'></i> Edit</span>
</div>
<% else %>
<a class='button edit u-marginBottom--15'>
<!--= on 'click' (open_modal 'uploadBannerImage') -->
<i class='fa fa-plus'></i> Add Image </i>
</a>
<% end %>
</fieldset>
</section>
<% if !@campaign.child_campaign? %>
<hr>
<section class='layout--two'>
<fieldset>
<label>Default reason for peer-to-peer campaigns</label>
<p><small>Use it to suggest a good, pre-filled reason for campaigners</small></p>
<textarea class='u-marginTop--15' rows='4' name='campaign[default_reason_for_supporting]'><%= @campaign.default_reason_for_supporting %></textarea>
</fieldset>
</section>
<% end %> <% end %>
<hr>
<section class='layout--two'>
<fieldset>
<input type='hidden' name='campaign[published]' value='false'>
<input id='campaign-published-input' type='checkbox' name='campaign[published]' <%= @campaign.published ? "checked='checked'" : '' %>>
<label class='u-marginBottom--10' for='campaign-published-input'>Published?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[show_total_raised]'>
<input id='show_total_raised-checkbox' type='checkbox' name='campaign[show_total_raised]' <%= @campaign.show_total_raised ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='show_total_raised-checkbox'>Show total dollars raised?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[show_total_count]'>
<input id='show_total_count-checkbox' type='checkbox' name='campaign[show_total_count]' <%= @campaign.show_total_count ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='show_total_count-checkbox'>Show total supporters?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[hide_goal]'>
<input id='hide_goal-checkbox' type='checkbox' name='campaign[hide_goal]' <%= @campaign.hide_goal ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='hide_goal-checkbox'>Hide goal amount?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[hide_thermometer]'>
<input id='hide_thermometer-checkbox' type='checkbox' name='campaign[hide_thermometer]' <%= @campaign.hide_thermometer ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='hide_thermometer-checkbox'>Hide thermometer?</label>
</fieldset>
<fieldset>
<input type='hidden' value='false' name='campaign[hide_activity_feed]'>
<input id='hide_activity_feed-checkbox' type='checkbox' name='campaign[hide_activity_feed]' <%= @campaign.hide_activity_feed ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='hide_activity_feed-checkbox'>Hide activity feed?</label>
</fieldset>
<% if @campaign_background_image %>
<fieldset>
<input type='hidden' value='false' name='campaign[hide_title]'>
<input id='hide_title-checkbox' type='checkbox' name='campaign[hide_title]' <%= @campaign.hide_title ? 'checked="checked"' : '' %>>
<label for='hide_title-checkbox'>Hide main title?</label>
</fieldset>
<% end %>
<fieldset>
<!--= show_if length gift_options.data -->
<input type='hidden' value='false' name='campaign[hide_custom_amounts]'>
<input id='hide_custom_amounts' type='checkbox' name='campaign[hide_custom_amounts]' <%= @campaign.hide_custom_amounts ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='hide_custom_amounts'>Disallow regular contributions during campaign?</label>
</fieldset>
</section>
<hr>
<fieldset> <fieldset>
<!--= show_if length gift_options.data --> <label>Short Description <small>(used for sharing on social media)</small></label>
<input type='hidden' value='false' name='campaign[hide_custom_amounts]'> <textarea rows='4' name='campaign[summary]'><%= @campaign.summary %></textarea>
<input id='hide_custom_amounts' type='checkbox' name='campaign[hide_custom_amounts]' <%= @campaign.hide_custom_amounts ? 'checked="checked"' : '' %>>
<label class='u-marginBottom--10' for='hide_custom_amounts'>Disallow regular contributions during campaign?</label>
</fieldset> </fieldset>
</section> <div><p class='error'></p></div>
</div>
<hr> <% end %>
<fieldset>
<label>Short Description <small>(used for sharing on social media)</small></label>
<textarea rows='4' name='campaign[summary]'><%= @campaign.summary %></textarea>
</fieldset>
<div><p class='error'></p></div>
</div>
<footer class='modal-footer u-padding--15 layout--two'> <footer class='modal-footer u-padding--15 layout--two'>
<span> <span>

View file

@ -10,15 +10,27 @@
<% content_for :javascripts do %> <% content_for :javascripts do %>
<script> <script>
<% if @npo %> <% if @nonprofit %>
appl.def('selected_result', {name: '<%= @npo.name.html_safe %>', id: <%= @npo.id %>}) appl.def('selected_result', {
app.nonprofit_id = <%= @npo.id %> name: '<%= @nonprofit.name.html_safe %>',
id: <%= @nonprofit.id %>,
modal_id: 'newCampaign'
})
app.nonprofit_id = <%= @nonprofit.id %>
<% elsif @parent_campaign %>
appl.def('selected_result', {
name: '<%= @parent_campaign.nonprofit.name.html_safe %>',
parent_campaign_id: <%= @parent_campaign.id %>,
campaign_name: '<%= @parent_campaign.name %>',
modal_id: 'newPeerToPeerCampaign'
})
app.nonprofit_id = <%= @parent_campaign.nonprofit.id %>
<% end %> <% end %>
<% if current_user %> <% if current_user %>
appl.def('is_logged_in', true) appl.def('is_logged_in', true)
appl.def('is_confirmed', <%= !current_user.confirmed_at.nil? %>) appl.def('is_confirmed', <%= !current_user.confirmed_at.nil? %>)
appl.def('user', { appl.def('user', {
name: '<%= current_user.profile.name %>', name: '<%= current_user.profile.name || current_user.email %>',
id: <%= current_user.id %> id: <%= current_user.id %>
}) })
<% end %> <% end %>
@ -26,13 +38,15 @@
<%= IncludeAsset.js '/client/js/campaigns/peer_to_peer/page.js' %> <%= IncludeAsset.js '/client/js/campaigns/peer_to_peer/page.js' %>
<% end %> <% end %>
<%= render 'layouts/top_nav' %> <% if @parent_campaign && @parent_campaign.banner_image_url %>
<div class='campaign-banner u-margin'>
<img src='<%= @parent_campaign.banner_image_url %>'>
</div>
<% end %>
<main> <main>
<header class='u-paddingX--15 container'> <header class='u-paddingX--15 container'>
<h1>Start a campaign</h1> <h1>Start my campaign</h1>
<h4>Start raising funds for your favorite nonprofit in less than 10 minutes.</h4>
</div>
</header> </header>
<hr> <hr>
@ -43,19 +57,39 @@
<i class='icon icon-bicycle u-fontSize--50'></i> <i class='icon icon-bicycle u-fontSize--50'></i>
</td> </td>
<td> <td>
<h5 class='u-paddingLeft--20'>Below is a roadmap to get you started on your campaign</h5> <h5 class='u-paddingLeft--20'>Below is a roadmap to get you started with your campaign</h5>
</td> </td>
</tr></table> </tr></table>
<ul class='u-paddingLeft--10 timeline--checklist'> <ul class='u-paddingLeft--10 timeline--checklist'>
<li> <% if @parent_campaign.present? %>
<!--= set_attr_if selected_result 'class' 'is-complete' --> <li>
<span class='annot'>10 seconds</span> <!--= set_attr_if selected_result 'class' 'is-complete' -->
<p class='strong u-marginBottom--15'>Search for a nonprofit that you want to fundraise for</p> <span class='annot'>10 seconds</span>
<div class='u-paddingLeft--20 u-maxWidth--500'> <p class='strong u-marginBottom--15'>My campaign</p>
<%= render 'search_for_npo' %> <div class='u-paddingLeft--20 u-maxWidth--500'>
</div> <h4><%= @parent_campaign.name %></h4>
</li> </div>
</li>
<% elsif @nonprofit.present?%>
<li>
<!--= set_attr_if selected_result 'class' 'is-complete' -->
<span class='annot'>10 seconds</span>
<p class='strong u-marginBottom--15'>My nonprofit</p>
<div class='u-paddingLeft--20 u-maxWidth--500'>
<h4><%= @nonprofit.name %></h4>
</div>
</li>
<% else %>
<li>
<!--= set_attr_if selected_result 'class' 'is-complete' -->
<span class='annot'>10 seconds</span>
<p class='strong u-marginBottom--15'>Search for a nonprofit that you want to fundraise for</p>
<div class='u-paddingLeft--20 u-maxWidth--500'>
<%= render 'search_for_npo' %>
</div>
</li>
<% end %>
<li> <li>
<!--= set_attr_if is_logged_in 'class' 'is-complete' --> <!--= set_attr_if is_logged_in 'class' 'is-complete' -->
@ -81,6 +115,8 @@
<p> <p>
<!--= hide_if is_confirmed --> <!--= hide_if is_confirmed -->
Simply click the confirmation link in the email we sent you when you created your <%= Settings.general.name %> account. Simply click the confirmation link in the email we sent you when you created your <%= Settings.general.name %> account.
<br/><br/>
Once you've clicked the confirmation link, come back here and <a href="javascript:window.location.reload(true)">reload this page</a>.
</p> </p>
<p class='pastelBox--green u-padding--5'> <p class='pastelBox--green u-padding--5'>
<!--= show_if is_confirmed --> <!--= show_if is_confirmed -->
@ -90,33 +126,44 @@
</li> </li>
<li> <li>
<p class='strong u-marginBottom--15'>Start your campaign</p> <% if !@child_campaign %>
<span class='annot'>5 minutes</span> <p class='strong u-marginBottom--15'>Start your campaign</p>
<div class='u-paddingLeft--20 u-maxWidth--500'> <span class='annot'>5 minutes</span>
<p>Use our simple wizard to create your campaign for <div class='u-paddingLeft--20 u-maxWidth--500'>
<strong> <p>Use our simple wizard to create your campaign for
<!--= show_if selected_result --> <strong>
<!--= put selected_result.name -->. <!--= show_if selected_result -->
</strong> <!--= put selected_result.name -->.
<strong> </strong>
<!--= hide_if selected_result --> <strong>
your favorite nonprofit. <!--= hide_if selected_result -->
</strong> your favorite nonprofit.
</p> </strong>
<p><small>If you need any further help setting up your campaign, check out <a target='_blank' href='/help/peer-to-peer-campaigns-essentials-package-feature'>this handy article</a>.</small></p> </p>
<div class='u-centered u-padding--15'> <p><small>If you need any further help setting up your campaign, check out <a target='_blank' href='/help/peer-to-peer-campaigns-essentials-package-feature'>this handy article</a>.</small></p>
<button class='button orange'> <div class='u-centered u-padding--15'>
<!--= show_if (all is_logged_in is_confirmed selected_result) --> <button class='button orange'>
<!--= on 'click' (open_modal 'newCampaign') --> <!--= show_if (all is_logged_in is_confirmed selected_result) -->
Start Campaign <!--= on 'click' (open_modal selected_result.modal_id) -->
</button> Start Campaign
</button>
</div>
</div> </div>
</div> <% else %>
<p>
Seems like you already have a campaign for that cause! <%= link_to "Click here to see it", @child_campaign.url %>.
</p>
<% end %>
</li> </li>
</ul> </ul>
</div> </div>
</main> </main>
<% if current_user %> <% if current_user %>
<%= render 'campaigns/new_modal' %> <% if @nonprofit.present? %>
<%= render 'campaigns/new_modal' %>
<% elsif @parent_campaign.present? %>
<%= render 'campaigns/new_peer_to_peer_modal' %>
<% end %>
<% end %> <% end %>

View file

@ -16,14 +16,15 @@
app.days_remaining = '<%= @campaign.days_left %>' app.days_remaining = '<%= @campaign.days_left %>'
app.recurring_fund = <%= @campaign.recurring_fund? %> app.recurring_fund = <%= @campaign.recurring_fund? %>
app.vimeo_id = "<%= @campaign.vimeo_video_id ? @campaign.vimeo_video_id : '' %>" app.vimeo_id = "<%= @campaign.vimeo_video_id ? @campaign.vimeo_video_id : '' %>"
app.current_campaign_editor = <%= current_campaign_editor? %> app.current_campaign_editor = <%= current_campaign_editor? %>
app.is_parent_campaign = <%= @campaign.parent_campaign? %>
appl.def('has_video', <%= @campaign.video_url.present? %>) appl.def('has_video', <%= @campaign.video_url.present? %>)
appl.def('campaign_is_deleted', <%= @campaign.deleted || false %>) appl.def('campaign_is_deleted', <%= @campaign.deleted || false %>)
appl.def('has_main_image', <%= @campaign.main_image.file.present? %>) appl.def('has_main_image', <%= @campaign.main_image.file.present? %>)
</script> </script>
<%= render 'schema', campaign: @campaign, url: @url %>
<%= render 'common/froala' if current_campaign_editor? %>
<%= render 'schema', campaign: @campaign, url: @url %>
<%= render 'common/froala' if current_campaign_editor? %>
<%= IncludeAsset.js '/client/js/campaigns/show/page.js' %> <%= IncludeAsset.js '/client/js/campaigns/show/page.js' %>
<% end %> <% end %>
@ -64,20 +65,20 @@
image_url: @campaign_background_image, image_url: @campaign_background_image,
is_editor: current_campaign_editor?, is_editor: current_campaign_editor?,
hide_title: @campaign.hide_title && @campaign_background_image, hide_title: @campaign.hide_title && @campaign_background_image,
header_content_partial: 'header_content' %> header_content_partial: 'header_content',
banner_image_url: @campaign.banner_image&.url %>
<%= render 'components/preview_mode_notification' %> <%= render 'components/preview_mode_notification' %>
<div class="container u-marginTop--15 <%= @brand_color ? 'is-branded' : '' %>" data-id='<%= @campaign.id %>'> <div class="container u-marginTop--15 <%= @brand_color ? 'is-branded' : '' %>" data-id='<%= @campaign.id %>'>
<section class='box'>
<section class='box'>
<%= render 'campaign_media' %> <%= render 'campaign_media' %>
</section> </section>
<section class='box-r'> <section class='box-r'>
<% if current_campaign_editor? %> <% if current_campaign_editor? && !@campaign.child_campaign? %>
<!-- Campaign editor gift option management modal --> <!-- Campaign editor gift option management modal -->
<button class='button edit u-width--full u-marginBottom--15'> <button class='button edit u-width--full u-marginBottom--15'>
<!--= on 'click' (open_modal 'manageGiftOptionsModal') --> <!--= on 'click' (open_modal 'manageGiftOptionsModal') -->
@ -85,6 +86,14 @@
</button> </button>
<% end %> <% end %>
<% if !@campaign.child_campaign? %>
<aside class='u-marginBottom--15 pastelBox--grey'>
<a class='button u-width--full' target='_blank' if-branded='background-color, dark' href='<%= @campaign.finished? ? "/peer-to-peer?npo_id=#{@nonprofit.id}" : "/peer-to-peer?campaign_id=#{ @peer_to_peer_campaign_param}" %>'>
Start Your Own Campaign for <%= @nonprofit.name %>
</a>
</aside>
<% end %>
<!-- flimflam gift options javascript gets rendered into this div: --> <!-- flimflam gift options javascript gets rendered into this div: -->
<div class='ff-sidebar'></div> <div class='ff-sidebar'></div>
@ -95,16 +104,22 @@
</div> </div>
</aside> </aside>
<% unless current_campaign_editor? %>
<aside class='u-marginTop--15'>
<a class='button u-width--full' target='_blank' if-branded='background-color, dark' href='/peer-to-peer?npo_id=<%=@nonprofit.id %>'>
Start Your Own Campaign for <%= @nonprofit.name %>
</a>
</aside>
<% end %>
</section> </section>
<% if @campaign.child_campaign? %>
<%= render 'components/fundraising_pages/campaigner_profile',
profile: @campaign.profile,
campaign_name: @campaign.name,
reason_for_supporting: @campaign.reason_for_supporting
%>
<section class='box u-centered' style="margin-top:20px; margin-bottom:20px;">
<a class='button--jumbo' target='_blank' if-branded='background-color, dark' href='/peer-to-peer?campaign_id=<%= @peer_to_peer_campaign_param %>'>
Start Your Own Campaign for <%= @nonprofit.name %>
</a>
</section>
<% end %>
<section class='box'> <section class='box'>
<div id='js-campaignBody' class='editable' data-path='/nonprofits/<%= @nonprofit.id %>/campaigns/<%= @campaign.id %>.json' data-key='campaign[body]'> <div id='js-campaignBody' class='editable' data-path='/nonprofits/<%= @nonprofit.id %>/campaigns/<%= @campaign.id %>.json' data-key='campaign[body]'>
@ -130,6 +145,10 @@
end_point: "/nonprofits/#{@nonprofit.id}/campaigns/#{@campaign.id}", end_point: "/nonprofits/#{@nonprofit.id}/campaigns/#{@campaign.id}",
image_url: @campaign_background_image, image_url: @campaign_background_image,
input_name: 'campaign[background_image]' %> input_name: 'campaign[background_image]' %>
<%= render 'components/upload_banner_image',
end_point: "/nonprofits/#{@nonprofit.id}/campaigns/#{@campaign.id}",
image_url: @campaign.banner_image_url,
input_name: 'campaign[banner_image]' %>
<%= render 'components/custom_receipt_modal', <%= render 'components/custom_receipt_modal',
title: 'Campaign Receipt Message', title: 'Campaign Receipt Message',
type: 'campaign', type: 'campaign',
@ -141,4 +160,3 @@
<%= render 'components/share_modal', name: @campaign.name, type: 'campaign' %> <%= render 'components/share_modal', name: @campaign.name, type: 'campaign' %>
<%= render 'common/email_share_modal', fundraiser: @campaign.name, fundraiser_url: @url %> <%= render 'common/email_share_modal', fundraiser: @campaign.name, fundraiser_url: @url %>

View file

@ -1,32 +0,0 @@
<%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%>
<!-- partial start: components/_guest_footer -->
<section class='group container globalFooter-guest'>
<ul class='col-4 u-noClear u-margin--0 u-paddingRight--20'>
<li class='globalFooter-title'>Get Started</li>
<li><a open-modal='loginModal'>Login</a></li>
<li><a data-ff-open-onboard>NPO Signup</a></li>
<li><a href='/peer-to-peer'>Peer to Peer Campaign</a></li>
</ul>
<ul class='col-4 u-noClear u-margin--0 u-paddingRight--20'>
</ul>
<ul class='col-4 u-noClear u-margin--0'>
<% if Settings.terms_and_privacy&.help_url %>
<li><%= link_to("Help", Settings.terms_and_privacy.help_url) %></li>
<% end %>
</ul>
<%# <div class='globalFooter-mailingListCol'> %>
<%# <a class='button--small blue u-floatR' href='/demo'> %>
<%# Free Demo %>
<%# </a> %>
<%# </div> %>
</section>
<!-- partial end: components/_guest_footer -->

View file

@ -20,7 +20,7 @@
Upload <%= image_url ? 'Different Image' : '' %> Upload <%= image_url ? 'Different Image' : '' %>
</button> </button>
<a class='button--small red u-marginTop--10 u-width--full' <%= image_url ? '' : 'disabled' %>> <a class='button--small red u-marginTop--10 u-width--full' <%= image_url ? '' : 'disabled' %>>
<!--= on 'click' (confirm 'Are you sure?' remove_this_image --> <!--= on 'click' (confirm 'Are you sure?' remove_background_image -->
Remove Image Remove Image
</a> </a>
</div> </div>

View file

@ -0,0 +1,31 @@
<%- # License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later -%>
<div class='modal' id='uploadBannerImage'>
<%= render 'common/modal_header', title: 'Banner Image' %>
<div class='modal-body'>
<fieldset class='u-centered'>
<p>Select and upload a banner image for this page.</p>
<p class='u-marginBottom--20'>For best results, the image should be <strong>980px by 120px</strong> in size.</p>
<form autosubmit action='<%= end_point %>' method='put' data-reload>
<div class='image-upload image-upload--banner' style='background-image:url(<%= image_url ? image_url : '' %>)'>
<span><i class='fa fa-image'></i> Select</span>
<input type='file' name="<%= input_name %>" required>
</div>
<p class='u-color--red'>
<!--= show_if (length image_upload.error) -->
<small><!--= put image_upload.error --></small>
</p>
<div class='u-width--500 u-margin--auto'>
<button type='submit' class='button--small u-width--full u-marginTop--20' data-loading='Uploading...'>
Upload <%= image_url ? 'Different Image' : '' %>
</button>
<a class='button--small red u-marginTop--10 u-width--full' <%= image_url ? '' : 'disabled' %>>
<!--= on 'click' (confirm 'Are you sure?' remove_banner_image ) -->
Remove Image
</a>
</div>
</form>
</fieldset>
</div> <!-- modal-body -->
</div>

View file

@ -0,0 +1,5 @@
<section class='box' style="font-style: italic">
<div class="well" style="padding-left:16px;">
<h4><%= profile.name %> <small>(<%= profile.city %><% if profile.state_code && profile.city %><%= profile.city_state %> <%= profile.state_code %><% end %>)</small></h4>
<blockquote><p>"<%= reason_for_supporting %>"</p></blockquote></div>
</section>

View file

@ -6,6 +6,11 @@
<header class="container fundraisingHeader--plain" <%= css_style.html_safe %> id='js-fundraisingHeader'> <header class="container fundraisingHeader--plain" <%= css_style.html_safe %> id='js-fundraisingHeader'>
<% if banner_image_url %>
<div class='campaign-banner u-margin'>
<img src='<%= banner_image_url %>'>
</div>
<% end %>
<div class='fundraisingHeader--image-container' id='js-fundraisingHeader-image' style='display: none;'> <div class='fundraisingHeader--image-container' id='js-fundraisingHeader-image' style='display: none;'>
<img class='fundraisingHeader--image-aspectRatio' src="<%= asset_path 'graphics/10x6.jpg' %>"> <img class='fundraisingHeader--image-aspectRatio' src="<%= asset_path 'graphics/10x6.jpg' %>">
</div> </div>
@ -16,4 +21,4 @@
</section> </section>
<% end %> <% end %>
</header> </header>
<!-- partial end: fundaising_pages/_header --> <!-- partial end: fundraising_pages/_header -->

View file

@ -49,7 +49,8 @@
image_url: @event_background_image, image_url: @event_background_image,
is_editor: current_event_editor?, is_editor: current_event_editor?,
hide_title: @event.hide_title, hide_title: @event.hide_title,
header_content_partial: 'header_content' %> header_content_partial: 'header_content',
banner_image_url: nil %>
<%= render 'components/preview_mode_notification' %> <%= render 'components/preview_mode_notification' %>

View file

@ -34,7 +34,6 @@
<% if yield(:footer_hidden) != 'hidden' %> <% if yield(:footer_hidden) != 'hidden' %>
<footer class='globalFooter'> <footer class='globalFooter'>
<%= render 'components/guest_footer' unless current_user %>
<%= render 'components/footer_sub' %> <%= render 'components/footer_sub' %>
</footer> </footer>
<% end %> <% end %>

View file

@ -25,10 +25,6 @@
<% unless current_role?([:nonprofit_admin,:nonprofit_associate]) %> <% unless current_role?([:nonprofit_admin,:nonprofit_associate]) %>
<section class='sideNav-section'> <section class='sideNav-section'>
<a class='sideNav-link' href='/explore'>
<i class='sideNav-icon icon-binocular'></i>
<span class='sideNav-text'>Explore</span>
</a>
<% if Settings.terms_and_privacy&.help_url %> <% if Settings.terms_and_privacy&.help_url %>
<a class='sideNav-link' href="<%=Settings.terms_and_privacy.help_url %>"> <a class='sideNav-link' href="<%=Settings.terms_and_privacy.help_url %>">
<i class='sideNav-icon icon-bubble-ask-2'></i> <i class='sideNav-icon icon-bubble-ask-2'></i>

View file

@ -4,7 +4,7 @@
<section class='sideNav-section'> <section class='sideNav-section'>
<a class='sideNav-link' href='<%= profile_url(current_user.profile) %>'> <a class='sideNav-link' href='<%= profile_url(current_user.profile) %>'>
<% if current_user.profile.picture? %> <% if current_user.profile.picture? %>
<img class='sideNav-profile'src="<%= current_user.profile.get_profile_picture(:tiny) %>')"> <img class='sideNav-profile' src="<%= current_user.profile.get_profile_picture(:tiny) %>">
<% else %> <% else %>
<i class="sideNav-icon icon-user-1"></i> <i class="sideNav-icon icon-user-1"></i>
<% end %> <% end %>
@ -46,4 +46,3 @@
</section> </section>
<% end %> <% end %>

View file

@ -64,7 +64,8 @@
<%= render 'components/fundraising_pages/header', <%= render 'components/fundraising_pages/header',
image_url: @nonprofit_background_image, image_url: @nonprofit_background_image,
is_editor: current_nonprofit_user?, is_editor: current_nonprofit_user?,
header_content_partial: 'header_content' %> header_content_partial: 'header_content',
banner_image_url: nil %>
<%= render 'components/preview_mode_notification' %> <%= render 'components/preview_mode_notification' %>

View file

@ -0,0 +1,43 @@
// License: LGPL-3.0-or-later
//This is used for federated p2p campaigns
require('../../components/wizard')
var format_err = require('../../common/format_response_error')
appl.def('advance_p2p_campaign_name_step', function(form_obj) {
var name = form_obj['campaign[name]']
appl.def('new_p2p_campaign', form_obj)
appl.wizard.advance('new_p2p_campaign_wiz')
})
// Post a new campaign.
appl.def('create_p2p_campaign', function(el) {
var form_data = utils.toFormData(appl.prev_elem(el))
form_data = utils.mergeFormData(form_data, appl.new_p2p_campaign)
appl.def('new_p2p_campaign_wiz.loading', true)
post_p2p_campaign(form_data)
.then(function(req) {
appl.notify("Redirecting to your campaign...")
appl.redirect(JSON.parse(req.response).url)
})
.catch(function(req) {
appl.def('new_p2p_campaign_wiz.loading', false)
appl.def('new_p2p_campaign_wiz.error', req.responseText)
})
})
// Using the bare-bones XMLHttpRequest API so we can post form data and upload the image
function post_p2p_campaign(form_data) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest()
req.open("POST", '/nonprofits/' + app.nonprofit_id + '/campaigns')
req.setRequestHeader('X-CSRF-Token', window._csrf)
console.log(form_data)
req.send(form_data)
req.onload = function(ev) {
if(req.status === 200) resolve(req)
else reject(req)
}
})
}

View file

@ -20,6 +20,8 @@ appl.def('create_campaign', function(el) {
form_data = utils.mergeFormData(form_data, appl.new_campaign) form_data = utils.mergeFormData(form_data, appl.new_campaign)
appl.def('new_campaign_wiz.loading', true) appl.def('new_campaign_wiz.loading', true)
// TODO: for p2p capmaigns, merge with preset campaing params
post_campaign(form_data) post_campaign(form_data)
.then(function(req) { .then(function(req) {
appl.notify("Redirecting to your campaign...") appl.notify("Redirecting to your campaign...")

View file

@ -1,13 +1,13 @@
// License: LGPL-3.0-or-later // License: LGPL-3.0-or-later
require('../new/peer_to_peer_wizard')
require('../new/wizard.js')
require('../../common/image_uploader')
require('../new/wizard')
var request = require("../../common/client") var request = require("../../common/client")
require('../../common/onboard')
// setting up some default values // setting up some default values
appl.def('is_signing_up', true) appl.def('is_signing_up', true)
.def('selected_result_index', -1) .def('selected_result_index', -1)
appl.def('search_nonprofits', function(value){ appl.def('search_nonprofits', function(value){
@ -23,8 +23,8 @@ appl.def('search_nonprofits', function(value){
// if the the input is empty, it clears the dropdown // if the the input is empty, it clears the dropdown
if (!value) { if (!value) {
appl.def('search_results', []) appl.def('search_results', [])
return return
} }
// logic for controlling the dropdown options with up // logic for controlling the dropdown options with up
@ -67,12 +67,12 @@ function setIndexWithArrows(dir) {
if(dir === 'down') { if(dir === 'down') {
var search_length = appl.search_results.length -1 var search_length = appl.search_results.length -1
appl.def('selected_result_index', appl.selected_result_index === search_length appl.def('selected_result_index', appl.selected_result_index === search_length
? search_length ? search_length
: appl.selected_result_index += 1) : appl.selected_result_index += 1)
} else { } else {
appl.def('selected_result_index', appl.selected_result_index === 0 appl.def('selected_result_index', appl.selected_result_index === 0
? 0 ? 0
: appl.selected_result_index -= 1) : appl.selected_result_index -= 1)
} }
} }

View file

@ -17,10 +17,12 @@ require('../../components/ajax/toggle_soft_delete')(url, 'campaign')
// Initialize the froala wysiwyg // Initialize the froala wysiwyg
var editable = require('../../common/editable') var editable = require('../../common/editable')
editable($('#js-campaignBody'), { if (app.is_parent_campaign) {
sticky: true, editable($('#js-campaignBody'), {
placeholder: "Add your campaign's story here. We strongly recommend that this section is filled out with at least 250 words. It will be saved automatically as you type. You can add images, videos and custom HTML too." sticky: true,
}) placeholder: "Add your campaign's story here. We strongly recommend that this section is filled out with at least 250 words. It will be saved automatically as you type. You can add images, videos and custom HTML too."
})
}
editable($('#js-customReceipt'), { editable($('#js-customReceipt'), {
button: ["bold", "italic", "formatBlock", "align", "createLink", button: ["bold", "italic", "formatBlock", "align", "createLink",
@ -34,8 +36,17 @@ editable($('#js-customReceipt'), {
var path = '/nonprofits/' + app.nonprofit_id + '/campaigns/' + app.campaign_id var path = '/nonprofits/' + app.nonprofit_id + '/campaigns/' + app.campaign_id
appl.def('remove_this_image', function() { appl.def('remove_banner_image', function() {
appl.remove_background_image(path, 'campaign') var url = '/nonprofits/' + app.nonprofit_id + '/campaigns/' + app.campaign_id
var notification = 'Removing banner image...'
var payload = {remove_banner_image : true}
appl.remove_image(url, 'campaign', notification, payload)
})
appl.def('remove_background_image', function(url, resource) {
var notification = 'Removing background image...'
var payload = {remove_background_image : true}
appl.remove_image(url, resource, notification, payload)
}) })
appl.def('count_story_words', function() { appl.def('count_story_words', function() {

View file

@ -59,7 +59,7 @@ const giftBox = state => gift => {
, h('p.u-marginBottom--15', gift.description) , h('p.u-marginBottom--15', gift.description)
, h('div', [ giftButton(state, gift) ]) , h('div', [ giftButton(state, gift) ])
]) ])
, app.current_campaign_editor // Show edit button only if the current user is a campaign editor , (app.current_campaign_editor && app.is_parent_campaign) // Show edit button only if the current user is a parent campaign editor
? h('button.button--tiny.absolute.edit.hasShadow', { ? h('button.button--tiny.absolute.edit.hasShadow', {
on: {click: ev => state.openEditGiftModal$(gift)} on: {click: ev => state.openEditGiftModal$(gift)}
}, [ }, [
@ -79,4 +79,3 @@ const totalContributions = gift => {
} }
module.exports = {view, init} module.exports = {view, init}

View file

@ -167,6 +167,3 @@ const patch = snabbdom.init([
render({state: init(), view, patch, container: document.querySelector('.ff-sidebar')}) render({state: init(), view, patch, container: document.querySelector('.ff-sidebar')})
// Init the metrics
appl.def('metrics.path_prefix', '/nonprofits/' + app.nonprofit_id + '/campaigns/' + app.campaign_id + '/')
appl.ajax_metrics.index()

View file

@ -7,7 +7,17 @@ module.exports = function(npo_id) {
request.get(campaignsPath).end(function(err, resp){ request.get(campaignsPath).end(function(err, resp){
resp.body.unshift(false) resp.body.unshift(false)
appl.def('campaigns.data', resp.body) let campaign_id_names = resp.body.map((i) => {
if (i.isChildCampaign)
{
return {id: i.id, name: i.name + " - " + i.creator}
}
else
{
return {id: i.id, name: i.name}
}
})
appl.def('campaigns.data', campaign_id_names)
}) })
request.get(eventsPath).end(function(err, resp){ request.get(eventsPath).end(function(err, resp){
resp.body.unshift(false) resp.body.unshift(false)

View file

@ -107,7 +107,8 @@ var froala = function($el, options) {
refresh: function () { refresh: function () {
} }
}, },
} },
videoAllowedAttrs: ["src","width","height","frameborder","allowfullscreen","webkitallowfullscreen","mozallowfullscreen","href","target","id","controls","value","name", "autoplay", "loop", "muted"]
}) })
$('.froala-popup').parents('.froala-editor').css('z-index', 99999) $('.froala-popup').parents('.froala-editor').css('z-index', 99999)

View file

@ -17,10 +17,10 @@ $('.image-upload input').change(function(e) {
} }
}) })
appl.def('remove_background_image', function(url, resource) { appl.def('remove_image', function(url, resource, notification, payload) {
var data = {} var data = {}
data[resource] = {remove_background_image: true} data[resource] = payload
appl.notify('Removing background image...') appl.notify(notification)
appl.def('loading', true) appl.def('loading', true)
$.ajax({ $.ajax({
type: 'put', type: 'put',

View file

@ -1,24 +0,0 @@
// License: LGPL-3.0-or-later
const R = require('ramda')
const h = require('flimflam/h')
const flyd = require('flimflam/flyd')
const wizard = require('flimflam/ui/wizard')
const carousel = require('./carousel')
// the api for this components is the same as the regular ff wizard.
// it wraps the wizard content in a carousel component which adds a horizontally
// scrolling animation whenever the wizard index changes.
// it also makes the heights of each wizard step the same.
const content = (state, content) => {
const count = content.length
const index = state.isCompleted$() ? (state.currentStep$() + 1) : state.currentStep$()
return carousel({count, index, content})
}
const labels = (state, steps) => {
const truncatedSteps = R.map(x => h('span.inline-block.truncate', x), steps)
return wizard.labels(state, truncatedSteps)
}
module.exports = {init: wizard.init, labels, content}

View file

@ -1,42 +0,0 @@
// License: LGPL-3.0-or-later
const R = require('ramda')
const h = require('flimflam/h')
const setWidth = (elm, number) =>
elm.style.width = number * elm.parentElement.offsetWidth + 'px'
const setItemsDimensions = (items, percent) => {
const heights = R.map(x => x.offsetHeight, items)
const tallest = R.reduce((a, b) => a >= b ? a : b , 0, heights)
R.map(x => {
x.style.width = percent + '%'
x.style.height = tallest + 'px'
}, items)
}
const init = (count, percent) => vnode => {
const elm = vnode.elm
const items = elm.childNodes
setItemsDimensions(items, percent)
setWidth(elm, count)
window.addEventListener('resize', () => {
setItemsDimensions(items, percent)
setWidth(elm, count)
})
}
module.exports = obj => {
const percent = 100 / obj.count
return h('div', [
h('div.overflow-hidden', [
h('div.transition-slow.clearfix'
, {
hook: {insert: init(obj.count, percent)}
, style: {transform: `translateZ(0) translateX(-${percent * obj.index}%)`}
}
, R.map(x => h('div.left.p-2.table', [h('div.middle-cell', [x])]), obj.content)
)
])
])
}

View file

@ -14,7 +14,7 @@ function view(state) {
h('a.button--small.facebook.u-width--full.share-button', { h('a.button--small.facebook.u-width--full.share-button', {
props: { props: {
target: '_blank' target: '_blank'
, href: 'https://www.facebook.com/dialog/feed?app_id='+app.facebook_app_id +"&display=popup&caption=" + (app.campaign.name || app.nonprofit.name) + "&link="+window.location.href , href: 'https://www.facebook.com/dialog/feed?app_id='+app.facebook_app_id +"&display=popup&caption=" + encodeURIComponent(app.campaign.name || app.nonprofit.name) + "&link="+window.location.href
} }
}, [h('i.fa.fa-facebook-square'), ` ${I18n.t('nonprofits.donate.followup.share.facebook')}`] ) }, [h('i.fa.fa-facebook-square'), ` ${I18n.t('nonprofits.donate.followup.share.facebook')}`] )
]) ])

View file

@ -67,7 +67,7 @@ Config.schema do
required(:aws).schema do required(:aws).schema do
# the region your AWS bucket is in # the region your AWS bucket is in
required(:region).filled(:str?) optional(:region).filled(:str?)
# the name of your aws bucket # the name of your aws bucket
required(:bucket).filled(:str?) required(:bucket).filled(:str?)
@ -299,4 +299,3 @@ Settings.reload!
# Initialize the rails application # Initialize the rails application
Commitchange::Application.initialize! Commitchange::Application.initialize!

View file

@ -52,7 +52,6 @@ Commitchange::Application.configure do
config.log_level = :debug config.log_level = :debug
config.threadsafe!
config.dependency_loading = true if $rails_rake_task config.dependency_loading = true if $rails_rake_task
# Turn this on if you want to mess with code inside /node_modules # Turn this on if you want to mess with code inside /node_modules
# config.browserify_rails.evaluate_node_modules = true # config.browserify_rails.evaluate_node_modules = true

View file

@ -8,4 +8,3 @@ AWS.config({
s3 = AWS::S3.new s3 = AWS::S3.new
S3Bucket = s3.buckets[Settings.aws.bucket] S3Bucket = s3.buckets[Settings.aws.bucket]

View file

@ -4,7 +4,7 @@ CarrierWave.configure do |config|
config.storage = :aws config.storage = :aws
config.aws_bucket = Settings.aws.bucket config.aws_bucket = Settings.aws.bucket
config.aws_acl = :public_read config.aws_acl = :public_read
config.asset_host = Settings.image&.host || "https://s3-#{Settings.aws.region}.amazonaws.com/#{Settings.aws.bucket}" config.asset_host = Settings.image&.host || "https://#{Settings.aws.bucket}.s3.amazonaws.com"
config.aws_authenticated_url_expiration = 60 * 60 * 24 * 365 config.aws_authenticated_url_expiration = 60 * 60 * 24 * 365
config.aws_credentials = { config.aws_credentials = {
access_key_id: Settings.aws.access_key_id, access_key_id: Settings.aws.access_key_id,

View file

@ -144,6 +144,7 @@ Commitchange::Application.routes.draw do
get(:activities, {on: :member}) get(:activities, {on: :member})
put(:soft_delete, {on: :member}) put(:soft_delete, {on: :member})
get(:name_and_id, {on: :collection}) get(:name_and_id, {on: :collection})
post :create_from_template, on: :collection
resources(:campaign_gift_options, {only: [:index, :show, :create, :update, :destroy]}) do resources(:campaign_gift_options, {only: [:index, :show, :create, :update, :destroy]}) do
put(:update_order, {on: :collection}) put(:update_order, {on: :collection})
end end

View file

@ -20,8 +20,7 @@ default:
aws: aws:
access_key_id: <%= ENV['AWS_ACCESS_KEY'] %> access_key_id: <%= ENV['AWS_ACCESS_KEY'] %>
secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %> secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
region: test bucket: <%= ENV['S3_BUCKET_NAME'] %>
bucket: test
mailer: mailer:
delivery_method: "sendmail" delivery_method: "sendmail"

View file

@ -0,0 +1,5 @@
class AddParentCampaignIdToCampaigns < ActiveRecord::Migration
def change
add_column :campaigns, :parent_campaign_id, :integer
end
end

View file

@ -0,0 +1,5 @@
class AddReasonForSupportingToCampaigns < ActiveRecord::Migration
def change
add_column :campaigns, :reason_for_supporting, :text
end
end

View file

@ -0,0 +1,5 @@
class AddDefaultReasonForSupportingToCampaigns < ActiveRecord::Migration
def change
add_column :campaigns, :default_reason_for_supporting, :text
end
end

View file

@ -0,0 +1,5 @@
class AddBannerImageToCampaigns < ActiveRecord::Migration
def change
add_column :campaigns, :banner_image, :string
end
end

View file

@ -0,0 +1,5 @@
class AddIndexParentCampaignIdToCampaign < ActiveRecord::Migration
def change
add_index :campaigns, :parent_campaign_id
end
end

View file

@ -3,7 +3,7 @@
-- --
-- Dumped from database version 9.6.5 -- Dumped from database version 9.6.5
-- Dumped by pg_dump version 9.6.10 -- Dumped by pg_dump version 9.6.11
SET statement_timeout = 0; SET statement_timeout = 0;
SET lock_timeout = 0; SET lock_timeout = 0;
@ -392,7 +392,11 @@ CREATE TABLE public.campaigns (
hide_custom_amounts boolean, hide_custom_amounts boolean,
show_recurring_amount boolean DEFAULT false, show_recurring_amount boolean DEFAULT false,
end_datetime timestamp without time zone, end_datetime timestamp without time zone,
external_identifier character varying(255) external_identifier character varying(255),
parent_campaign_id integer,
reason_for_supporting text,
default_reason_for_supporting text,
banner_image character varying(255)
); );
@ -3143,6 +3147,13 @@ CREATE INDEX index_activities_on_supporter_id ON public.activities USING btree (
CREATE INDEX index_campaign_gifts_on_campaign_gift_option_id ON public.campaign_gifts USING btree (campaign_gift_option_id); CREATE INDEX index_campaign_gifts_on_campaign_gift_option_id ON public.campaign_gifts USING btree (campaign_gift_option_id);
--
-- Name: index_campaigns_on_parent_campaign_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_campaigns_on_parent_campaign_id ON public.campaigns USING btree (parent_campaign_id);
-- --
-- Name: index_cards_on_id_and_holder_type_and_holder_id_and_inactive; Type: INDEX; Schema: public; Owner: - -- Name: index_cards_on_id_and_holder_type_and_holder_id_and_inactive; Type: INDEX; Schema: public; Owner: -
-- --
@ -4337,6 +4348,18 @@ INSERT INTO schema_migrations (version) VALUES ('20180608205049');
INSERT INTO schema_migrations (version) VALUES ('20180608212658'); INSERT INTO schema_migrations (version) VALUES ('20180608212658');
INSERT INTO schema_migrations (version) VALUES ('20180703165400');
INSERT INTO schema_migrations (version) VALUES ('20180703165401');
INSERT INTO schema_migrations (version) VALUES ('20180703165402');
INSERT INTO schema_migrations (version) VALUES ('20180703165403');
INSERT INTO schema_migrations (version) VALUES ('20180703165404');
INSERT INTO schema_migrations (version) VALUES ('20180703165405');
INSERT INTO schema_migrations (version) VALUES ('20180713213748'); INSERT INTO schema_migrations (version) VALUES ('20180713213748');
INSERT INTO schema_migrations (version) VALUES ('20180713215825'); INSERT INTO schema_migrations (version) VALUES ('20180713215825');
@ -4347,3 +4370,5 @@ INSERT INTO schema_migrations (version) VALUES ('20181002160627');
INSERT INTO schema_migrations (version) VALUES ('20181003212559'); INSERT INTO schema_migrations (version) VALUES ('20181003212559');
INSERT INTO schema_migrations (version) VALUES ('20181120182105');

View file

@ -11,8 +11,8 @@ export interface FundraiserInfo {
name: string name: string
} }
function LoadReactPage(element:HTMLElement, events: FundraiserInfo[], function LoadReactPage(element:HTMLElement, campaigns: FundraiserInfo[],
campaigns: FundraiserInfo[], events: FundraiserInfo[],
nonprofitId: number, nonprofitId: number,
supporterId:number, supporterId:number,
preupdateDonationAction:() => void, preupdateDonationAction:() => void,

View file

@ -172,7 +172,6 @@ class CreateNewOffsitePaymentPane extends React.Component<CreateOffsitePaymentPa
params.date.validators = [Validations.isDate('MM/DD/YYYY')] params.date.validators = [Validations.isDate('MM/DD/YYYY')]
params.gross_amount.validators = [Validations.isGreaterThanOrEqualTo(0.01)]; params.gross_amount.validators = [Validations.isGreaterThanOrEqualTo(0.01)];
// params.fee_total.validators = [Validations.optional(Validations.isLessThanOrEqualTo(0))];
@ -205,6 +204,7 @@ class CreateNewOffsitePaymentPane extends React.Component<CreateOffsitePaymentPa
{/* <CurrencyField field={this.form.$('fee_total')} label={"Processing Fees"} mustBeNegative={true}/> */} {/* <CurrencyField field={this.form.$('fee_total')} label={"Processing Fees"} mustBeNegative={true}/> */}
<BasicField field={this.form.$('date')} label={"Date"} /> <BasicField field={this.form.$('date')} label={"Date"} />
<BasicField field={this.form.$('check_number')} label={"Check or Payment Number/ID"}/>
<SelectField field={this.form.$('campaign')} <SelectField field={this.form.$('campaign')}
label={"Campaign"} label={"Campaign"}
options={this.props.campaigns}/> options={this.props.campaigns}/>

View file

@ -371,7 +371,7 @@ class EditPaymentPane extends React.Component<EditPaymentPaneProps & InjectedInt
</table>; </table>;
let checkNumber = this.props.data.offsite_payment && this.props.data.offsite_payment.check_number ? let checkNumber = this.props.data.offsite_payment ?
<BasicField field={this.form.$('check_number')} label={"Check or Payment Number/ID"}/> : false; <BasicField field={this.form.$('check_number')} label={"Check or Payment Number/ID"}/> : false;
let offsitePayment = this.props.data.kind === "OffsitePayment" ? (<div> let offsitePayment = this.props.data.kind === "OffsitePayment" ? (<div>

View file

@ -36,14 +36,14 @@ module CreateCampaignGift
if ((donation.recurring_donation != nil) && (campaign_gift_option.amount_recurring != nil && campaign_gift_option.amount_recurring > 0)) if ((donation.recurring_donation != nil) && (campaign_gift_option.amount_recurring != nil && campaign_gift_option.amount_recurring > 0))
# it's a recurring_donation. Is it enough? for the gift level? # it's a recurring_donation. Is it enough? for the gift level?
unless donation.recurring_donation.amount >= (campaign_gift_option.amount_recurring) unless donation.recurring_donation.amount == (campaign_gift_option.amount_recurring)
AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option) AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option)
raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} gift options requires a recurring donation of at least #{campaign_gift_option.amount_recurring} for donation #{donation.id}", {:key => :campaign_gift_option_id}) raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} gift options requires a recurring donation of #{campaign_gift_option.amount_recurring} for donation #{donation.id}", {:key => :campaign_gift_option_id})
end end
else else
unless donation.amount >= (campaign_gift_option.amount_one_time) unless donation.amount == (campaign_gift_option.amount_one_time)
AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option) AdminMailer.delay.notify_failed_gift(donation, campaign_gift_option)
raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} gift options requires a donation of at least #{campaign_gift_option.amount_one_time} for donation #{donation.id}", {:key => :campaign_gift_option_id}) raise ParamValidation::ValidationError.new("#{params[:campaign_gift_option_id]} gift options requires a donation of #{campaign_gift_option.amount_one_time} for donation #{donation.id}", {:key => :campaign_gift_option_id})
end end
end end
@ -65,11 +65,11 @@ module CreateCampaignGift
campaign_gift_option = cg.campaign_gift_option campaign_gift_option = cg.campaign_gift_option
if ((donation.recurring_donation != nil) && (campaign_gift_option.amount_recurring != nil && campaign_gift_option.amount_recurring > 0)) if ((donation.recurring_donation != nil) && (campaign_gift_option.amount_recurring != nil && campaign_gift_option.amount_recurring > 0))
# it's a recurring_donation. Is it enough? for the gift level? # it's a recurring_donation. Is it enough? for the gift level?
unless donation.recurring_donation.amount >= (campaign_gift_option.amount_recurring) unless donation.recurring_donation.amount == (campaign_gift_option.amount_recurring)
raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a recurring donation of at least #{campaign_gift_option.amount_recurring}", {:key => :campaign_gift_option_id}) raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a recurring donation of at least #{campaign_gift_option.amount_recurring}", {:key => :campaign_gift_option_id})
end end
else else
unless donation.amount >= (campaign_gift_option.amount_one_time) unless donation.amount == (campaign_gift_option.amount_one_time)
raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a donation of at least #{campaign_gift_option.amount_one_time}", {:key => :campaign_gift_option_id}) raise ParamValidation::ValidationError.new("#{campaign_gift_option.id} gift options requires a donation of at least #{campaign_gift_option.amount_one_time}", {:key => :campaign_gift_option_id})
end end
end end

View file

@ -0,0 +1,33 @@
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
module CreatePeerToPeerCampaign
def self.create(campaign_params, profile_id)
begin
parent_campaign = Campaign.find(campaign_params[:parent_campaign_id])
rescue ActiveRecord::RecordNotFound
return { errors: { parent_campaign_id: 'not found' } }.as_json
end
p2p_params = campaign_params.except(:nonprofit_id, :summary,:goal_amount)
p2p_params.merge!(parent_campaign.child_params)
profile = Profile.find(profile_id)
base_slug = Format::Url.convert_to_slug "#{p2p_params[:name]}-#{profile.name}"
algo = SlugP2pCampaignNamingAlgorithm.new(p2p_params[:nonprofit_id])
p2p_params[:slug] = algo.create_copy_name(base_slug)
campaign = Campaign.create(p2p_params)
campaign.published = true
campaign.profile = profile
campaign.save
campaign.update_attribute(:main_image, parent_campaign.main_image) unless !parent_campaign.main_image rescue AWS::S3::Errors::NoSuchKey
campaign.update_attribute(:background_image, parent_campaign.background_image) unless !parent_campaign.background_image rescue AWS::S3::Errors::NoSuchKey
campaign.update_attribute(:banner_image, parent_campaign.banner_image) unless !parent_campaign.banner_image rescue AWS::S3::Errors::NoSuchKey
return { errors: campaign.errors.messages }.as_json unless campaign.errors.empty?
campaign.as_json
end
end

View file

@ -2,21 +2,31 @@
module QueryCampaignMetrics module QueryCampaignMetrics
def self.on_donations(campaign_id) def self.on_donations(campaign_id)
Qx.select( campaign = Campaign.find(campaign_id)
result = Qx.select(
"COALESCE(COUNT(DISTINCT donations.id), 0) AS supporters_count", "COALESCE(COUNT(DISTINCT donations.id), 0) AS supporters_count",
"COALESCE(SUM(payments.gross_amount), 0) AS total_raised", "COALESCE(SUM(payments.gross_amount), 0) AS total_raised"
"campaigns.goal_amount", )
"campaigns.show_total_count",
"campaigns.show_total_raised")
.from("campaigns") .from("campaigns")
.left_join( .join(
["donations", "donations.campaign_id=campaigns.id"], ["donations", "donations.campaign_id=campaigns.id"],
["payments", "payments.donation_id=donations.id"] ["payments", "payments.donation_id=donations.id"]
) )
.where("campaigns.id=$id", id: campaign_id) .where("campaigns.id IN (#{QueryCampaigns
.group_by('campaigns.id') .get_campaign_and_children(campaign_id)
.parse
})")
.execute .execute
.last .last
return {
'supporters_count' => result['supporters_count'],
'total_raised'=> result['total_raised'],
'goal_amount'=> campaign.goal_amount,
'show_total_count'=> campaign.show_total_count,
'show_total_raised'=> campaign.show_total_raised
}
end end
end end

View file

@ -50,7 +50,7 @@ module QueryCampaigns
["payments AS onetime", "onetime.id=payments.id AND onetime.kind='Donation'"], ["payments AS onetime", "onetime.id=payments.id AND onetime.kind='Donation'"],
["payments AS offsite", "offsite.id=payments.id AND offsite.kind='OffsitePayment'"], ["payments AS offsite", "offsite.id=payments.id AND offsite.kind='OffsitePayment'"],
["payments AS recurring", "recurring.id=payments.id AND recurring.kind='RecurringDonation'"]) ["payments AS recurring", "recurring.id=payments.id AND recurring.kind='RecurringDonation'"])
.where("donations.campaign_id" => campaign_id) .where("donations.campaign_id IN (#{QueryCampaigns.get_campaign_and_children(campaign_id).parse})")
end end
@ -62,15 +62,25 @@ module QueryCampaigns
def self.name_and_id(npo_id) def self.name_and_id(npo_id)
Psql.execute(
Qexpr.new.select( np = Nonprofit.find(npo_id)
"campaigns.name", campaigns = np.campaigns.not_deleted.includes(:profile).order('campaigns.name ASC')
"campaigns.id") output = campaigns.map do |i|
.from("campaigns") {
.where("campaigns.nonprofit_id=$id", id: npo_id) 'name' => i.name,
.where("campaigns.deleted='f' OR campaigns.deleted IS NULL") 'id' => i.id,
.order_by("campaigns.name ASC") 'isChildCampaign' => i.child_campaign?,
) 'creator' => i.profile&.name || "user ##{i.profile.id}"
}
end
output
end
def self.get_campaign_and_children(campaign_id)
Qx.select("id")
.from('campaigns')
.where("campaigns.id = $id OR campaigns.parent_campaign_id=$id",
id: campaign_id)
end end

View file

@ -19,7 +19,9 @@ module QueryDonations
.join(:supporters, "supporters.id=donations.supporter_id") .join(:supporters, "supporters.id=donations.supporter_id")
.left_outer_join(:campaign_gifts, "campaign_gifts.donation_id=donations.id") .left_outer_join(:campaign_gifts, "campaign_gifts.donation_id=donations.id")
.left_outer_join(:campaign_gift_options, "campaign_gift_options.id=campaign_gifts.campaign_gift_option_id") .left_outer_join(:campaign_gift_options, "campaign_gift_options.id=campaign_gifts.campaign_gift_option_id")
.where("donations.campaign_id=$id", id: campaign_id) .where("donations.campaign_id IN (#{QueryCampaigns
.get_campaign_and_children(campaign_id)
.parse})")
.group_by("donations.id", "supporters.id") .group_by("donations.id", "supporters.id")
.order_by("donations.date") .order_by("donations.date")
) )
@ -27,7 +29,9 @@ module QueryDonations
def self.for_campaign_activities(id) def self.for_campaign_activities(id)
QueryDonations.activities_expression(['donations.recurring']) QueryDonations.activities_expression(['donations.recurring'])
.where('donations.campaign_id=$id', id: id) .where("donations.campaign_id IN (#{QueryCampaigns
.get_campaign_and_children(id)
.parse})")
.execute .execute
end end

View file

@ -140,7 +140,8 @@ module QueryPayments
inner_donation_search = inner_donation_search.where('donations.event_id=$id', id: query[:event_id]) inner_donation_search = inner_donation_search.where('donations.event_id=$id', id: query[:event_id])
end end
if (query[:campaign_id].present?) if (query[:campaign_id].present?)
inner_donation_search = inner_donation_search.where('donations.campaign_id=$id', id: query[:campaign_id]) campaign_search = campaign_and_child_query_as_raw_string
inner_donation_search = inner_donation_search.where("donations.campaign_id IN (#{campaign_search})", id: query[:campaign_id])
end end
expr = Qexpr.new.select('payments.id').from('payments') expr = Qexpr.new.select('payments.id').from('payments')
.left_outer_join('supporters', "supporters.id=payments.supporter_id") .left_outer_join('supporters', "supporters.id=payments.supporter_id")
@ -191,9 +192,10 @@ module QueryPayments
expr = expr.where('payments.kind IN ($kinds)', kinds: query[:donation_type].split(',')) expr = expr.where('payments.kind IN ($kinds)', kinds: query[:donation_type].split(','))
end end
if query[:campaign_id].present? if query[:campaign_id].present?
campaign_search = campaign_and_child_query_as_raw_string
expr = expr expr = expr
.left_outer_join("campaigns", "campaigns.id=donations.campaign_id" ) .left_outer_join("campaigns", "campaigns.id=donations.campaign_id" )
.where("campaigns.id=$id", id: query[:campaign_id]) .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id])
end end
if query[:event_id].present? if query[:event_id].present?
tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by("payment_id").as("tix") tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by("payment_id").as("tix")
@ -224,7 +226,8 @@ module QueryPayments
inner_donation_search = inner_donation_search.where('donations.event_id=$id', id: query[:event_id]) inner_donation_search = inner_donation_search.where('donations.event_id=$id', id: query[:event_id])
end end
if (query[:campaign_id].present?) if (query[:campaign_id].present?)
inner_donation_search = inner_donation_search.where('donations.campaign_id=$id', id: query[:campaign_id]) campaign_search = campaign_and_child_query_as_raw_string
inner_donation_search = inner_donation_search.where("donations.campaign_id IN (#{campaign_search})", id: query[:campaign_id])
end end
expr = Qexpr.new.select('payments.id').from('payments') expr = Qexpr.new.select('payments.id').from('payments')
.left_outer_join('supporters', "supporters.id=payments.supporter_id") .left_outer_join('supporters', "supporters.id=payments.supporter_id")
@ -278,9 +281,10 @@ module QueryPayments
expr = expr.where('payments.kind IN ($kinds)', kinds: query[:donation_type].split(',')) expr = expr.where('payments.kind IN ($kinds)', kinds: query[:donation_type].split(','))
end end
if query[:campaign_id].present? if query[:campaign_id].present?
campaign_search = campaign_and_child_query_as_raw_string
expr = expr expr = expr
.left_outer_join("campaigns", "campaigns.id=donations.campaign_id" ) .left_outer_join("campaigns", "campaigns.id=donations.campaign_id" )
.where("campaigns.id=$id", id: query[:campaign_id]) .where("campaigns.id IN (#{campaign_search})", id: query[:campaign_id])
end end
if query[:event_id].present? if query[:event_id].present?
tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by("payment_id").as("tix") tickets_subquery = Qexpr.new.select("payment_id", "MAX(event_id) AS event_id").from("tickets").where('tickets.event_id=$event_id', event_id: query[:event_id]).group_by("payment_id").as("tix")
@ -446,4 +450,8 @@ module QueryPayments
} }
end end
def self.campaign_and_child_query_as_raw_string
"SELECT c_temp.id from campaigns c_temp where c_temp.id=$id OR c_temp.parent_campaign_id=$id"
end
end end

View file

@ -14,7 +14,9 @@ module QuerySupporters
.left_outer_join('campaign_gifts', 'donations.id=campaign_gifts.donation_id') .left_outer_join('campaign_gifts', 'donations.id=campaign_gifts.donation_id')
.left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id') .left_outer_join('campaign_gift_options', 'campaign_gifts.campaign_gift_option_id=campaign_gift_options.id')
.where("supporters.nonprofit_id=$id", id: np_id) .where("supporters.nonprofit_id=$id", id: np_id)
.where("donations.campaign_id=$id", id: campaign_id) .where("donations.campaign_id IN (#{QueryCampaigns
.get_campaign_and_children(campaign_id)
.parse})")
.group_by('supporters.id') .group_by('supporters.id')
.order_by('MAX(donations.date) DESC') .order_by('MAX(donations.date) DESC')
@ -253,7 +255,9 @@ module QuerySupporters
expr = expr.and_where("tags.ids @> ARRAY[$tag_ids]", tag_ids: tag_ids) expr = expr.and_where("tags.ids @> ARRAY[$tag_ids]", tag_ids: tag_ids)
end end
if query[:campaign_id].present? if query[:campaign_id].present?
expr = expr.add_join("donations", "donations.supporter_id=supporters.id AND donations.campaign_id=#{query[:campaign_id].to_i}") expr = expr.add_join("donations", "donations.supporter_id=supporters.id AND donations.campaign_id IN (#{QueryCampaigns
.get_campaign_and_children(query[:campaign_id].to_i)
.parse})")
end end
if query[:event_id].present? if query[:event_id].present?

1209
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -61,8 +61,8 @@
"less": "^3.0.4", "less": "^3.0.4",
"less-loader": "^4.1.0", "less-loader": "^4.1.0",
"lodash": "^4.17.5", "lodash": "^4.17.5",
"node-sass": "^4.9.0", "node-sass": "^4.10.0",
"phantomjs-prebuilt": "2.1.12", "phantomjs-prebuilt": "^2.1.16",
"postcss-cssnext": "^2.9.0", "postcss-cssnext": "^2.9.0",
"postcss-import": "^9.1.0", "postcss-import": "^9.1.0",
"postcss-loader": "^2.1.1", "postcss-loader": "^2.1.1",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View file

@ -0,0 +1,78 @@
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
require 'rails_helper'
describe CreatePeerToPeerCampaign do
describe '.create' do
let!(:profile) { force_create(:profile, :user => force_create(:user)) }
let!(:parent_campaign) { force_create(:campaign, name: 'Parent campaign') }
context 'on success' do
it 'returns a hash' do
campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, goal_amount_dollars: "1000" }
Timecop.freeze(2020, 4, 5) do
result = CreatePeerToPeerCampaign.create(campaign_params, profile.id)
expect(result).to be_kind_of Hash
end
end
it 'returns created peer-to-peer campaign' do
campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, goal_amount_dollars: "1000" }
Timecop.freeze(2020, 4, 5) do
result = CreatePeerToPeerCampaign.create(campaign_params, profile.id)
expect(result).not_to include 'errors'
expect(result['parent_campaign_id']).to eq parent_campaign.id
expect(result['created_at']).to eq 'Sun, 05 Apr 2020 00:00:00 UTC +00:00'
end
end
it 'assigns proper slug' do
campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, goal_amount_dollars: "1000" }
Timecop.freeze(2020, 4, 5) do
result = CreatePeerToPeerCampaign.create(campaign_params, profile.id)
expect(result).not_to include 'errors'
expect(result['slug']).to eq 'child-campaign_000'
end
end
it 'saves campaign' do
campaign_params = { name: 'Child campaign', parent_campaign_id: parent_campaign.id, goal_amount_dollars: "1000" }
Timecop.freeze(2020, 4, 5) do
expect { CreatePeerToPeerCampaign.create(campaign_params, profile.id) }.to change(Campaign, :count).by 1
end
end
end
context 'on failure' do
it "returns an error if parent campaign can't be found" do
campaign_params = {}
Timecop.freeze(2020, 4, 5) do
result = CreatePeerToPeerCampaign.create(campaign_params, profile.id)
expect(result).to be_kind_of Hash
expect(result['errors']['parent_campaign_id']).to eq 'not found'
end
end
it 'returns a list of error messages for attribute validation' do
campaign_params = { parent_campaign_id: parent_campaign.id }
Timecop.freeze(2020, 4, 5) do
result = CreatePeerToPeerCampaign.create(campaign_params, profile.id)
expect(result).to be_kind_of Hash
expect(result).to include 'errors'
expect(result['errors']['goal_amount']).to match ["can't be blank", 'is not a number']
end
end
it "doesn't save campaign" do
campaign_params = {}
Timecop.freeze(2020, 4, 5) do
expect { CreatePeerToPeerCampaign.create(campaign_params, profile.id) }.not_to change(Campaign, :count)
end
end
end
end
end

View file

@ -44,6 +44,8 @@ describe InsertDuplicate do
let(:common_result_attributes) { let(:common_result_attributes) {
{ {
nonprofit_id: nonprofit.id, nonprofit_id: nonprofit.id,
parent_campaign_id: nil,
reason_for_supporting: nil,
profile_id: profile.id, profile_id: profile.id,
:background_image => nil, :background_image => nil,
:body => nil, :body => nil,
@ -71,6 +73,8 @@ describe InsertDuplicate do
:video_url => nil, :video_url => nil,
:vimeo_video_id => nil, :vimeo_video_id => nil,
:youtube_video_id => nil, :youtube_video_id => nil,
banner_image: nil,
default_reason_for_supporting: nil,
name: copy_name, name: copy_name,
slug: copy_slug, slug: copy_slug,
@ -114,7 +118,8 @@ describe InsertDuplicate do
expect(result.attributes.with_indifferent_access).to eq(common_result_attributes.merge( expect(result.attributes.with_indifferent_access).to eq(common_result_attributes.merge(
{ {
id: result.id, id: result.id,
end_datetime: nil end_datetime: nil,
banner_image: nil
}).with_indifferent_access) }).with_indifferent_access)
validate_cgo(result) validate_cgo(result)
end end

View file

@ -0,0 +1,81 @@
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
require 'rails_helper'
describe QueryCampaignMetrics do
describe 'calculates your metrics plus children' do
let(:nonprofit) {force_create(:nonprofit)}
let(:campaign) {force_create(:campaign, nonprofit:nonprofit, show_total_count:false, show_total_raised: false, goal_amount: 16000)}
let(:campaign_child) {force_create(:campaign, nonprofit:nonprofit, parent_campaign:campaign, show_total_count:true, show_total_raised: true, goal_amount: 8000)}
let(:campaign_child_2) {force_create(:campaign, nonprofit:nonprofit, parent_campaign:campaign, show_total_count:true, show_total_raised: true, goal_amount: 4000 )}
let(:donation) { force_create(:donation, campaign: campaign, amount: 1000)}
let(:payment) { force_create(:payment, donation: donation, gross_amount:1000)}
let(:donation2) { force_create(:donation, campaign: campaign, amount: 2000)}
let(:payment2) { force_create(:payment, donation: donation2, gross_amount:2000)}
let(:donation3) { force_create(:donation, campaign: campaign_child, amount: 4000)}
let(:payment3) { force_create(:payment, donation: donation3, gross_amount:4000)}
let(:donation4) { force_create(:donation, campaign: campaign_child_2, amount: 8000)}
let(:payment4) { force_create(:payment, donation: donation4, gross_amount:8000)}
let(:payments) do
payment
payment2
payment3
payment4
end
let (:campaign_metric) do
payments
QueryCampaignMetrics.on_donations(campaign.id)
end
let(:campaign_child_metric) do
payments
QueryCampaignMetrics.on_donations(campaign_child.id)
end
let(:campaign_child_2_metric) do
payments
QueryCampaignMetrics.on_donations(campaign_child_2.id)
end
it 'campaign metric is valid' do
expect(campaign_metric['supporters_count']).to eq 4
expect(campaign_metric['total_raised']).to eq 15000
expect(campaign_metric['goal_amount']).to eq 16000
expect(campaign_metric['show_total_count']).to eq false
expect(campaign_metric['show_total_raised']).to eq false
end
it 'campaign child metric is valid' do
expect(campaign_child_metric['supporters_count']).to eq 1
expect(campaign_child_metric['total_raised']).to eq 4000
expect(campaign_child_metric['goal_amount']).to eq 8000
expect(campaign_child_metric['show_total_count']).to eq true
expect(campaign_child_metric['show_total_raised']).to eq true
end
it 'campaign child 2metric is valid' do
expect(campaign_child_2_metric['supporters_count']).to eq 1
expect(campaign_child_2_metric['total_raised']).to eq 8000
expect(campaign_child_2_metric['goal_amount']).to eq 4000
expect(campaign_child_2_metric['show_total_count']).to eq true
expect(campaign_child_2_metric['show_total_raised']).to eq true
end
end
end

View file

@ -46,20 +46,8 @@ describe SlugP2pCampaignNamingAlgorithm do
expect(algo.create_copy_name(@name2)).to eq short_slug_copy_today_plus_1 expect(algo.create_copy_name(@name2)).to eq short_slug_copy_today_plus_1
end end
it 'errors when at max copies' do it 'has 999 as the max_copies' do
@name = short_slug expect(algo.max_copies).to eq 999
@copy_base = copy_base
campaign
campaigns_at_max_copies
expect{ algo.create_copy_name(@name) }.to(raise_error{|error|
expect(error).to be_a ArgumentError
})
campaigns_at_max_copies.each {|i|
expect {algo.create_copy_name(i.slug)}.to(raise_error{|error|
expect(error).to be_a ArgumentError
})
}
end end
end end
end end