diff --git a/Gemfile.lock b/Gemfile.lock index a6437663e..c33459f75 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -199,7 +199,7 @@ GEM terminal-table (>= 1.5.1) initialjs-rails (0.2.0.5) railties (>= 3.1, < 6.0) - invisible_captcha (0.9.2) + invisible_captcha (0.9.3) rails (>= 3.2.0) jquery-fileupload-rails (0.4.7) actionpack (>= 3.1) @@ -251,7 +251,7 @@ GEM mime-types-data (3.2016.0521) mimemagic (0.3.2) mini_portile2 (2.2.0) - minitest (5.10.2) + minitest (5.10.3) mixlib-cli (1.7.0) mixlib-config (2.2.4) multi_json (1.12.1) @@ -368,7 +368,7 @@ GEM rspec-mocks (3.6.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.6.0) - rspec-rails (3.6.0) + rspec-rails (3.6.1) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) @@ -398,7 +398,7 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - savon (2.11.1) + savon (2.11.2) akami (~> 1.2) builder (>= 2.1.2) gyoku (~> 1.2) @@ -430,7 +430,7 @@ GEM babel-source (>= 5.8.11) babel-transpiler sprockets (>= 3.0.0) - sprockets-rails (3.2.0) + sprockets-rails (3.2.1) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) @@ -565,6 +565,5 @@ DEPENDENCIES web-console (~> 3.3.0) whenever (~> 0.9.7) - BUNDLED WITH 1.15.3 diff --git a/app/assets/images/help/help_icon_budgets.png b/app/assets/images/help/help_icon_budgets.png index f8a909d7e..fc5e3022f 100644 Binary files a/app/assets/images/help/help_icon_budgets.png and b/app/assets/images/help/help_icon_budgets.png differ diff --git a/app/assets/images/help/help_icon_debates.png b/app/assets/images/help/help_icon_debates.png index c8d59e4c1..afc729671 100644 Binary files a/app/assets/images/help/help_icon_debates.png and b/app/assets/images/help/help_icon_debates.png differ diff --git a/app/assets/images/help/help_icon_legislation_processes.png b/app/assets/images/help/help_icon_legislation_processes.png index 9dd93ad8c..00872c247 100644 Binary files a/app/assets/images/help/help_icon_legislation_processes.png and b/app/assets/images/help/help_icon_legislation_processes.png differ diff --git a/app/assets/images/help/help_icon_polls.png b/app/assets/images/help/help_icon_polls.png index 503f8642d..b7f7cf479 100644 Binary files a/app/assets/images/help/help_icon_polls.png and b/app/assets/images/help/help_icon_polls.png differ diff --git a/app/assets/images/help/help_icon_proposals.png b/app/assets/images/help/help_icon_proposals.png index 05861d042..e41db1cf8 100644 Binary files a/app/assets/images/help/help_icon_proposals.png and b/app/assets/images/help/help_icon_proposals.png differ diff --git a/app/assets/images/logo_header.png b/app/assets/images/logo_header.png index 9bce3cef8..c178ec781 100644 Binary files a/app/assets/images/logo_header.png and b/app/assets/images/logo_header.png differ diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 6db475365..19c73de32 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -9,6 +9,7 @@ @import 'pages'; @import 'legislation'; @import 'legislation_process'; +@import 'community'; @import 'custom'; @import 'c3'; @import 'annotator.min'; diff --git a/app/assets/stylesheets/community.scss b/app/assets/stylesheets/community.scss new file mode 100644 index 000000000..0dddf4cdb --- /dev/null +++ b/app/assets/stylesheets/community.scss @@ -0,0 +1,44 @@ +.communities-show { + .button.disabled, .button[disabled] { + pointer-events: none; + } + + .wide-order-selector { + margin-top: 0; + } + + .panel { + min-height: auto; + margin: 0.375rem 0; + + .button { + margin-top: $line-height; + } + } +} + +.communities-participant { + + .comment-body { + display: inline-block; + float: left; + margin-right: $line-height; + margin-bottom: $line-height; + } +} + +.topic-show { + + p, + ul li { + margin-bottom: 0; + } + + .comments { + + .first-comment { + margin-top: $line-height; + margin-bottom: $line-height; + } + } +} diff --git a/app/assets/stylesheets/legislation_process.scss b/app/assets/stylesheets/legislation_process.scss index eda341185..2ec9f8ee9 100644 --- a/app/assets/stylesheets/legislation_process.scss +++ b/app/assets/stylesheets/legislation_process.scss @@ -13,37 +13,29 @@ // // 01. Utils -// ----------------- +// --------- + +$grey-heading: #e6e6e6; +$border-dark: darken($border, 10%); .grey-heading { - background: #e6e6e6; + background: $grey-heading; } -$epigraph-font-size: rem-calc(15); -$epigraph-line-height: rem-calc(22); - // 02. Hero -// ----------------- +// -------- + .legislation-hero { - padding-top: 1.5rem; - - @include breakpoint(medium) { - padding-top: 3.5rem; - } - - h4 { - text-transform: uppercase; - } ul { list-style: none; margin-left: 0; li::before { - vertical-align: text-bottom; - padding-right: 0.5rem; - content: '■'; color: #8aa8be; + content: '■'; + padding-right: $line-height / 4; + vertical-align: text-bottom; } } @@ -52,79 +44,33 @@ $epigraph-line-height: rem-calc(22); } .debate-add-info { - margin-top: 3rem; - padding-top: 4rem; - border-top: 1px solid darken($border, 10%); + border-top: 1px solid $border-dark; + margin-top: $line-height; + padding-top: $line-height; - @include breakpoint(medium) { - margin-bottom: 2rem; - } - - .debate-info-wrapper { - - h2 { - font-size: $lead-font-size; - - @include breakpoint(medium) { - float: left; - } - } - } } - .half-gradient { - background: #e6e6e6; - background: linear-gradient(to bottom, #e6e6e6 0%, #e6e6e6 50%, #fff 50%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e6e6e6', endColorstr='#fff', GradientType=0); - } - - .text-center .button { - background: $brand; - margin-bottom: 0; - } - - .headline { - margin-bottom: 1rem; - - @include breakpoint(medium) { - margin-bottom: 4rem; - - } + .title { + font-weight: bold; + text-transform: uppercase; } .description { - margin-bottom: 1rem; - - p { - font-size: $epigraph-font-size; - line-height: $epigraph-line-height; - } - - ul { - font-size: $epigraph-font-size; - line-height: $epigraph-line-height; - } li { - margin-bottom: 1rem; p { display: inline; - margin-bottom: 0; } } - - h4 { - font-size: $base-font-size; - } } .button-subscribe { - margin-top: 1rem; + margin-top: $line-height; @include breakpoint(medium) { + margin-top: $line-height * 2; padding: 0.5em 1em; - margin-top: 3rem; } h3 { @@ -132,8 +78,8 @@ $epigraph-line-height: rem-calc(22); } p { - margin-bottom: 0; font-size: $small-font-size; + margin-bottom: 0; } &:hover h3 { @@ -143,41 +89,21 @@ $epigraph-line-height: rem-calc(22); } // 03. Legislation process navigation -// ----------------- +// ---------------------------------- + .legislation-process-categories { position: relative; .legislation-process-list { border-bottom: 1px solid $medium-gray; margin: 0 1rem 1rem; - padding-top: 4rem; - - @include breakpoint(medium) { - margin-left: 0; - } ul { - position: relative; - max-width: 75rem; - margin-left: auto; - margin-right: auto; + list-style: none; - padding-left: 0; + margin: 0 auto; margin-bottom: 0; - - @include breakpoint(medium) { - padding-left: 1rem; - } - - svg { - position: absolute; - top: 1.25rem; - - @include breakpoint(1280px) { - transform: rotate(-6deg); - left: -1rem; - } - } + padding-left: 0; } li { @@ -187,6 +113,10 @@ $epigraph-line-height: rem-calc(22); transition: all 0.4s; border-bottom: 2px solid transparent; + @include breakpoint(medium) { + margin-left: $line-height * 2; + } + &:first-of-type { margin-left: 0; } @@ -197,29 +127,25 @@ $epigraph-line-height: rem-calc(22); border-bottom: 2px solid $brand; } - @media (min-width: 950px) { - margin: 0 0 0 3rem; - } - a, h4 { display: block; color: #6d6d6d; margin-bottom: 0; } + } - a { - &:hover, - &:active { - text-decoration: none; - } + a { + &:hover, + &:active { + text-decoration: none; + } - p { - margin-bottom: 0; + p { + margin-bottom: 0; - @include breakpoint(medium) { - margin-bottom: 1rem; - } + @include breakpoint(medium) { + margin-bottom: 1rem; } } } @@ -231,7 +157,8 @@ $epigraph-line-height: rem-calc(22); } // 04. Debate list -// ----------------- +// ---------------- + .debate-chooser { padding: 2rem 1rem; @@ -277,38 +204,43 @@ $epigraph-line-height: rem-calc(22); } // 05. Debate quiz -// ----------------- +// --------------- + .debate-questions { + .comments { - margin-top: 4rem; + margin-top: $line-height * 2.5; } .quiz-header { - margin-bottom: 2rem; + margin-bottom: $line-height; .quiz-title, .quiz-next { - padding: 1rem; - height: 6rem; + padding: $line-height; + + @include breakpoint(medium) { + height: $line-height * 4; + } } .quiz-title { background: #e5ecf2; .quiz-header-title { + font-size: $small-font-size; + font-weight: 700; margin-bottom: 0; text-transform: uppercase; - font-weight: 700; - font-size: $small-font-size; } } h4 a { color: $brand; - } - h4 a:hover { - text-decoration: none; + &:hover { + text-decoration: none; + } } .quiz-next-link { @@ -318,57 +250,49 @@ $epigraph-line-height: rem-calc(22); &:active { text-decoration: none; } + } - .quiz-next { - background: #ccdbe5; - font-weight: 700; - color: $brand; - font-size: $small-font-size; - text-align: right; - text-transform: uppercase; - transition: background 0.25s ease-out, background 0.25s ease-out; + .quiz-next { + background: #ccdbe5; + color: $brand; + font-size: $small-font-size; + font-weight: bold; + text-align: right; + text-transform: uppercase; + transition: background 0.25s ease-out, background 0.25s ease-out; - .icon-angle-right { - vertical-align: sub; - } + .icon-angle-right { + vertical-align: middle; + } - &:hover, - &:active { - text-decoration: none; - background: $brand; - color: #fff; - - .icon-angle-right { - color: #fff; - } - } + &:hover, + &:active { + background: $brand; + color: #fff; + text-decoration: none; } } } .quiz-question { - margin-bottom: 2rem; + margin-bottom: $line-height; } .debate-questions { position: relative; list-style: none; - .participation-not-allowed { - padding-bottom: 3rem; - } - .control { - position: relative; - display: inline-block; - color: #555; - cursor: pointer; background: #fff; border: 1px solid $border; - border-radius: 4px; - padding: 0.75rem 2.5rem; - margin-right: 1.5rem; - margin-bottom: 0.5rem; + border-radius: rem-calc(4); + color: #555; + cursor: pointer; + display: inline-block; + margin-bottom: $line-height / 2; + margin-right: $line-height; + padding: $line-height / 2 $line-height * 2; + position: relative; } .active { @@ -409,14 +333,15 @@ $epigraph-line-height: rem-calc(22); } // 06. Legislation draft -// ----------------- +// --------------------- + .debate-draft { padding: 10rem 2rem 15rem; display: block; background: #f2f2f2; button { - height: 90px; + height: rem-calc(90); h3 { margin-bottom: 0; @@ -430,7 +355,8 @@ $epigraph-line-height: rem-calc(22); } // 07. Legislation allegations -// ----------------- +// --------------------------- + .legislation-allegation { padding-top: 1rem; @@ -449,12 +375,12 @@ $epigraph-line-height: rem-calc(22); .button-circle { line-height: 0; padding: 0; - width: 30px; - height: 30px; + width: rem-calc(30); + height: rem-calc(30); border-radius: 50%; span { - padding-left: 1px; + padding-left: rem-calc(1); &::before { line-height: 1.55; @@ -580,7 +506,7 @@ $epigraph-line-height: rem-calc(22); .calc-comments { cursor: pointer; background: #f2f2f2; - width: 50px; + width: rem-calc(50); .draft-panel { .panel-title { @@ -733,7 +659,7 @@ $epigraph-line-height: rem-calc(22); .comments-on { .calc-index { - width: 50px; + width: rem-calc(50); background: #f2f2f2; cursor: pointer; @@ -797,11 +723,11 @@ $epigraph-line-height: rem-calc(22); .comments-box-container { position: absolute; - top: 230px; + top: rem-calc(230); } .comment-box { - width: 375px; + width: rem-calc(375); padding: 1rem; background: #f9f9f9; border: 1px solid $border; @@ -852,7 +778,7 @@ $epigraph-line-height: rem-calc(22); .participation-not-allowed { font-size: 0.875rem; - height: 50px; + height: rem-calc(50); padding: 0.85rem 0.75rem; top: -18px; } @@ -891,7 +817,7 @@ $epigraph-line-height: rem-calc(22); border-right: 1px solid #d0d0d0; border-left: 1px solid #d0d0d0; width: 100%; - height: 200px; + height: rem-calc(200); margin-bottom: 0.5rem; } diff --git a/app/assets/stylesheets/pages.scss b/app/assets/stylesheets/pages.scss index d3db7e9b2..7114b01d6 100644 --- a/app/assets/stylesheets/pages.scss +++ b/app/assets/stylesheets/pages.scss @@ -44,7 +44,8 @@ // 03. Content // ---------------------- -.more-info-content { +.more-info-content, +.communities-show { h3 { color: $brand; diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss index 8d79eca55..e10c0327f 100644 --- a/app/assets/stylesheets/participation.scss +++ b/app/assets/stylesheets/participation.scss @@ -249,7 +249,9 @@ .proposal-form, .budget-investment-form, .spending-proposal-form, -.document-form { +.document-form, +.topic-new, +.topic-form { .icon-debates, .icon-proposals, @@ -298,6 +300,8 @@ } .proposal-form, +.topic-form, +.topic-new, .document-form { .recommendations li::before { @@ -316,7 +320,9 @@ .debate-quiz, .budget-investment-show, .draft-panels, -.debate-questions { +.debate-questions, +.communities-show, +.topic-show { p { word-wrap: break-word; @@ -350,7 +356,8 @@ .debate-info, .proposal-info, .investment-project-info, - .budget-investment-show { + .budget-investment-show, + .topic-info { clear: both; color: $text-medium; font-size: $small-font-size; @@ -627,7 +634,8 @@ .proposal, .investment-project, .budget-investment, -.legislation { +.legislation, +.communities-show { margin: $line-height / 4 0; .panel { @@ -699,7 +707,8 @@ .debate-info, .proposal-info, .investment-project-info, - .budget-investment-info { + .budget-investment-info, + .topic-info { color: $text-medium; font-size: $small-font-size; margin: rem-calc(6) 0 0; @@ -885,17 +894,10 @@ } } -.help-link { - margin-left: $line-height; - position: relative; +.help-header { - &::before { - color: $link; - content: '\4e'; - font-family: 'icons'; - position: absolute; - left: -24px; - top: -2px; + h1 { + font-size: rem-calc(24); } } diff --git a/app/controllers/admin/poll/officer_assignments_controller.rb b/app/controllers/admin/poll/officer_assignments_controller.rb index 1f2a7ca2c..45c9a225a 100644 --- a/app/controllers/admin/poll/officer_assignments_controller.rb +++ b/app/controllers/admin/poll/officer_assignments_controller.rb @@ -32,35 +32,6 @@ class Admin::Poll::OfficerAssignmentsController < Admin::BaseController end end - def create - @officer_assignment = ::Poll::OfficerAssignment.new(booth_assignment: @booth_assignment, - officer_id: create_params[:officer_id], - date: create_params[:date]) - @officer_assignment.final = true if @officer_assignment.date > @booth_assignment.poll.ends_at.to_date - - if @officer_assignment.save - notice = t("admin.poll_officer_assignments.flash.create") - else - notice = t("admin.poll_officer_assignments.flash.error_create") - end - - redirect_params = { poll_id: create_params[:poll_id], officer_id: create_params[:officer_id] } - redirect_to by_officer_admin_poll_officer_assignments_path(redirect_params), notice: notice - end - - def destroy - @officer_assignment = ::Poll::OfficerAssignment.includes(:booth_assignment).find(params[:id]) - - if @officer_assignment.destroy - notice = t("admin.poll_officer_assignments.flash.destroy") - else - notice = t("admin.poll_officer_assignments.flash.error_destroy") - end - - redirect_params = { poll_id: @officer_assignment.poll_id, officer_id: @officer_assignment.officer_id } - redirect_to by_officer_admin_poll_officer_assignments_path(redirect_params), notice: notice - end - private def officer_assignment_params diff --git a/app/controllers/admin/poll/shifts_controller.rb b/app/controllers/admin/poll/shifts_controller.rb new file mode 100644 index 000000000..8a808a7a9 --- /dev/null +++ b/app/controllers/admin/poll/shifts_controller.rb @@ -0,0 +1,53 @@ +class Admin::Poll::ShiftsController < Admin::BaseController + + before_action :load_booth + before_action :load_polls + + def new + load_officers + load_shifts + @shift = ::Poll::Shift.new + end + + def create + @shift = ::Poll::Shift.new(shift_params) + if @shift.save + notice = t("admin.poll_shifts.flash.create") + redirect_to new_admin_booth_shift_path(@shift.booth), notice: notice + else + load_officers + load_shifts + render :new + end + end + + def destroy + @shift = Poll::Shift.find(params[:id]) + @shift.destroy + notice = t("admin.poll_shifts.flash.destroy") + redirect_to new_admin_booth_shift_path(@booth), notice: notice + end + + private + + def load_booth + @booth = ::Poll::Booth.find(params[:booth_id]) + end + + def load_polls + @polls = ::Poll.current_or_incoming + end + + def load_officers + @officers = ::Poll::Officer.all + end + + def load_shifts + @shifts = @booth.shifts + end + + def shift_params + params.require(:shift).permit(:booth_id, :officer_id, :date) + end + +end \ No newline at end of file diff --git a/app/controllers/communities_controller.rb b/app/controllers/communities_controller.rb new file mode 100644 index 000000000..3462c8425 --- /dev/null +++ b/app/controllers/communities_controller.rb @@ -0,0 +1,30 @@ +class CommunitiesController < ApplicationController + + before_action :set_order, :set_community, :load_topics, :load_participants, only: :show + + has_orders %w{newest most_commented oldest}, only: :show + + skip_authorization_check + + def show + redirect_to root_path unless Setting['feature.community'].present? + end + + private + + def set_order + @order = params[:order].present? ? params[:order] : "newest" + end + + def set_community + @community = Community.find(params[:id]) + end + + def load_topics + @topics = @community.topics.send("sort_by_#{@order}").page(params[:page]) + end + + def load_participants + @participants = @community.participants + end +end diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb new file mode 100644 index 000000000..f0e57a383 --- /dev/null +++ b/app/controllers/topics_controller.rb @@ -0,0 +1,55 @@ +class TopicsController < ApplicationController + include CommentableActions + include FlagActions + + before_action :load_community + before_action :load_topic, only: [:show, :edit, :update] + + has_orders %w{most_voted newest oldest}, only: :show + + skip_authorization_check + + def new + @topic = Topic.new + end + + def create + @topic = Topic.new(topic_params.merge(author: current_user, community_id: params[:community_id])) + if @topic.save + redirect_to community_path(@community), notice: I18n.t('flash.actions.create.topic') + else + render :new + end + end + + def show + @commentable = @topic + @comment_tree = CommentTree.new(@commentable, params[:page], @current_order) + set_comment_flags(@comment_tree.comments) + end + + def edit + end + + def update + if @topic.update(topic_params) + redirect_to community_path(@community), notice: t('flash.actions.update.topic') + else + render :edit + end + end + + private + + def topic_params + params.require(:topic).permit(:title, :description) + end + + def load_community + @community = Community.find(params[:community_id]) + end + + def load_topic + @topic = Topic.find(params[:id]) + end +end diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb index 1936f843c..1ab6c9826 100644 --- a/app/helpers/comments_helper.rb +++ b/app/helpers/comments_helper.rb @@ -42,7 +42,7 @@ module CommentsHelper def commentable_path(comment) commentable = comment.commentable - + case comment.commentable_type when "Budget::Investment" budget_investment_path(commentable.budget_id, commentable) @@ -50,6 +50,8 @@ module CommentsHelper legislation_process_question_path(commentable.process, commentable) when "Legislation::Annotation" legislation_process_draft_version_annotation_path(commentable.draft_version.process, commentable.draft_version, commentable) + when "Topic" + community_topic_path(comment.commentable.community, comment.commentable) else commentable end diff --git a/app/helpers/communities_helper.rb b/app/helpers/communities_helper.rb new file mode 100644 index 000000000..1d50c5388 --- /dev/null +++ b/app/helpers/communities_helper.rb @@ -0,0 +1,42 @@ +module CommunitiesHelper + + def community_title(community) + if community.from_proposal? + community.proposal.title + else + investment = Budget::Investment.where(community_id: community.id).first + investment.title + end + end + + def community_text(community) + community.from_proposal? ? t("community.show.title.proposal") : t("community.show.title.investment") + end + + def community_description(community) + community.from_proposal? ? t("community.show.description.proposal") : t("community.show.description.investment") + end + + def is_author?(community, participant) + if community.from_proposal? + community.proposal.author_id == participant.id + else + investment = Budget::Investment.where(community_id: community.id).first + investment.author_id == participant.id + end + end + + def community_back_link_path(community) + if community.from_proposal? + proposal_path(community.proposal) + else + investment = Budget::Investment.where(community_id: community.id).first + budget_investment_path(investment.budget_id, investment) + end + end + + def community_access_text(community) + community.from_proposal? ? t("community.sidebar.description.proposal") : t("community.sidebar.description.investment") + end + +end diff --git a/app/helpers/shifts_helper.rb b/app/helpers/shifts_helper.rb new file mode 100644 index 000000000..37f22a3e2 --- /dev/null +++ b/app/helpers/shifts_helper.rb @@ -0,0 +1,23 @@ +module ShiftsHelper + + def shift_dates_select_options(polls) + options = [] + (start_date(polls)..end_date(polls)).each do |date| + options << [l(date, format: :long), l(date)] + end + options_for_select(options, params[:date]) + end + + def start_date(polls) + polls.map(&:starts_at).min.to_date + end + + def end_date(polls) + polls.map(&:ends_at).max.to_date + end + + def officer_select_options(officers) + officers.collect { |officer| [officer.name, officer.id] } + end + +end diff --git a/app/helpers/topics_helper.rb b/app/helpers/topics_helper.rb new file mode 100644 index 000000000..1d5f1964f --- /dev/null +++ b/app/helpers/topics_helper.rb @@ -0,0 +1,11 @@ +module TopicsHelper + + def disabled_create_topic + "disabled" unless current_user + end + + def disabled_info_title + t("community.show.sidebar.disabled_info_title") unless current_user + end + +end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index b8f80c0cd..db4cee09d 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -33,7 +33,7 @@ module Abilities can :unmark_featured, Debate can :comment_as_administrator, [Debate, Comment, Proposal, Poll::Question, Budget::Investment, - Legislation::Question, Legislation::Annotation] + Legislation::Question, Legislation::Annotation, Topic] can [:search, :create, :index, :destroy], ::Administrator can [:search, :create, :index, :destroy], ::Moderator diff --git a/app/models/abilities/moderator.rb b/app/models/abilities/moderator.rb index 796bb185a..4e1427c12 100644 --- a/app/models/abilities/moderator.rb +++ b/app/models/abilities/moderator.rb @@ -6,7 +6,7 @@ module Abilities merge Abilities::Moderation.new(user) can :comment_as_moderator, [Debate, Comment, Proposal, Budget::Investment, Poll::Question, - Legislation::Question, Legislation::Annotation] + Legislation::Question, Legislation::Annotation, Topic] end end end diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 0dfd7836c..d658e7ab2 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -6,6 +6,7 @@ class Budget include Searchable include Reclassification include Followable + include Communitable include Documentable documentable max_documents_allowed: 3, max_file_size: 3.megabytes, diff --git a/app/models/comment.rb b/app/models/comment.rb index 1db9809ee..8b68e11ad 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -3,7 +3,7 @@ class Comment < ActiveRecord::Base include HasPublicAuthor include Graphqlable - COMMENTABLE_TYPES = %w(Debate Proposal Budget::Investment Poll::Question Legislation::Question Legislation::Annotation).freeze + COMMENTABLE_TYPES = %w(Debate Proposal Budget::Investment Poll::Question Legislation::Question Legislation::Annotation Topic).freeze acts_as_paranoid column: :hidden_at include ActsAsParanoidAliases diff --git a/app/models/community.rb b/app/models/community.rb new file mode 100644 index 000000000..710982200 --- /dev/null +++ b/app/models/community.rb @@ -0,0 +1,39 @@ +class Community < ActiveRecord::Base + has_one :proposal + has_one :investment + has_many :topics + + def participants + users_participants = users_who_commented_by + + users_who_topics_author_by + + author_from_community + users_participants.uniq + end + + def from_proposal? + self.proposal.present? + end + + private + + def users_who_commented_by + topics_ids = topics.pluck(:id) + query = "comments.commentable_id IN (?)and comments.commentable_type = 'Topic'" + User.by_comments(query, topics_ids) + end + + def users_who_topics_author_by + author_ids = topics.pluck(:author_id) + User.by_authors(author_ids) + end + + def author_from_community + if from_proposal? + User.where(id: proposal.author_id) + else + investment = Budget::Investment.where(community_id: id).first + User.where(id: investment.author_id) + end + end + +end diff --git a/app/models/concerns/communitable.rb b/app/models/concerns/communitable.rb new file mode 100644 index 000000000..6f0a10f43 --- /dev/null +++ b/app/models/concerns/communitable.rb @@ -0,0 +1,14 @@ +module Communitable + extend ActiveSupport::Concern + + included do + belongs_to :community + before_create :associate_community + end + + def associate_community + community = Community.create + self.community_id = community.id + end + +end diff --git a/app/models/poll.rb b/app/models/poll.rb index 6d033f514..4ba313963 100644 --- a/app/models/poll.rb +++ b/app/models/poll.rb @@ -35,6 +35,10 @@ class Poll < ActiveRecord::Base ends_at < timestamp end + def self.current_or_incoming + current + incoming + end + def answerable_by?(user) user.present? && user.level_two_or_three_verified? && diff --git a/app/models/poll/booth.rb b/app/models/poll/booth.rb index c7fb63efc..9edbcbaf0 100644 --- a/app/models/poll/booth.rb +++ b/app/models/poll/booth.rb @@ -2,6 +2,7 @@ class Poll class Booth < ActiveRecord::Base has_many :booth_assignments, class_name: "Poll::BoothAssignment" has_many :polls, through: :booth_assignments + has_many :shifts validates :name, presence: true, uniqueness: true diff --git a/app/models/poll/shift.rb b/app/models/poll/shift.rb new file mode 100644 index 000000000..8ee646ea4 --- /dev/null +++ b/app/models/poll/shift.rb @@ -0,0 +1,22 @@ +class Poll + class Shift < ActiveRecord::Base + belongs_to :booth + belongs_to :officer + + validates :booth_id, presence: true + validates :officer_id, presence: true + validates :date, presence: true + validates :date, uniqueness: { scope: [:officer_id, :booth_id] } + + after_create :create_officer_assignments + + def create_officer_assignments + booth.booth_assignments.each do |booth_assignment| + attrs = { officer_id: officer_id, + date: date, + booth_assignment_id: booth_assignment.id } + Poll::OfficerAssignment.create!(attrs) + end + end + end + end \ No newline at end of file diff --git a/app/models/proposal.rb b/app/models/proposal.rb index bb8ddfa29..82aa627cc 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -9,6 +9,7 @@ class Proposal < ActiveRecord::Base include HasPublicAuthor include Graphqlable include Followable + include Communitable include Documentable documentable max_documents_allowed: 3, max_file_size: 3.megabytes, diff --git a/app/models/topic.rb b/app/models/topic.rb new file mode 100644 index 000000000..8c8f3f6c9 --- /dev/null +++ b/app/models/topic.rb @@ -0,0 +1,20 @@ +class Topic < ActiveRecord::Base + include Flaggable + + acts_as_paranoid column: :hidden_at + include ActsAsParanoidAliases + + belongs_to :community + belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' + + has_many :comments, as: :commentable + + validates :title, presence: true + validates :description, presence: true + validates :author, presence: true + + scope :sort_by_newest, -> { order(created_at: :desc) } + scope :sort_by_oldest, -> { order(created_at: :asc) } + scope :sort_by_most_commented, -> { reorder(comments_count: :desc) } + +end diff --git a/app/models/user.rb b/app/models/user.rb index 21b526963..427683298 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -57,11 +57,13 @@ class User < ActiveRecord::Base scope :officials, -> { where("official_level > 0") } scope :newsletter, -> { where(newsletter: true) } scope :for_render, -> { includes(:organization) } - scope :by_document, ->(document_type, document_number) { where(document_type: document_type, document_number: document_number) } + scope :by_document, -> (document_type, document_number) { where(document_type: document_type, document_number: document_number) } scope :email_digest, -> { where(email_digest: true) } scope :active, -> { where(erased_at: nil) } scope :erased, -> { where.not(erased_at: nil) } scope :public_for_api, -> { all } + scope :by_comments, -> (query, topics_ids) { joins(:comments).where(query, topics_ids).uniq } + scope :by_authors, -> (author_ids) { where("users.id IN (?)", author_ids) } before_validation :clean_document_number diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 62638f3b7..b42e717b4 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -73,9 +73,13 @@ <%= link_to t('admin.menu.poll_officers'), admin_officers_path %> -
  • > +
  • > <%= link_to t('admin.menu.poll_booths'), admin_booths_path %>
  • + +
  • > + <%= link_to t('admin.menu.poll_shifts'), admin_booths_path %> +
  • <% end %> diff --git a/app/views/admin/budget_investments/index.html.erb b/app/views/admin/budget_investments/index.html.erb index beb5eb856..e86402fd5 100644 --- a/app/views/admin/budget_investments/index.html.erb +++ b/app/views/admin/budget_investments/index.html.erb @@ -41,4 +41,3 @@
    <%= render '/admin/budget_investments/investments' %>
    - diff --git a/app/views/admin/budgets/index.html.erb b/app/views/admin/budgets/index.html.erb index 87aaa8c66..6d9c4aee7 100644 --- a/app/views/admin/budgets/index.html.erb +++ b/app/views/admin/budgets/index.html.erb @@ -41,4 +41,4 @@ -<%= paginate @budgets %> \ No newline at end of file +<%= paginate @budgets %> diff --git a/app/views/admin/poll/booths/_booth.html.erb b/app/views/admin/poll/booths/_booth.html.erb index 5732400a8..80b1ef38f 100644 --- a/app/views/admin/poll/booths/_booth.html.erb +++ b/app/views/admin/poll/booths/_booth.html.erb @@ -6,6 +6,9 @@ <%= booth.location %> + <%= link_to t("admin.booths.booth.shifts"), + new_admin_booth_shift_path(booth), + class: "button hollow" %> <%= link_to t("admin.actions.edit"), edit_admin_booth_path(booth), class: "button hollow" %> diff --git a/app/views/admin/poll/booths/index.html.erb b/app/views/admin/poll/booths/index.html.erb index 9618aec59..0dbb62cdf 100644 --- a/app/views/admin/poll/booths/index.html.erb +++ b/app/views/admin/poll/booths/index.html.erb @@ -16,6 +16,7 @@ <%= t("admin.booths.index.name") %> <%= t("admin.booths.index.location") %>   +   <% @booths.each do |booth| %> diff --git a/app/views/admin/poll/officer_assignments/by_officer.html.erb b/app/views/admin/poll/officer_assignments/by_officer.html.erb index 6e505040e..8cc6c0437 100644 --- a/app/views/admin/poll/officer_assignments/by_officer.html.erb +++ b/app/views/admin/poll/officer_assignments/by_officer.html.erb @@ -5,35 +5,6 @@

    <%= @officer.name %> - <%= @officer.email %>

    -<%= form_tag(admin_poll_officer_assignments_path(@poll), {id: "officer_assignment_form"}) do %> -
    - <%= t("admin.poll_officer_assignments.by_officer.new_assignment") %> -
    - - <%= select_tag :date, - poll_dates_select_options(@poll) + poll_final_recount_option(@poll), - { prompt: t("admin.poll_officer_assignments.by_officer.select_date"), - label: false } %> -
    - -
    - - <%= select_tag :booth_id, - poll_booths_select_options(@poll), - { prompt: t("admin.poll_officer_assignments.by_officer.select_booth"), - label: false } %> -
    - -
    - <%= hidden_field_tag :officer_id, @officer.id %> - <%= hidden_field_tag :poll_id, @poll.id %> - <%= submit_tag t("admin.poll_officer_assignments.by_officer.add_assignment"), - class: "button expanded hollow margin-top" %> -
    -
    -<% end %> - - <% if @officer_assignments.empty? %>
    <%= t("admin.poll_officer_assignments.by_officer.no_assignments") %> @@ -45,7 +16,6 @@ <%= t("admin.poll_officer_assignments.by_officer.date") %> <%= t("admin.poll_officer_assignments.by_officer.booth") %> - <%= t("admin.poll_officer_assignments.by_officer.assignment") %> @@ -53,12 +23,6 @@ <%= officer_assignment.final? ? t('polls.final_date') : l(officer_assignment.date.to_date) %> <%= booth_name_with_location(officer_assignment.booth_assignment.booth) %> - - <%= link_to t("admin.poll_officer_assignments.by_officer.remove_assignment"), - admin_poll_officer_assignment_path(@poll, officer_assignment), - method: :delete, - class: "button hollow alert" %> - <% end %> @@ -93,6 +57,3 @@ <% end %> - - - diff --git a/app/views/admin/poll/shifts/_shifts.html.erb b/app/views/admin/poll/shifts/_shifts.html.erb new file mode 100644 index 000000000..800c6944b --- /dev/null +++ b/app/views/admin/poll/shifts/_shifts.html.erb @@ -0,0 +1,24 @@ +

    <%= t("admin.poll_shifts.new.assignments") %>

    + + + + + + + + + + <% @shifts.each do |shift| %> + + + + + + <% end %> + +
    <%= t("admin.poll_shifts.new.date") %><%= t("admin.poll_shifts.new.officer") %><%= t("admin.poll_shifts.new.assignment") %>
    <%= l(shift.date.to_date, format: :long) %><%= shift.officer.name %> + <%= link_to t("admin.poll_shifts.new.remove_assignment"), + admin_booth_shift_path(@booth, shift), + method: :delete, + class: "button hollow alert" %> +
    diff --git a/app/views/admin/poll/shifts/new.html.erb b/app/views/admin/poll/shifts/new.html.erb new file mode 100644 index 000000000..c997dc35f --- /dev/null +++ b/app/views/admin/poll/shifts/new.html.erb @@ -0,0 +1,46 @@ +<%= back_link_to admin_booths_path %> + +

    <%= @booth.name %>

    + +<%= form_for @shift, as: :shift, url: admin_booth_shifts_path do |f| %> + <%= render "shared/errors", resource: @shift %> + +
    + + <%= t("admin.poll_shifts.new.new_assignment") %> + + +
    + + <%= f.select :date, + shift_dates_select_options(@polls), + prompt: t("admin.poll_shifts.new.select_date"), + label: false %> +
    + +
    + + <%= f.select :officer_id, + officer_select_options(@officers), + prompt: t("admin.poll_shifts.new.select_officer"), + label: false %> +
    + + <%= f.hidden_field :booth_id, value: @booth.id %> + +
    + <%= f.submit t("admin.poll_shifts.new.add_assignment"), + class: "button expanded hollow margin-top" %> +
    +
    +<% end %> + +
    + <% if @shifts.empty? %> +
    + <%= t("admin.poll_shifts.new.no_assignments") %> +
    + <% else %> + <%= render "shifts" %> + <% end %> +
    \ No newline at end of file diff --git a/app/views/budgets/investments/_investment_show.html.erb b/app/views/budgets/investments/_investment_show.html.erb index 3f1890ae8..db2a2562d 100644 --- a/app/views/budgets/investments/_investment_show.html.erb +++ b/app/views/budgets/investments/_investment_show.html.erb @@ -123,6 +123,8 @@ <%= render 'follows/follow_button', follow: find_or_build_follow(current_user, investment) %> <% end %> + <%= render 'communities/access_button', community: investment.community %> +
    diff --git a/app/views/comments/show.html.erb b/app/views/comments/show.html.erb index 37d379d4f..a779d1dfa 100644 --- a/app/views/comments/show.html.erb +++ b/app/views/comments/show.html.erb @@ -11,4 +11,4 @@ <%= render @comment %> - \ No newline at end of file + diff --git a/app/views/communities/_access_button.html.erb b/app/views/communities/_access_button.html.erb new file mode 100644 index 000000000..6e1a6dc76 --- /dev/null +++ b/app/views/communities/_access_button.html.erb @@ -0,0 +1,8 @@ +<% if feature?("community") %> + +

    <%= t("community.sidebar.title") %>

    +

    + <%= community_access_text(community) %> +

    + <%= link_to t("community.sidebar.button_to_access"), community_path(community.id), class: 'button hollow expanded' %> +<% end %> diff --git a/app/views/communities/_participants.html.erb b/app/views/communities/_participants.html.erb new file mode 100644 index 000000000..931ebf105 --- /dev/null +++ b/app/views/communities/_participants.html.erb @@ -0,0 +1,41 @@ +
    + + + + <% @participants.each do |participant| %> +
    +
    + + <%= avatar_image( participant, seed: participant.id, size: 32, class: 'author-photo') %> + +
    + + + <%= link_to participant.name, user_path(participant)%> + + + <% if is_author?(@community, participant) %> +  •  + + <%= t("comments.comment.author") %> + + <% end %> + +
    + +
    +
    + <% end %> + +
    diff --git a/app/views/communities/show.html.erb b/app/views/communities/show.html.erb new file mode 100644 index 000000000..8190ff6b6 --- /dev/null +++ b/app/views/communities/show.html.erb @@ -0,0 +1,39 @@ +
    + +
    +
    +
    + <%= back_link_to community_back_link_path(@community) %> +

    <%= community_text(@community) %>

    +

    <%= community_title(@community) %>

    +

    <%= community_description(@community) %>

    +
    +
    +
    + +
    + + + +
    +
    + <%= render "topics/topics", topics: @topics %> +
    + <%= paginate @topics %> +
    + + + +
    + +
    + +<%= render 'participants' %> diff --git a/app/views/legislation/annotations/index.html.erb b/app/views/legislation/annotations/index.html.erb index cc67f9f2d..2b8e4d469 100644 --- a/app/views/legislation/annotations/index.html.erb +++ b/app/views/legislation/annotations/index.html.erb @@ -2,7 +2,7 @@ <%= render 'legislation/processes/header', process: @process, header: :small %> -<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations %> +<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations_phase %>
    diff --git a/app/views/legislation/annotations/show.html.erb b/app/views/legislation/annotations/show.html.erb index e85e7ea76..808474269 100644 --- a/app/views/legislation/annotations/show.html.erb +++ b/app/views/legislation/annotations/show.html.erb @@ -2,7 +2,7 @@ <%= render 'legislation/processes/header', process: @process, header: :small %> -<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations %> +<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations_phase %>
    diff --git a/app/views/legislation/draft_versions/changes.html.erb b/app/views/legislation/draft_versions/changes.html.erb index bb3a05d7e..dc6e0aa06 100644 --- a/app/views/legislation/draft_versions/changes.html.erb +++ b/app/views/legislation/draft_versions/changes.html.erb @@ -2,7 +2,7 @@ <%= render 'legislation/processes/header', process: @process, header: :small %> -<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations %> +<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations_phase %>
    diff --git a/app/views/legislation/draft_versions/show.html.erb b/app/views/legislation/draft_versions/show.html.erb index 754d02494..b3067049b 100644 --- a/app/views/legislation/draft_versions/show.html.erb +++ b/app/views/legislation/draft_versions/show.html.erb @@ -2,7 +2,7 @@ <%= render 'legislation/processes/header', process: @process, header: :small %> -<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations %> +<%= render 'legislation/processes/key_dates', process: @process, phase: :allegations_phase %>
    diff --git a/app/views/legislation/processes/_header.html.erb b/app/views/legislation/processes/_header.html.erb index a369f8c88..660c5a5de 100644 --- a/app/views/legislation/processes/_header.html.erb +++ b/app/views/legislation/processes/_header.html.erb @@ -1,5 +1,5 @@ <% if header == :small %> -
    +

    <%= process.title %>

    @@ -9,21 +9,19 @@
    <% if process.description.present? %> -

    <%= t('legislation.processes.header_full.description') %>

    +

    <%= t('legislation.processes.header_full.description') %>

    <%= markdown process.description %> <% end %>
    <% if process.additional_info.present? %>
    -
    - <%= markdown process.additional_info if process.additional_info %> -
    + <%= markdown process.additional_info if process.additional_info %>
    <% end %>
    <% if process.description.present? || process.additional_info.present? %> -
    +
    diff --git a/app/views/legislation/processes/_header_full.html.erb b/app/views/legislation/processes/_header_full.html.erb index a50278c39..7a3e29550 100644 --- a/app/views/legislation/processes/_header_full.html.erb +++ b/app/views/legislation/processes/_header_full.html.erb @@ -1,7 +1,7 @@ -
    +
    -

    <%= t('.title') %>

    + <%= back_link_to legislation_processes_path %>

    <%= process.title %>

    @@ -11,21 +11,19 @@
    <% if process.description.present? %> -

    <%= t('.description') %>

    +

    <%= t('.description') %>

    <%= markdown process.description %> <% end %>
    <% if process.additional_info.present? %>
    -
    - <%= markdown process.additional_info if process.additional_info %> -
    + <%= markdown process.additional_info if process.additional_info %>
    <% end %>
    <% if process.additional_info.present? %> -
    +
    <%= t('.more_info') %> diff --git a/app/views/legislation/processes/_key_dates.html.erb b/app/views/legislation/processes/_key_dates.html.erb index 375be7d51..f1198c2e3 100644 --- a/app/views/legislation/processes/_key_dates.html.erb +++ b/app/views/legislation/processes/_key_dates.html.erb @@ -3,45 +3,45 @@

    <%= t("legislation.processes.shared.key_dates") %>

    + +
      + <% if process.debate_phase.enabled? %> +
    • > + <%= link_to debate_legislation_process_path(process) do %> +

      <%= t('legislation.processes.shared.debate_dates') %>

      +

      <%= format_date(process.debate_start_date) %> - <%= format_date(process.debate_end_date) %>

      + <% end %> +
    • + <% end %> + + <% if process.draft_publication.enabled? %> +
    • > + <%= link_to draft_publication_legislation_process_path(process) do %> +

      <%= t('legislation.processes.shared.draft_publication_date') %>

      +

      <%= format_date(process.draft_publication_date) %>

      + <% end %> +
    • + <% end %> + + <% if process.allegations_phase.enabled? %> +
    • > + <%= link_to allegations_legislation_process_path(process) do %> +

      <%= t('legislation.processes.shared.allegations_dates') %>

      +

      <%= format_date(process.allegations_start_date) %> - <%= format_date(process.allegations_end_date) %>

      + <% end %> +
    • + <% end %> + + <% if process.result_publication.enabled? %> +
    • > + <%= link_to result_publication_legislation_process_path(process) do %> +

      <%= t('legislation.processes.shared.result_publication_date') %>

      +

      <%= format_date(process.result_publication_date) %>

      + <% end %> +
    • + <% end %> +
    - -
      - <% if process.debate_phase.enabled? %> -
    • > - <%= link_to debate_legislation_process_path(process) do %> -

      <%= t('legislation.processes.shared.debate_dates') %>

      -

      <%= format_date(process.debate_start_date) %> - <%= format_date(process.debate_end_date) %>

      - <% end %> -
    • - <% end %> - - <% if process.draft_publication.enabled? %> -
    • > - <%= link_to draft_publication_legislation_process_path(process) do %> -

      <%= t('legislation.processes.shared.draft_publication_date') %>

      -

      <%= format_date(process.draft_publication_date) %>

      - <% end %> -
    • - <% end %> - - <% if process.allegations_phase.enabled? %> -
    • > - <%= link_to allegations_legislation_process_path(process) do %> -

      <%= t('legislation.processes.shared.allegations_dates') %>

      -

      <%= format_date(process.allegations_start_date) %> - <%= format_date(process.allegations_end_date) %>

      - <% end %> -
    • - <% end %> - - <% if process.result_publication.enabled? %> -
    • > - <%= link_to result_publication_legislation_process_path(process) do %> -

      <%= t('legislation.processes.shared.result_publication_date') %>

      -

      <%= format_date(process.result_publication_date) %>

      - <% end %> -
    • - <% end %> -
    diff --git a/app/views/proposals/index.html.erb b/app/views/proposals/index.html.erb index ef3df0faa..154c5f43f 100644 --- a/app/views/proposals/index.html.erb +++ b/app/views/proposals/index.html.erb @@ -93,12 +93,12 @@
    diff --git a/app/views/proposals/show.html.erb b/app/views/proposals/show.html.erb index 523c0961d..177228d76 100644 --- a/app/views/proposals/show.html.erb +++ b/app/views/proposals/show.html.erb @@ -159,6 +159,8 @@ <%= render 'follows/follow_button', follow: find_or_build_follow(current_user, @proposal) %> <% end %> + <%= render 'communities/access_button', community: @proposal.community %> +
    diff --git a/app/views/shared/_section_header.html.erb b/app/views/shared/_section_header.html.erb index 29688b487..ca0476bb9 100644 --- a/app/views/shared/_section_header.html.erb +++ b/app/views/shared/_section_header.html.erb @@ -1,10 +1,12 @@ -
    +
    <%= image_tag "help/help_icon_#{image}.png", alt: t("#{i18n_namespace}.icon_alt"), class: "align-top" %>

    <%= t("#{i18n_namespace}.title") %>

    -

    <%= t("#{i18n_namespace}.description") %>

    - <%= link_to t("#{i18n_namespace}.help"), "#section_help", class: "help-link" %> +

    + <%= t("#{i18n_namespace}.description") %>
    + <%= link_to t("#{i18n_namespace}.help"), "#section_help" %> +

    diff --git a/app/views/shared/_wide_order_selector.html.erb b/app/views/shared/_wide_order_selector.html.erb index d6cda44e6..47144198d 100644 --- a/app/views/shared/_wide_order_selector.html.erb +++ b/app/views/shared/_wide_order_selector.html.erb @@ -5,12 +5,12 @@
    -
    +
    -
    +