Merge branch 'dashboard' into rebase_consul_master

This commit is contained in:
Juan Salvador Pérez García
2018-09-27 09:18:27 +02:00
committed by GitHub
72 changed files with 1825 additions and 536 deletions

View File

@@ -3,6 +3,75 @@
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [0.16.0](https://github.com/consul/consul/compare/v0.15...v0.16) - 2018-07-16
### Added
- **Budgets:** Budgets investment show messages https://github.com/consul/consul/pull/2766
- **Budgets:** Add Valuator Group name validation & related specs https://github.com/consul/consul/pull/2576
- **Budgets:** Investment milestone's project status https://github.com/consul/consul/pull/2706
- **Budgets:** Budget statuses https://github.com/consul/consul/pull/2705
- **Budgets:** Display only selected budget investmests in "Publishing prices" phase https://github.com/consul/consul/pull/2657
- **Budgets:** Budgets see results https://github.com/consul/consul/pull/2620
- **Budgets:** Show 'See Results' button in budget admin panel https://github.com/consul/consul/pull/2632
- **Budgets:** Adds message to selected budget investments https://github.com/consul/consul/pull/2622
- **Budgets:** Fixes Issue \#2604 https://github.com/consul/consul/pull/2614
- **Officing:** Officing not to vote https://github.com/consul/consul/pull/2726
- **Officing:** Officing sidebar menu https://github.com/consul/consul/pull/2725
- **Homepage:** Homepage cards https://github.com/consul/consul/pull/2693
- **Homepage:** Adding homepage header and cards seeds https://github.com/consul/consul/pull/2679
- **Homepage:** Add customization of homepage from admin section https://github.com/consul/consul/pull/2641
- **Globalization:** Allow admin generated content to be translatable https://github.com/consul/consul/pull/2619
- **Recommendations:** Debates and proposals recommendations for users https://github.com/consul/consul/pull/2760
- **Notifications:** Allow author notifications to be moderated https://github.com/consul/consul/pull/2717
- **Configuration:** Document upload setting https://github.com/consul/consul/pull/2585
- **Maintenance:** add proposal image on dev\_seeds task https://github.com/consul/consul/pull/2768
- **Docker:** Add imagemagick package to Docker configuration https://github.com/consul/consul/pull/2655
- **Design/UX:** Legislation help gif https://github.com/consul/consul/pull/2732
### Changed
- **Budgets:** Add valuator groups assigned to investments to admin tables & csv export https://github.com/consul/consul/pull/2592
- **Design/UX:** Adds ballot booths menu on admin https://github.com/consul/consul/pull/2716
- **Design/UX:** Polls UI https://github.com/consul/consul/pull/2765
- **Design/UX:** Manager UI https://github.com/consul/consul/pull/2715
- **Design/UX:** Homepage design https://github.com/consul/consul/pull/2694
- **Design/UX:** Admin UI https://github.com/consul/consul/pull/2666
- **Design/UX:** Minor fixes https://github.com/consul/consul/pull/2665
- **Design/UX:** Homepage layout https://github.com/consul/consul/pull/2663
- **Design/UX:** Admin form improvements https://github.com/consul/consul/pull/2645
- **Maintenance:** Regenerate Gemfile.lock https://github.com/consul/consul/pull/2701
- **Maintenance:** Update Sprockets to fix vulnerability https://github.com/consul/consul/pull/2758
- **Maintenance:** Split spec common actions support helper https://github.com/consul/consul/pull/2653
- **Maintenance:** Split admin settings https://github.com/consul/consul/pull/2650
- **Maintenance:** Update README with production configuration https://github.com/consul/consul/pull/2648
- **Maintenance:** Remove sitemap generator output when running specs https://github.com/consul/consul/pull/2599
- **Maintenance:** Avoid db:dev\_seed log print when run from its test https://github.com/consul/consul/pull/2598
- **Maintenance:** Foundation update https://github.com/consul/consul/pull/2590
- **Docker:** Docker/docker-compose enhancements https://github.com/consul/consul/pull/2661
### Fixed
- **Budgets:** Fix valuation heading filters https://github.com/consul/consul/pull/2578
- **Budgets:** Budgets homepage map fixes https://github.com/consul/consul/pull/2654
- **Budgets:** Display message in budget's index when there are no budgets https://github.com/consul/consul/pull/2575
- **Proposals:** Fix validation error when creating proposals without user verification https://github.com/consul/consul/pull/2775
- **Design/UX:** UI design https://github.com/consul/consul/pull/2733
- **Design/UX:** A11y https://github.com/consul/consul/pull/2724
- **Design/UX:** UI design https://github.com/consul/consul/pull/2608
- **Design/UX:** Fixes admin menu toggle https://github.com/consul/consul/pull/2692
- **Maintenance:** Fix flaky spec: Budget Investments Show milestones https://github.com/consul/consul/pull/2719
- **Maintenance:** Fix flaky specs: Votes Debates and Voting comments Update https://github.com/consul/consul/pull/2734
- **Maintenance:** Fix flaky specs using CKEditor https://github.com/consul/consul/pull/2711
- **Maintenance:** Fix suggestions being requested with every keystroke https://github.com/consul/consul/pull/2708
- **Maintenance:** Fix valuation heading filters https://github.com/consul/consul/pull/2702
- **Maintenance:** Flaky spec: Polls Concerns behaves like notifiable in-app Multiple users commented on my notifiable https://github.com/consul/consul/pull/2699
- **Maintenance:** Fix flaky spec: Proposals Voting Voting proposals on behalf of someone in show view https://github.com/consul/consul/pull/2697
- **Maintenance:** Fix flaky spec: Admin budgets Manage groups and headings Create group https://github.com/consul/consul/pull/2696
- **Maintenance:** Fix flaky specs: Emails Budgets Selected/Unselected investment https://github.com/consul/consul/pull/2695
- **Maintenance:** Fix flaky specs: Officing Results Add/Edit results https://github.com/consul/consul/pull/2712
- **Maintenance:** Add issue template https://github.com/consul/consul/pull/2722
- **Users activity:** Deal gracefully with hidden followable in my activity https://github.com/consul/consul/pull/2752
- **Recommendations:** Deal gracefully with recommendations of hidden proposals https://github.com/consul/consul/pull/2751
- **Maps:** Fix MapLocation json\_data to return mappable ids https://github.com/consul/consul/pull/2613
## [0.15.0](https://github.com/consul/consul/compare/v0.14...v0.15) - 2018-05-23
### Added
@@ -56,7 +125,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- **Social share:** Fixes social share buttons https://github.com/consul/consul/pull/2525
- **Newsletters:** Fixed how newsletters controller and mailer handle recipients https://github.com/consul/consul/pull/2492
- **Newsletters:** Fix UserSegment feasible and undecided investment authors https://github.com/consul/consul/pull/2491
- **Newsletters:** Remove empty emails from user segment usages
- **Newsletters:** Remove empty emails from user segment usages
- **Design:** Mode view https://github.com/consul/consul/pull/2567
- **Design:** Minor fixes https://github.com/consul/consul/pull/2566
- **Design:** Improve Documents list https://github.com/consul/consul/pull/2490
@@ -347,7 +416,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Rails 4.2.6
- Ruby 2.2.3
[Unreleased]: https://github.com/consul/consul/compare/v0.15...consul:master
[Unreleased]: https://github.com/consul/consul/compare/v0.16...consul:master
[0.16.0]: https://github.com/consul/consul/compare/v0.15...v.016
[0.15.0]: https://github.com/consul/consul/compare/v0.14...v0.15
[0.14.0]: https://github.com/consul/consul/compare/v0.13...v0.14
[0.13.0]: https://github.com/consul/consul/compare/v0.12...v0.13

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -83,6 +83,7 @@
//= require clipboard
//= require clipboard_button
//= require best_in_place_initialize
//= require send_admin_notification_alert
var initialize_modules = function() {
App.Comments.initialize();
@@ -130,6 +131,7 @@ var initialize_modules = function() {
App.Globalize.initialize();
App.ClipboardButton.initialize();
App.BestInPlace.initialize();
App.SendAdminNotificationAlert.initialize();
};
$(function(){

View File

@@ -0,0 +1,4 @@
App.SendAdminNotificationAlert =
initialize: ->
$('#js-send-admin_notification-alert').on 'click', ->
confirm(this.dataset.alert);

View File

@@ -1165,6 +1165,17 @@ table {
}
}
.max-headings-label {
color: $text-medium;
font-size: $small-font-size;
margin-left: $line-height / 2;
}
.current-of-max-headings {
color: #000;
font-weight: bold;
}
// 11. Newsletters
// -----------------

View File

@@ -34,6 +34,12 @@
background-color: $brand;
}
html,
body {
height: 100%;
margin: 0;
}
body {
font-size: $base-font-size;
}
@@ -542,6 +548,20 @@ header {
}
}
}
.top-bar-title {
line-height: $line-height;
a img {
height: rem-calc(48);
margin: 0;
width: auto;
@include breakpoint(medium up) {
height: auto;
}
}
}
}
.menu-icon {
@@ -780,8 +800,7 @@ footer {
}
.footer {
background: $border;
border-top: 6px solid $brand;
background: #f1f1f1;
margin-top: $line-height * 2;
padding-top: $line-height;
}
@@ -2483,10 +2502,6 @@ table {
padding: 0 $line-height / 2;
position: relative;
a {
word-wrap: break-word;
}
.icon-document {
color: #007bb7;
display: inline-block;
@@ -2501,6 +2516,10 @@ table {
}
}
.document-link a {
word-wrap: break-word;
}
.additional-document-link {
background: $highlight-soft;
border: 1px solid $highlight;

View File

@@ -0,0 +1,67 @@
class Admin::AdminNotificationsController < Admin::BaseController
def index
@admin_notifications = AdminNotification.all
end
def show
@admin_notification = AdminNotification.find(params[:id])
end
def new
@admin_notification = AdminNotification.new
end
def create
@admin_notification = AdminNotification.new(admin_notification_params)
if @admin_notification.save
notice = t("admin.admin_notifications.create_success")
redirect_to [:admin, @admin_notification], notice: notice
else
render :new
end
end
def edit
@admin_notification = AdminNotification.find(params[:id])
end
def update
@admin_notification = AdminNotification.find(params[:id])
if @admin_notification.update(admin_notification_params)
notice = t("admin.admin_notifications.update_success")
redirect_to [:admin, @admin_notification], notice: notice
else
render :edit
end
end
def destroy
@admin_notification = AdminNotification.find(params[:id])
@admin_notification.destroy
notice = t("admin.admin_notifications.delete_success")
redirect_to admin_admin_notifications_path, notice: notice
end
def deliver
@admin_notification = AdminNotification.find(params[:id])
if @admin_notification.valid?
@admin_notification.deliver
flash[:notice] = t("admin.admin_notifications.send_success")
else
flash[:error] = t("admin.segment_recipient.invalid_recipients_segment")
end
redirect_to [:admin, @admin_notification]
end
private
def admin_notification_params
params.require(:admin_notification).permit(:title, :body, :link, :segment_recipient)
end
end

View File

@@ -84,12 +84,8 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
end
def load_investments
@investments = if params[:title_or_id].present?
Budget::Investment.search_by_title_or_id(params)
else
Budget::Investment.scoped_filter(params, @current_filter)
.order(sort_by(params[:sort_by]))
end
@investments = Budget::Investment.scoped_filter(params, @current_filter)
.order(sort_by(params[:sort_by]))
@investments = @investments.page(params[:page]) unless request.format.csv?
end

View File

@@ -32,7 +32,11 @@ module Budgets
respond_to :html, :js
def index
@investments = investments.page(params[:page]).per(10).for_render
if @budget.finished?
@investments = investments.winners.page(params[:page]).per(10).for_render
else
@investments = investments.page(params[:page]).per(10).for_render
end
@investment_ids = @investments.pluck(:id)
load_investment_votes(@investments)
@@ -112,8 +116,9 @@ module Budgets
def set_random_seed
if params[:order] == 'random' || params[:order].blank?
seed = params[:random_seed] || session[:random_seed] || rand(-100000..100000)
params[:random_seed] ||= Float(seed) rescue 0
seed = params[:random_seed] || session[:random_seed] || rand
params[:random_seed] = seed
session[:random_seed] = params[:random_seed]
else
params[:random_seed] = nil
end

View File

@@ -12,7 +12,7 @@ class InstallationController < ApplicationController
def consul_installation_details
{
release: 'v0.15'
release: 'v0.16'
}.merge(features: settings_feature_flags)
end
@@ -21,4 +21,3 @@ class InstallationController < ApplicationController
end
end

View File

@@ -44,7 +44,11 @@ class NotificationsController < ApplicationController
when "Topic"
community_topic_path @notification.linkable_resource.community, @notification.linkable_resource
else
url_for @notification.linkable_resource
if @notification.linkable_resource.is_a?(AdminNotification)
@notification.linkable_resource.link || notifications_path
else
url_for @notification.linkable_resource
end
end
end

View File

@@ -0,0 +1,11 @@
module AdminBudgetInvestmentsHelper
def advanced_menu_visibility
(params[:advanced_filters].empty? && params["max_per_heading"].blank?) ? 'hide' : ''
end
def init_advanced_menu
params[:advanced_filters] = [] unless params[:advanced_filters]
end
end

View File

@@ -0,0 +1,44 @@
class AdminNotification < ActiveRecord::Base
include Notifiable
validates :title, presence: true
validates :body, presence: true
validates :segment_recipient, presence: true
validate :validate_segment_recipient
before_validation :complete_link_url
def list_of_recipients
UserSegments.send(segment_recipient) if valid_segment_recipient?
end
def valid_segment_recipient?
segment_recipient && UserSegments.respond_to?(segment_recipient)
end
def draft?
sent_at.nil?
end
def list_of_recipients_count
list_of_recipients.try(:count) || 0
end
def deliver
list_of_recipients.each { |user| Notification.add(user, self) }
self.update(sent_at: Time.current, recipients_count: list_of_recipients.count)
end
private
def validate_segment_recipient
errors.add(:segment_recipient, :invalid) unless valid_segment_recipient?
end
def complete_link_url
return unless link.present?
unless self.link[/\Ahttp:\/\//] || self.link[/\Ahttps:\/\//]
self.link = "http://#{self.link}"
end
end
end

View File

@@ -146,6 +146,8 @@ class Budget < ActiveRecord::Base
%w{random}
when 'publishing_prices', 'balloting', 'reviewing_ballots'
%w{random price}
when 'finished'
%w{random}
else
%w{random confidence_score}
end
@@ -193,5 +195,3 @@ class Budget < ActiveRecord::Base
slug.nil? || drafting?
end
end

View File

@@ -109,14 +109,15 @@ class Budget
budget = Budget.find_by(slug: params[:budget_id]) || Budget.find_by(id: params[:budget_id])
results = Investment.by_budget(budget)
results = limit_results(budget, params, results) if params[:max_per_heading].present?
results = results.where(group_id: params[:group_id]) if params[:group_id].present?
results = results.by_tag(params[:tag_name]) if params[:tag_name].present?
results = results.by_heading(params[:heading_id]) if params[:heading_id].present?
results = results.by_valuator(params[:valuator_id]) if params[:valuator_id].present?
results = results.by_valuator_group(params[:valuator_group_id]) if params[:valuator_group_id].present?
results = results.by_admin(params[:administrator_id]) if params[:administrator_id].present?
results = advanced_filters(params, results) if params[:advanced_filters].present?
results = limit_results(budget, params, results) if params[:max_per_heading].present?
results = results.where(group_id: params[:group_id]) if params[:group_id].present?
results = results.by_tag(params[:tag_name]) if params[:tag_name].present?
results = results.by_heading(params[:heading_id]) if params[:heading_id].present?
results = results.by_valuator(params[:valuator_id]) if params[:valuator_id].present?
results = results.by_valuator_group(params[:valuator_group_id]) if params[:valuator_group_id].present?
results = results.by_admin(params[:administrator_id]) if params[:administrator_id].present?
results = advanced_filters(params, results) if params[:advanced_filters].present?
results = search_by_title_or_id(params[:title_or_id].strip, results) if params[:title_or_id]
results = results.send(current_filter) if current_filter.present?
results.includes(:heading, :group, :budget, administrator: :user, valuators: :user)
@@ -143,11 +144,12 @@ class Budget
results.where("budget_investments.id IN (?)", ids)
end
def self.search_by_title_or_id(params)
results = Investment.where(budget_id: params[:budget_id])
return results.where(id: params[:title_or_id]) if params[:title_or_id] =~ /\A[0-9]+\z/
results.where("title ILIKE ?", "%#{params[:title_or_id].strip}%")
def self.search_by_title_or_id(title_or_id, results)
if title_or_id =~ /^[0-9]+$/
results.where(id: title_or_id)
else
results.where("title ILIKE ?", "%#{title_or_id}%")
end
end
def searchable_values

View File

@@ -16,16 +16,18 @@ class Budget::Investment::Exporter
def headers
[
I18n.t("admin.budget_investments.index.table_id"),
I18n.t("admin.budget_investments.index.table_title"),
I18n.t("admin.budget_investments.index.table_supports"),
I18n.t("admin.budget_investments.index.table_admin"),
I18n.t("admin.budget_investments.index.table_valuator"),
I18n.t("admin.budget_investments.index.table_valuation_group"),
I18n.t("admin.budget_investments.index.table_geozone"),
I18n.t("admin.budget_investments.index.table_feasibility"),
I18n.t("admin.budget_investments.index.table_valuation_finished"),
I18n.t("admin.budget_investments.index.table_selection")
I18n.t("admin.budget_investments.index.list.id"),
I18n.t("admin.budget_investments.index.list.title"),
I18n.t("admin.budget_investments.index.list.supports"),
I18n.t("admin.budget_investments.index.list.admin"),
I18n.t("admin.budget_investments.index.list.valuator"),
I18n.t("admin.budget_investments.index.list.valuation_group"),
I18n.t("admin.budget_investments.index.list.geozone"),
I18n.t("admin.budget_investments.index.list.feasibility"),
I18n.t("admin.budget_investments.index.list.valuation_finished"),
I18n.t("admin.budget_investments.index.list.selected"),
I18n.t("admin.budget_investments.index.list.visible_to_valuators"),
I18n.t("admin.budget_investments.index.list.author_username")
]
end
@@ -40,7 +42,9 @@ class Budget::Investment::Exporter
investment.heading.name,
price(investment),
investment.valuation_finished? ? I18n.t('shared.yes') : I18n.t('shared.no'),
investment.selected? ? I18n.t('shared.yes') : I18n.t('shared.no')
investment.selected? ? I18n.t('shared.yes') : I18n.t('shared.no'),
investment.visible_to_valuators? ? I18n.t('shared.yes') : I18n.t('shared.no'),
investment.author.username
]
end

View File

@@ -53,9 +53,19 @@ class Notification < ActiveRecord::Base
"proposal_notification"
when "Comment"
"replies_to"
when "AdminNotification"
nil
else
"comments_on"
end
end
end
def link
if notifiable.is_a?(AdminNotification) && notifiable.link.blank?
nil
else
self
end
end
end

View File

@@ -39,12 +39,12 @@ class Proposal < ActiveRecord::Base
validates :question, presence: true
validates :summary, presence: true
validates :author, presence: true
validates :responsible_name, presence: true
validates :responsible_name, presence: true, unless: :skip_user_verification?
validates :title, length: { in: 4..Proposal.title_max_length }
validates :description, length: { maximum: Proposal.description_max_length }
validates :question, length: { in: 10..Proposal.question_max_length }
validates :responsible_name, length: { in: 6..Proposal.responsible_name_max_length }
validates :responsible_name, length: { in: 6..Proposal.responsible_name_max_length }, unless: :skip_user_verification?
validates :retired_reason, inclusion: { in: RETIRE_OPTIONS, allow_nil: true }
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
@@ -232,6 +232,10 @@ class Proposal < ActiveRecord::Base
return orders
end
def skip_user_verification?
Setting["feature.user.skip_verification"].present?
end
protected
def set_responsible_name

View File

@@ -79,18 +79,21 @@
</li>
<% end %>
<% messages_sections = %w(newsletters emails_download) %>
<% messages_menu_active = messages_sections.include?(controller_name) %>
<li class="section-title" <%= "class=is-active" if messages_menu_active %>>
<% newsletters_notifications_sections = %w(newsletters emails_download admin_notifications) %>
<% newsletters_menu_active = newsletters_notifications_sections.include?(controller_name) %>
<li class="section-title" <%= "class=active" if newsletters_menu_active %>>
<a href="#">
<span class="icon-zip"></span>
<strong><%= t("admin.menu.emails") %></strong>
<strong><%= t("admin.menu.newsletters_and_notifications") %></strong>
</a>
<ul <%= "class=is-active" if messages_menu_active %>>
<li <%= "class=is-active" if controller_name == "newsletters" %>>
<ul id="newsletters_and_notifications_menu" <%= "class=is-active" if newsletters_menu_active %>>
<li <%= "class=active" if controller_name == "newsletters" %>>
<%= link_to t("admin.menu.newsletters"), admin_newsletters_path %>
</li>
<li <%= "class=is-active" if controller_name == "emails_download" %>>
<li <%= "class=active" if controller_name == "admin_notifications" %>>
<%= link_to t("admin.menu.admin_notifications"), admin_admin_notifications_path %>
</li>
<li <%= "class=active" if controller_name == "emails_download" %>>
<%= link_to t("admin.menu.emails_download"), admin_emails_download_index_path %>
</li>
</ul>
@@ -231,7 +234,6 @@
<li <%= "class=is-active" if controller_name == "content_blocks" %>>
<%= link_to t("admin.menu.site_customization.content_blocks"), admin_site_customization_content_blocks_path%>
</li>
</ul>
</li>
<li class="section-title">

View File

@@ -0,0 +1,13 @@
<%= form_for [:admin, @admin_notification] do |f| %>
<%= render 'shared/errors', resource: @admin_notification %>
<%= f.select :segment_recipient, options_for_select(user_segments_options,
@admin_notification[:segment_recipient]) %>
<%= f.text_field :title %>
<%= f.text_field :link %>
<%= f.text_area :body %>
<div class="margin-top">
<%= f.submit class: "button success" %>
</div>
<% end %>

View File

@@ -0,0 +1,4 @@
<%= back_link_to %>
<h2><%= t("admin.admin_notifications.edit.section_title") %></h2>
<%= render "form" %>

View File

@@ -0,0 +1,56 @@
<h2 class="inline-block"><%= t("admin.admin_notifications.index.section_title") %></h2>
<%= link_to t("admin.admin_notifications.index.new_notification"), new_admin_admin_notification_path,
class: "button float-right" %>
<% if @admin_notifications.any? %>
<table id="admin_notifications">
<thead>
<tr>
<th><%= t("admin.admin_notifications.index.title") %></th>
<th><%= t("admin.admin_notifications.index.segment_recipient") %></th>
<th><%= t("admin.admin_notifications.index.sent") %></th>
<th class="small-5 text-right"><%= t("admin.admin_notifications.index.actions") %></th>
</tr>
</thead>
<tbody>
<% @admin_notifications.order(created_at: :desc).each do |admin_notification| %>
<tr id="<%= dom_id(admin_notification) %>" class="admin_notification">
<td>
<%= admin_notification.title %>
</td>
<td>
<%= segment_name(admin_notification.segment_recipient) %>
</td>
<td>
<% if admin_notification.draft? %>
<%= t("admin.admin_notifications.index.draft") %>
<% else %>
<%= l admin_notification.sent_at.to_date %>
<% end %>
</td>
<td class="text-right">
<% if admin_notification.draft? %>
<%= link_to t("admin.admin_notifications.index.edit"),
edit_admin_admin_notification_path(admin_notification),
method: :get, class: "button hollow" %>
<%= link_to t("admin.admin_notifications.index.delete"),
admin_admin_notification_path(admin_notification),
method: :delete, class: "button hollow alert" %>
<%= link_to t("admin.admin_notifications.index.preview"),
admin_admin_notification_path(admin_notification),
class: "button" %>
<% else %>
<%= link_to t("admin.admin_notifications.index.view"),
admin_admin_notification_path(admin_notification),
class: "button" %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<div data-alert class="callout primary margin-top clear">
<%= t("admin.admin_notifications.index.empty_notifications") %>
</div>
<% end %>

View File

@@ -0,0 +1,4 @@
<%= back_link_to %>
<h2><%= t("admin.admin_notifications.new.section_title") %></h2>
<%= render "form" %>

View File

@@ -0,0 +1,77 @@
<%= back_link_to admin_admin_notifications_path %>
<h2><%= t("admin.admin_notifications.show.section_title") %></h2>
<div class="small-12 column">
<div class="callout highlight">
<div class="row">
<div class="small-12 medium-6 column">
<strong><%= t("admin.admin_notifications.show.sent_at") %></strong><br>
<% if @admin_notification.draft? %>
<%= t("admin.admin_notifications.index.draft") %>
<% else %>
<%= l(@admin_notification.sent_at.to_date) %>
<% end %>
</div>
<div class="small-12 medium-6 column">
<strong><%= t("admin.admin_notifications.show.title") %></strong><br>
<%= @admin_notification.title %>
</div>
</div>
<div class="row">
<div class="small-12 medium-6 column">
<strong><%= t("admin.admin_notifications.show.body") %></strong><br>
<%= @admin_notification.body %>
</div>
<div class="small-12 medium-6 column">
<strong><%= t("admin.admin_notifications.show.link") %></strong><br>
<%= @admin_notification.link %>
</div>
</div>
<div class="row">
<div class="small-12 column">
<strong><%= t("admin.admin_notifications.show.segment_recipient") %></strong><br>
<%= segment_name(@admin_notification.segment_recipient) %>
<% if @admin_notification.draft? %>
<%= t("admin.admin_notifications.show.will_get_notified",
n: @admin_notification.list_of_recipients_count) %>
<% else %>
<%= t("admin.admin_notifications.show.got_notified",
n: @admin_notification.recipients_count) %>
<% end %>
</div>
</div>
</div>
<p class="help-text" id="phase-description-help-text">
<% if @admin_notification.draft? %>
<%= t("admin.admin_notifications.show.preview_guide") %>
<% else %>
<%= t("admin.admin_notifications.show.sent_guide") %>
<% end %>
</p>
<hr>
<div class="admin_notification-body-content">
<ul class="no-bullet clear notifications-list">
<li class="notification unread">
<% locals = { notification: nil,
title: @admin_notification.title,
body: @admin_notification.body,
timestamp: Time.current } %>
<% link_text = render partial: '/notifications/notification_body', locals: locals %>
<%= link_to_if @admin_notification.link.present?, link_text, @admin_notification.link %>
</li>
</ul>
</div>
<hr>
</div>
<% if @admin_notification.draft? && @admin_notification.valid_segment_recipient? %>
<%= link_to t("admin.admin_notifications.show.send"),
deliver_admin_admin_notification_path(@admin_notification),
"data-alert": t("admin.admin_notifications.show.send_alert",
n: @admin_notification.list_of_recipients_count),
method: :post,
id: "js-send-admin_notification-alert",
class: "button success" %>
<% end %>

View File

@@ -2,5 +2,6 @@
$("#group-form-<%= @group.id %>").html('<%= j render("admin/budgets/group_form", group: @group, budget: @group.budget, button_title: t("admin.budgets.form.submit"), id: "group-form-#{@group.id}", css_class: "group-toggle-#{@group.id}" ) %>');
<% else %>
$("#group-name-<%= @group.id %>").html('<%= @group.name %>')
$("#max-heading-label-<%=@group.id%>").html('<%= j render("admin/budgets/max_headings_label", current: @group.max_votable_headings, max: @group.headings.count, group: @group) %>')
$(".group-toggle-<%= @group.id %>").toggle()
<% end %>

View File

@@ -1,45 +0,0 @@
<%= link_to "#advanced_filters_content",
data: {toggle: "advanced_filters"},
class: "advanced-filters float-right clear" do %>
<%= t("admin.budget_investments.index.advanced_filters") %>
<% end %>
<div id="advanced_filters" class="row expanded advanced-filters-content hide" data-toggler=".hide">
<%= form_tag(admin_budget_budget_investments_path(budget: @budget,
filter: params[:filter],
sort_by: params[:sort_by],
max_per_heading: params[:max_per_heading],
advanced_filters: params[:advanced_filters],
page: 1), method: :get, remote: true, enforce_utf8: false) do %>
<div class="small-12 medium-8 large-10 column">
<span class="filter">
<%= check_box_tag "advanced_filters[]", "feasible" %>
<%= t("#{i18n_namespace}.filters.feasible") %>
</span>
<span class="filter">
<%= check_box_tag "advanced_filters[]", "selected" %>
<%= t("#{i18n_namespace}.filters.selected") %>
</span>
<span class="filter">
<%= check_box_tag "advanced_filters[]", "undecided" %>
<%= t("#{i18n_namespace}.filters.undecided") %>
</span>
<span class="filter">
<%= check_box_tag "advanced_filters[]", "unfeasible" %>
<%= t("#{i18n_namespace}.filters.unfeasible") %>
</span>
<span class="filter">
<strong><%= t("#{i18n_namespace}.filters.max_per_heading") %></strong>
<%= text_field_tag :max_per_heading %>
</span>
</div>
<div class="small-12 medium-4 large-2 column">
<%= submit_tag t("admin.budget_investments.index.buttons.filter"), class: "button expanded" %>
</div>
<% end %>
</div>

View File

@@ -35,21 +35,21 @@
<table class="table-for-mobile">
<thead>
<tr>
<th><%= t("admin.budget_investments.index.table_id") %></th>
<th class="small-3"><%= t("admin.budget_investments.index.table_title") %></th>
<th><%= t("admin.budget_investments.index.table_supports") %></th>
<th><%= t("admin.budget_investments.index.table_admin") %></th>
<th><%= t("admin.budget_investments.index.list.id") %></th>
<th class="small-3"><%= t("admin.budget_investments.index.list.title") %></th>
<th><%= t("admin.budget_investments.index.list.supports") %></th>
<th><%= t("admin.budget_investments.index.list.admin") %></th>
<th>
<%= t("admin.budget_investments.index.table_valuation_group") %>
<%= t("admin.budget_investments.index.table_valuator") %>
<%= t("admin.budget_investments.index.list.valuation_group") %>
<%= t("admin.budget_investments.index.list.valuator") %>
</th>
<th><%= t("admin.budget_investments.index.table_geozone") %></th>
<th><%= t("admin.budget_investments.index.table_feasibility") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.table_valuation_finished") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.table_evaluation") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.table_selection") %></th>
<th><%= t("admin.budget_investments.index.list.geozone") %></th>
<th><%= t("admin.budget_investments.index.list.feasibility") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.list.valuation_finished") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.list.visible_to_valuators") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.list.selected") %></th>
<% if params[:filter] == "selected" %>
<th class="text-center"><%= t("admin.budget_investments.index.table_incompatible") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.list.incompatible") %></th>
<% end %>
</tr>
</thead>

View File

@@ -1,12 +1,61 @@
<div class="small-12 medium-6">
<%= form_for(Budget::Investment.new, url: admin_budget_budget_investments_path(budget: @budget),
method: :get,
remote: true) do |f| %>
<div class="input-group">
<%= text_field_tag :title_or_id, "", placeholder: t("admin.budget_investments.index.placeholder") %>
<div class="input-group-button">
<%= f.submit t("admin.budget_investments.index.buttons.search"), class: "button" %>
<% init_advanced_menu %>
<%= form_tag(admin_budget_budget_investments_path(budget: @budget), method: :get, enforce_utf8: false) do %>
<div class="row">
<div class="small-12 medium-8 large-12 column">
<%= link_to "#advanced_filters_content",
data: {toggle: "advanced_filters"},
class: "advanced-filters float-right clear" do %>
<%= t("admin.budget_investments.index.advanced_filters") %>
<% end %>
</div>
</div>
<div id="advanced_filters" class="row advanced-filters-content <%= advanced_menu_visibility %>" data-toggler=".hide">
<div class="small-12 medium-8 large-12 column">
<% ["feasible", "selected", "undecided", "unfeasible"].each do |option| %>
<div class="filter">
<%= check_box_tag "advanced_filters[]", option, params[:advanced_filters].index(option), id: "advanced_filters_#{option}" %>
<%= t("admin.budget_investments.index.filters.#{option}") %>
</div>
<% end %>
<div class="filter">
<%= text_field_tag :max_per_heading, params["max_per_heading"], placeholder: t("admin.budget_investments.index.filters.max_per_heading") %>
</div>
</div>
<% end %>
</div>
</div>
<div class="row" >
<div class="small-12 medium-3 column">
<%= select_tag :administrator_id,
options_for_select(admin_select_options, params[:administrator_id]),
{ prompt: t("admin.budget_investments.index.administrator_filter_all"),
label: false} %>
</div>
<div class="small-12 medium-3 column">
<%= select_tag :valuator_or_group_id,
options_for_select(valuator_or_group_select_options, params[:valuator_or_group_id]),
{ prompt: t("admin.budget_investments.index.valuator_filter_all"),
label: false} %>
</div>
<div class="small-12 medium-3 column">
<%= select_tag :heading_id,
options_for_select(budget_heading_select_options(@budget), params[:heading_id]),
{ prompt: t("admin.budget_investments.index.heading_filter_all"),
label: false} %>
</div>
<div class="small-12 medium-3 column">
<%= select_tag :tag_name,
options_for_select(investment_tags_select_options(@budget), params[:tag_name]),
{ prompt: t("admin.budget_investments.index.tags_filter_all"),
label: false} %>
</div>
</div>
<div class="row" >
<div class="small-12 medium-6 column">
<div class="input-group">
<%= text_field_tag :title_or_id, params["title_or_id"], placeholder: t("admin.budget_investments.index.placeholder") %>
</div>
</div>
<div class="small-12 medium-6 column">
<%= submit_tag t("admin.budget_investments.index.buttons.filter"), class: "button expanded" %>
</div>
</div>
<% end %>

View File

@@ -8,42 +8,6 @@
<%= render "search_form" %>
<%= form_tag(admin_budget_budget_investments_path(budget: @budget), method: :get, enforce_utf8: false) do %>
<div class="small-12 medium-3 column">
<%= select_tag :administrator_id,
options_for_select(admin_select_options, params[:administrator_id]),
{ prompt: t("admin.budget_investments.index.administrator_filter_all"),
label: false,
class: "js-submit-on-change" } %>
</div>
<div class="small-12 medium-3 column">
<%= select_tag :valuator_or_group_id,
options_for_select(valuator_or_group_select_options, params[:valuator_or_group_id]),
{ prompt: t("admin.budget_investments.index.valuator_filter_all"),
label: false,
class: "js-submit-on-change" } %>
</div>
<div class="small-12 medium-3 column">
<%= select_tag :heading_id,
options_for_select(budget_heading_select_options(@budget), params[:heading_id]),
{ prompt: t("admin.budget_investments.index.heading_filter_all"),
label: false,
class: "js-submit-on-change" } %>
</div>
<div class="small-12 medium-3 column">
<%= select_tag :tag_name,
options_for_select(investment_tags_select_options(@budget), params[:tag_name]),
{ prompt: t("admin.budget_investments.index.tags_filter_all"),
label: false,
class: "js-submit-on-change" } %>
</div>
<% end %>
<%= render "advanced_filters", i18n_namespace: "admin.budget_investments.index" %>
<%= render "/shared/filter_subnav", i18n_namespace: "admin.budget_investments.index" %>
<div id="investments">

View File

@@ -3,6 +3,9 @@
<tr>
<th colspan="4" class="with-button">
<%= content_tag(:span, group.name, class:"group-toggle-#{group.id}", id:"group-name-#{group.id}") %>
<%= content_tag(:span, (render 'admin/budgets/max_headings_label', current: group.max_votable_headings, max: group.headings.count, group: group if group.max_votable_headings), class:"max-headings-label group-toggle-#{group.id}", id:"max-heading-label-#{group.id}") %>
<%= render 'admin/budgets/group_form', budget: @budget, group: group, id: "group-form-#{group.id}", button_title: t("admin.budgets.form.submit"), css_class: "group-toggle-#{group.id}" %>
<%= link_to t("admin.budgets.form.edit_group"), "#", class: "button float-right js-toggle-link hollow", data: { "toggle-selector" => ".group-toggle-#{group.id}" } %>
<%= link_to t("admin.budgets.form.add_heading"), "#", class: "button float-right js-toggle-link", data: { "toggle-selector" => "#group-#{group.id}-new-heading-form" } %>

View File

@@ -0,0 +1,5 @@
<%= t("admin.budgets.form.max_votable_headings")%>
<%= content_tag(:strong,
t('admin.budgets.form.current_of_max_headings', current: current, max: max ),
class:"current-of-max-headings") %>

View File

@@ -10,68 +10,47 @@
</div>
<div class="row">
<div class="title-bar" data-responsive-toggle="responsive_menu" data-hide-for="medium">
<button class="menu-icon" type="button" data-toggle="responsive_menu"></button>
<div class="title-bar-title"><%= t("application.menu")%></div>
</div>
<div class="top-bar">
<ul class="menu show-for-small-only">
<li class="menu-text">
<%= link_to root_path, accesskey: "0" do %>
<%= image_tag(image_path_for("logo_header.png"),
class: "float-left",
size: "48x48",
alt: t("layouts.header.logo")) %>
<%= setting["org_name"] %>
<% end %>
</li>
</ul>
</div>
<div class="top-bar" id="responsive_menu">
<div class="top-bar-left">
<ul class="menu">
<li class="menu-text">
<%= link_to root_path, class: "hide-for-small-only", accesskey: "0" do %>
<%= image_tag(image_path_for("logo_header.png"),
class: "hide-for-small-only float-left",
size: "80x80",
alt: t("layouts.header.logo")) %>
<%= setting["org_name"] %>
<% end %>
</li>
</ul>
<span data-responsive-toggle="responsive-menu" data-hide-for="medium" class="float-right">
<span class="menu-icon dark" data-toggle></span>
<%= t("application.menu")%>
</span>
<div class="top-bar-title">
<%= link_to root_path, accesskey: "0" do %>
<%= image_tag(image_path_for('logo_header.png'), class: 'float-left', alt: t("layouts.header.logo")) %>
<% end %>
</div>
<div class="top-bar-right">
<ul class="dropdown menu" data-dropdown-menu>
<%= render "shared/admin_login_items" %>
<%= render "layouts/notification_item" %>
<%= render "devise/menu/login_items" %>
</ul>
</div>
<div id="responsive-menu">
<div class="top-bar-right">
<ul class="menu" data-responsive-menu="medium-dropdown">
<%= render "shared/admin_login_items" %>
<%= render "layouts/notification_item" %>
<%= render "devise/menu/login_items" %>
</ul>
<div class="show-for-small-only">
<div class="subnavigation row">
<%= render "shared/subnavigation" %>
<div class="small-12 column">
<%= render "shared/top_links" %>
<div class="show-for-small-only">
<div class="subnavigation row">
<%= render "shared/subnavigation" %>
<div class="small-12 column">
<%= render "shared/top_links" %>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<% if with_subnavigation %>
<div class="subnavigation expanded">
<div class="row">
<div class="hide-for-small-only">
<%= render "shared/subnavigation" %>
</div>
<div class="small-12 medium-3 column">
<%= yield :header_addon %>
</div>
<div id="navigation_bar" class="subnavigation expanded">
<div class="row">
<div class="hide-for-small-only">
<%= render "shared/subnavigation" %>
</div>
<div class="small-12 medium-3 column">
<%= yield :header_addon %>
</div>
</div>
<% end %>

View File

@@ -1,21 +1,11 @@
<li id="<%= dom_id(notification) %>" class="notification <%= "unread" if notification.unread? %>">
<% if notification.notifiable_available? %>
<%= link_to notification do %>
<p>
<em>
<%= t("notifications.notification.action.#{notification.notifiable_action}",
count: notification.counter) %>
</em>
<strong id="<%= dom_id(notification) %>_title">
<%= notification.notifiable_title %>
</strong>
</p>
<p class="time">
<%= l notification.timestamp, format: :datetime %>
</p>
<% end %>
<li id="<%= dom_id(notification) %>" class="notification <%= 'unread' if notification&.unread? %>">
<% if notification.try(:notifiable_available?) %>
<% locals = { notification: notification,
timestamp: notification.timestamp,
title: notification.notifiable_title,
body: notification.notifiable.try(:body) } %>
<% link_text = render partial: '/notifications/notification_body', locals: locals %>
<%= link_to_if notification.link.present?, link_text, notification.link %>
<% else %>
<p>
<strong>

View File

@@ -0,0 +1,17 @@
<p>
<% if notification && notification.notifiable_action %>
<em>
<%= t("notifications.notification.action.#{notification.notifiable_action}",
count: notification.counter) %>
</em>
<% end %>
<strong id="<%= dom_id(notification) if notification %>_title">
<%= title %>
</strong>
<% if body %>
<p><%= body %></p>
<% end %>
</p>
<p class="time">
<%= l(timestamp, format: :datetime) %>
</p>

View File

@@ -24,7 +24,9 @@
</div>
<% else %>
<ul class="no-bullet clear notifications-list">
<%= render @notifications %>
<% @notifications.each do |notification| %>
<%= render partial: '/notifications/notification', locals: {notification: notification} %>
<% end %>
</ul>
<% end %>
</div>

View File

@@ -309,6 +309,10 @@ en:
attributes:
segment_recipient:
invalid: "The user recipients segment is invalid"
admin_notification:
attributes:
segment_recipient:
invalid: "The user recipients segment is invalid"
map_location:
attributes:
map:

View File

@@ -127,7 +127,8 @@ en:
table_amount: Amount
table_population: Population
population_info: "Budget Heading population field is used for Statistic purposes at the end of the Budget to show for each Heading that represents an area with population what percentage voted. The field is optional so you can leave it empty if it doesn't apply."
max_votable_headings: "Maxium number of headings in which a user can vote"
max_votable_headings: "Maximum number of headings in which a user can vote"
current_of_max_headings: "%{current} of %{max}"
winners:
calculate: Calculate Winner Investments
calculated: Winners being calculated, it may take a minute.
@@ -171,7 +172,6 @@ en:
one_filter_html: "Current applied filters: <b><em>%{filter}</em></b>"
two_filters_html: "Current applied filters: <b><em>%{filter}, %{advanced_filters}</em></b>"
buttons:
search: Search
filter: Filter
download_current_selection: "Download current selection"
no_budget_investments: "There are no investment projects."
@@ -186,18 +186,20 @@ en:
undecided: "Undecided"
selected: "Selected"
select: "Select"
table_id: "ID"
table_title: "Title"
table_supports: "Supports"
table_admin: "Administrator"
table_valuator: "Valuator"
table_valuation_group: "Valuation Group"
table_geozone: "Scope of operation"
table_feasibility: "Feasibility"
table_valuation_finished: "Val. Fin."
table_selection: "Selected"
table_evaluation: "Show to valuators"
table_incompatible: "Incompatible"
list:
id: ID
title: Title
supports: Supports
admin: Administrator
valuator: Valuator
valuation_group: Valuation Group
geozone: Scope of operation
feasibility: Feasibility
valuation_finished: Val. Fin.
selected: Selected
visible_to_valuators: Show to valuators
author_username: Author username
incompatible: Incompatible
cannot_calculate_winners: The budget has to stay on phase "Balloting projects", "Reviewing Ballots" or "Finished budget" in order to calculate winners projects
see_results: "See results"
show:
@@ -562,8 +564,9 @@ en:
administrators: Administrators
managers: Managers
moderators: Moderators
emails: Sending of emails
newsletters_and_notifications: Newsletters & Notifications
newsletters: Newsletters
admin_notifications: Notifications
emails_download: Emails download
valuators: Valuators
poll_officers: Poll officers
@@ -660,6 +663,41 @@ en:
body: Email content
body_help_text: This is how the users will see the email
send_alert: Are you sure you want to send this newsletter to %{n} users?
admin_notifications:
create_success: Notification created successfully
update_success: Notification updated successfully
send_success: Notification sent successfully
delete_success: Notification deleted successfully
index:
section_title: Notifications
new_notification: New notification
title: Title
segment_recipient: Recipients
sent: Sent
actions: Actions
draft: Draft
edit: Edit
delete: Delete
preview: Preview
view: View
empty_notifications: There are no notifications to show
new:
section_title: New notification
edit:
section_title: Edit notification
show:
section_title: Notification preview
send: Send
will_get_notified: (%{n} users will be notified)
got_notified: (%{n} users got notified)
sent_at: Sent at
title: Title
body: Text
link: Link
segment_recipient: Recipients
preview_guide: "This is how the users will see the notification:"
sent_guide: "This is how the users see the notification:"
send_alert: Are you sure you want to send this notification to %{n} users?
emails_download:
index:
title: Emails download

View File

@@ -1,11 +1,11 @@
en:
seeds:
settings:
official_level_1_name: Public workers
official_level_2_name: Municipal Organization
official_level_3_name: General Directors
official_level_4_name: Councillors
official_level_5_name: Mayor
official_level_1_name: Official position 1
official_level_2_name: Official position 2
official_level_3_name: Official position 3
official_level_4_name: Official position 4
official_level_5_name: Official position 5
geozones:
north_district: North District
west_district: West District
@@ -53,3 +53,18 @@ en:
recounting_poll: "Recounting Poll"
expired_poll_without_stats: "Expired Poll without Stats & Results"
expired_poll_with_stats: "Expired Poll with Stats & Results"
admin_notifications:
internal_link:
title: 'Do you have a proposal?'
body: 'Remember you can create a proposal with your ideas and people will discuss & support it.'
link: '/proposals'
external_link:
title: Help us translate consul
body: 'If you are proficient in a language, please help us translate consul!.'
link: 'https://crwd.in/consul'
without_link:
title: 'You can now geolocate proposals & investments'
body: 'When you create a proposal or investment you now can specify a point on a map'
not_sent:
title: 'We are closing the Participatory Budget!!'
body: 'Hurry up and create a last proposal before it ends next in few days!'

View File

@@ -311,6 +311,10 @@ es:
attributes:
segment_recipient:
invalid: "El segmento de usuarios es inválido"
admin_notification:
attributes:
segment_recipient:
invalid: "El segmento de usuarios es inválido"
map_location:
attributes:
map:

View File

@@ -128,6 +128,7 @@ es:
table_population: Población
population_info: "El campo población de las partidas presupuestarias se usa con fines estadísticos únicamente, con el objetivo de mostrar el porcentaje de votos habidos en cada partida que represente un área con población. Es un campo opcional, así que puedes dejarlo en blanco si no aplica."
max_votable_headings: "Máximo número de partidas en que un usuario puede votar"
current_of_max_headings: "%{current} de %{max}"
winners:
calculate: Calcular propuestas ganadoras
calculated: Calculando ganadoras, puede tardar un minuto.
@@ -186,18 +187,20 @@ es:
undecided: "Sin decidir"
selected: "Seleccionada"
select: "Seleccionar"
table_id: "ID"
table_title: "Título"
table_supports: "Apoyos"
table_admin: "Administrador"
table_valuator: "Evaluador"
table_valuation_group: "Grupos evaluadores"
table_geozone: "Ámbito de actuación"
table_feasibility: "Viabilidad"
table_valuation_finished: "Ev. Fin."
table_selection: "Seleccionado"
table_evaluation: "Mostrar a evaluadores"
table_incompatible: "Incompatible"
list:
id: ID
title: Título
supports: Apoyos
admin: Administrador
valuator: Evaluador
valuation_group: Grupos evaluadores
geozone: Ámbito de actuación
feasibility: Viabilidad
valuation_finished: Ev. Fin.
selected: Seleccionado
visible_to_valuators: Mostrar a evaluadores
author_username: Usuario autor
incompatible: Incompatible
cannot_calculate_winners: El presupuesto debe estar en las fases "Votación final", "Votación finalizada" o "Resultados" para poder calcular las propuestas ganadoras
see_results: "Ver resultados"
show:
@@ -562,8 +565,9 @@ es:
administrators: Administradores
managers: Gestores
moderators: Moderadores
emails: Envío de emails
newsletters_and_notifications: Newsletters & Notificaciones
newsletters: Newsletters
admin_notifications: Notificaciones
emails_download: Descarga de emails
valuators: Evaluadores
poll_officers: Presidentes de mesa
@@ -660,6 +664,41 @@ es:
body: Contenido del email
body_help_text: Así es como verán el email los usuarios
send_alert: ¿Estás seguro/a de que quieres enviar esta newsletter a %{n} usuarios?
admin_notifications:
create_success: Notificación creada correctamente
update_success: Notificación actualizada correctamente
send_success: Notificación enviada correctamente
delete_success: Notificación borrada correctamente
index:
section_title: Envío de notificaciones
new_notification: Crear notificación
title: Título
segment_recipient: Destinatarios
sent: Enviado
actions: Acciones
draft: Borrador
edit: Editar
delete: Borrar
preview: Previsualizar
view: Visualizar
empty_notifications: No hay notificaciones para mostrar
new:
section_title: Nueva notificación
edit:
section_title: Editar notificación
show:
section_title: Vista previa de notificación
send: Enviar
will_get_notified: (%{n} usuarios serán notificados)
got_notified: (%{n} usuarios fueron notificados)
sent_at: Enviado
title: Título
body: Texto
link: Enlace
segment_recipient: Destinatarios
preview_guide: "Así es como los usuarios verán la notificación:"
sent_guide: "Así es como los usuarios ven la notificación:"
send_alert: ¿Estás seguro/a de que quieres enviar esta notificación a %{n} usuarios?
emails_download:
index:
title: Descarga de emails

View File

@@ -126,10 +126,10 @@ es:
milestone_publication_date: "Publicado el %{publication_date}"
milestone_status_changed: El proyecto ha cambiado al estado
author: Autor
project_unfeasible_html: 'Este proyecto de inversión <strong>ha sido marcado como inviable</strong> y no pasará a la fase de votación.'
project_unfeasible_html: 'Este proyecto de gasto <strong>ha sido marcado como inviable</strong> y no pasará a la fase de votación.'
project_selected_html: 'Este proyecto de gasto <strong>ha sido seleccionado</strong> para la fase de votación.'
project_winner: 'Proyecto de gasto ganador'
project_not_selected_html: 'Este proyecto de inversión <strong>no ha sido seleccionado</strong> para la fase de votación.'
project_not_selected_html: 'Este proyecto de gasto <strong>no ha sido seleccionado</strong> para la fase de votación.'
wrong_price_format: Solo puede incluir caracteres numéricos
investment:
add: Votar

View File

@@ -1,11 +1,11 @@
es:
seeds:
settings:
official_level_1_name: Empleados públicos
official_level_2_name: Organización Municipal
official_level_3_name: Directores generales
official_level_4_name: Concejales
official_level_5_name: Alcaldesa
official_level_1_name: Cargo oficial 1
official_level_2_name: Cargo oficial 2
official_level_3_name: Cargo oficial 3
official_level_4_name: Cargo oficial 4
official_level_5_name: Cargo oficial 5
geozones:
north_district: Distrito Norte
west_district: Distrito Oeste
@@ -53,3 +53,18 @@ es:
recounting_poll: "Votación en Recuento"
expired_poll_without_stats: "Votación Finalizada (sin Estadísticas o Resultados)"
expired_poll_with_stats: "Votación Finalizada (con Estadísticas y Resultado)"
admin_notifications:
internal_link:
title: 'Tienes una propuesta?'
body: 'Recuerda que puedes crear propuestas y los ciudadanos las debatirán y apoyarán.'
link: '/proposals'
external_link:
title: 'Ayúdanos a traducir CONSUL'
body: 'Si dominas un idioma, ayúdanos a completar su traducción en CONSUL.'
link: 'https://crwd.in/consul'
without_link:
title: 'Ahora puedes geolocalizar propuestas y proyectos de inversión'
body: 'Cuando crees una propuesta o proyecto de inversión podrás especificar su localización en el mapa'
not_sent:
title: 'Últimos días para crear proyectos de Presupuestos Participativos'
body: 'Quedan pocos dias para que se cierre el plazo de presentación de proyectos de inversión para los presupuestos participativos!'

View File

@@ -159,6 +159,12 @@ namespace :admin do
get :users, on: :collection
end
resources :admin_notifications do
member do
post :deliver
end
end
resources :emails_download, only: :index do
get :generate_csv, on: :collection
end

View File

@@ -34,5 +34,6 @@ require_relative 'dev_seeds/legislation_processes'
require_relative 'dev_seeds/newsletters'
require_relative 'dev_seeds/notifications'
require_relative 'dev_seeds/widgets'
require_relative 'dev_seeds/admin_notifications'
log "All dev seeds created successfuly 👍"

View File

@@ -0,0 +1,28 @@
section "Creating Admin Notifications & Templates" do
AdminNotification.create!(
title: I18n.t('seeds.admin_notification.internal_link.title'),
body: I18n.t('seeds.admin_notification.internal_link.body'),
link: Setting['url'] + I18n.t('seeds.admin_notification.internal_link.link'),
segment_recipient: 'administrators'
).deliver
AdminNotification.create!(
title: I18n.t('seeds.admin_notification.external_link.title'),
body: I18n.t('seeds.admin_notification.external_link.body'),
link: I18n.t('seeds.admin_notification.external_link.link'),
segment_recipient: 'administrators'
).deliver
AdminNotification.create!(
title: I18n.t('seeds.admin_notification.without_link.title'),
body: I18n.t('seeds.admin_notification.without_link.body'),
segment_recipient: 'administrators'
).deliver
AdminNotification.create!(
title: I18n.t('seeds.admin_notification.not_sent.title'),
body: I18n.t('seeds.admin_notification.not_sent.body'),
segment_recipient: 'administrators',
sent_at: nil
)
end

View File

@@ -5,12 +5,6 @@ section "Creating banners" do
target_url = Rails.application.routes.url_helpers.proposal_path(proposal)
banner = Banner.create!(title: title,
description: description,
style: ["banner-style banner-style-one",
"banner-style banner-style-two",
"banner-style banner-style-three"].sample,
image: ["banner-img banner-img-one",
"banner-img banner-img-two",
"banner-img banner-img-three"].sample,
target_url: target_url,
post_started_at: rand((Time.current - 1.week)..(Time.current - 1.day)),
post_ended_at: rand((Time.current - 1.day)..(Time.current + 1.week)),

View File

@@ -1,3 +1,29 @@
INVESTMENT_IMAGE_FILES = %w{
brennan-ehrhardt-25066-unsplash_713x513.jpg
carl-nenzen-loven-381554-unsplash_713x475.jpg
carlos-zurita-215387-unsplash_713x475.jpg
hector-arguello-canals-79584-unsplash_713x475.jpg
olesya-grichina-218176-unsplash_713x475.jpg
sole-d-alessandro-340443-unsplash_713x475.jpg
}.map do |filename|
File.new(Rails.root.join("db",
"dev_seeds",
"images",
"budget",
"investments", filename))
end
def add_image_to(imageable)
# imageable should respond to #title & #author
imageable.image = Image.create!({
imageable: imageable,
title: imageable.title,
attachment: INVESTMENT_IMAGE_FILES.sample,
user: imageable.author
})
imageable.save
end
section "Creating Budgets" do
Budget.create(
name: "#{I18n.t('seeds.budgets.budget')} #{Date.current.year - 1}",
@@ -53,6 +79,8 @@ section "Creating Investments" do
skip_map: "1",
terms_of_service: "1"
)
add_image_to(investment) if Random.rand > 0.5
end
end
@@ -83,7 +111,7 @@ section "Winner Investments" do
budget = Budget.finished.first
50.times do
heading = budget.headings.all.sample
Budget::Investment.create!(
investment = Budget::Investment.create!(
author: User.all.sample,
heading: heading,
group: heading.group,
@@ -98,6 +126,7 @@ section "Winner Investments" do
skip_map: "1",
terms_of_service: "1"
)
add_image_to(investment) if Random.rand > 0.3
end
budget.headings.each do |heading|
Budget::Result.new(budget, heading).calculate_winners

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -0,0 +1,6 @@
class RemoveImageAndStyleFromBanners < ActiveRecord::Migration
def change
remove_column :banners, :image
remove_column :banners, :style
end
end

View File

@@ -0,0 +1,14 @@
class CreateAdminNotifications < ActiveRecord::Migration
def change
create_table :admin_notifications do |t|
t.string :title
t.text :body
t.string :link
t.string :segment_recipient
t.integer :recipients_count
t.date :sent_at, default: nil
t.timestamps null: false
end
end
end

View File

@@ -30,6 +30,17 @@ ActiveRecord::Schema.define(version: 20180726055120) do
add_index "activities", ["actionable_id", "actionable_type"], name: "index_activities_on_actionable_id_and_actionable_type", using: :btree
add_index "activities", ["user_id"], name: "index_activities_on_user_id", using: :btree
create_table "admin_notifications", force: :cascade do |t|
t.string "title"
t.text "body"
t.string "link"
t.string "segment_recipient"
t.integer "recipients_count"
t.date "sent_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "administrators", force: :cascade do |t|
t.integer "user_id"
end
@@ -74,8 +85,6 @@ ActiveRecord::Schema.define(version: 20180726055120) do
t.string "title", limit: 80
t.string "description"
t.string "target_url"
t.string "style"
t.string "image"
t.date "post_started_at"
t.date "post_ended_at"
t.datetime "hidden_at"

View File

@@ -7,11 +7,11 @@ end
# Names for the moderation console, as a hint for moderators
# to know better how to assign users with official positions
Setting["official_level_1_name"] = "Empleados públicos"
Setting["official_level_2_name"] = "Organización Municipal"
Setting["official_level_3_name"] = "Directores generales"
Setting["official_level_4_name"] = "Concejales"
Setting["official_level_5_name"] = "Alcaldesa"
Setting["official_level_1_name"] = "Cargo oficial 1"
Setting["official_level_2_name"] = "Cargo oficial 2"
Setting["official_level_3_name"] = "Cargo oficial 3"
Setting["official_level_4_name"] = "Cargo oficial 4"
Setting["official_level_5_name"] = "Cargo oficial 5"
# Max percentage of allowed anonymous votes on a debate
Setting["max_ratio_anon_votes_on_debates"] = 50
@@ -26,7 +26,7 @@ Setting["max_votes_for_proposal_edit"] = 1000
Setting['comments_body_max_length'] = 1000
# Prefix for the Proposal codes
Setting["proposal_code_prefix"] = 'MAD'
Setting["proposal_code_prefix"] = 'CONSUL'
# Number of votes needed for proposal success
Setting["votes_for_proposal_success"] = 53726

View File

@@ -1,227 +1,267 @@
{
"spec/models/setting_spec.rb": 0.07869887351989746,
"spec/features/admin/managers_spec.rb": 5.029380798339844,
"spec/features/management/managed_users_spec.rb": 3.1642160415649414,
"spec/features/admin/poll/booths_spec.rb": 1.4152588844299316,
"spec/features/admin/comments_spec.rb": 3.889301061630249,
"spec/helpers/admin_helper_spec.rb": 0.005057334899902344,
"spec/models/abilities/moderator_spec.rb": 2.3274271488189697,
"spec/controllers/admin/api/stats_controller_spec.rb": 0.4249396324157715,
"spec/features/admin/organizations_spec.rb": 3.339292049407959,
"spec/features/admin/newsletters_spec.rb": 0.2460641860961914,
"spec/helpers/geozones_helper_spec.rb": 0.08249163627624512,
"spec/lib/graph_ql/api_types_creator_spec.rb": 0.006573915481567383,
"spec/features/emails_spec.rb": 18.91256046295166,
"spec/features/admin/hidden_users_spec.rb": 1.3854436874389648,
"spec/features/welcome_spec.rb": 1.1956276893615723,
"spec/features/sessions_spec.rb": 0.3943772315979004,
"spec/models/custom/residence_spec.rb": 0.07002687454223633,
"spec/models/poll/booth_spec.rb": 0.05489993095397949,
"spec/models/direct_message_spec.rb": 0.3973381519317627,
"spec/features/valuation/budget_investments_spec.rb": 7.6013023853302,
"spec/models/map_location_spec.rb": 0.12476563453674316,
"spec/models/budget/heading_spec.rb": 0.09248590469360352,
"spec/models/user_spec.rb": 2.9006423950195312,
"spec/features/admin/site_customization/content_blocks_spec.rb": 1.6733989715576172,
"spec/mailers/mailer_spec.rb": 0.08513784408569336,
"spec/models/site_customization/page_spec.rb": 0.015056133270263672,
"spec/features/management/budget_investments_spec.rb": 8.112786293029785,
"spec/features/admin/activity_spec.rb": 12.442089080810547,
"spec/features/registration_form_spec.rb": 1.0509357452392578,
"spec/controllers/legislation/annotations_controller_spec.rb": 0.8151364326477051,
"spec/lib/census_caller_spec.rb": 0.018165111541748047,
"spec/features/users_auth_spec.rb": 6.5102221965789795,
"spec/features/tags/proposals_spec.rb": 10.001718521118164,
"spec/features/account_spec.rb": 2.2510504722595215,
"spec/features/admin/users_spec.rb": 0.4342050552368164,
"spec/lib/cache_spec.rb": 0.057682037353515625,
"spec/features/valuation_spec.rb": 1.3436784744262695,
"spec/models/budget/investment_spec.rb": 12.89230751991272,
"spec/lib/migrate_spending_proposals_to_investments_spec.rb": 0.904367208480835,
"spec/helpers/settings_helper_spec.rb": 0.02300858497619629,
"spec/helpers/application_helper_spec.rb": 0.09152626991271973,
"spec/models/legislation/draft_version_spec.rb": 0.020322084426879883,
"spec/models/legislation/question_spec.rb": 0.3402721881866455,
"spec/models/document_spec.rb": 1.3238348960876465,
"spec/models/poll/question_spec.rb": 0.12588191032409668,
"spec/features/admin/poll/polls_spec.rb": 11.77881646156311,
"spec/lib/manager_authenticator_spec.rb": 0.006296873092651367,
"spec/features/admin/debates_spec.rb": 1.688420295715332,
"spec/features/moderation/debates_spec.rb": 5.343512773513794,
"spec/controllers/debates_controller_spec.rb": 0.40573883056640625,
"spec/models/tag_cloud_spec.rb": 1.6984672546386719,
"spec/models/budget/investment/milestone_spec.rb": 0.15051603317260742,
"spec/models/proposal_notification_spec.rb": 0.2914905548095703,
"spec/features/budgets/investments_spec.rb": 93.5263159275055,
"spec/i18n_spec.rb": 96.26275777816772,
"spec/models/community_spec.rb": 0.16270899772644043,
"spec/controllers/graphql_controller_spec.rb": 0.5831413269042969,
"spec/models/legislation/annotation_spec.rb": 0.16232728958129883,
"spec/lib/acts_as_taggable_on_spec.rb": 0.5747356414794922,
"spec/lib/census_api_spec.rb": 0.0021581649780273438,
"spec/features/moderation/comments_spec.rb": 6.70704984664917,
"spec/models/poll/voter_spec.rb": 0.32018303871154785,
"spec/features/proposal_notifications_spec.rb": 3.906450033187866,
"spec/models/budget/result_spec.rb": 0.8468267917633057,
"spec/helpers/users_helper_spec.rb": 0.25751638412475586,
"spec/features/valuation/budgets_spec.rb": 0.2564871311187744,
"spec/controllers/users/registrations_controller_spec.rb": 0.022383689880371094,
"spec/controllers/management/base_controller_spec.rb": 0.06711888313293457,
"spec/features/admin/officials_spec.rb": 0.893528938293457,
"spec/features/comments/topics_spec.rb": 29.998314142227173,
"spec/features/users_spec.rb": 11.885858297348022,
"spec/models/topic_spec.rb": 0.27634167671203613,
"spec/models/follow_spec.rb": 0.1256728172302246,
"spec/lib/local_census_spec.rb": 0.005529880523681641,
"spec/features/verification/sms_spec.rb": 1.5214743614196777,
"spec/helpers/comments_helper_spec.rb": 0.010879278182983398,
"spec/models/valuator_spec.rb": 0.02650904655456543,
"spec/features/proposal_ballots_spec.rb": 0.3937220573425293,
"spec/features/proposals_spec.rb": 142.48229122161865,
"spec/features/legislation/processes_spec.rb": 2.863476514816284,
"spec/features/ckeditor_spec.rb": 0.8433480262756348,
"spec/models/letter_spec.rb": 0.0695810317993164,
"spec/features/admin/budget_investments_spec.rb": 18.484699964523315,
"spec/models/officing/residence_spec.rb": 0.3402073383331299,
"spec/controllers/concerns/has_orders_spec.rb": 0.1844041347503662,
"spec/features/admin/legislation/processes_spec.rb": 4.020649433135986,
"spec/features/management/users_spec.rb": 2.288966178894043,
"spec/lib/tasks/communities_spec.rb": 0.15353775024414062,
"spec/models/abilities/organization_spec.rb": 0.24793481826782227,
"spec/features/polls/polls_spec.rb": 2.591568946838379,
"spec/features/communities_spec.rb": 1.6137127876281738,
"spec/models/legislation/process/phase_spec.rb": 0.07121586799621582,
"spec/features/officing_spec.rb": 0.979363203048706,
"spec/features/site_customization/custom_pages_spec.rb": 0.5588700771331787,
"spec/features/comments/legislation_questions_spec.rb": 14.133169889450073,
"spec/features/organizations_spec.rb": 0.46280837059020996,
"spec/controllers/legislation/answers_controller_spec.rb": 0.39082813262939453,
"spec/models/image_spec.rb": 7.636544466018677,
"spec/features/management/account_spec.rb": 1.150636911392212,
"spec/models/abilities/common_spec.rb": 5.959435701370239,
"spec/features/comments/debates_spec.rb": 13.69457721710205,
"spec/models/poll/shift_spec.rb": 0.19109749794006348,
"spec/features/site_customization/content_blocks_spec.rb": 0.3058288097381592,
"spec/models/poll/recount_spec.rb": 0.1983809471130371,
"spec/features/verification/level_two_verification_spec.rb": 0.4596068859100342,
"spec/features/verification/level_three_verification_spec.rb": 1.456559658050537,
"spec/lib/tasks/settings_spec.rb": 0.04654407501220703,
"spec/features/admin/budget_investment_milestones_spec.rb": 1.3974273204803467,
"spec/features/management/localization_spec.rb": 1.1653187274932861,
"spec/features/admin/tags_spec.rb": 1.0751111507415771,
"spec/features/officing/results_spec.rb": 1.2672057151794434,
"spec/features/admin/poll/booth_assigments_spec.rb": 4.1742753982543945,
"spec/models/poll/officer_assignment_spec.rb": 0.024514198303222656,
"spec/controllers/management/sessions_controller_spec.rb": 0.07244610786437988,
"spec/features/admin/signature_sheets_spec.rb": 1.4268932342529297,
"spec/models/debate_spec.rb": 4.550540924072266,
"spec/features/comments/proposals_spec.rb": 25.726442337036133,
"spec/models/poll/partial_result_spec.rb": 0.32181620597839355,
"spec/features/admin/legislation/draft_versions_spec.rb": 3.4613990783691406,
"spec/models/budget_spec.rb": 0.14807415008544922,
"spec/models/sms_spec.rb": 0.018825769424438477,
"spec/features/admin/proposals_spec.rb": 1.837270975112915,
"spec/models/geozone_spec.rb": 0.11852264404296875,
"spec/features/admin/banners_spec.rb": 3.0584604740142822,
"spec/models/legislation/process/publication_spec.rb": 0.06270265579223633,
"spec/lib/graph_ql/query_type_creator_spec.rb": 0.009456157684326172,
"spec/features/moderation_spec.rb": 1.001516342163086,
"spec/features/campaigns_spec.rb": 0.8359789848327637,
"spec/features/admin/verifications_spec.rb": 0.6421175003051758,
"spec/features/localization_spec.rb": 0.756089448928833,
"spec/features/admin/poll/questions_spec.rb": 41.59848093986511,
"spec/features/tags/debates_spec.rb": 3.4022486209869385,
"spec/helpers/text_helper_spec.rb": 0.0006229877471923828,
"spec/features/admin/moderators_spec.rb": 1.3467354774475098,
"spec/models/flag_spec.rb": 0.5202171802520752,
"spec/mailers/devise_mailer_spec.rb": 0.2588930130004883,
"spec/features/user_invites_spec.rb": 0.18819189071655273,
"spec/features/legislation/draft_versions_spec.rb": 9.352471828460693,
"spec/features/home_spec.rb": 3.0868682861328125,
"spec/features/budgets/results_spec.rb": 2.4918482303619385,
"spec/features/budgets/votes_spec.rb": 4.285862922668457,
"spec/features/comments/budget_investments_spec.rb": 16.1397545337677,
"spec/features/admin/stats_spec.rb": 2.678718090057373,
"spec/features/polls/questions_spec.rb": 2.594414472579956,
"spec/features/admin/poll/shifts_spec.rb": 4.629284143447876,
"spec/helpers/votes_helper_spec.rb": 0.31733107566833496,
"spec/models/ahoy/data_source_spec.rb": 0.04695439338684082,
"spec/models/residence_spec.rb": 0.20260858535766602,
"spec/features/admin_spec.rb": 0.6963987350463867,
"spec/controllers/comments_controller_spec.rb": 0.2683417797088623,
"spec/lib/age_spec.rb": 0.0007379055023193359,
"spec/models/legislation/answer_spec.rb": 0.14532899856567383,
"spec/features/tags_spec.rb": 3.0131027698516846,
"spec/features/admin/valuators_spec.rb": 1.0099408626556396,
"spec/models/notification_spec.rb": 0.37938618659973145,
"spec/views/welcome/index.html.erb_spec.rb": 0.1471250057220459,
"spec/customization_engine_spec.rb": 1.5587348937988281,
"spec/models/poll/officer_spec.rb": 0.2980079650878906,
"spec/features/budgets/ballots_spec.rb": 25.24861741065979,
"spec/controllers/concerns/has_filters_spec.rb": 0.1412961483001709,
"spec/features/moderation/proposals_spec.rb": 5.947849273681641,
"spec/features/management/document_verifications_spec.rb": 0.9574480056762695,
"spec/features/legislation/questions_spec.rb": 1.605849027633667,
"spec/models/proposal_spec.rb": 5.872406482696533,
"spec/models/legislation/question_option_spec.rb": 0.0395960807800293,
"spec/features/budgets/budgets_spec.rb": 0.8722023963928223,
"spec/lib/email_digests_spec.rb": 0.440814733505249,
"spec/features/official_positions_spec.rb": 1.5717194080352783,
"spec/features/officing/residence_spec.rb": 0.9819045066833496,
"spec/features/officing/voters_spec.rb": 2.078903913497925,
"spec/features/direct_messages_spec.rb": 1.6070659160614014,
"spec/models/abilities/everyone_spec.rb": 0.059804677963256836,
"spec/lib/acts_as_paranoid_aliases_spec.rb": 0.33096909523010254,
"spec/features/debates_spec.rb": 32.84718298912048,
"spec/features/votes_spec.rb": 18.217467069625854,
"spec/models/activity_spec.rb": 1.0154414176940918,
"spec/controllers/pages_controller_spec.rb": 0.19468045234680176,
"spec/features/admin/feature_flags_spec.rb": 0.726452112197876,
"spec/models/signature_sheet_spec.rb": 0.6403882503509521,
"spec/features/admin/poll/officers_spec.rb": 1.2912020683288574,
"spec/models/lock_spec.rb": 0.08562397956848145,
"spec/helpers/proposals_helper_spec.rb": 0.17275524139404297,
"spec/features/tags/budget_investments_spec.rb": 14.154245615005493,
"spec/models/vote_spec.rb": 0.9258472919464111,
"spec/features/admin/site_customization/pages_spec.rb": 1.0365827083587646,
"spec/features/moderation/users_spec.rb": 1.3000907897949219,
"spec/features/comments/legislation_annotations_spec.rb": 19.67066717147827,
"spec/features/admin/legislation/questions_spec.rb": 4.043334007263184,
"spec/models/comment_spec.rb": 1.6633994579315186,
"spec/features/admin/site_customization/images_spec.rb": 1.2299704551696777,
"spec/models/abilities/valuator_spec.rb": 1.1985805034637451,
"spec/models/organization_spec.rb": 0.12121891975402832,
"spec/models/budget/ballot_spec.rb": 0.6403298377990723,
"spec/lib/wysiwyg_sanitizer_spec.rb": 0.0018651485443115234,
"spec/features/stats_spec.rb": 0.8169982433319092,
"spec/models/poll/answer_spec.rb": 0.13266730308532715,
"spec/features/admin/settings_spec.rb": 3.1228368282318115,
"spec/features/verification/verification_path_spec.rb": 1.1146795749664307,
"spec/controllers/management/users_controller_spec.rb": 0.004178762435913086,
"spec/models/direct_upload_spec.rb": 1.1311051845550537,
"spec/features/management/email_verifications_spec.rb": 0.3727388381958008,
"spec/models/abilities/administrator_spec.rb": 2.355985164642334,
"spec/models/budget/ballot/line_spec.rb": 0.49976515769958496,
"spec/features/verification/letter_spec.rb": 1.5464122295379639,
"spec/features/notifications_spec.rb": 19.54401397705078,
"spec/features/admin/administrators_spec.rb": 1.7901337146759033,
"spec/models/signature_spec.rb": 1.5397937297821045,
"spec/models/identity_spec.rb": 0.0023458003997802734,
"spec/models/verification/management/document_spec.rb": 0.017922163009643555,
"spec/models/legislation/process_spec.rb": 0.09648776054382324,
"spec/models/budget/group_spec.rb": 0.049637794494628906,
"spec/models/verification/management/email_spec.rb": 0.057023048400878906,
"spec/helpers/verification_helper_spec.rb": 0.0009088516235351562,
"spec/features/verification/residence_spec.rb": 2.2246382236480713,
"spec/features/tracks_spec.rb": 2.320988178253174,
"spec/lib/tag_sanitizer_spec.rb": 0.0005729198455810547,
"spec/features/admin/budgets_spec.rb": 4.4486541748046875,
"spec/models/site_customization/content_block_spec.rb": 0.010473012924194336,
"spec/features/verification/email_spec.rb": 0.5266687870025635,
"spec/models/budget/reclassified_vote_spec.rb": 0.19786882400512695,
"spec/features/management/proposals_spec.rb": 4.107697486877441,
"spec/models/poll/poll_spec.rb": 0.38217735290527344,
"spec/features/admin/geozones_spec.rb": 1.561723232269287,
"spec/lib/graphql_spec.rb": 3.063258647918701,
"spec/features/verification/verified_user_spec.rb": 0.8179008960723877
"spec/helpers/votes_helper_spec.rb": 1.9247241020202637,
"spec/features/admin/site_customization/content_blocks_spec.rb": 5.525654077529907,
"spec/features/moderation/proposals_spec.rb": 21.10563063621521,
"spec/features/polls/polls_spec.rb": 41.82700848579407,
"spec/models/setting_spec.rb": 2.9200007915496826,
"spec/features/valuation/budgets_spec.rb": 1.8399147987365723,
"spec/features/admin/poll/questions_spec.rb": 2.6838932037353516,
"spec/lib/wysiwyg_sanitizer_spec.rb": 0.8582510948181152,
"spec/models/poll/poll_spec.rb": 6.990106582641602,
"spec/features/verification/level_three_verification_spec.rb": 2.8142292499542236,
"spec/features/admin/emails/newsletters_spec.rb": 8.045061826705933,
"spec/lib/tasks/dev_seed_spec.rb": 154.5065369606018,
"spec/models/debate_spec.rb": 32.5616397857666,
"spec/features/admin/poll/polls_spec.rb": 20.53029990196228,
"spec/features/official_positions_spec.rb": 3.159071683883667,
"spec/controllers/pages_controller_spec.rb": 1.939023494720459,
"spec/controllers/concerns/has_orders_spec.rb": 1.4417927265167236,
"spec/features/comments/budget_investments_spec.rb": 40.476513147354126,
"spec/features/registration_form_spec.rb": 4.7642998695373535,
"spec/features/admin/settings_spec.rb": 11.108770847320557,
"spec/models/poll/voter_spec.rb": 4.39433741569519,
"spec/features/guides_spec.rb": 2.948526382446289,
"spec/features/officing/results_spec.rb": 2.1444389820098877,
"spec/features/verification/letter_spec.rb": 3.7225558757781982,
"spec/features/admin/site_customization/pages_spec.rb": 1.790579080581665,
"spec/features/admin/widgets/cards_spec.rb": 8.64452600479126,
"spec/features/admin/banners_spec.rb": 7.32423996925354,
"spec/features/legislation/questions_spec.rb": 2.5584514141082764,
"spec/features/proposal_ballots_spec.rb": 0.7401783466339111,
"spec/features/admin/managers_spec.rb": 4.2071428298950195,
"spec/controllers/application_controller_spec.rb": 0.8678901195526123,
"spec/controllers/users/registrations_controller_spec.rb": 0.44539594650268555,
"spec/features/translations_spec.rb": 16.89036774635315,
"spec/models/poll/partial_result_spec.rb": 1.3466713428497314,
"spec/features/admin/poll/questions/answers/videos/videos_spec.rb": 0.45564794540405273,
"spec/models/organization_spec.rb": 2.4066359996795654,
"spec/features/budgets/ballots_spec.rb": 52.6602725982666,
"spec/models/budget/ballot/line_spec.rb": 2.5589516162872314,
"spec/features/admin/poll/questions/answers/images/images_spec.rb": 6.252883195877075,
"spec/features/admin/valuator_groups_spec.rb": 3.4325931072235107,
"spec/models/budget/result_spec.rb": 2.5409233570098877,
"spec/helpers/verification_helper_spec.rb": 0.7236690521240234,
"spec/i18n_spec.rb": 9.241354942321777,
"spec/features/admin/poll/shifts_spec.rb": 11.702121496200562,
"spec/features/admin/poll/officers_spec.rb": 2.325108528137207,
"spec/controllers/graphql_controller_spec.rb": 3.2026760578155518,
"spec/models/comment_spec.rb": 7.425090074539185,
"spec/models/direct_message_spec.rb": 2.570894479751587,
"spec/features/admin_spec.rb": 2.3781089782714844,
"spec/models/geozone_spec.rb": 1.578934907913208,
"spec/lib/census_caller_spec.rb": 0.47748804092407227,
"spec/models/budget/group_spec.rb": 2.085042953491211,
"spec/models/image_spec.rb": 15.60672116279602,
"spec/models/legislation/proposal_spec.rb": 1.3015773296356201,
"spec/models/activity_spec.rb": 2.7077889442443848,
"spec/features/home_spec.rb": 4.511173486709595,
"spec/models/budget/investment/milestone_spec.rb": 5.136592626571655,
"spec/models/legislation/process/phase_spec.rb": 1.3941795825958252,
"spec/models/budget/phase_spec.rb": 11.81902813911438,
"spec/lib/user_segments_spec.rb": 9.551864862442017,
"spec/models/abilities/organization_spec.rb": 2.282193899154663,
"spec/lib/local_census_spec.rb": 1.4585235118865967,
"spec/helpers/application_helper_spec.rb": 0.7274577617645264,
"spec/features/polls/voter_spec.rb": 21.75647211074829,
"spec/models/verification/management/document_spec.rb": 1.4520442485809326,
"spec/models/vote_spec.rb": 5.250682592391968,
"spec/models/custom/verification/residence_spec.rb": 0.7798707485198975,
"spec/features/comments/proposals_spec.rb": 44.320897579193115,
"spec/features/admin/legislation/draft_versions_spec.rb": 5.146088123321533,
"spec/lib/acts_as_taggable_on_spec.rb": 2.6721038818359375,
"spec/lib/census_api_spec.rb": 1.3697211742401123,
"spec/features/verification/level_two_verification_spec.rb": 0.6944849491119385,
"spec/models/legislation/answer_spec.rb": 0.9158306121826172,
"spec/models/notification_spec.rb": 4.91338849067688,
"spec/lib/manager_authenticator_spec.rb": 1.679121732711792,
"spec/models/verification/letter_spec.rb": 1.2081491947174072,
"spec/lib/tasks/map_location_spec.rb": 0.25089311599731445,
"spec/features/officing/voters_spec.rb": 6.966830492019653,
"spec/models/legislation/annotation_spec.rb": 1.1694798469543457,
"spec/features/sessions_spec.rb": 0.5324661731719971,
"spec/features/direct_messages_spec.rb": 3.043520212173462,
"spec/controllers/legislation/annotations_controller_spec.rb": 1.898331880569458,
"spec/features/budgets/votes_spec.rb": 16.01220202445984,
"spec/features/management/localization_spec.rb": 5.850449085235596,
"spec/models/signature_spec.rb": 14.875547409057617,
"spec/features/ckeditor_spec.rb": 2.9620261192321777,
"spec/controllers/management/sessions_controller_spec.rb": 1.3280744552612305,
"spec/features/admin/proposal_notifications_spec.rb": 4.826445579528809,
"spec/features/polls/results_spec.rb": 6.088449001312256,
"spec/models/related_content_spec.rb": 2.161971092224121,
"spec/controllers/debates_controller_spec.rb": 1.026824951171875,
"spec/models/poll/recount_spec.rb": 1.383685827255249,
"spec/models/budget/investment/status_spec.rb": 0.40141797065734863,
"spec/models/legislation/process/publication_spec.rb": 1.3006155490875244,
"spec/models/site_customization/content_block_spec.rb": 0.46710920333862305,
"spec/customization_engine_spec.rb": 2.2306907176971436,
"spec/features/moderation/comments_spec.rb": 11.995895862579346,
"spec/models/tag_cloud_spec.rb": 4.235608816146851,
"spec/features/admin/organizations_spec.rb": 6.28728461265564,
"spec/features/tags/budget_investments_spec.rb": 37.69240593910217,
"spec/features/admin/stats_spec.rb": 6.9300689697265625,
"spec/features/comments/legislation_annotations_spec.rb": 40.50071859359741,
"spec/features/admin/legislation/questions_spec.rb": 6.142740964889526,
"spec/features/admin/geozones_spec.rb": 2.9746437072753906,
"spec/features/debates_spec.rb": 80.45999050140381,
"spec/features/stats_spec.rb": 1.2480409145355225,
"spec/models/signature_sheet_spec.rb": 4.21362566947937,
"spec/features/admin/valuators_spec.rb": 5.309014081954956,
"spec/features/admin/budget_groups_spec.rb": 6.729426145553589,
"spec/features/verification/residence_spec.rb": 3.118638277053833,
"spec/models/poll/officer_spec.rb": 1.5057151317596436,
"spec/models/budget/ballot_spec.rb": 2.901576280593872,
"spec/models/abilities/administrator_spec.rb": 13.805708646774292,
"spec/models/topic_spec.rb": 8.181006908416748,
"spec/features/management/budget_investments_spec.rb": 17.35987091064453,
"spec/features/legislation/proposals_spec.rb": 21.712324142456055,
"spec/features/admin/emails/emails_download_spec.rb": 0.6266088485717773,
"spec/models/newsletter_spec.rb": 2.008305072784424,
"spec/features/proposal_notifications_spec.rb": 20.093811511993408,
"spec/features/budget_polls/officing_spec.rb": 0.7592868804931641,
"spec/features/admin/poll/questions/answers/answers_spec.rb": 1.621028184890747,
"spec/features/management/users_spec.rb": 3.4778735637664795,
"spec/features/admin/budget_investment_milestones_spec.rb": 6.3836870193481445,
"spec/features/management/managed_users_spec.rb": 4.452433824539185,
"spec/models/flag_spec.rb": 3.003862142562866,
"spec/features/admin/comments_spec.rb": 7.13858437538147,
"spec/features/management/document_verifications_spec.rb": 2.122368812561035,
"spec/models/poll/officer_assignment_spec.rb": 0.2809889316558838,
"spec/models/poll/booth_spec.rb": 1.116940975189209,
"spec/features/admin/poll/officer_assignments_spec.rb": 2.2718498706817627,
"spec/features/proposals_spec.rb": 362.78499245643616,
"spec/mailers/devise_mailer_spec.rb": 0.6141948699951172,
"spec/features/moderation/proposal_notifications_spec.rb": 9.295955657958984,
"spec/models/widget/card_spec.rb": 2.7824501991271973,
"spec/lib/tag_sanitizer_spec.rb": 0.8820271492004395,
"spec/controllers/legislation/answers_controller_spec.rb": 1.008268117904663,
"spec/features/management/email_verifications_spec.rb": 0.5439820289611816,
"spec/models/valuator_group_spec.rb": 0.6066617965698242,
"spec/features/admin/poll/booth_assigments_spec.rb": 11.954967260360718,
"spec/features/tags/debates_spec.rb": 6.132092475891113,
"spec/models/legislation/process_spec.rb": 4.4246649742126465,
"spec/features/organizations_spec.rb": 1.736802577972412,
"spec/features/admin/site_customization/images_spec.rb": 2.010110855102539,
"spec/mailers/mailer_spec.rb": 0.44429469108581543,
"spec/features/officing/residence_spec.rb": 2.012357473373413,
"spec/features/comments/debates_spec.rb": 31.455246686935425,
"spec/features/admin/activity_spec.rb": 10.88606572151184,
"spec/lib/tasks/settings_spec.rb": 0.8854072093963623,
"spec/features/admin/budget_investment_statuses_spec.rb": 1.7528102397918701,
"spec/features/admin/hidden_users_spec.rb": 2.298340082168579,
"spec/features/account_spec.rb": 4.742053747177124,
"spec/models/abilities/moderator_spec.rb": 12.851414442062378,
"spec/features/moderation/users_spec.rb": 1.7415039539337158,
"spec/controllers/comments_controller_spec.rb": 0.915616512298584,
"spec/features/legislation/processes_spec.rb": 9.67371153831482,
"spec/models/abilities/common_spec.rb": 46.193737506866455,
"spec/features/admin/homepage/homepage_spec.rb": 7.786237001419067,
"spec/features/legislation/draft_versions_spec.rb": 20.253584623336792,
"spec/models/lock_spec.rb": 1.1113524436950684,
"spec/models/verification/management/email_spec.rb": 1.1114835739135742,
"spec/models/poll/stats_spec.rb": 0.3968682289123535,
"spec/models/follow_spec.rb": 0.8256139755249023,
"spec/features/comments/polls_spec.rb": 21.96089220046997,
"spec/features/banners_spec.rb": 0.2906479835510254,
"spec/models/site_customization/page_spec.rb": 0.3322629928588867,
"spec/features/communities_spec.rb": 3.2789883613586426,
"spec/features/admin/feature_flags_spec.rb": 1.132093906402588,
"spec/lib/graph_ql/query_type_creator_spec.rb": 0.6072323322296143,
"spec/features/admin/budget_investments_spec.rb": 86.10131597518921,
"spec/features/budgets/budgets_spec.rb": 13.255339860916138,
"spec/features/valuation/budget_investments_spec.rb": 31.438318729400635,
"spec/models/ahoy/data_source_spec.rb": 0.6344237327575684,
"spec/models/poll/booth_assignment_spec.rb": 0.46668219566345215,
"spec/models/proposal_notification_spec.rb": 4.204906940460205,
"spec/features/user_invites_spec.rb": 0.4354379177093506,
"spec/helpers/geozones_helper_spec.rb": 0.9684832096099854,
"spec/models/legislation/question_spec.rb": 6.248215675354004,
"spec/models/verification/residence_spec.rb": 2.4803614616394043,
"spec/models/legislation/draft_version_spec.rb": 0.3877832889556885,
"spec/features/admin/budgets_spec.rb": 18.929471492767334,
"spec/features/management/proposals_spec.rb": 9.127071380615234,
"spec/features/moderation/debates_spec.rb": 7.70769739151001,
"spec/features/social_media_meta_tags_spec.rb": 0.30097007751464844,
"spec/controllers/admin/api/stats_controller_spec.rb": 2.202134847640991,
"spec/features/admin/signature_sheets_spec.rb": 2.9197773933410645,
"spec/lib/tasks/sitemap_spec.rb": 0.7607641220092773,
"spec/features/users_auth_spec.rb": 10.074970483779907,
"spec/models/budget/investment_spec.rb": 77.52746367454529,
"spec/features/admin/legislation/processes_spec.rb": 5.921939373016357,
"spec/models/poll/answer_spec.rb": 1.8080997467041016,
"spec/models/abilities/everyone_spec.rb": 6.280303716659546,
"spec/features/admin/proposals_spec.rb": 3.280435085296631,
"spec/features/polls/answers_spec.rb": 28.02806258201599,
"spec/models/map_location_spec.rb": 1.8255784511566162,
"spec/models/officing/residence_spec.rb": 2.852863073348999,
"spec/features/verification/verified_user_spec.rb": 3.1749560832977295,
"spec/models/user_spec.rb": 22.271785974502563,
"spec/models/identity_spec.rb": 0.17369508743286133,
"spec/lib/tasks/communities_spec.rb": 0.7490401268005371,
"spec/features/admin/officials_spec.rb": 1.6272509098052979,
"spec/models/direct_upload_spec.rb": 3.0308420658111572,
"spec/features/site_customization/content_blocks_spec.rb": 0.8640329837799072,
"spec/features/moderation_spec.rb": 2.6949400901794434,
"spec/features/tracks_spec.rb": 3.0615041255950928,
"spec/features/admin/verifications_spec.rb": 1.4874811172485352,
"spec/helpers/users_helper_spec.rb": 1.5008788108825684,
"spec/features/comments/budget_investments_valuation_spec.rb": 22.839407920837402,
"spec/lib/acts_as_paranoid_aliases_spec.rb": 0.8761029243469238,
"spec/controllers/installation_controller_spec.rb": 0.3377339839935303,
"spec/features/management/account_spec.rb": 7.201076984405518,
"spec/models/legislation/question_option_spec.rb": 0.4266631603240967,
"spec/lib/graphql_spec.rb": 17.87411117553711,
"spec/models/budget/heading_spec.rb": 3.4914908409118652,
"spec/features/admin/poll/booths_spec.rb": 2.516435146331787,
"spec/features/welcome_spec.rb": 3.0004467964172363,
"spec/helpers/comments_helper_spec.rb": 1.2135119438171387,
"spec/features/users_spec.rb": 24.293161392211914,
"spec/features/admin/administrators_spec.rb": 4.341719627380371,
"spec/features/verification/verification_path_spec.rb": 2.854844093322754,
"spec/features/verification/email_spec.rb": 1.0166842937469482,
"spec/helpers/proposals_helper_spec.rb": 1.3801281452178955,
"spec/features/comments/legislation_questions_spec.rb": 45.956820249557495,
"spec/features/admin/tags_spec.rb": 2.420088291168213,
"spec/features/valuation_spec.rb": 4.048749208450317,
"spec/features/emails_spec.rb": 19.99254083633423,
"spec/features/officing_spec.rb": 11.246239423751831,
"spec/features/comments/topics_spec.rb": 69.58891487121582,
"spec/views/welcome/index.html.erb_spec.rb": 0.5793781280517578,
"spec/helpers/admin_helper_spec.rb": 0.4212000370025635,
"spec/features/admin/users_spec.rb": 1.1472148895263672,
"spec/features/votes_spec.rb": 29.099965810775757,
"spec/features/tags_spec.rb": 5.1985626220703125,
"spec/lib/age_spec.rb": 0.7978200912475586,
"spec/features/budgets/investments_spec.rb": 351.26232838630676,
"spec/controllers/management/users_controller_spec.rb": 0.26859092712402344,
"spec/models/valuator_spec.rb": 1.962721347808838,
"spec/models/poll/question_spec.rb": 0.6985437870025635,
"spec/models/widget/feed_spec.rb": 0.9729278087615967,
"spec/lib/migrate_spending_proposals_to_investments_spec.rb": 3.59675669670105,
"spec/models/budget/reclassified_vote_spec.rb": 1.5055556297302246,
"spec/lib/email_digests_spec.rb": 2.27150559425354,
"spec/features/localization_spec.rb": 2.979036569595337,
"spec/models/proposal_spec.rb": 33.42528510093689,
"spec/features/tags/proposals_spec.rb": 12.582791090011597,
"spec/controllers/management/base_controller_spec.rb": 0.3726541996002197,
"spec/models/community_spec.rb": 0.4524242877960205,
"spec/features/polls/questions_spec.rb": 0.3054237365722656,
"spec/features/admin/moderators_spec.rb": 4.331509590148926,
"spec/features/admin/budget_phases_spec.rb": 0.6040239334106445,
"spec/features/notifications_spec.rb": 6.421470880508423,
"spec/lib/graph_ql/api_types_creator_spec.rb": 0.9511966705322266,
"spec/models/poll/shift_spec.rb": 2.6664018630981445,
"spec/features/verification/sms_spec.rb": 2.5740511417388916,
"spec/helpers/text_helper_spec.rb": 0.36423563957214355,
"spec/models/verification/sms_spec.rb": 0.5979208946228027,
"spec/features/campaigns_spec.rb": 1.467015027999878,
"spec/models/abilities/valuator_spec.rb": 18.044712781906128,
"spec/features/admin/debates_spec.rb": 2.581214189529419,
"spec/models/budget_spec.rb": 11.64527177810669,
"spec/features/budgets/results_spec.rb": 5.408561706542969,
"spec/helpers/settings_helper_spec.rb": 0.49603271484375,
"spec/features/site_customization/custom_pages_spec.rb": 2.270458698272705,
"spec/controllers/concerns/has_filters_spec.rb": 1.1834051609039307,
"spec/lib/cache_spec.rb": 0.27863121032714844,
"spec/models/document_spec.rb": 7.068117380142212
}

View File

@@ -1016,6 +1016,20 @@ LOREM_IPSUM
sequence(:body) { |n| "Body #{n}" }
end
factory :admin_notification do
title { |n| "Admin Notification title #{n}" }
body { |n| "Admin Notification body #{n}" }
link nil
segment_recipient UserSegments::SEGMENTS.sample
recipients_count nil
sent_at nil
trait :sent do
recipients_count 1
sent_at Time.current
end
end
factory :widget_card, class: 'Widget::Card' do
sequence(:title) { |n| "Title #{n}" }
sequence(:description) { |n| "Description #{n}" }

View File

@@ -0,0 +1,236 @@
require 'rails_helper'
feature "Admin Notifications" do
background do
admin = create(:administrator)
login_as(admin.user)
create(:budget)
end
context "Show" do
scenario "Valid Admin Notification" do
notification = create(:admin_notification, title: 'Notification title',
body: 'Notification body',
link: 'https://www.decide.madrid.es/vota',
segment_recipient: :all_users)
visit admin_admin_notification_path(notification)
expect(page).to have_content('Notification title')
expect(page).to have_content('Notification body')
expect(page).to have_content('https://www.decide.madrid.es/vota')
expect(page).to have_content('All users')
end
scenario "Notification with invalid segment recipient" do
invalid_notification = create(:admin_notification)
invalid_notification.update_attribute(:segment_recipient, 'invalid_segment')
visit admin_admin_notification_path(invalid_notification)
expect(page).to have_content("Recipients user segment is invalid")
end
end
context "Index" do
scenario "Valid Admin Notifications" do
draft = create(:admin_notification, segment_recipient: :all_users, title: 'Not yet sent')
sent = create(:admin_notification, :sent, segment_recipient: :administrators,
title: 'Sent one')
visit admin_admin_notifications_path
expect(page).to have_css(".admin_notification", count: 2)
within("#admin_notification_#{draft.id}") do
expect(page).to have_content('Not yet sent')
expect(page).to have_content('All users')
expect(page).to have_content('Draft')
end
within("#admin_notification_#{sent.id}") do
expect(page).to have_content('Sent one')
expect(page).to have_content('Administrators')
expect(page).to have_content(I18n.l(Date.current))
end
end
scenario "Notifications with invalid segment recipient" do
invalid_notification = create(:admin_notification)
invalid_notification.update_attribute(:segment_recipient, 'invalid_segment')
visit admin_admin_notifications_path
expect(page).to have_content("Recipients user segment is invalid")
end
end
scenario "Create" do
visit admin_admin_notifications_path
click_link "New notification"
fill_in_admin_notification_form(segment_recipient: 'Proposal authors',
title: 'This is a title',
body: 'This is a body',
link: 'http://www.dummylink.dev')
click_button "Create Admin notification"
expect(page).to have_content "Notification created successfully"
expect(page).to have_content "Proposal authors"
expect(page).to have_content "This is a title"
expect(page).to have_content "This is a body"
expect(page).to have_content "http://www.dummylink.dev"
end
context "Update" do
scenario "A draft notification can be updated" do
notification = create(:admin_notification)
visit admin_admin_notifications_path
within("#admin_notification_#{notification.id}") do
click_link "Edit"
end
fill_in_admin_notification_form(segment_recipient: 'All users',
title: 'Other title',
body: 'Other body',
link: '')
click_button "Update Admin notification"
expect(page).to have_content "Notification updated successfully"
expect(page).to have_content "All users"
expect(page).to have_content "Other title"
expect(page).to have_content "Other body"
expect(page).not_to have_content "http://www.dummylink.dev"
end
scenario "Sent notification can not be updated" do
notification = create(:admin_notification, :sent)
visit admin_admin_notifications_path
within("#admin_notification_#{notification.id}") do
expect(page).not_to have_link("Edit")
end
end
end
context "Destroy" do
scenario "A draft notification can be destroyed" do
notification = create(:admin_notification)
visit admin_admin_notifications_path
within("#admin_notification_#{notification.id}") do
click_link "Delete"
end
expect(page).to have_content "Notification deleted successfully"
expect(page).to have_css(".notification", count: 0)
end
scenario "Sent notification can not be destroyed" do
notification = create(:admin_notification, :sent)
visit admin_admin_notifications_path
within("#admin_notification_#{notification.id}") do
expect(page).not_to have_link("Delete")
end
end
end
context "Visualize" do
scenario "A draft notification can be previewed" do
notification = create(:admin_notification, segment_recipient: :administrators)
visit admin_admin_notifications_path
within("#admin_notification_#{notification.id}") do
click_link "Preview"
end
expect(page).to have_content "This is how the users will see the notification:"
expect(page).to have_content "Administrators (1 users will be notified)"
end
scenario "A sent notification can be viewed" do
notification = create(:admin_notification, :sent, recipients_count: 7,
segment_recipient: :administrators)
visit admin_admin_notifications_path
within("#admin_notification_#{notification.id}") do
click_link "View"
end
expect(page).to have_content "This is how the users see the notification:"
expect(page).to have_content "Administrators (7 users got notified)"
end
end
scenario 'Errors on create' do
visit new_admin_admin_notification_path
click_button "Create Admin notification"
expect(page).to have_content error_message
end
scenario "Errors on update" do
notification = create(:admin_notification)
visit edit_admin_admin_notification_path(notification)
fill_in :admin_notification_title, with: ''
click_button "Update Admin notification"
expect(page).to have_content error_message
end
context "Send notification", :js do
scenario "A draft Admin notification can be sent", :js do
2.times { create(:user) }
notification = create(:admin_notification, segment_recipient: :all_users)
total_users = notification.list_of_recipients.count
confirm_message = "Are you sure you want to send this notification to #{total_users} users?"
visit admin_admin_notification_path(notification)
accept_confirm { click_link "Send" }
expect(page).to have_content "Notification sent successfully"
User.all.each do |user|
expect(user.notifications.count).to eq(1)
end
end
scenario "A sent Admin notification can not be sent", :js do
notification = create(:admin_notification, :sent)
visit admin_admin_notification_path(notification)
expect(page).not_to have_link("Send")
end
scenario "Admin notification with invalid segment recipient cannot be sent", :js do
invalid_notification = create(:admin_notification)
invalid_notification.update_attribute(:segment_recipient, 'invalid_segment')
visit admin_admin_notification_path(invalid_notification)
expect(page).not_to have_link("Send")
end
end
scenario "Select list of users to send notification" do
UserSegments::SEGMENTS.each do |user_segment|
segment_recipient = I18n.t("admin.segment_recipient.#{user_segment}")
visit new_admin_admin_notification_path
fill_in_admin_notification_form(segment_recipient: segment_recipient)
click_button "Create Admin notification"
expect(page).to have_content(I18n.t("admin.segment_recipient.#{user_segment}"))
end
end
end

View File

@@ -49,6 +49,8 @@ feature 'Admin can change the groups name' do
scenario "Defaults to 1 heading per group", :js do
visit admin_budget_path(group.budget)
expect(page).to have_content('Maximum number of headings in which a user can vote 1 of 3')
within("#budget_group_#{group.id}") do
click_link 'Edit group'
@@ -66,7 +68,7 @@ feature 'Admin can change the groups name' do
click_button 'Save group'
end
visit admin_budget_path(group.budget)
expect(page).to have_content('Maximum number of headings in which a user can vote 2 of 3')
within("#budget_group_#{group.id}") do
click_link 'Edit group'
@@ -75,13 +77,13 @@ feature 'Admin can change the groups name' do
end
end
scenario "Do not display maxium votable headings' select in new form", :js do
scenario "Do not display maximum votable headings' select in new form", :js do
visit admin_budget_path(group.budget)
click_link 'Add new group'
expect(page).to have_field('budget_group_name')
expect(page).to_not have_field('budget_group_max_votable_headings')
expect(page).not_to have_field('budget_group_max_votable_headings')
end
end

View File

@@ -110,24 +110,28 @@ feature 'Admin budget investments' do
expect(page).to have_link("Plant trees")
select "Central Park", from: "heading_id"
click_button 'Filter'
expect(page).not_to have_link("Realocate visitors")
expect(page).not_to have_link("Change name")
expect(page).to have_link("Plant trees")
select "All headings", from: "heading_id"
click_button 'Filter'
expect(page).to have_link("Realocate visitors")
expect(page).to have_link("Change name")
expect(page).to have_link("Plant trees")
select "Streets: Main Avenue", from: "heading_id"
click_button 'Filter'
expect(page).to have_link("Realocate visitors")
expect(page).not_to have_link("Change name")
expect(page).not_to have_link("Plant trees")
select "Streets: Mercy Street", from: "heading_id"
click_button 'Filter'
expect(page).not_to have_link("Realocate visitors")
expect(page).to have_link("Change name")
@@ -146,18 +150,22 @@ feature 'Admin budget investments' do
expect(page).to have_link("Destroy the city")
select "Admin 1", from: "administrator_id"
click_button 'Filter'
expect(page).to have_content('There is 1 investment')
expect(page).not_to have_link("Destroy the city")
expect(page).to have_link("Realocate visitors")
select "All administrators", from: "administrator_id"
click_button 'Filter'
expect(page).to have_content('There are 2 investments')
expect(page).to have_link("Destroy the city")
expect(page).to have_link("Realocate visitors")
select "Admin 1", from: "administrator_id"
click_button 'Filter'
expect(page).to have_content('There is 1 investment')
expect(page).not_to have_link("Destroy the city")
expect(page).to have_link("Realocate visitors")
@@ -177,18 +185,21 @@ feature 'Admin budget investments' do
expect(page).to have_link("Destroy the city")
select "Valuator 1", from: "valuator_or_group_id"
click_button 'Filter'
expect(page).to have_content('There is 1 investment')
expect(page).not_to have_link("Destroy the city")
expect(page).to have_link("Realocate visitors")
select "All valuators", from: "valuator_or_group_id"
click_button 'Filter'
expect(page).to have_content('There are 2 investments')
expect(page).to have_link("Destroy the city")
expect(page).to have_link("Realocate visitors")
select "Valuator 1", from: "valuator_or_group_id"
click_button 'Filter'
expect(page).to have_content('There is 1 investment')
expect(page).not_to have_link("Destroy the city")
expect(page).to have_link("Realocate visitors")
@@ -210,18 +221,22 @@ feature 'Admin budget investments' do
expect(page).to have_link("Build a theatre")
select "Health", from: "valuator_or_group_id"
click_button 'Filter'
expect(page).to have_content('There is 1 investment')
expect(page).to have_link("Build a hospital")
expect(page).not_to have_link("Build a theatre")
select "All valuators", from: "valuator_or_group_id"
click_button 'Filter'
expect(page).to have_content('There are 2 investments')
expect(page).to have_link("Build a hospital")
expect(page).to have_link("Build a theatre")
select "Culture", from: "valuator_or_group_id"
click_button 'Filter'
expect(page).to have_content('There is 1 investment')
expect(page).to have_link("Build a theatre")
expect(page).not_to have_link("Build a hospital")
@@ -411,6 +426,140 @@ feature 'Admin budget investments' do
end
end
scenario "Combination of checkbox with text search", :js do
user = create(:user, username: 'Admin 1')
administrator = create(:administrator, user: user)
create(:budget_investment, budget: budget, title: 'Educate the children',
id: 20, administrator: administrator)
create(:budget_investment, budget: budget, title: 'More schools',
id: 10, administrator: administrator)
create(:budget_investment, budget: budget, title: 'More hospitals')
visit admin_budget_budget_investments_path(budget_id: budget.id)
expect(page).to have_css(".budget_investment", count: 3)
expect(page).to have_content("Educate the children")
expect(page).to have_content("More schools")
expect(page).to have_content("More hospitals")
select "Admin 1", from: "administrator_id"
click_button "Filter"
expect(page).to have_css(".budget_investment", count: 2)
expect(page).to have_content("Educate the children")
expect(page).to have_content("More schools")
expect(page).not_to have_content("More hospitals")
fill_in 'title_or_id', with: 20
click_button "Filter"
expect(page).to have_css(".budget_investment", count: 1)
expect(page).to have_content("Educate the children")
expect(page).not_to have_content("More schools")
expect(page).not_to have_content("More hospitals")
expect(page).to have_content('Selected')
end
scenario "Combination of select with text search", :js do
create(:budget_investment, budget: budget, title: 'Educate the children',
feasibility: 'feasible', id: 20,
valuation_finished: true)
create(:budget_investment, budget: budget, title: 'More schools',
feasibility: 'feasible', id: 10,
valuation_finished: true)
create(:budget_investment, budget: budget, title: 'More hospitals')
visit admin_budget_budget_investments_path(budget_id: budget.id)
expect(page).to have_css(".budget_investment", count: 3)
expect(page).to have_content("Educate the children")
expect(page).to have_content("More schools")
expect(page).to have_content("More hospitals")
click_link 'Advanced filters'
page.check('advanced_filters_feasible')
click_button "Filter"
expect(page).to have_css(".budget_investment", count: 2)
expect(page).to have_content("Educate the children")
expect(page).to have_content("More schools")
expect(page).not_to have_content("More hospitals")
fill_in 'title_or_id', with: 20
click_button "Filter"
expect(page).to have_css(".budget_investment", count: 1)
expect(page).to have_content("Educate the children")
expect(page).not_to have_content("More schools")
expect(page).not_to have_content("More hospitals")
expect(page).to have_content('Selected')
end
scenario "Combination of checkbox with text search and checkbox", :js do
user = create(:user, username: 'Admin 1')
administrator = create(:administrator, user: user)
create(:budget_investment, budget: budget, title: 'Educate the children',
feasibility: 'feasible', id: 20,
valuation_finished: true,
administrator: administrator)
create(:budget_investment, budget: budget, title: 'More schools',
feasibility: 'feasible', id: 10,
valuation_finished: true,
administrator: administrator)
create(:budget_investment, budget: budget, title: 'More hospitals',
administrator: administrator)
create(:budget_investment, budget: budget, title: 'More hostals')
visit admin_budget_budget_investments_path(budget_id: budget.id)
expect(page).to have_css(".budget_investment", count: 4)
expect(page).to have_content("Educate the children")
expect(page).to have_content("More schools")
expect(page).to have_content("More hospitals")
expect(page).to have_content("More hostals")
select "Admin 1", from: "administrator_id"
click_button "Filter"
expect(page).to have_css(".budget_investment", count: 3)
expect(page).to have_content("Educate the children")
expect(page).to have_content("More schools")
expect(page).to have_content("More hospitals")
expect(page).not_to have_content("More hostals")
click_link 'Advanced filters'
page.check('advanced_filters_feasible')
click_button "Filter"
expect(page).to have_css(".budget_investment", count: 2)
expect(page).to have_content("Educate the children")
expect(page).to have_content("More schools")
expect(page).not_to have_content("More hospitals")
expect(page).not_to have_content("More hostals")
fill_in 'title_or_id', with: 20
click_button "Filter"
expect(page).to have_css(".budget_investment", count: 1)
expect(page).to have_content("Educate the children")
expect(page).not_to have_content("More schools")
expect(page).not_to have_content("More hospitals")
expect(page).not_to have_content("More hostals")
expect(page).to have_content('Selected')
end
end
context 'Search' do
@@ -429,7 +578,7 @@ feature 'Admin budget investments' do
expect(page).to have_content('Some other investment')
fill_in 'title_or_id', with: 'Some investment'
click_button 'Search'
click_button 'Filter'
expect(page).to have_content('Some investment')
expect(page).not_to have_content('Some other investment')
@@ -442,7 +591,7 @@ feature 'Admin budget investments' do
expect(page).to have_content('Some other investment')
fill_in 'title_or_id', with: first_investment.id
click_button 'Search'
click_button 'Filter'
expect(page).to have_content('Some other investment')
expect(page).not_to have_content('Some investment')
@@ -823,7 +972,7 @@ feature 'Admin budget investments' do
expect(page).to have_content(winner_bi.title)
click_link 'Advanced filters'
within('#advanced_filters') { find(:css, "#advanced_filters_[value='feasible']").set(true) }
within('#advanced_filters') { find(:css, "#advanced_filters_feasible").set(true) }
click_button 'Filter'
expect(page).not_to have_content(unfeasible_bi.title)
@@ -832,8 +981,8 @@ feature 'Admin budget investments' do
expect(page).to have_content(selected_bi.title)
expect(page).to have_content(winner_bi.title)
within('#advanced_filters') { find(:css, "#advanced_filters_[value='selected']").set(true) }
within('#advanced_filters') { find(:css, "#advanced_filters_[value='feasible']").set(false) }
within('#advanced_filters') { find(:css, "#advanced_filters_selected").set(true) }
within('#advanced_filters') { find(:css, "#advanced_filters_feasible").set(false) }
click_button 'Filter'
expect(page).not_to have_content(unfeasible_bi.title)
@@ -854,7 +1003,7 @@ feature 'Admin budget investments' do
visit admin_budget_budget_investments_path(budget)
click_link 'Advanced filters'
within('#advanced_filters') { find(:css, "#advanced_filters_[value='undecided']").set(true) }
within('#advanced_filters') { find(:css, "#advanced_filters_undecided").set(true) }
click_button 'Filter'
expect(page).to have_content(undecided_bi.title)
@@ -864,7 +1013,7 @@ feature 'Admin budget investments' do
expect(page).not_to have_content(unfeasible_bi.title)
expect(page).not_to have_content(feasible_vf_bi.title)
within('#advanced_filters') { find(:css, "#advanced_filters_[value='unfeasible']").set(true) }
within('#advanced_filters') { find(:css, "#advanced_filters_unfeasible").set(true) }
click_button 'Filter'
expect(page).to have_content(undecided_bi.title)
@@ -908,7 +1057,7 @@ feature 'Admin budget investments' do
end
click_link 'Advanced filters'
within('#advanced_filters') { find(:css, "#advanced_filters_[value='selected']").set(true) }
within('#advanced_filters') { find(:css, "#advanced_filters_selected").set(true) }
click_button 'Filter'
within("#budget_investment_#{feasible_vf_bi.id}") do
@@ -920,7 +1069,9 @@ feature 'Admin budget investments' do
scenario "Unselecting an investment", :js do
visit admin_budget_budget_investments_path(budget)
click_link 'Advanced filters'
within('#advanced_filters') { find(:css, "#advanced_filters_[value='selected']").set(true) }
within('#advanced_filters') { find(:css, "#advanced_filters_selected").set(true) }
click_button 'Filter'
expect(page).to have_content('There are 2 investments')
@@ -1060,13 +1211,15 @@ feature 'Admin budget investments' do
cached_votes_up: 88, price: 99,
valuators: [],
valuator_groups: [valuator_group],
administrator: admin)
administrator: admin,
visible_to_valuators: true)
second_investment = create(:budget_investment, :unfeasible, title: "Alt Investment",
budget: budget, group: budget_group,
heading: second_budget_heading,
cached_votes_up: 66, price: 88,
valuators: [valuator],
valuator_groups: [])
valuator_groups: [],
visible_to_valuators: false)
visit admin_budget_budget_investments_path(budget)
@@ -1077,10 +1230,11 @@ feature 'Admin budget investments' do
expect(header).to match(/filename="budget_investments.csv"$/)
csv_contents = "ID,Title,Supports,Administrator,Valuator,Valuation Group,Scope of operation,"\
"Feasibility,Val. Fin.,Selected\n#{first_investment.id},Le Investment,88,"\
"Admin,-,Valuator Group,Budget Heading,Feasible (€99),Yes,Yes\n"\
"#{second_investment.id},Alt Investment,66,No admin assigned,Valuator,-,"\
"Other Heading,Unfeasible,No,No\n"
"Feasibility,Val. Fin.,Selected,Show to valuators,Author username\n"\
"#{first_investment.id},Le Investment,88,Admin,-,Valuator Group,"\
"Budget Heading,Feasible (€99),Yes,Yes,Yes,#{first_investment.author.username}\n#{second_investment.id},"\
"Alt Investment,66,No admin assigned,Valuator,-,Other Heading,"\
"Unfeasible,No,No,No,#{second_investment.author.username}\n"
expect(page.body).to eq(csv_contents)
end

View File

@@ -501,7 +501,7 @@ feature 'Budget Investments' do
end
end
context("Orders") do
context "Orders" do
before { budget.update(phase: 'selecting') }
scenario "Default order is random" do
@@ -533,7 +533,7 @@ feature 'Budget Investments' do
expect(order).not_to eq(new_order)
end
scenario 'Random order maintained with pagination', :js do
scenario 'Random order maintained with pagination' do
per_page = Kaminari.config.default_per_page
(per_page + 2).times { create(:budget_investment, heading: heading) }
@@ -551,7 +551,21 @@ feature 'Budget Investments' do
expect(order).to eq(new_order)
end
scenario "Investments are not repeated with random order", :js do
scenario 'Random order maintained when going back from show' do
10.times { |i| create(:budget_investment, heading: heading) }
visit budget_investments_path(budget, heading_id: heading.id)
order = all(".budget-investment h3").collect {|i| i.text }
click_link Budget::Investment.first.title
click_link "Go back"
new_order = all(".budget-investment h3").collect {|i| i.text }
expect(order).to eq(new_order)
end
scenario "Investments are not repeated with random order" do
12.times { create(:budget_investment, heading: heading) }
# 12 instead of per_page + 2 because in each page there are 10 (in this case), not 25
@@ -570,7 +584,7 @@ feature 'Budget Investments' do
end
scenario 'Proposals are ordered by confidence_score', :js do
scenario 'Proposals are ordered by confidence_score' do
best_proposal = create(:budget_investment, heading: heading, title: 'Best proposal')
best_proposal.update_column(:confidence_score, 10)
worst_proposal = create(:budget_investment, heading: heading, title: 'Worst proposal')
@@ -591,7 +605,7 @@ feature 'Budget Investments' do
expect(current_url).to include('page=1')
end
scenario 'Each user has a different and consistent random budget investment order when random_seed is disctint', :js do
scenario 'Each user has a different and consistent random budget investment order when random_seed is disctint' do
(Kaminari.config.default_per_page * 1.3).to_i.times { create(:budget_investment, heading: heading) }
in_browser(:one) do
@@ -627,7 +641,7 @@ feature 'Budget Investments' do
end
end
scenario 'Each user has a equal and consistent budget investment order when the random_seed is equal', :js do
scenario 'Each user has a equal and consistent budget investment order when the random_seed is equal' do
(Kaminari.config.default_per_page * 1.3).to_i.times { create(:budget_investment, heading: heading) }
in_browser(:one) do
@@ -641,7 +655,44 @@ feature 'Budget Investments' do
end
expect(@first_user_investments_order).to eq(@second_user_investments_order)
end
scenario "Set votes for investments randomized with a seed" do
voter = create(:user, :level_two)
login_as(voter)
10.times { create(:budget_investment, heading: heading) }
voted_investments = []
10.times do
investment = create(:budget_investment, heading: heading)
create(:vote, votable: investment, voter: voter)
voted_investments << investment
end
visit budget_investments_path(budget, heading_id: heading.id)
voted_investments.each do |investment|
if page.has_link?(investment.title)
within("#budget_investment_#{investment.id}") do
expect(page).to have_content "You have already supported this investment"
end
end
end
end
scenario 'Order is random if budget is finished' do
10.times { create(:budget_investment) }
budget.update(phase: 'finished')
visit budget_investments_path(budget, heading_id: heading.id)
order = all(".budget-investment h3").collect {|i| i.text }
visit budget_investments_path(budget, heading_id: heading.id)
new_order = eq(all(".budget-investment h3").collect {|i| i.text })
expect(order).not_to eq(new_order)
end
def investments_order
@@ -832,6 +883,10 @@ feature 'Budget Investments' do
expect(page).to have_content(investment.formatted_price)
expect(page).to have_content(investment.price_explanation)
if budget.finished?
investment.update(winner: true)
end
visit budget_investments_path(budget)
expect(page).to have_content(investment.formatted_price)
@@ -1079,6 +1134,20 @@ feature 'Budget Investments' do
end
end
scenario "Only winner investments are show when budget is finished" do
3.times { create(:budget_investment, heading: heading) }
Budget::Investment.first.update(feasibility: 'feasible', selected: true, winner: true)
Budget::Investment.second.update(feasibility: 'feasible', selected: true, winner: true)
budget.update(phase: 'finished')
visit budget_investments_path(budget, heading_id: heading.id)
expect(page).to have_content("#{Budget::Investment.first.title}")
expect(page).to have_content("#{Budget::Investment.second.title}")
expect(page).not_to have_content("#{Budget::Investment.third.title}")
end
it_behaves_like "followable", "budget_investment", "budget_investment_path", { "budget_id": "budget_id", "id": "id" }
it_behaves_like "imageable", "budget_investment", "budget_investment_path", { "budget_id": "budget_id", "id": "id" }

View File

@@ -128,4 +128,50 @@ feature "Notifications" do
expect(page).to_not have_css("#notifications")
end
context "Admin Notifications" do
let(:admin_notification) do
create(:admin_notification, title: 'Notification title',
body: 'Notification body',
link: 'https://www.external.link.dev/',
segment_recipient: 'all_users')
end
let!(:notification) do
create(:notification, user: user, notifiable: admin_notification)
end
before do
login_as user
end
scenario "With external link" do
visit notifications_path
expect(page).to have_content('Notification title')
expect(page).to have_content('Notification body')
first("#notification_#{notification.id} a").click
expect(page.current_url).to eq('https://www.external.link.dev/')
end
scenario "With internal link" do
admin_notification.update_attributes(link: '/stats')
visit notifications_path
expect(page).to have_content('Notification title')
expect(page).to have_content('Notification body')
first("#notification_#{notification.id} a").click
expect(page).to have_current_path('/stats')
end
scenario "Without a link" do
admin_notification.update_attributes(link: '/stats')
visit notifications_path
expect(page).to have_content('Notification title')
expect(page).to have_content('Notification body')
expect(page).not_to have_link(notification_path(notification), visible: false)
end
end
end

View File

@@ -360,15 +360,21 @@ feature 'Polls' do
context 'Booth & Website' do
let(:poll) { create(:poll, summary: "Summary", description: "Description") }
let(:poll) { create(:poll, summary: "Summary", description: "Description", starts_at: '2017-12-01', ends_at: '2018-02-01') }
let(:booth) { create(:poll_booth) }
let(:officer) { create(:poll_officer) }
before do
allow(Date).to receive(:current).and_return Date.new(2018,1,1)
allow(Date).to receive(:today).and_return Date.new(2018,1,1)
allow(Time).to receive(:current).and_return Time.zone.parse("2018-01-01 12:00:00")
end
scenario 'Already voted on booth cannot vote on website', :js do
create(:poll_shift, officer: officer, booth: booth, date: Date.current, task: :vote_collection)
booth_assignment = create(:poll_booth_assignment, poll: poll, booth: booth)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment)
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment, date: Date.current)
question = create(:poll_question, poll: poll)
create(:poll_question_answer, question: question, title: 'Han Solo')
create(:poll_question_answer, question: question, title: 'Chewbacca')

View File

@@ -1811,4 +1811,41 @@ feature 'Successful proposals' do
end
end
context "Skip user verification" do
before do
Setting["feature.user.skip_verification"] = 'true'
end
after do
Setting["feature.user.skip_verification"] = nil
end
scenario "Create" do
author = create(:user)
login_as(author)
visit proposals_path
within('aside') do
click_link 'Create a proposal'
end
expect(current_path).to eq(new_proposal_path)
fill_in 'proposal_title', with: 'Help refugees'
fill_in 'proposal_summary', with: 'In summary what we want is...'
fill_in 'proposal_question', with: 'Would you like to?'
fill_in 'proposal_description', with: 'This is very important because...'
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
fill_in 'proposal_video_url', with: 'https://www.youtube.com/watch?v=yPQfcG-eimk'
fill_in 'proposal_tag_list', with: 'Refugees, Solidarity'
check 'proposal_terms_of_service'
click_button 'Create proposal'
expect(page).to have_content 'Proposal created successfully.'
end
end
end

View File

@@ -254,6 +254,12 @@ feature 'Tags' do
investment.update(selected: true, feasibility: "feasible")
end
if budget.finished?
[investment1, investment2, investment3].each do |investment|
investment.update(selected: true, feasibility: "feasible", winner: true)
end
end
login_as(admin) if budget.drafting?
visit budget_path(budget)
click_link group.name
@@ -299,6 +305,12 @@ feature 'Tags' do
investment.update(selected: true, feasibility: "feasible")
end
if budget.finished?
[investment1, investment2, investment3].each do |investment|
investment.update(selected: true, feasibility: "feasible", winner: true)
end
end
login_as(admin) if budget.drafting?
visit budget_path(budget)
click_link group.name

View File

@@ -0,0 +1,91 @@
require 'rails_helper'
describe AdminNotification do
let(:admin_notification) { build(:admin_notification) }
it "is valid" do
expect(admin_notification).to be_valid
end
it 'is not valid without a title' do
admin_notification.title = nil
expect(admin_notification).not_to be_valid
end
it 'is not valid without a body' do
admin_notification.body = nil
expect(admin_notification).not_to be_valid
end
it 'is not valid without a segment_recipient' do
admin_notification.segment_recipient = nil
expect(admin_notification).not_to be_valid
end
describe '#complete_link_url' do
it 'does not change link if there is no value' do
expect(admin_notification.link).to be_nil
end
it 'fixes a link without http://' do
admin_notification.link = 'lol.consul.dev'
expect(admin_notification).to be_valid
expect(admin_notification.link).to eq('http://lol.consul.dev')
end
it 'fixes a link with wwww. but without http://' do
admin_notification.link = 'www.lol.consul.dev'
expect(admin_notification).to be_valid
expect(admin_notification.link).to eq('http://www.lol.consul.dev')
end
it 'does not modify a link with http://' do
admin_notification.link = 'http://lol.consul.dev'
expect(admin_notification).to be_valid
expect(admin_notification.link).to eq('http://lol.consul.dev')
end
it 'does not modify a link with https://' do
admin_notification.link = 'https://lol.consul.dev'
expect(admin_notification).to be_valid
expect(admin_notification.link).to eq('https://lol.consul.dev')
end
it 'does not modify a link with http://wwww.' do
admin_notification.link = 'http://www.lol.consul.dev'
expect(admin_notification).to be_valid
expect(admin_notification.link).to eq('http://www.lol.consul.dev')
end
end
describe '#valid_segment_recipient?' do
it 'is false when segment_recipient value is invalid' do
admin_notification.update(segment_recipient: 'invalid_segment_name')
error = 'The user recipients segment is invalid'
expect(admin_notification).not_to be_valid
expect(admin_notification.errors.messages[:segment_recipient]).to include(error)
end
end
describe '#list_of_recipients' do
let(:erased_user) { create(:user, username: 'erased_user') }
before do
2.times { create(:user) }
erased_user.erase
admin_notification.update(segment_recipient: 'all_users')
end
it 'returns list of all active users' do
expect(admin_notification.list_of_recipients.count).to eq(2)
expect(admin_notification.list_of_recipients).not_to include(erased_user)
end
end
end

View File

@@ -56,4 +56,11 @@ module Notifications
field_check_message = 'Please check the marked fields to know how to correct them:'
/\d errors? prevented this #{resource_model} from being saved. #{field_check_message}/
end
def fill_in_admin_notification_form(options = {})
select (options[:segment_recipient] || 'All users'), from: :admin_notification_segment_recipient
fill_in :admin_notification_title, with: (options[:title] || 'This is the notification title')
fill_in :admin_notification_body, with: (options[:body] || 'This is the notification body')
fill_in :admin_notification_link, with: (options[:link] || 'https://www.decide.madrid.es/vota')
end
end