Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better winning project publishing form #426

Merged
merged 13 commits into from
Jan 17, 2020
3 changes: 2 additions & 1 deletion app/assets/javascripts/projects.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mark_as_winner_before_send = (event, data, xhr) ->

mark_as_winner_success = (event, data, status, xhr) ->
project_container = $('article[data-id="'+data.project_id+'"]')

if data.winner
project_container.addClass('winner')
project_container.find('a.mark-as-winner').attr('data-method', 'delete')
Expand All @@ -46,7 +47,7 @@ $(".short-list")
.bind("ajax:success", shortlist_success)
.bind("ajax:failure", shortlist_failure)

$(".mark-as-winner")
$(".mark-as-winner, .remove-as-winner")
.bind("ajax:beforeSend", mark_as_winner_before_send)
.bind("ajax:success", mark_as_winner_success)
.bind("ajax:failure", mark_as_winner_failure)
Expand Down
10 changes: 8 additions & 2 deletions app/assets/stylesheets/_projects-index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,10 @@ body.projects-index {
}
}

&.edit-winner {
&.non-winner-action {
display: block;
}
&.winner-action {
display: none;
}
}
Expand Down Expand Up @@ -590,9 +593,12 @@ body.projects-index {
color: $blue;
font-weight: bolder;
}
li.edit-winner {
li.winner-action {
display: block;
}
li.non-winner-action {
display: none;
}
}

div.title {
Expand Down
14 changes: 14 additions & 0 deletions app/assets/stylesheets/_winners.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.center-form__cancel {
text-align: center;
}

.center-form__cancel-link {
color: $lighter-base-font-color !important;
font-size: .85em;

text-decoration: none !important;

&:hover {
text-decoration: underline !important;
}
}
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
@import 'shared-flash-messages';
@import 'about';
@import 'faq';
@import 'winners';
@import 'pagination';
@import 'magnific-popup';

Expand Down
43 changes: 40 additions & 3 deletions app/controllers/winners_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class WinnersController < ApplicationController
before_action :must_be_able_to_mark_winner
before_action :must_be_able_to_mark_winner, only: [:create, :update, :destroy]

def create
@project = Project.find(params[:project_id])
Expand All @@ -9,6 +9,27 @@ def create
render :json => response_json
end

def edit
@project = FundedProject.find(params[:project_id])
@project.funded_description = @project.about_project if @project.funded_description.blank?
end

def update
@project = FundedProject.find(params[:project_id])
@project.attributes = winner_params

if @project.save
if @project.chapter_id_previously_changed? || params[:return_to].blank?
redirect_to chapter_project_path(@project.chapter, @project)
else
redirect_to params[:return_to]
end
else
flash.now[:notice] = t("flash.projects.error")
render action: "edit"
end
end

def destroy
@project = Project.find(params[:project_id])
@project.revoke_winner!
Expand All @@ -17,9 +38,20 @@ def destroy

private

def winner_params
permitted = [:funded_on, :title, :name, :url, :rss_feed_url, :funded_description, photo_ids_to_delete: [], new_photos: [], new_photo_direct_upload_urls: [] ]
permitted << :chapter_id if current_project.in_any_chapter? || current_user.admin?

params.require(:project).permit(permitted)
end

def winning_chapter
if params[:chapter_id].present?
@chapter ||= Chapter.find(params[:chapter_id])
elsif params.dig(:project, :chapter_id).present?
@chapter ||= Chapter.find(params[:project][:chapter_id])
else
@chapter ||= current_project.chapter
end
end

Expand All @@ -28,9 +60,14 @@ def current_project
end

def must_be_able_to_mark_winner
unless current_user.admin? || (current_user.can_mark_winner?(current_project) && current_user.chapters.include?(winning_chapter))
unless current_user.can_mark_winner?(current_project) && current_user.chapters.include?(winning_chapter)
flash[:notice] = t("flash.permissions.cannot-mark-winner")
render :json => { :location => chapter_projects_path(current_project.chapter) }
redirect_location = chapter_projects_path(current_project.chapter)

respond_to do |format|
format.js { render json: { :location => redirect_location } }
format.html { redirect_to redirect_location and return }
end
end
end
end
8 changes: 8 additions & 0 deletions app/helpers/projects_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ def selectable_chapters_for(user)
end
end

def winnable_chapters_for(project)
if current_user.admin?
Chapter.visitable.for_display
else
project.in_any_chapter? ? current_user.dean_chapters : Array(project.chapter)
end
end

def show_winner_buttons_for(project, options = {})
if @chapter.any_chapter?
winnable_chapters = current_user.dean_chapters
Expand Down
3 changes: 3 additions & 0 deletions app/models/funded_project.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class FundedProject < Project
validates :funded_on, presence: true
end
2 changes: 2 additions & 0 deletions app/models/project.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
require "textacular/searchable"

class Project < ApplicationRecord
MAX_PHOTOS = 5

attr_accessor :photo_order
attr_accessor :photo_ids_to_delete

Expand Down
57 changes: 3 additions & 54 deletions app/views/projects/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,7 @@
</div>
</div>

<div class="image-upload">
<% if form.object.photos.present? %>
<section class="current-images">
<label><%= t "simple_form.labels.project.current_photos-html" %></label>
<ul class="old-photos">
<%= form.input :photo_order, :as => :hidden %>
<% form.object.photos.each do |photo| %>
<li data-id="<%= photo.id %>">
<span><%= photo.image_file_name %></span>
<a href="#" class="remove-image" data-remove="true">remove</a>
</li>
<% end %>
</ul>
</section>
<% end %>

<% if s3_uploader_available? %>
<%= render :partial => "image_form", :locals => { :form => form, :upload_mechanism => :s3 } %>
<% else %>
<%= render :partial => "image_form", :locals => { :form => form, :upload_mechanism => :classic } %>
<% end %>

</div>
<%= render partial: "image_upload", locals: { form: form } %>

<div class="extra-questions" style="display:none">
<%= form.input :extra_question_1, :as => :hidden, :wrapper_html => {:class => "extra-question"} %>
Expand All @@ -62,9 +40,8 @@

<% if current_user.can_edit_project?(project) %>
<a name="winner"></a>
<div class="funded_on">
<%= form.input :funded_on, :as => :string %>
</div>

<%= render partial: "funded_date", locals: { form: form } %>

<div class="funded_description">
<%= form.input :funded_description %>
Expand All @@ -77,11 +54,7 @@

<% content_for :javascript do %>
<%= javascript_tag do %>
window.awesomeEnvironment.remainingUploads = 0;

$(window).load(function(){
$('#project_funded_on').datepicker({dateFormat: 'yy-mm-dd', onClose: function(){ $('#project_funded_on').blur() }});

// Update the remaining character counts on pageload
$('#project_about_me').keydown();
$('#project_about_project').keydown();
Expand All @@ -93,29 +66,5 @@
"<%= chapter.id %>": <%= extra_questions_json(chapter) %>,
<% end %>}

function reorderPhotos(){
var photo_order = $('.old-photos li[data-id]').map(function(x, el){
return $(el).attr('data-id')
});
$('#project_photo_order').val($.makeArray(photo_order).join(" "));
}

$(".old-photos *[data-remove='true']").on("click", function(){
var val = $('#project_photo_order').val();
val = val.replace($(this.parentNode).attr('data-id'), '');
$('#project_photo_order').val(val);

el = document.createElement('input');
el.type = 'hidden';
el.name = 'project[photo_ids_to_delete][]';
el.value = $(this.parentNode).attr('data-id');

$('#project_photo_order').after(el);
});

$(window).load(function(){
$(".old-photos").sortable({
update: reorderPhotos
})});
<% end %>
<% end %>
14 changes: 14 additions & 0 deletions app/views/projects/_funded_date.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div class="funded_on">
<%= form.input :funded_on, as: :string, input_html: { class: "datepicker", autocomplete: "off" }, required: local_assigns[:required], hint: local_assigns[:hint] %>
</div>

<% content_for :javascript do %>
<%= javascript_tag do %>
$(window).load(function(){
$('.datepicker').datepicker({
dateFormat: 'yy-mm-dd',
onClose: function(){ $('.datepicker').blur() }
});
});
<% end %>
<% end %>
4 changes: 2 additions & 2 deletions app/views/projects/_image_form.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="input file optional" style="<%= 'display:none' unless display_uploader?(upload_mechanism) %>">
<label class="file optional"><%= t "simple_form.labels.project.new_photos-html" %></label>
<div class="multi-input first noremove" data-num-files="5">
<div class="multi-input first noremove" data-num-files="<%= Project::MAX_PHOTOS %>">
<% if upload_mechanism == :s3 %>
<%= form.s3_file_field :new_photos, :class => "s3_upload_field", :name => "project[new_photo_direct_upload_urls][]", :accept => "image/*" %>
<% else %>
Expand All @@ -12,5 +12,5 @@
<div class="progress-meter"></div>
</div>

<div><%= t("projects.form.image-notes", :dimensions => Photo::DIMENSIONS[:main]) %></div>
<div><%= markdown(local_assigns[:image_notes].presence || t("projects.form.image-notes", :dimensions => Photo::DIMENSIONS[:main])) %></div>
</div>
54 changes: 54 additions & 0 deletions app/views/projects/_image_upload.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<div class="image-upload">
<% if form.object.photos.present? %>
<section class="current-images">
<label><%= t "simple_form.labels.project.current_photos-html" %></label>
<ul class="old-photos">
<%= form.input :photo_order, as: :hidden %>
<% form.object.photos.each do |photo| %>
<li data-id="<%= photo.id %>">
<span><%= photo.image_file_name %></span>
<a href="#" class="remove-image" data-remove="true">remove</a>
</li>
<% end %>
</ul>
</section>
<% end %>

<% if s3_uploader_available? %>
<%= render partial: "projects/image_form", locals: { form: form, upload_mechanism: :s3, image_notes: local_assigns[:image_notes] } %>
<% else %>
<%= render partial: "projects/image_form", locals: { form: form, upload_mechanism: :classic, image_notes: local_assigns[:image_notes] } %>
<% end %>

</div>

<% content_for :javascript do %>
<%= javascript_tag do %>
window.awesomeEnvironment.remainingUploads = 0;

function reorderPhotos(){
var photo_order = $('.old-photos li[data-id]').map(function(x, el){
return $(el).attr('data-id')
});
$('#project_photo_order').val($.makeArray(photo_order).join(" "));
}

$(".old-photos *[data-remove='true']").on("click", function(){
var val = $('#project_photo_order').val();
val = val.replace($(this.parentNode).attr('data-id'), '');
$('#project_photo_order').val(val);

el = document.createElement('input');
el.type = 'hidden';
el.name = 'project[photo_ids_to_delete][]';
el.value = $(this.parentNode).attr('data-id');

$('#project_photo_order').after(el);
});

$(window).load(function(){
$(".old-photos").sortable({
update: reorderPhotos
})});
<% end %>
<% end %>
20 changes: 16 additions & 4 deletions app/views/projects/_project_details.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,23 @@
<section class="project-actions">
<ul class="icons-ul">
<% if current_user.can_mark_winner?(project) %>
<%= show_winner_buttons_for(project, { :pre => "<li>", :post => "</li>", :link_prefix => '<i class="icon-li icon-forward"></i>' }) %>
<li class="non-winner-action">
<%= link_to edit_chapter_project_winner_path(project.chapter, project, return_to: "#{request.path}#project#{project.id}") do %>
<i class="icon-li icon-forward"></i>
<%= t("projects.project.publish-as-winner") %>
<% end %>
</li>

<li class="winner-action">
<%= link_to edit_chapter_project_winner_path(project.chapter, project, return_to: "#{request.path}#project#{project.id}"), class: "mark-as-winner" do %>
<i class="icon-li icon-forward"></i> <%= t("projects.project.edit-winner") %>
<% end %>
</li>

<li class="edit-winner">
<%= link_to edit_project_path(project, :anchor => "winner") do %>
<i class="icon-li icon-ellipsis-horizontal"></i> <%= t("projects.project.edit-winner") %>
<li class="winner-action">
<%= link_to project_winner_path(project), remote: true, method: :delete, class: "remove-as-winner" do %>
<i class="icon-li icon-minus"></i>
<%= t("projects.project.unpublish-as-winner") %>
<% end %>
</li>
<% end %>
Expand Down
1 change: 1 addition & 0 deletions app/views/shared/_navigation.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<% end %>
<p><%= link_to chapter.display_name, chapter %></p>
<% end %>
</div>
</article>
</section>
</div>
Expand Down
17 changes: 17 additions & 0 deletions app/views/winners/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<%= hidden_field_tag :return_to, params[:return_to] %>
<div class="chapter-select">
<%= form.input :chapter_id, collection: winnable_chapters_for(form.object), label: t(".chapter_id"), include_blank: false, disabled: !(form.object.in_any_chapter? || current_user.admin?), hint: t(".hints.chapter_id") %>
</div>
<div class="personal-info">
<%= render partial: "projects/funded_date", locals: { form: form, required: true, hint: t(".hints.funded_on") } %>
<%= form.input :title, maxlength: 50 %>
<%= form.input :name, label: t(".name") %>
<%= form.input :url %>
<%= form.input :rss_feed_url %>
</div>
<div class="project-info">
<%= form.input :funded_description, required: true %>
</div>

<%= render partial: "projects/image_upload", locals: { form: form, image_notes: t(".image-notes") } %>

Loading