diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 088209b..dfff169 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -18,143 +18,3 @@ //= require turbolinks //= require_tree . //= require jquery_nested_form - - -(function($) { - "use strict"; // Start of use strict - - // Floating label headings for the contact form - $("body").on("input propertychange", ".floating-label-form-group", function(e) { - $(this).toggleClass("floating-label-form-group-with-value", !!$(e.target).val()); - }).on("focus", ".floating-label-form-group", function() { - $(this).addClass("floating-label-form-group-with-focus"); - }).on("blur", ".floating-label-form-group", function() { - $(this).removeClass("floating-label-form-group-with-focus"); - }); - - // Show the navbar when the page is scrolled up - var MQL = 992; - - //primary navigation slide-in effect - if ($(window).width() > MQL) { - var headerHeight = $('#mainNav').height(); - $(window).on('scroll', { - previousTop: 0 - }, - function() { - var currentTop = $(window).scrollTop(); - //check if user is scrolling up - if (currentTop < this.previousTop) { - //if scrolling up... - if (currentTop > 0 && $('#mainNav').hasClass('is-fixed')) { - $('#mainNav').addClass('is-visible'); - } else { - $('#mainNav').removeClass('is-visible is-fixed'); - } - } else if (currentTop > this.previousTop) { - //if scrolling down... - $('#mainNav').removeClass('is-visible'); - if (currentTop > headerHeight && !$('#mainNav').hasClass('is-fixed')) $('#mainNav').addClass('is-fixed'); - } - this.previousTop = currentTop; - }); - } - -})(jQuery); // End of use strict - -$('.remove-posts_category:first').hide(); - -function reorderPostsCategories() { - $('#posts_categories-form h4.subsection.new-posts_categories span:visible').each(function(index) { - $(this).html(index + 1); - }); -}; - -$(document).on('nested:fieldAdded nested:fieldRemoved', function(event){ - reorderPostsCategories(); -}); - -//Rating -var $stars; - -jQuery(document).ready(function ($) { - - // Custom whitelist to allow for using HTML tags in popover content - var myDefaultWhiteList = $.fn.tooltip.Constructor.Default.whiteList - myDefaultWhiteList.textarea = []; - myDefaultWhiteList.button = []; - - $stars = $('.rate-popover'); - - const currentPost = $('#current_post'); - const postId = currentPost.data('id'); - let exists_rank = false; - let response_request; - let rank_id; - let new_rank; - - $stars.on('mouseover', function () { - var index = $(this).attr('data-index'); - markStarsAsActive(index); - }); - - function markStarsAsActive(index) { - unmarkActive(); - for (var i = 0; i <= index; i++) { - $($stars.get(i)).addClass('amber-text'); - } - } - - function unmarkActive() { - $stars.removeClass('amber-text'); - } - - $stars.on('click', function () { - new_rank = $(this).attr('data-index'); - $stars.popover('hide'); - }); - - // Submit, you can add some extra custom code here - // ex. to send the information to the server - $('#rateMe').on('click', '#voteSubmitButton', function () { - $stars.popover('hide'); - let url_request = "/rankings" - if (exists_rank) { - url_request += ("/"+rank_id); - - $.ajax({ - type: 'PATCH', - url: url_request, - data: JSON.stringify ({id: rank_id,ranking:{post_id:postId, rank: new_rank},commit:"Update Ranking"}), - success: function(data) {/* alert('data: ' + data);*/ }, - contentType: "application/json", - dataType: 'json' - }); - } else { - $.ajax({ - type: 'POST', - url: url_request, - data: JSON.stringify ({ranking:{post_id:postId, rank: new_rank},commit:"Create Ranking"}), - success: function(data) { /*alert('data: ' + data); */}, - contentType: "application/json", - dataType: 'json' - }); - } - }); - - // Cancel, just close the popover - $('#rateMe').on('click', '#closePopoverButton', function () { - $stars.popover('hide'); - }); - -}); - -$(function () { - $('.rate-popover').popover({ - // Append popover to #rateMe to allow handling form inside the popover - container: '#rateMe', - // Custom content for popover - content: `
` - }); - $('.rate-popover').tooltip(); -}); \ No newline at end of file diff --git a/app/assets/javascripts/posts.js.coffee b/app/assets/javascripts/posts.js.coffee new file mode 100644 index 0000000..41e4b2c --- /dev/null +++ b/app/assets/javascripts/posts.js.coffee @@ -0,0 +1,44 @@ +jQuery -> + "use strict" + # Floating label headings for the contact form + $( "body" ).on("input propertychange", ".floating-label-form-group", (e) -> + $(@).toggleClass "floating-label-form-group-with-value", !!$(e.target).val() + ).on("focus", ".floating-label-form-group", -> + $(@).addClass "floating-label-form-group-with-focus" + ).on("blur", ".floating-label-form-group", -> + $(@).removeClass "floating-label-form-group-with-focus" + ) + + minimunScreenSize = 992 + + #primary navigation slide-in effect + if $(window).width() > minimunScreenSize + headerHeight = $('#mainNav').height() + $(window).on('scroll', + previousTop: 0, + -> + currentTop = $(window).scrollTop() + #check if user is scrolling up + if (currentTop < @.previousTop) + #if scrolling up... + if currentTop > 0 && $('#mainNav').hasClass('is-fixed') + $('#mainNav').addClass('is-visible') + else + $('#mainNav').removeClass('is-visible is-fixed') + else if currentTop > @.previousTop + #if scrolling down... + $('#mainNav').removeClass('is-visible') + $('#mainNav').addClass('is-fixed') if (currentTop > headerHeight && !$('#mainNav').hasClass('is-fixed')) + @.previousTop = currentTop + ) + +$('.remove-posts_category:first').hide() + +reorderPostsCategories = -> + $('#posts_categories-form h4.subsection.new-posts_categories span:visible').each((index) -> + $(@).html(index + 1) + ) + +$(document).on('nested:fieldAdded nested:fieldRemoved', (event) -> + reorderPostsCategories() +) \ No newline at end of file diff --git a/app/assets/javascripts/rankings.js.coffee b/app/assets/javascripts/rankings.js.coffee new file mode 100644 index 0000000..b2e79f6 --- /dev/null +++ b/app/assets/javascripts/rankings.js.coffee @@ -0,0 +1,44 @@ + +$(document).on "turbolinks:load", -> + return unless $("body").data("controller") == "posts" && $("body").data("action") == "show" + + $stars = $('.rate-popover') + + new_rank = 0 + currentElement = $('#current_post') + postId = currentElement.attr "data-post" + userId = currentElement.attr "data-user" + + $stars.on('mouseover', -> + index = $(@).attr('data-index') + markStarsAsActive(index) + ) + + markStarsAsActive = (index) -> + unmarkActive() + i = 0 + while i <= index + $($stars.get(i)).addClass('amber-text') + i++ + + unmarkActive = -> + $stars.removeClass('amber-text') + + $stars.on('click', -> + new_rank = $(@).attr('data-index') + url_request = "/rankings" + + $.ajax( + type: 'POST', + url: url_request, + data: JSON.stringify ( + post_id: postId + user_id: userId + rank: new_rank, + commit: "Change Ranking" + ) + success: (data) -> + contentType: "application/json" + dataType: 'json' + ) + ) \ No newline at end of file diff --git a/app/controllers/rankings_controller.rb b/app/controllers/rankings_controller.rb index 2727824..a29dc40 100644 --- a/app/controllers/rankings_controller.rb +++ b/app/controllers/rankings_controller.rb @@ -3,60 +3,44 @@ class RankingsController < ApplicationController access all: :all - before_action :set_ranking, only: %i[update destroy] - before_action :set_index_type, only: :index + before_action :set_ranking_match_by_search, only: :create def index - if @index_type - @rankings = Ranking.where(post_id: @post_id, user_id: current_user.id) - else - @posts = Post.all.sort_by(&:ranking_value).reverse - @rankings = Ranking.all - end + @posts = Post.all.sort_by(&:ranking_value).reverse end def create - @ranking = current_user.rankings.new(ranking_params) - - respond_to do |format| - if @ranking.save - format.html { redirect_to @ranking, notice: "Ranking was successfully created." } - format.json { render json: @ranking, status: :created } - else - format.html { render json: @ranking.errors, status: :unprocessable_entity } - end - end + ranking_exists ? update_ranking : create_ranking end - def update - respond_to do |format| - if @ranking.update(ranking_params) - format.html { redirect_to @ranking, notice: "Ranking was successfully updated" } - else - format.html { render :edit } - end - end - end + private - def destroy - respond_to do |format| - format.html { redirect_to rankings_path, notice: "Ranking was successfully deleted" } if @ranking.destroy - end + def json_render(message, status) + render json: message, status: status end - private + def create_ranking + @ranking = Ranking.new(ranking_params) - def set_ranking - @ranking = Ranking.find(params[:id]) + @ranking.save ? json_render(@ranking, :created) : json_render(@ranking.errors, :unprocessable_entity) end - def set_index_type - @index_type = params["index_type"] - @post_id = params["post_id"] + def ranking_exists + @ranking_match&.count&.positive? end def ranking_params params.require(:ranking).permit(:rank, :index_type, :user_id, :post_id) end + def set_ranking_match_by_search + @ranking_match = Ranking.where(user_id: params[:user_id], post_id: params[:post_id]) + end + + def update_ranking + @ranking = @ranking_match.first + + @ranking.update(ranking_params) ? json_render(@ranking, :ok) : json_render(@ranking.errors, :unprocessable_entity) + end + end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index be027aa..4277b8d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -36,12 +36,7 @@ def client_li_tags def admin_li_tags concat li_tag_path "Home", root_path, :get - concat li_tag_path "Users", users_path, :get - concat li_tag_path "Posts", posts_path, :get - concat li_tag_path "Categories", categories_path, :get - concat li_tag_path "PostsCategories", posts_categories_path, :get - concat li_tag_path "Comments", comments_path, :get - concat li_tag_path "Rankings", rankings_path, :get + concat li_tag_path "Ranking", rankings_path, :get concat li_tag_path "Logout", destroy_user_session_path, :delete end @@ -59,13 +54,13 @@ def user_create_post (link_to "Create post", new_post_path, class: "btn btn-primary") + content_tag(:hr) if current_user end - def set_post_ranking + def add_start_by_post_ranking(user_ranking) star_titles = ["Very bad", "Poor", "Ok", "Good", "Excellent"] star_class = "" number_stars = 5 content_tag(:span, id: "rateMe") do number_stars.times do |n| - star_class = n <= @user_ranking ? "amber-text" : "" + star_class = n <= user_ranking ? "amber-text" : "" concat li_for_ranking n, star_titles[n], star_class end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index f28e6a1..053c64e 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -17,7 +17,7 @@ - + <%= content_tag :body, data: {action: action_name, controller: controller_name} do %> <%= render "shared/nav" %> @@ -26,5 +26,5 @@
<%= yield %>
- + <% end %> diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index 8e643bd..400899c 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -1,10 +1,12 @@ -
+

Categories: <%= render partial: "categories/category", collection: @post.categories %>

- <%= set_post_ranking %> +

+ <%= add_start_by_post_ranking @user_ranking %> +

<%= @post.content %>

diff --git a/app/views/rankings/_ranking.html.erb b/app/views/rankings/_ranking.html.erb index 7c8a12e..5ef5681 100644 --- a/app/views/rankings/_ranking.html.erb +++ b/app/views/rankings/_ranking.html.erb @@ -1,5 +1,5 @@ - <%= ranking.title %> + <%= link_to ranking.title, ranking %> <%= ranking.user.username %> <%= ranking.ranking_value %> \ No newline at end of file diff --git a/app/views/rankings/index.html.erb b/app/views/rankings/index.html.erb index 2ce37fe..e36899a 100644 --- a/app/views/rankings/index.html.erb +++ b/app/views/rankings/index.html.erb @@ -9,6 +9,6 @@ - <%= render @posts %> + <%= render partial: "ranking", collection: @posts %> diff --git a/config/routes.rb b/config/routes.rb index 50a8e5b..574c298 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -11,7 +11,7 @@ resources :comments, only: %i[create update destroy] - resources :rankings, only: %i[index create update destroy] + resources :rankings, only: %i[index create] root "posts#index" end diff --git a/spec/controllers/rankings_controller_spec.rb b/spec/controllers/rankings_controller_spec.rb index 8d5e13f..c719664 100644 --- a/spec/controllers/rankings_controller_spec.rb +++ b/spec/controllers/rankings_controller_spec.rb @@ -5,10 +5,14 @@ RSpec.describe RankingsController, type: :controller do let(:global_user) { FactoryBot.create(:user) } - before { sign_in global_user } + before do + FactoryBot.create_list(:post, 3) + sign_in global_user + end describe "GET #index" do - let(:rankings) { FactoryBot.create_list(:ranking, 3) } + + let(:posts_sorted) { Post.all.sort_by(&:ranking_value).reverse } context "when the request is valid" do before do @@ -24,58 +28,9 @@ end it "validates @rankings" do - expect(assigns(:rankings)).to match(rankings) - end - end - end - - describe "POST #update" do - - let(:ranking) { FactoryBot.create(:ranking) } - let(:ranking_id) { ranking.id } - let(:updated_ranking) { FactoryBot.attributes_for(:ranking) } - - let(:params) do - { - id: ranking_id, - ranking: updated_ranking, - } - end - - context "when the request is valid" do - - before { post :update, params: params } - - it "returns status code :found" do - expect(response).to have_http_status(:found) + expect(assigns(:posts)).to match(posts_sorted) end - end end - describe "POST #destroy" do - - let(:ranking) { FactoryBot.create(:ranking) } - let(:ranking_id) { ranking.id } - - let(:params) do - { - id: ranking_id, - } - end - - context "when the request is valid" do - - before { post :destroy, params: params } - - it "returns status code :found" do - expect(response).to have_http_status(:found) - end - - it "redirect_to :index" do - expect(response).to redirect_to(action: :index) - end - - end - end end