diff --git a/Gemfile b/Gemfile index ae12ddb0b..b9659381a 100644 --- a/Gemfile +++ b/Gemfile @@ -10,6 +10,8 @@ gem "ancestry", "~> 3.0.7" gem "audited", "~> 4.9.0" gem "autoprefixer-rails", "~> 8.2.0" gem "cancancan", "~> 2.3.0" +gem "caxlsx", "~> 3.0.2" +gem "caxlsx_rails", "~> 0.6.2" gem "ckeditor", "~> 4.3.0" gem "cocoon", "~> 1.2.14" gem "daemons", "~> 1.3.1" diff --git a/Gemfile.lock b/Gemfile.lock index 566735c56..71fdf2d8d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -131,6 +131,14 @@ GEM rack (>= 1.4) rack-proxy (>= 0.6.0) selenium-webdriver (~> 3.0) + caxlsx (3.0.2) + htmlentities (~> 4.3, >= 4.3.4) + mimemagic (~> 0.3) + nokogiri (~> 1.10, >= 1.10.4) + rubyzip (>= 1.3.0, < 3) + caxlsx_rails (0.6.2) + actionpack (>= 3.1) + caxlsx (>= 3.0) chef-utils (16.4.41) childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) @@ -638,6 +646,8 @@ DEPENDENCIES capistrano3-puma (~> 4.0.0) capybara (~> 3.29.0) capybara-webmock (~> 0.5.5) + caxlsx (~> 3.0.2) + caxlsx_rails (~> 0.6.2) ckeditor (~> 4.3.0) cocoon (~> 1.2.14) coveralls (~> 0.8.22) diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss index c089d3b3d..25c769a2a 100644 --- a/app/assets/stylesheets/layout.scss +++ b/app/assets/stylesheets/layout.scss @@ -2045,10 +2045,6 @@ table { padding: $line-height / 4; position: relative; - .relative { - padding-left: rem-calc(18); - } - .divider { color: $text-light; display: inline-block; @@ -2060,23 +2056,22 @@ table { } .responses-count { - .far { - @extend .fa-minus-square; - font-size: $small-font-size; - left: 0; - position: absolute; - text-decoration: none; - top: 2px; - } - .show-children { + @include has-fa-icon(plus-square, r); display: none; } + .collapse-children { + @include has-fa-icon(minus-square, r); + } + + .show-children::before, + .collapse-children::before { + margin-right: rem-calc(6); + transform: translateY(1px); + } + &.collapsed { - .far { - @extend .fa-plus-square; - } .collapse-children { display: none; diff --git a/app/assets/stylesheets/legislation_process.scss b/app/assets/stylesheets/legislation_process.scss index cb4488004..8f3199c06 100644 --- a/app/assets/stylesheets/legislation_process.scss +++ b/app/assets/stylesheets/legislation_process.scss @@ -1006,3 +1006,91 @@ font-weight: bold; } } + +// 10. Legislation summary +// ------------------------- + +.process-summary { + > section { + @include grid-row; + margin-top: $line-height * 1.5; + padding: 0 rem-calc(16); + + > header { + background: none; + border: 0; + margin: 0; + } + } + + h4, + p { + margin-bottom: 0; + } + + > section > header, + .question-title, + .annotation-title, + .comment-summary, + .proposal-summary { + @include breakpoint(medium) { + align-items: center; + display: flex; + + > :first-child { + $margin: rem-calc(map-get($grid-column-gutter, "medium")); + + margin-right: $margin; + width: calc(75% - #{$margin}); + } + } + } + + .debate-summary, + .proposal-summary, + .annotation-summary { + @extend %panel; + min-height: auto; + padding-bottom: rem-calc(16); + padding-top: rem-calc(16); + + &:not(:last-child) { + margin-bottom: $line-height / 2; + } + } + + .comments-count { + @include has-fa-icon(comments, r); + } + + .question-title:not(:only-child) { + margin-bottom: $line-height / 2; + } + + .annotation-title { + margin-bottom: $line-height / 2; + margin-top: $line-height / 2; + } + + .annotation-quote { + border: 1px solid $black; + padding: rem-calc(10); + } + + .comment-summary { + margin-bottom: $line-height / 2; + + > :first-child { + background-color: rgba(217, 216, 243, 0.2); + border-radius: rem-calc(10); + padding: rem-calc(12); + } + } + + .download-button { + margin-bottom: 0; + margin-left: 50%; + margin-top: $line-height; + transform: translateX(-50%); + } +} diff --git a/app/assets/stylesheets/mixins.scss b/app/assets/stylesheets/mixins.scss index b5fb4b9f3..289eb83a6 100644 --- a/app/assets/stylesheets/mixins.scss +++ b/app/assets/stylesheets/mixins.scss @@ -148,3 +148,18 @@ transition: none; } } + +@mixin has-fa-icon($icon, $style) { + @extend .fa-#{$icon}; + + &::before { + @extend %fa-icon; + font-family: "Font Awesome 5 Free"; + + @if $style == "r" { + font-weight: normal; + } @else { + font-weight: bold; + } + } +} diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss index 895e4d2cc..a825c77bb 100644 --- a/app/assets/stylesheets/participation.scss +++ b/app/assets/stylesheets/participation.scss @@ -612,6 +612,45 @@ } } +%panel { + background: #fff; + border: 1px solid; + border-color: #e5e6e9 #dfe0e4 #d0d1d5; + border-radius: 0; + box-shadow: 0 1px 3px 0 $border; + margin-bottom: rem-calc(12); + min-height: rem-calc(192); + padding: rem-calc(12) rem-calc(12) 0; + + @include breakpoint(medium) { + margin-bottom: rem-calc(-1); + padding-bottom: rem-calc(12); + } + + @include breakpoint(medium) { + .divider { + display: inline-block; + } + } + + h3 { + font-weight: bold; + margin-top: $line-height / 2; + + a { + color: $text; + } + } + + &.past-budgets { + min-height: 0; + + .button ~ .button { + margin-left: $line-height / 2; + } + } +} + .debate, .proposal, .investment-project, @@ -621,42 +660,7 @@ margin: $line-height / 4 0; .panel { - background: #fff; - border: 1px solid; - border-color: #e5e6e9 #dfe0e4 #d0d1d5; - border-radius: 0; - box-shadow: 0 1px 3px 0 $border; - margin-bottom: rem-calc(12); - min-height: rem-calc(192); - padding: rem-calc(12) rem-calc(12) 0; - - @include breakpoint(medium) { - margin-bottom: rem-calc(-1); - padding-bottom: rem-calc(12); - } - - @include breakpoint(medium) { - .divider { - display: inline-block; - } - } - - h3 { - font-weight: bold; - margin-top: $line-height / 2; - - a { - color: $text; - } - } - - &.past-budgets { - min-height: 0; - - .button ~ .button { - margin-left: $line-height / 2; - } - } + @extend %panel; } .debate-content, diff --git a/app/controllers/legislation/processes_controller.rb b/app/controllers/legislation/processes_controller.rb index d6dd6d3e5..0edd2cc5a 100644 --- a/app/controllers/legislation/processes_controller.rb +++ b/app/controllers/legislation/processes_controller.rb @@ -97,6 +97,17 @@ class Legislation::ProcessesController < Legislation::BaseController @phase = :milestones end + def summary + @phase = :summary + @proposals = @process.proposals.selected + @comments = @process.draft_versions.published.last&.best_comments || Comment.none + + respond_to do |format| + format.html + format.xlsx { render xlsx: "summary", filename: "summary-#{Date.current}.xlsx" } + end + end + def proposals set_process @phase = :proposals_phase diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 25dcb60c7..24b70e453 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -90,7 +90,9 @@ module Abilities can :access, :ckeditor can :manage, Ckeditor::Picture - can [:manage], ::Legislation::Process + can [:read, :debate, :draft_publication, :allegations, :result_publication, + :milestones], Legislation::Process + can [:create, :update, :destroy], Legislation::Process can [:manage], ::Legislation::DraftVersion can [:manage], ::Legislation::Question can [:manage], ::Legislation::Proposal diff --git a/app/models/abilities/everyone.rb b/app/models/abilities/everyone.rb index 89a29f4b9..432099150 100644 --- a/app/models/abilities/everyone.rb +++ b/app/models/abilities/everyone.rb @@ -21,6 +21,8 @@ module Abilities can :new, DirectMessage can [:read, :debate, :draft_publication, :allegations, :result_publication, :proposals, :milestones], Legislation::Process, published: true + can :summary, Legislation::Process, + id: Legislation::Process.past.published.where(result_publication_enabled: true).ids can [:read, :changes, :go_to_version], Legislation::DraftVersion can [:read], Legislation::Question can [:read, :map, :share], Legislation::Proposal diff --git a/app/models/comment.rb b/app/models/comment.rb index 1552ce3a5..7af862a73 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -49,6 +49,7 @@ class Comment < ApplicationRecord scope :sort_by_most_voted, -> { order(confidence_score: :desc, created_at: :desc) } scope :sort_descendants_by_most_voted, -> { order(confidence_score: :desc, created_at: :asc) } + scope :sort_by_supports, -> { order("cached_votes_up - cached_votes_down DESC") } scope :sort_by_newest, -> { order(created_at: :desc) } scope :sort_descendants_by_newest, -> { order(created_at: :desc) } @@ -129,6 +130,10 @@ class Comment < ApplicationRecord cached_votes_up) end + def votes_score + cached_votes_up - cached_votes_down + end + private def validate_body_length diff --git a/app/models/legislation/draft_version.rb b/app/models/legislation/draft_version.rb index 93b65eb8f..9019d6cb8 100644 --- a/app/models/legislation/draft_version.rb +++ b/app/models/legislation/draft_version.rb @@ -40,4 +40,8 @@ class Legislation::DraftVersion < ApplicationRecord def total_comments annotations.sum(:comments_count) end + + def best_comments + Comment.where(commentable: annotations, ancestry: nil).sort_by_supports.limit(10) + end end diff --git a/app/models/legislation/question.rb b/app/models/legislation/question.rb index ff9e0ea94..73f1cc946 100644 --- a/app/models/legislation/question.rb +++ b/app/models/legislation/question.rb @@ -44,4 +44,8 @@ class Legislation::Question < ApplicationRecord def comments_open? process.debate_phase.open? end + + def best_comments + comments.sort_by_supports.limit(3) + end end diff --git a/app/views/comments/_responses_count.html.erb b/app/views/comments/_responses_count.html.erb index 3915b5495..d9ac9fdf0 100644 --- a/app/views/comments/_responses_count.html.erb +++ b/app/views/comments/_responses_count.html.erb @@ -1,6 +1,5 @@ <% if count > 0 %> - <%= link_to "", class: "js-toggle-children relative" do %> - + <%= link_to "", class: "js-toggle-children" do %> <%= t("comments.comment.responses_show", count: count) %> <%= t("comments.comment.responses_collapse", count: count) %> <% end %> diff --git a/app/views/legislation/processes/_key_dates.html.erb b/app/views/legislation/processes/_key_dates.html.erb index 4e8ab85c0..7e5842d1a 100644 --- a/app/views/legislation/processes/_key_dates.html.erb +++ b/app/views/legislation/processes/_key_dates.html.erb @@ -52,6 +52,15 @@ <% end %> <% end %> + + <% if can?(:summary, process) %> +
  • > + <%= link_to summary_legislation_process_path(process) do %> +

    <%= t("legislation.summary.title") %>

    + <%= format_date(process.result_publication_date) %> + <% end %> +
  • + <% end %> diff --git a/app/views/legislation/processes/_summary_allegations.html.erb b/app/views/legislation/processes/_summary_allegations.html.erb new file mode 100644 index 000000000..345542dc1 --- /dev/null +++ b/app/views/legislation/processes/_summary_allegations.html.erb @@ -0,0 +1,32 @@ +
    +
    +

    <%= t("legislation.summary.allegations_phase") %>

    +

    <%= t("legislation.summary.top_comments", count: comments.count) %>

    +
    + + <% if comments.any? %> +
    + <% comments.group_by(&:commentable).each do |annotation, annotation_comments| %> +
    + <%= t("legislation.annotations.index.comments_about") %> +
    +
    + <%= annotation.quote %> +
    + + + <%= link_to t("legislation.summary.comments", count: annotation.comments.count), + polymorphic_path(annotation, anchor: "comments") %> + +
    + + <%= render "summary_comments", comments: annotation_comments %> +
    + <% end %> +
    + <% else %> +
    +

    <%= t("legislation.summary.no_allegation") %>

    +
    + <% end %> +
    diff --git a/app/views/legislation/processes/_summary_comments.html.erb b/app/views/legislation/processes/_summary_comments.html.erb new file mode 100644 index 000000000..7e8b61d60 --- /dev/null +++ b/app/views/legislation/processes/_summary_comments.html.erb @@ -0,0 +1,10 @@ +<% if comments.any? %> + <%= t("legislation.summary.most_voted_comments") %> + + <% comments.each do |comment| %> +
    + <%= link_to simple_format(sanitize(comment.body, tags: [])), comment_path(comment) %> +

    <%= t("legislation.summary.votes", count: comment.votes_score) %>

    +
    + <% end %> +<% end %> diff --git a/app/views/legislation/processes/_summary_debate.html.erb b/app/views/legislation/processes/_summary_debate.html.erb new file mode 100644 index 000000000..8530f192d --- /dev/null +++ b/app/views/legislation/processes/_summary_debate.html.erb @@ -0,0 +1,28 @@ +
    +
    +

    <%= t("legislation.summary.debate_phase") %>

    +

    <%= t("legislation.summary.debates", count: questions.count) %>

    +
    + + <% if questions.any? %> +
    + <% questions.each do |question| %> +
    +
    +

    <%= link_to question.title, polymorphic_path(question) %>

    + + <%= link_to t("legislation.summary.comments", count: question.comments.count), + polymorphic_path(question, anchor: "comments") %> + +
    + + <%= render "summary_comments", comments: question.best_comments %> +
    + <% end %> +
    + <% else %> +
    +

    <%= t("legislation.processes.debate.empty_questions") %>

    +
    + <% end %> +
    diff --git a/app/views/legislation/processes/_summary_proposals.html.erb b/app/views/legislation/processes/_summary_proposals.html.erb new file mode 100644 index 000000000..09ccca777 --- /dev/null +++ b/app/views/legislation/processes/_summary_proposals.html.erb @@ -0,0 +1,23 @@ +
    +
    +

    <%= t("legislation.summary.proposals_phase") %>

    +

    <%= t("legislation.summary.proposals", count: proposals.count) %>

    +
    + + <% if proposals.any? %> +
    + <% proposals.sort_by_supports.each do |proposal| %> +
    +

    + <%= link_to proposal.title, polymorphic_path(proposal) %> +

    +

    <%= t("legislation.summary.votes", count: proposal.votes_score) %>

    +
    + <% end %> +
    + <% else %> +
    +

    <%= t("legislation.processes.proposals.empty_proposals") %>

    +
    + <% end %> +
    diff --git a/app/views/legislation/processes/summary.html.erb b/app/views/legislation/processes/summary.html.erb new file mode 100644 index 000000000..81145e8fe --- /dev/null +++ b/app/views/legislation/processes/summary.html.erb @@ -0,0 +1,29 @@ +<% provide(:title) { @process.title } %> + +<%= render "legislation/processes/header", process: @process, header: :full %> + +<%= render "key_dates", process: @process, phase: @phase %> + +<% if @process.debate_phase.enabled? || @process.proposals_phase.enabled? || @process.allegations_phase.enabled? %> +
    + <%= link_to t("legislation.summary.download"), + summary_legislation_process_path(@process, format: :xlsx), + class: "button hollow download-button" %> + + <% if @process.debate_phase.enabled? %> + <%= render "summary_debate", questions: @process.questions %> + <% end %> + + <% if @process.proposals_phase.enabled? %> + <%= render "summary_proposals", proposals: @proposals %> + <% end %> + + <% if @process.allegations_phase.enabled? %> + <%= render "summary_allegations", comments: @comments %> + <% end %> +
    +<% else %> +
    +

    <%= t("legislation.summary.process_empty") %>

    +
    +<% end %> diff --git a/app/views/legislation/processes/summary.xlsx.axlsx b/app/views/legislation/processes/summary.xlsx.axlsx new file mode 100644 index 000000000..97baddc24 --- /dev/null +++ b/app/views/legislation/processes/summary.xlsx.axlsx @@ -0,0 +1,50 @@ +xlsx_package.workbook.add_worksheet(name: "Summary") do |sheet| + +styles = xlsx_package.workbook.styles +title = styles.add_style(b:true) +link = styles.add_style(fg_color: "0000FF", u: true) + + if @process.debate_phase.enabled? && @process.questions.any? + sheet.add_row [t("legislation.summary.debate_phase"), t("legislation.summary.debates", count: @process.questions.count)], style: title + @process.questions.each do |question| + sheet.add_row [question.title, t("legislation.summary.comments", count: question.comments.count)], style: link + sheet.add_hyperlink location: legislation_process_question_url(question.process, question), ref: sheet.rows.last.cells.first + sheet.add_hyperlink location: polymorphic_url(question, anchor: "comments"), ref: sheet.rows.last.cells.last + sheet.add_row [t("legislation.summary.most_voted_comments")] if question.best_comments.any? + question.best_comments.each do |comment| + sheet.add_row [comment.body, t("legislation.summary.votes", count: comment.votes_score)] + sheet.add_hyperlink location: comment_url(comment), ref: sheet.rows.last.cells.first + sheet.rows.last.cells.first.style = link + end + sheet.add_row ["", ""] + end + end + + if @process.proposals_phase.enabled? && @proposals.any? + sheet.add_row [t("legislation.summary.proposals_phase"), t("legislation.summary.proposals", count: @proposals.count)], style: title + @proposals.sort_by_supports.each do |proposal| + sheet.add_row [proposal.title, t("legislation.summary.votes", count: proposal.votes_score)] + sheet.add_hyperlink location: legislation_process_proposal_url(proposal.legislation_process_id, proposal), ref: sheet.rows.last.cells.first + sheet.rows.last.cells.first.style = link + end + sheet.add_row ["", ""] + end + + if @process.allegations_phase.enabled? && @comments.any? + sheet.add_row [t("legislation.summary.allegations_phase"), + t("legislation.summary.top_comments", count: @comments.count)], style: title + @comments.group_by(&:commentable).each do |annotation, annotation_comments| + sheet.add_row [t("legislation.annotations.index.comments_about")] + sheet.add_row [annotation.quote, t("legislation.summary.comments", count: annotation.comments.count)] + sheet.add_hyperlink location: polymorphic_url(annotation, anchor: "comments"), ref: sheet.rows.last.cells.last + sheet.rows.last.cells.last.style = link + + annotation_comments.each do |comment| + sheet.add_row [comment.body, t("legislation.summary.votes", count: comment.votes_score)] + sheet.add_hyperlink location: comment_url(comment), ref: sheet.rows.last.cells.first + sheet.rows.last.cells.first.style = link + end + sheet.add_row ["", ""] + end + end +end diff --git a/config/locales/en/legislation.yml b/config/locales/en/legislation.yml index 967f6d1d9..263dd4662 100644 --- a/config/locales/en/legislation.yml +++ b/config/locales/en/legislation.yml @@ -118,3 +118,32 @@ en: tags_label: "Categories" not_verified: "For vote proposals %{verify_account}." process_title: Collaborative legislation process + summary: + title: "Summary" + votes: + zero: "%{count} votes" + one: "%{count} vote" + other: "%{count} votes" + debate_phase: "Debate phase" + proposals_phase: "Proposals phase" + allegations_phase: "Comments phase" + debates: + zero: "No debates" + one: "%{count} debate" + other: "%{count} debates" + proposals: + zero: "No proposals" + one: "%{count} proposal" + other: "%{count} proposals" + comments: + zero: "No comments" + one: "%{count} comment" + other: "%{count} comments" + download: "Download summary" + top_comments: + zero: "No comments" + one: "%{count} comment" + other: "Top comments" + most_voted_comments: "Most voted comments" + no_allegation: "There are no comments" + process_empty: "This process didn't have any participation phases" diff --git a/config/locales/es/legislation.yml b/config/locales/es/legislation.yml index fe723e250..480fce46b 100644 --- a/config/locales/es/legislation.yml +++ b/config/locales/es/legislation.yml @@ -118,3 +118,32 @@ es: tags_label: "Categorías" not_verified: "Para votar propuestas %{verify_account}." process_title: Proceso de legislación colaborativa + summary: + title: "Resumen" + votes: + zero: "%{count} votos" + one: "%{count} voto" + other: "%{count} votos" + debate_phase: "Fase de debate" + proposals_phase: "Fase de propuestas" + allegations_phase: "Fase de comentarios" + debates: + zero: "No hay debates" + one: "%{count} debate" + other: "%{count} debates" + proposals: + zero: "No hay propuestas" + one: "%{count} propuesta" + other: "%{count} propuestas" + comments: + zero: "No hay comentarios" + one: "%{count} comentario" + other: "%{count} comentarios" + download: "Descargar resumen" + top_comments: + zero: "No hay comentarios" + one: "%{count} comentario" + other: "Los más votados" + most_voted_comments: "Comentarios más votados" + no_allegation: "No hay comentarios" + process_empty: "Este proceso no ha tenido fases de participación" diff --git a/config/routes/legislation.rb b/config/routes/legislation.rb index 2458a2bae..ee92ce26c 100644 --- a/config/routes/legislation.rb +++ b/config/routes/legislation.rb @@ -7,6 +7,7 @@ namespace :legislation do get :result_publication get :proposals get :milestones + get :summary end resources :questions, only: [:show] do diff --git a/spec/controllers/legislation/processes_controller_spec.rb b/spec/controllers/legislation/processes_controller_spec.rb new file mode 100644 index 000000000..c15a293f3 --- /dev/null +++ b/spec/controllers/legislation/processes_controller_spec.rb @@ -0,0 +1,13 @@ +require "rails_helper" + +describe Legislation::ProcessesController do + let(:legislation_process) { create(:legislation_process, end_date: Date.current - 1.day) } + + it "download excel file test" do + create(:legislation_question, process: legislation_process, title: "Question 1") + + get :summary, params: { id: legislation_process, format: :xlsx } + + expect(response).to be_success + end +end diff --git a/spec/models/abilities/administrator_spec.rb b/spec/models/abilities/administrator_spec.rb index bbf8f91fe..c87cc889d 100644 --- a/spec/models/abilities/administrator_spec.rb +++ b/spec/models/abilities/administrator_spec.rb @@ -18,6 +18,10 @@ describe Abilities::Administrator do let(:legislation_question) { create(:legislation_question) } let(:poll_question) { create(:poll_question) } + let(:past_process) { create(:legislation_process, :past) } + let(:past_draft_process) { create(:legislation_process, :past, :not_published) } + let(:open_process) { create(:legislation_process, :open) } + let(:proposal_document) { build(:document, documentable: proposal, user: proposal.author) } let(:budget_investment_document) { build(:document, documentable: budget_investment) } let(:poll_question_document) { build(:document, documentable: poll_question) } @@ -67,6 +71,10 @@ describe Abilities::Administrator do it { should be_able_to(:comment_as_administrator, legislation_question) } it { should_not be_able_to(:comment_as_moderator, legislation_question) } + it { should be_able_to(:summary, past_process) } + it { should_not be_able_to(:summary, past_draft_process) } + it { should_not be_able_to(:summary, open_process) } + it { should be_able_to(:create, Budget) } it { should be_able_to(:update, Budget) } it { should be_able_to(:read_results, Budget) } diff --git a/spec/models/abilities/everyone_spec.rb b/spec/models/abilities/everyone_spec.rb index cfdbbf932..fdc03c74d 100644 --- a/spec/models/abilities/everyone_spec.rb +++ b/spec/models/abilities/everyone_spec.rb @@ -48,4 +48,8 @@ describe Abilities::Everyone do it { should be_able_to(:read_stats, create(:budget, :valuating, stats_enabled: true)) } it { should_not be_able_to(:read_stats, create(:budget, :valuating, stats_enabled: false)) } it { should_not be_able_to(:read_stats, create(:budget, :selecting, stats_enabled: true)) } + + it { should be_able_to(:summary, create(:legislation_process, :past)) } + it { should_not be_able_to(:summary, create(:legislation_process, :open)) } + it { should_not be_able_to(:summary, create(:legislation_process, :past, :not_published)) } end diff --git a/spec/system/legislation/summary_spec.rb b/spec/system/legislation/summary_spec.rb new file mode 100644 index 000000000..880c7ee4e --- /dev/null +++ b/spec/system/legislation/summary_spec.rb @@ -0,0 +1,179 @@ +require "rails_helper" + +describe "Legislation" do + context "process summary page" do + scenario "summary tab is not shown for open processes" do + process = create(:legislation_process, :open) + + visit legislation_process_path(process) + + expect(page).not_to have_content "Summary" + end + + scenario "summary tab is shown por past processes" do + process = create(:legislation_process, :past) + + visit legislation_process_path(process) + + expect(page).to have_content "Summary" + end + end + + scenario "empty process" do + process = create(:legislation_process, :empty, + result_publication_enabled: true, + end_date: Date.current - 1.day + ) + + visit summary_legislation_process_path(process) + + expect(page).to have_content "This process didn't have any participation phases" + end + + scenario "empty phases" do + process = create(:legislation_process, end_date: Date.current - 1.day) + visit summary_legislation_process_path(process) + + expect(page).to have_content "Debate phase" + expect(page).to have_content "No debates" + expect(page).to have_content "There aren't any questions" + + expect(page).to have_content "Proposals phase" + expect(page).to have_content "No proposals" + expect(page).to have_content "There are no proposals" + + expect(page).to have_content "Comments phase" + expect(page).to have_content "No comments" + expect(page).to have_content "There are no comments" + end + + context "only debates exist" do + let(:process) { create(:legislation_process, end_date: Date.current - 1.day) } + let(:user) { create(:user, :level_two) } + + before do + create(:legislation_question, process: process, title: "Question 1") do |question| + create(:comment, user: user, commentable: question, body: "Answer 1") + create(:comment, user: user, commentable: question, body: "Answer 2") + end + + create(:legislation_question, process: process, title: "Question 2") do |question| + create(:comment, user: user, commentable: question, body: "Answer 3") + create(:comment, user: user, commentable: question, body: "Answer 4") + end + end + + scenario "shows debates list" do + visit summary_legislation_process_path(process) + + expect(page).to have_content "Debate phase" + expect(page).to have_content "2 debates" + expect(page).to have_link "Question 1" + expect(page).to have_content "Answer 1" + expect(page).to have_content "Answer 2" + expect(page).to have_link "Question 2" + expect(page).to have_content "Answer 3" + expect(page).to have_content "Answer 4" + + expect(page).to have_content "Proposals phase" + expect(page).to have_content "No proposals" + expect(page).to have_content "There are no proposals" + + expect(page).to have_content "Comments phase" + expect(page).to have_content "No comments" + expect(page).to have_content "There are no comments" + end + end + + context "only proposals exist" do + let(:process) { create(:legislation_process, end_date: Date.current - 1.day) } + + before do + create(:legislation_proposal, legislation_process_id: process.id, + title: "Legislation proposal 1", selected: true) + create(:legislation_proposal, legislation_process_id: process.id, + title: "Legislation proposal 2", selected: false) + create(:legislation_proposal, legislation_process_id: process.id, + title: "Legislation proposal 3", selected: true) + create(:legislation_proposal, legislation_process_id: process.id, + title: "Legislation proposal 4", selected: false) + end + + scenario "shows proposals list" do + visit summary_legislation_process_path(process) + + expect(page).to have_content "Debate phase" + expect(page).to have_content "No debates" + expect(page).to have_content "There aren't any questions" + + expect(page).to have_content "Proposals phase" + expect(page).to have_content "2 proposals" + expect(page).to have_link "Legislation proposal 1" + expect(page).not_to have_content "Legislation proposal 2" + expect(page).to have_link "Legislation proposal 3" + expect(page).not_to have_content "Legislation proposal 4" + + expect(page).to have_content "Comments phase" + expect(page).to have_content "No comments" + expect(page).to have_content "There are no comments" + end + end + + context "only text comments exist" do + let(:process) { create(:legislation_process, end_date: Date.current - 1.day) } + + before do + user = create(:user, :level_two) + draft_version_1 = create(:legislation_draft_version, process: process, + title: "Version 1", body: "Body of the first version", + status: "published") + draft_version_2 = create(:legislation_draft_version, process: process, + title: "Version 2", body: "Body of the second version and that's it all of it", + status: "published") + annotation0 = create(:legislation_annotation, + draft_version: draft_version_1, text: "my annotation123", + ranges: annotation_ranges(5, 10)) + annotation1 = create(:legislation_annotation, + draft_version: draft_version_2, text: "hola", + ranges: annotation_ranges(5, 10)) + annotation2 = create(:legislation_annotation, + draft_version: draft_version_2, + ranges: annotation_ranges(12, 19)) + + create(:comment, user: user, commentable: annotation0, body: "Comment 0") + create(:comment, user: user, commentable: annotation1, body: "Comment 1") + create(:comment, user: user, commentable: annotation2, body: "Comment 2") + create(:comment, user: user, commentable: annotation2, body: "Comment 3") + end + + scenario "shows coments list" do + visit summary_legislation_process_path(process) + + expect(page).to have_content "Debate phase" + expect(page).to have_content "No debates" + expect(page).to have_content "There aren't any questions" + + expect(page).to have_content "Proposals phase" + expect(page).to have_content "No proposals" + expect(page).to have_content "There are no proposals" + + expect(page).to have_content "Comments phase" + expect(page).to have_content "Top comments" + expect(page).not_to have_content "Comment 0" + expect(page).to have_link "Comment 1" + expect(page).to have_link "Comment 2" + expect(page).to have_link "Comment 3" + end + + scenario "excel download" do + visit summary_legislation_process_path(process) + click_link "Download summary" + + expect(page.response_headers["Content-Type"]).to match(/officedocument.spreadsheetml/) + end + end + + def annotation_ranges(start_offset, end_offset) + [{ "start" => "/p[1]", "startOffset" => start_offset, "end" => "/p[1]", "endOffset" => end_offset }] + end +end