Collaborative legislation summary
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,4 +38,3 @@
|
||||
public/sitemap.xml
|
||||
public/system/
|
||||
/public/ckeditor_assets/
|
||||
|
||||
|
||||
74
CHANGELOG.md
74
CHANGELOG.md
@@ -3,6 +3,77 @@
|
||||
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)
|
||||
|
||||
## [1.0.0](https://github.com/consul/consul/tree/1.0.0) (2019-06-10)
|
||||
[Full Changelog](https://github.com/consul/consul/compare/1.0.0-beta...1.0.0)
|
||||
|
||||
### Added
|
||||
- **Accounts:** Add description field to administrator users like evaluators description [\#3389](https://github.com/consul/consul/pull/3389)
|
||||
- **Admin:** Add document uploads from admin section [\#3466](https://github.com/consul/consul/pull/3466)
|
||||
- **Admin:** Images and documents settings [\#3585](https://github.com/consul/consul/pull/3585)
|
||||
- **Budgets:** notify by email new evaluation comments [\#3413](https://github.com/consul/consul/pull/3413)
|
||||
- **Installation:** Add deploy-secrets.yml.example file [\#3516](https://github.com/consul/consul/pull/3516)
|
||||
- **Installation:** Add new settings automatically on every deployment [\#3576](https://github.com/consul/consul/pull/3576)
|
||||
- **Installation:** Add task to upgrade to a new release [\#3590](https://github.com/consul/consul/pull/3590)
|
||||
- **Legislations:** Create Legislation::PeopleProposal model [\#3591](https://github.com/consul/consul/pull/3591)
|
||||
- **Translations:** Update translations from Crowdin [\#3378](https://github.com/consul/consul/pull/3378)
|
||||
- **Translations:** Admin basic customization texts [\#3488](https://github.com/consul/consul/pull/3488)
|
||||
- **Translations:** Add Bosnian, Croatian, Czech, Danish, Greek, and Turkish locales [\#3571](https://github.com/consul/consul/pull/3571)
|
||||
- **Newsletters:** Proposals authors user segment [\#3507](https://github.com/consul/consul/pull/3507)
|
||||
- **Polls:** Add slug to polls [\#3504](https://github.com/consul/consul/pull/3504)
|
||||
- **Statistics:** Add budget stats [\#3438](https://github.com/consul/consul/pull/3438)
|
||||
- **Statistics:** Add admin budget stats [\#3499](https://github.com/consul/consul/pull/3499)
|
||||
- **Statistics:** Add options to show advanced stats [\#3520](https://github.com/consul/consul/pull/3520)
|
||||
|
||||
### Changed
|
||||
- **Accounts:** Change devise configuration [\#3561](https://github.com/consul/consul/pull/3561)
|
||||
- **Admin:** Show count of votes associated to verified signatures [\#2616](https://github.com/consul/consul/pull/2616)
|
||||
- **Budgets:** Don't destroy budgets with an associated poll [\#3492](https://github.com/consul/consul/pull/3492)
|
||||
- **Budgets:** Add task to regenerate ballot\_lines\_count cache [\#3563](https://github.com/consul/consul/pull/3563)
|
||||
- **Dashboard:** Hide polls created by users from proposals dashboard on admin poll index [\#3572](https://github.com/consul/consul/pull/3572)
|
||||
- **Dashboard:** Allow users to delete dashboard polls [\#3574](https://github.com/consul/consul/pull/3574)
|
||||
- **Maintenance:** Add Rails 5.1 compatibility [\#3562](https://github.com/consul/consul/pull/3562)
|
||||
- **Maintenance:** Update migrations and schema file [\#3598](https://github.com/consul/consul/pull/3598)
|
||||
- **Maintenance-Refactoring:** Refactor admin/debates and admin/comments to hidden [\#3376](https://github.com/consul/consul/pull/3376)
|
||||
- **Maintenance-Refactoring:** Simplify stats caching [\#3510](https://github.com/consul/consul/pull/3510)
|
||||
- **Maintenance-Refactoring:** Refactor gender and age stats methods [\#3511](https://github.com/consul/consul/pull/3511)
|
||||
- **Maintenance-Refactoring:** Simplify link to poll [\#3519](https://github.com/consul/consul/pull/3519)
|
||||
- **Maintenance-Refactoring:** Extract partial with mobile sticky content [\#3577](https://github.com/consul/consul/pull/3577)
|
||||
- **Maintenance-Refactoring:** Use find instead of find by [\#3580](https://github.com/consul/consul/pull/3580)
|
||||
- **Maintenance-Rubocop:** Allow lines to be 110 characters long by Rubocop [\#3529](https://github.com/consul/consul/pull/3529)
|
||||
- **Maintenance-Seeds:** Simplify settings seeds [\#3564](https://github.com/consul/consul/pull/3564)
|
||||
- **Polls:** Display all polls for current booth [\#3361](https://github.com/consul/consul/pull/3361)
|
||||
- **Polls:** Allow delete polls with associated questions and answers [\#3476](https://github.com/consul/consul/pull/3476)
|
||||
- **Polls:** Remove redirect for poll officers [\#3506](https://github.com/consul/consul/pull/3506)
|
||||
- **Polls:** Remove token on views [\#3539](https://github.com/consul/consul/pull/3539)
|
||||
- **Proposals:** Remove question and external_url fields from proposals and legislation proposals [\#3397](https://github.com/consul/consul/pull/3397)
|
||||
- **Proposals:** Proposals support on mobile [\#3515](https://github.com/consul/consul/pull/3515)
|
||||
- **Proposals:** Make proposals to be selected by administrators [\#3567](https://github.com/consul/consul/pull/3567)
|
||||
- **Statistics:** Improve poll stats [\#3503](https://github.com/consul/consul/pull/3503)
|
||||
- **Statistics:** Change stats layout [\#3512](https://github.com/consul/consul/pull/3512)
|
||||
- **UX/UI:** Improve help texts on Admin UI [\#3508](https://github.com/consul/consul/pull/3508)
|
||||
- **UX/UI:** Users menu [\#3509](https://github.com/consul/consul/pull/3509)
|
||||
- **UX/UI:** Add help texs, links and new message section to improve UX [\#3573](https://github.com/consul/consul/pull/3573)
|
||||
|
||||
### Fixed
|
||||
- **Budgets:** Don't show links to disabled budget results [\#3592](https://github.com/consul/consul/pull/3592)
|
||||
- **Legislations:** Fix order in annotation comments with same score [\#3565](https://github.com/consul/consul/pull/3565)
|
||||
- **Maintenance:** Fix obsolete `respond\_with\_bip` usage [\#3483](https://github.com/consul/consul/pull/3483)
|
||||
- **Maintenance:** Remove Rspec deprecation warning [\#3530](https://github.com/consul/consul/pull/3530)
|
||||
- **Maintenance:** Fix column order in schema file [\#3533](https://github.com/consul/consul/pull/3533)
|
||||
- **Maintenance:** Fix indentation in schema file [\#3595](https://github.com/consul/consul/pull/3595)
|
||||
- **Maintenance-Specs:** Fix typo in budget executions spec [\#3486](https://github.com/consul/consul/pull/3486)
|
||||
- **Maintenance-Specs:** Remove unused \(and flaky\) card code and its spec [\#3487](https://github.com/consul/consul/pull/3487)
|
||||
- **Maintenance-Specs:** Resize Capybara window back to its original size [\#3534](https://github.com/consul/consul/pull/3534)
|
||||
- **Maintenance-Specs:** Check the comment is present after commenting [\#3596](https://github.com/consul/consul/pull/3596)
|
||||
- **Maintenance-Specs:** Reset globalize fallbacks before every test [\#3601](https://github.com/consul/consul/pull/3601)
|
||||
- **Multi-language:** Avoid duplicate records using translations [\#3581](https://github.com/consul/consul/pull/3581)
|
||||
- **Polls:** Fix valid votes labels [\#3570](https://github.com/consul/consul/pull/3570)
|
||||
- **Polls:** Show name and email for deleted poll officer's user account [\#3587](https://github.com/consul/consul/pull/3587)
|
||||
- **UX/UI:** Always use map image from admin site customization images [\#3472](https://github.com/consul/consul/pull/3472)
|
||||
|
||||
### Removed
|
||||
- **Maintenance-Deprecated:** Delete spending proposals [\#3569](https://github.com/consul/consul/pull/3569)
|
||||
|
||||
## [1.0.0-beta](https://github.com/consul/consul/compare/v0.19...1.0.0-beta) (2019-04-29)
|
||||
|
||||
### Added
|
||||
@@ -782,7 +853,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/1.0.0-beta...consul:master
|
||||
[Unreleased]: https://github.com/consul/consul/compare/1.0.0...consul:master
|
||||
[1.0.0]: https://github.com/consul/consul/compare/1.0.0-beta...1.0.0
|
||||
[1.0.0-beta]: https://github.com/consul/consul/compare/v0.19...1.0.0-beta
|
||||
[0.19.0]: https://github.com/consul/consul/compare/v0.18...v.019
|
||||
[0.18.0]: https://github.com/consul/consul/compare/v0.17...v.018
|
||||
|
||||
@@ -414,6 +414,15 @@ code {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.content-type {
|
||||
white-space: nowrap;
|
||||
padding-right: $line-height;
|
||||
|
||||
label {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 02. Sidebar
|
||||
// -----------
|
||||
|
||||
|
||||
@@ -28,4 +28,22 @@ class Admin::AdministratorsController < Admin::BaseController
|
||||
|
||||
redirect_to admin_administrators_path
|
||||
end
|
||||
|
||||
def edit
|
||||
end
|
||||
|
||||
def update
|
||||
if @administrator.update(update_administrator_params)
|
||||
notice = t("admin.administrators.form.updated")
|
||||
redirect_to admin_administrators_path, notice: notice
|
||||
else
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_administrator_params
|
||||
params.require(:administrator).permit(:description)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -46,11 +46,11 @@ class Admin::BudgetGroupsController < Admin::BaseController
|
||||
private
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.includes(:groups).find(params[:budget_id])
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def load_group
|
||||
@group = @budget.groups.find(params[:id])
|
||||
@group = @budget.groups.find_by_slug_or_id! params[:id]
|
||||
end
|
||||
|
||||
def groups_index
|
||||
|
||||
@@ -47,15 +47,15 @@ class Admin::BudgetHeadingsController < Admin::BaseController
|
||||
private
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.includes(:groups).find(params[:budget_id])
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def load_group
|
||||
@group = @budget.groups.find(params[:group_id])
|
||||
@group = @budget.groups.find_by_slug_or_id! params[:group_id]
|
||||
end
|
||||
|
||||
def load_heading
|
||||
@heading = @group.headings.find(params[:id])
|
||||
@heading = @group.headings.find_by_slug_or_id! params[:id]
|
||||
end
|
||||
|
||||
def headings_index
|
||||
|
||||
@@ -83,11 +83,11 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
|
||||
params.require(:budget_investment)
|
||||
.permit(:title, :description, :external_url, :heading_id, :administrator_id, :tag_list,
|
||||
:valuation_tag_list, :incompatible, :visible_to_valuators, :selected,
|
||||
valuator_ids: [], valuator_group_ids: [])
|
||||
:milestone_tag_list, valuator_ids: [], valuator_group_ids: [])
|
||||
end
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.includes(:groups).find(params[:budget_id])
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def load_investment
|
||||
|
||||
@@ -6,6 +6,7 @@ class Admin::BudgetsController < Admin::BaseController
|
||||
|
||||
has_filters %w{open finished}, only: :index
|
||||
|
||||
before_action :load_budget, except: [:index, :new, :create]
|
||||
load_and_authorize_resource
|
||||
|
||||
def index
|
||||
@@ -66,4 +67,8 @@ class Admin::BudgetsController < Admin::BaseController
|
||||
params.require(:budget).permit(*valid_attributes, *report_attributes, translation_params(Budget))
|
||||
end
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find_by_slug_or_id! params[:id]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class Admin::CommentsController < Admin::BaseController
|
||||
class Admin::HiddenCommentsController < Admin::BaseController
|
||||
has_filters %w{without_confirmed_hide all with_confirmed_hide}
|
||||
|
||||
before_action :load_comment, only: [:confirm_hide, :restore]
|
||||
@@ -1,4 +1,4 @@
|
||||
class Admin::DebatesController < Admin::BaseController
|
||||
class Admin::HiddenDebatesController < Admin::BaseController
|
||||
include FeatureFlags
|
||||
|
||||
feature_flag :debates
|
||||
@@ -29,4 +29,4 @@ class Admin::DebatesController < Admin::BaseController
|
||||
@debate = Debate.with_hidden.find(params[:id])
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -14,6 +14,7 @@ class Admin::SettingsController < Admin::BaseController
|
||||
@participation_processes_settings = all_settings["process"]
|
||||
@map_configuration_settings = all_settings["map"]
|
||||
@proposals_settings = all_settings["proposals"]
|
||||
@uploads_settings = all_settings["uploads"]
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -29,10 +30,24 @@ class Admin::SettingsController < Admin::BaseController
|
||||
redirect_to admin_settings_path, notice: t("admin.settings.index.map.flash.update")
|
||||
end
|
||||
|
||||
def update_content_types
|
||||
setting = Setting.find(params[:id])
|
||||
group = setting.content_type_group
|
||||
mime_type_values = content_type_params.keys.map do |content_type|
|
||||
Setting.mime_types[group][content_type]
|
||||
end
|
||||
setting.update value: mime_type_values.join(" ")
|
||||
redirect_to admin_settings_path, notice: t("admin.settings.flash.updated")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def settings_params
|
||||
params.require(:setting).permit(:value)
|
||||
end
|
||||
|
||||
def content_type_params
|
||||
params.permit(:jpg, :png, :gif, :pdf, :doc, :docx, :xls, :xlsx, :csv, :zip)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -14,7 +14,8 @@ class Admin::SystemEmailsController < Admin::BaseController
|
||||
direct_message_for_receiver: %w[view edit_info],
|
||||
direct_message_for_sender: %w[view edit_info],
|
||||
email_verification: %w[view edit_info],
|
||||
user_invite: %w[view edit_info]
|
||||
user_invite: %w[view edit_info],
|
||||
evaluation_comment: %w[view edit_info]
|
||||
}
|
||||
end
|
||||
|
||||
@@ -34,6 +35,8 @@ class Admin::SystemEmailsController < Admin::BaseController
|
||||
load_sample_user
|
||||
when "user_invite"
|
||||
@subject = t("mailers.user_invite.subject", org_name: Setting["org_name"])
|
||||
when "evaluation_comment"
|
||||
load_sample_valuation_comment
|
||||
end
|
||||
end
|
||||
|
||||
@@ -97,6 +100,17 @@ class Admin::SystemEmailsController < Admin::BaseController
|
||||
end
|
||||
end
|
||||
|
||||
def load_sample_valuation_comment
|
||||
comment = Comment.where(commentable_type: "Budget::Investment").last
|
||||
if comment
|
||||
@email = EvaluationCommentEmail.new(comment)
|
||||
@email_to = @email.to.first
|
||||
else
|
||||
redirect_to admin_system_emails_path,
|
||||
alert: t("admin.system_emails.alert.no_evaluation_comments")
|
||||
end
|
||||
end
|
||||
|
||||
def load_sample_user
|
||||
@user = User.last
|
||||
@token = @user.email_verification_token || SecureRandom.hex
|
||||
|
||||
@@ -37,7 +37,7 @@ module Budgets
|
||||
end
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find(params[:budget_id])
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def load_ballot
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module Budgets
|
||||
class BallotsController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
before_action :load_budget
|
||||
load_and_authorize_resource :budget
|
||||
before_action :load_ballot
|
||||
after_action :store_referer, only: [:show]
|
||||
@@ -13,6 +14,10 @@ module Budgets
|
||||
|
||||
private
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def load_ballot
|
||||
query = Budget::Ballot.where(user: current_user, budget: @budget)
|
||||
@ballot = @budget.balloting? ? query.first_or_create : query.first_or_initialize
|
||||
|
||||
@@ -12,15 +12,15 @@ module Budgets
|
||||
|
||||
private
|
||||
def investments_by_heading
|
||||
base = @budget.investments.winners
|
||||
base = base.joins(milestones: :translations).includes(:milestones)
|
||||
base = base.tagged_with(params[:milestone_tag]) if params[:milestone_tag].present?
|
||||
|
||||
if params[:status].present?
|
||||
@budget.investments.winners
|
||||
.with_milestone_status_id(params[:status])
|
||||
.uniq
|
||||
.group_by(&:heading)
|
||||
base = base.with_milestone_status_id(params[:status])
|
||||
base.uniq.group_by(&:heading)
|
||||
else
|
||||
@budget.investments.winners
|
||||
.joins(milestones: :translations)
|
||||
.distinct.group_by(&:heading)
|
||||
base.distinct.group_by(&:heading)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module Budgets
|
||||
class GroupsController < ApplicationController
|
||||
before_action :load_budget
|
||||
before_action :load_group
|
||||
load_and_authorize_resource :budget
|
||||
load_and_authorize_resource :group, class: "Budget::Group"
|
||||
|
||||
@@ -9,5 +11,14 @@ module Budgets
|
||||
def show
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def load_group
|
||||
@group = @budget.groups.find_by_slug_or_id! params[:id]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -10,6 +10,7 @@ module Budgets
|
||||
PER_PAGE = 10
|
||||
|
||||
before_action :authenticate_user!, except: [:index, :show, :json_data]
|
||||
before_action :load_budget, except: :json_data
|
||||
|
||||
load_and_authorize_resource :budget, except: :json_data
|
||||
load_and_authorize_resource :investment, through: :budget, class: "Budget::Investment",
|
||||
@@ -136,7 +137,7 @@ module Budgets
|
||||
|
||||
def load_heading
|
||||
if params[:heading_id].present?
|
||||
@heading = @budget.headings.find(params[:heading_id])
|
||||
@heading = @budget.headings.find_by_slug_or_id! params[:heading_id]
|
||||
@assigned_heading = @ballot.try(:heading_for_group, @heading.try(:group))
|
||||
load_map
|
||||
end
|
||||
@@ -154,6 +155,10 @@ module Budgets
|
||||
TagCloud.new(Budget::Investment, params[:search])
|
||||
end
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def set_view
|
||||
@view = (params[:view] == "minimal") ? "minimal" : "default"
|
||||
end
|
||||
|
||||
@@ -14,15 +14,14 @@ module Budgets
|
||||
private
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find_by(id: params[:budget_id])
|
||||
@budget = Budget.find_by_slug_or_id(params[:budget_id]) || Budget.first
|
||||
end
|
||||
|
||||
def load_heading
|
||||
@heading = if params[:heading_id].present?
|
||||
@budget.headings.find(params[:heading_id])
|
||||
else
|
||||
@budget.headings.first
|
||||
end
|
||||
if @budget.present?
|
||||
headings = @budget.headings
|
||||
@heading = headings.find_by_slug_or_id(params[:heading_id]) || headings.first
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ module Budgets
|
||||
private
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find_by(slug: params[:budget_id]) || Budget.find_by(id: params[:budget_id])
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@ class BudgetsController < ApplicationController
|
||||
include BudgetsHelper
|
||||
feature_flag :budgets
|
||||
|
||||
before_action :load_budget, only: :show
|
||||
load_and_authorize_resource
|
||||
before_action :set_default_budget_filter, only: :show
|
||||
has_filters %w[not_unfeasible feasible unfeasible unselected selected winners], only: :show
|
||||
@@ -19,4 +20,10 @@ class BudgetsController < ApplicationController
|
||||
@banners = Banner.in_section("budgets").with_active
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find_by_slug_or_id! params[:id]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -14,6 +14,7 @@ class CommentsController < ApplicationController
|
||||
if @comment.save
|
||||
CommentNotifier.new(comment: @comment).process
|
||||
add_notification @comment
|
||||
EvaluationCommentNotifier.new(comment: @comment).process if send_evaluation_notification?
|
||||
else
|
||||
render :new
|
||||
end
|
||||
@@ -107,4 +108,7 @@ class CommentsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def send_evaluation_notification?
|
||||
@comment.valuation && Setting["feature.valuation_comment_notification"]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ class InstallationController < ApplicationController
|
||||
|
||||
def consul_installation_details
|
||||
{
|
||||
release: "1.0.0-beta"
|
||||
release: "1.0.0"
|
||||
}.merge(features: settings_feature_flags)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class Management::Budgets::InvestmentsController < Management::BaseController
|
||||
before_action :load_budget
|
||||
|
||||
load_resource :budget
|
||||
load_resource :investment, through: :budget, class: "Budget::Investment"
|
||||
@@ -60,6 +61,10 @@ class Management::Budgets::InvestmentsController < Management::BaseController
|
||||
check_verified_user t("management.budget_investments.alert.unverified_user")
|
||||
end
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def load_categories
|
||||
@categories = ActsAsTaggableOn::Tag.category.order(:name)
|
||||
end
|
||||
|
||||
@@ -45,5 +45,4 @@ class Officing::BaseController < ApplicationController
|
||||
def current_booth
|
||||
Poll::Booth.where(id: session[:booth_id]).first
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -12,8 +12,9 @@ class PollsController < ApplicationController
|
||||
::Poll::Answer # trigger autoload
|
||||
|
||||
def index
|
||||
@polls = @polls.not_budget.public_polls.send(@current_filter).includes(:geozones)
|
||||
.sort_for_list.page(params[:page])
|
||||
@polls = Kaminari.paginate_array(
|
||||
@polls.public_polls.not_budget.send(@current_filter).includes(:geozones).sort_for_list
|
||||
).page(params[:page])
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -65,7 +65,7 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
|
||||
end
|
||||
|
||||
def load_budget
|
||||
@budget = Budget.find(params[:budget_id])
|
||||
@budget = Budget.find_by_slug_or_id! params[:budget_id]
|
||||
end
|
||||
|
||||
def load_investment
|
||||
@@ -75,9 +75,7 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
|
||||
def heading_filters
|
||||
investments = @budget.investments.by_valuator(current_user.valuator.try(:id))
|
||||
.visible_to_valuators.distinct
|
||||
investment_headings = Budget::Heading.joins(:translations)
|
||||
.where(id: investments.pluck(:heading_id).uniq)
|
||||
.order(name: :asc)
|
||||
investment_headings = Budget::Heading.where(id: investments.pluck(:heading_id)).sort_by(&:name)
|
||||
|
||||
all_headings_filter = [
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ module AdminHelper
|
||||
end
|
||||
|
||||
def moderated_sections
|
||||
["hidden_proposals", "debates", "comments", "hidden_users", "activity",
|
||||
["hidden_proposals", "hidden_debates", "hidden_comments", "hidden_users", "activity",
|
||||
"hidden_budget_investments"]
|
||||
end
|
||||
|
||||
@@ -77,7 +77,9 @@ module AdminHelper
|
||||
end
|
||||
|
||||
def admin_select_options
|
||||
Administrator.all.order("users.username asc").includes(:user).collect { |v| [ v.name, v.id ] }
|
||||
Administrator.with_user
|
||||
.collect { |v| [ v.description_or_name, v.id ] }
|
||||
.sort_by { |a| a[0] }
|
||||
end
|
||||
|
||||
def admin_submit_action(resource)
|
||||
|
||||
@@ -4,6 +4,12 @@ module BudgetExecutionsHelper
|
||||
@budget.investments.winners.with_milestone_status_id(status).count
|
||||
end
|
||||
|
||||
def options_for_milestone_tags
|
||||
@budget.milestone_tags.map do |tag|
|
||||
["#{tag} (#{@budget.investments.winners.tagged_with(tag).count})", tag]
|
||||
end
|
||||
end
|
||||
|
||||
def first_milestone_with_image(investment)
|
||||
investment.milestones.order_by_publication_date
|
||||
.select{ |milestone| milestone.image.present? }.last
|
||||
|
||||
@@ -105,4 +105,18 @@ module BudgetsHelper
|
||||
ends_at: balloting_phase.ends_at }),
|
||||
method: :post
|
||||
end
|
||||
|
||||
def budget_subnav_items_for(budget)
|
||||
{
|
||||
results: t("budgets.results.link"),
|
||||
stats: t("stats.budgets.link"),
|
||||
executions: t("budgets.executions.link")
|
||||
}.select { |section, _| can?(:"read_#{section}", budget) }.map do |section, text|
|
||||
{
|
||||
text: text,
|
||||
url: send("budget_#{section}_path", budget),
|
||||
active: controller_name == section.to_s
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,15 +17,11 @@ module DocumentablesHelper
|
||||
end
|
||||
|
||||
def accepted_content_types_extensions(documentable_class)
|
||||
documentable_class.accepted_content_types
|
||||
.collect{ |content_type| ".#{content_type.split("/").last}" }
|
||||
.join(",")
|
||||
Setting.accepted_content_types_for("documents").map { |content_type| ".#{content_type}" }.join(",")
|
||||
end
|
||||
|
||||
def documentable_humanized_accepted_content_types(documentable_class)
|
||||
documentable_class.accepted_content_types
|
||||
.collect{ |content_type| content_type.split("/").last }
|
||||
.join(", ")
|
||||
Setting.accepted_content_types_for("documents").join(", ")
|
||||
end
|
||||
|
||||
def documentables_note(documentable)
|
||||
|
||||
@@ -9,7 +9,7 @@ module ImageablesHelper
|
||||
end
|
||||
|
||||
def imageable_max_file_size
|
||||
bytes_to_megabytes(Image::MAX_IMAGE_SIZE)
|
||||
bytes_to_megabytes(Setting["uploads.images.max_size"].to_i.megabytes)
|
||||
end
|
||||
|
||||
def bytes_to_megabytes(bytes)
|
||||
@@ -17,19 +17,21 @@ module ImageablesHelper
|
||||
end
|
||||
|
||||
def imageable_accepted_content_types
|
||||
Image::ACCEPTED_CONTENT_TYPE
|
||||
Setting["uploads.images.content_types"]&.split(" ") || [ "image/jpeg" ]
|
||||
end
|
||||
|
||||
def imageable_accepted_content_types_extensions
|
||||
Image::ACCEPTED_CONTENT_TYPE
|
||||
.collect{ |content_type| ".#{content_type.split("/").last}" }
|
||||
.join(",")
|
||||
Setting.accepted_content_types_for("images").map do |content_type|
|
||||
if content_type == "jpg"
|
||||
".jpg,.jpeg"
|
||||
else
|
||||
".#{content_type}"
|
||||
end
|
||||
end.join(",")
|
||||
end
|
||||
|
||||
def imageable_humanized_accepted_content_types
|
||||
Image::ACCEPTED_CONTENT_TYPE
|
||||
.collect{ |content_type| content_type.split("/").last }
|
||||
.join(", ")
|
||||
Setting.accepted_content_types_for("images").join(", ")
|
||||
end
|
||||
|
||||
def imageables_note(_imageable)
|
||||
|
||||
@@ -8,4 +8,16 @@ module MailerHelper
|
||||
return budget_investment_url(commentable.budget_id, commentable) if commentable.is_a?(Budget::Investment)
|
||||
end
|
||||
|
||||
def valuation_comments_url(commentable)
|
||||
admin_budget_budget_investment_url(commentable.budget, commentable, anchor: "comments")
|
||||
end
|
||||
|
||||
def valuation_comments_link(commentable)
|
||||
link_to(
|
||||
commentable.title,
|
||||
valuation_comments_url(@email.commentable),
|
||||
target: :blank,
|
||||
style: "color: #2895F1; text-decoration:none;"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -120,6 +120,13 @@ class Mailer < ApplicationMailer
|
||||
mail(to: @email_to, from: @newsletter.from, subject: @newsletter.subject)
|
||||
end
|
||||
|
||||
def evaluation_comment(comment, to)
|
||||
@email = EvaluationCommentEmail.new(comment)
|
||||
@email_to = to
|
||||
|
||||
mail(to: @email_to.email, subject: @email.subject) if @email.can_be_sent?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_user(user, &block)
|
||||
|
||||
@@ -51,7 +51,7 @@ module Abilities
|
||||
can :comment_as_administrator, [Debate, Comment, Proposal, Poll::Question, Budget::Investment,
|
||||
Legislation::Question, Legislation::Proposal, Legislation::Annotation, Topic]
|
||||
|
||||
can [:search, :create, :index, :destroy], ::Administrator
|
||||
can [:search, :create, :index, :destroy, :edit, :update], ::Administrator
|
||||
can [:search, :create, :index, :destroy], ::Moderator
|
||||
can [:search, :show, :edit, :update, :create, :index, :destroy, :summary], ::Valuator
|
||||
can [:search, :create, :index, :destroy], ::Manager
|
||||
|
||||
@@ -3,4 +3,14 @@ class Administrator < ApplicationRecord
|
||||
delegate :name, :email, :name_and_email, to: :user
|
||||
|
||||
validates :user_id, presence: true, uniqueness: true
|
||||
|
||||
scope :with_user, -> { includes(:user) }
|
||||
|
||||
def description_or_name
|
||||
description.presence || name
|
||||
end
|
||||
|
||||
def description_or_name_and_email
|
||||
"#{description_or_name} (#{email})"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -195,6 +195,10 @@ class Budget < ApplicationRecord
|
||||
investments.winners.any?
|
||||
end
|
||||
|
||||
def milestone_tags
|
||||
investments.winners.map(&:milestone_tag_list).flatten.uniq.sort
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sanitize_descriptions
|
||||
|
||||
@@ -28,7 +28,9 @@ class Budget
|
||||
validates :budget_id, presence: true
|
||||
validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/
|
||||
|
||||
scope :sort_by_name, -> { joins(:translations).order(:name) }
|
||||
def self.sort_by_name
|
||||
all.sort_by(&:name)
|
||||
end
|
||||
|
||||
def single_heading_group?
|
||||
headings.count == 1
|
||||
|
||||
@@ -40,8 +40,7 @@ class Budget
|
||||
|
||||
delegate :budget, :budget_id, to: :group, allow_nil: true
|
||||
|
||||
scope :i18n, -> { joins(:translations) }
|
||||
scope :allow_custom_content, -> { i18n.where(allow_custom_content: true).order("budget_heading_translations.name") }
|
||||
scope :allow_custom_content, -> { where(allow_custom_content: true).sort_by(&:name) }
|
||||
|
||||
def self.sort_by_name
|
||||
all.sort do |heading, other_heading|
|
||||
|
||||
@@ -13,9 +13,6 @@ class Budget
|
||||
include Imageable
|
||||
include Mappable
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
|
||||
acts_as_votable
|
||||
acts_as_paranoid column: :hidden_at
|
||||
@@ -113,7 +110,7 @@ class Budget
|
||||
end
|
||||
|
||||
def self.scoped_filter(params, current_filter)
|
||||
budget = Budget.find_by(slug: params[:budget_id]) || Budget.find_by(id: params[:budget_id])
|
||||
budget = Budget.find_by_slug_or_id params[:budget_id]
|
||||
results = Investment.by_budget(budget)
|
||||
|
||||
results = results.where("cached_votes_up + physical_votes >= ?",
|
||||
@@ -377,6 +374,12 @@ class Budget
|
||||
milestones.published.with_status.order_by_publication_date.last&.status_id
|
||||
end
|
||||
|
||||
def admin_and_valuator_users_associated
|
||||
valuator_users = (valuator_groups.map(&:valuators) + valuators).flatten
|
||||
all_users = valuator_users << administrator
|
||||
all_users.compact.uniq
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_denormalized_ids
|
||||
|
||||
@@ -4,8 +4,9 @@ class Comment < ApplicationRecord
|
||||
include Graphqlable
|
||||
include Notifiable
|
||||
|
||||
COMMENTABLE_TYPES = %w(Debate Proposal Budget::Investment Poll Topic Legislation::Question
|
||||
Legislation::Annotation Legislation::Proposal).freeze
|
||||
COMMENTABLE_TYPES = %w[Debate Proposal Budget::Investment Poll Topic
|
||||
Legislation::Question Legislation::Annotation
|
||||
Legislation::Proposal Legislation::PeopleProposal].freeze
|
||||
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
@@ -7,16 +7,17 @@ module Documentable
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
attr_reader :max_documents_allowed, :max_file_size, :accepted_content_types
|
||||
|
||||
private
|
||||
|
||||
def documentable(options = {})
|
||||
@max_documents_allowed = options[:max_documents_allowed]
|
||||
@max_file_size = options[:max_file_size]
|
||||
@accepted_content_types = options[:accepted_content_types]
|
||||
def max_documents_allowed
|
||||
Setting["uploads.documents.max_amount"].to_i
|
||||
end
|
||||
|
||||
def max_file_size
|
||||
Setting["uploads.documents.max_size"].to_i.megabytes
|
||||
end
|
||||
|
||||
def accepted_content_types
|
||||
Setting["uploads.documents.content_types"]&.split(" ") || [ "application/pdf" ]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -8,6 +8,8 @@ module Milestoneable
|
||||
|
||||
has_many :progress_bars, as: :progressable
|
||||
|
||||
acts_as_taggable_on :milestone_tags
|
||||
|
||||
def primary_progress_bar
|
||||
progress_bars.primary.first
|
||||
end
|
||||
|
||||
@@ -7,6 +7,10 @@ module Sluggable
|
||||
def self.find_by_slug_or_id(slug_or_id)
|
||||
find_by_slug(slug_or_id) || find_by_id(slug_or_id)
|
||||
end
|
||||
|
||||
def self.find_by_slug_or_id!(slug_or_id)
|
||||
find_by_slug(slug_or_id) || find(slug_or_id)
|
||||
end
|
||||
end
|
||||
|
||||
def generate_slug
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
class Dashboard::Action < ApplicationRecord
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf",
|
||||
"image/jpeg",
|
||||
"image/jpg",
|
||||
"image/png",
|
||||
"application/zip" ]
|
||||
|
||||
include Linkable
|
||||
|
||||
acts_as_paranoid column: :hidden_at
|
||||
|
||||
16
app/models/evaluation_comment_notifier.rb
Normal file
16
app/models/evaluation_comment_notifier.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
class EvaluationCommentNotifier
|
||||
def initialize(args = {})
|
||||
@comment = args.fetch(:comment)
|
||||
end
|
||||
|
||||
def process
|
||||
send_evaluation_comment_email
|
||||
end
|
||||
|
||||
private
|
||||
def send_evaluation_comment_email
|
||||
EvaluationCommentEmail.new(@comment).to.each do |to|
|
||||
Mailer.evaluation_comment(@comment, to).deliver_later
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,12 +2,11 @@ class Image < ApplicationRecord
|
||||
include ImagesHelper
|
||||
include ImageablesHelper
|
||||
|
||||
TITLE_LENGTH_RANGE = 4..80
|
||||
MIN_SIZE = 475
|
||||
MAX_IMAGE_SIZE = 1.megabyte
|
||||
ACCEPTED_CONTENT_TYPE = %w(image/jpeg image/jpg).freeze
|
||||
|
||||
has_attached_file :attachment, styles: { large: "x#{MIN_SIZE}", medium: "300x300#", thumb: "140x245#" },
|
||||
has_attached_file :attachment, styles: {
|
||||
large: "x#{Setting["uploads.images.min_height"]}",
|
||||
medium: "300x300#",
|
||||
thumb: "140x245#"
|
||||
},
|
||||
url: "/system/:class/:prefix/:style/:hash.:extension",
|
||||
hash_data: ":class/:style",
|
||||
use_timestamp: false,
|
||||
@@ -23,7 +22,8 @@ class Image < ApplicationRecord
|
||||
validate :attachment_presence
|
||||
validate :validate_attachment_content_type, if: -> { attachment.present? }
|
||||
validate :validate_attachment_size, if: -> { attachment.present? }
|
||||
validates :title, presence: true, length: { in: TITLE_LENGTH_RANGE }
|
||||
validates :title, presence: true
|
||||
validate :validate_title_length
|
||||
validates :user_id, presence: true
|
||||
validates :imageable_id, presence: true, if: -> { persisted? }
|
||||
validates :imageable_type, presence: true, if: -> { persisted? }
|
||||
@@ -71,20 +71,38 @@ class Image < ApplicationRecord
|
||||
return true if imageable_class == Widget::Card
|
||||
|
||||
dimensions = Paperclip::Geometry.from_file(attachment.queued_for_write[:original].path)
|
||||
errors.add(:attachment, :min_image_width, required_min_width: MIN_SIZE) if dimensions.width < MIN_SIZE
|
||||
errors.add(:attachment, :min_image_height, required_min_height: MIN_SIZE) if dimensions.height < MIN_SIZE
|
||||
min_width = Setting["uploads.images.min_width"].to_i
|
||||
min_height = Setting["uploads.images.min_height"].to_i
|
||||
errors.add(:attachment, :min_image_width, required_min_width: min_width) if dimensions.width < min_width
|
||||
errors.add(:attachment, :min_image_height, required_min_height: min_height) if dimensions.height < min_height
|
||||
end
|
||||
end
|
||||
|
||||
def validate_attachment_size
|
||||
if imageable_class &&
|
||||
attachment_file_size > 1.megabytes
|
||||
attachment_file_size > Setting["uploads.images.max_size"].to_i.megabytes
|
||||
errors.add(:attachment, I18n.t("images.errors.messages.in_between",
|
||||
min: "0 Bytes",
|
||||
max: "#{imageable_max_file_size} MB"))
|
||||
end
|
||||
end
|
||||
|
||||
def validate_title_length
|
||||
if title.present?
|
||||
|
||||
title_min_length = Setting["uploads.images.title.min_length"].to_i
|
||||
title_max_length = Setting["uploads.images.title.max_length"].to_i
|
||||
|
||||
if title.size < title_min_length
|
||||
errors.add(:title, I18n.t("errors.messages.too_short", count: title_min_length))
|
||||
end
|
||||
|
||||
if title.size > title_max_length
|
||||
errors.add(:title, I18n.t("errors.messages.too_long", count: title_max_length))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def validate_attachment_content_type
|
||||
if imageable_class && !attachment_of_valid_content_type?
|
||||
message = I18n.t("images.errors.messages.wrong_content_type",
|
||||
|
||||
152
app/models/legislation/people_proposal.rb
Normal file
152
app/models/legislation/people_proposal.rb
Normal file
@@ -0,0 +1,152 @@
|
||||
class Legislation::PeopleProposal < ApplicationRecord
|
||||
include ActsAsParanoidAliases
|
||||
include Flaggable
|
||||
include Taggable
|
||||
include Conflictable
|
||||
include Measurable
|
||||
include Sanitizable
|
||||
include Searchable
|
||||
include Filterable
|
||||
include Followable
|
||||
include Communitable
|
||||
include Documentable
|
||||
include Notifiable
|
||||
include Imageable
|
||||
include Randomizable
|
||||
|
||||
accepts_nested_attributes_for :documents, allow_destroy: true
|
||||
|
||||
acts_as_votable
|
||||
acts_as_paranoid column: :hidden_at
|
||||
|
||||
belongs_to :process, class_name: "Legislation::Process", foreign_key: "legislation_process_id"
|
||||
belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
|
||||
has_many :comments, as: :commentable
|
||||
|
||||
validates :title, presence: true
|
||||
validates :summary, presence: true
|
||||
validates :author, presence: true
|
||||
validates :process, presence: true
|
||||
|
||||
validates :title, length: { in: 4..Legislation::PeopleProposal.title_max_length }
|
||||
validates :description, length: { maximum: Legislation::PeopleProposal.description_max_length }
|
||||
|
||||
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
|
||||
|
||||
before_validation :set_responsible_name
|
||||
|
||||
before_save :calculate_hot_score, :calculate_confidence_score
|
||||
|
||||
scope :for_render, -> { includes(:tags) }
|
||||
scope :sort_by_hot_score, -> { reorder(hot_score: :desc) }
|
||||
scope :sort_by_confidence_score, -> { reorder(confidence_score: :desc) }
|
||||
scope :sort_by_created_at, -> { reorder(created_at: :desc) }
|
||||
scope :sort_by_most_commented, -> { reorder(comments_count: :desc) }
|
||||
scope :sort_by_title, -> { reorder(title: :asc) }
|
||||
scope :sort_by_id, -> { reorder(id: :asc) }
|
||||
scope :sort_by_supports, -> { reorder(cached_votes_score: :desc) }
|
||||
scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
|
||||
scope :last_week, -> { where("people_proposals.created_at >= ?", 7.days.ago)}
|
||||
scope :validated, -> { where(validated: true) }
|
||||
scope :selected, -> { where(selected: true) }
|
||||
scope :winners, -> { selected.sort_by_confidence_score }
|
||||
|
||||
def to_param
|
||||
"#{id}-#{title}".parameterize
|
||||
end
|
||||
|
||||
def searchable_values
|
||||
{ title => "A",
|
||||
author.username => "B",
|
||||
tag_list.join(" ") => "B",
|
||||
summary => "C",
|
||||
description => "D"}
|
||||
end
|
||||
|
||||
def self.search(terms)
|
||||
by_code = search_by_code(terms.strip)
|
||||
by_code.present? ? by_code : pg_search(terms)
|
||||
end
|
||||
|
||||
def self.search_by_code(terms)
|
||||
matched_code = match_code(terms)
|
||||
results = where(id: matched_code[1]) if matched_code
|
||||
return results if results.present? && results.first.code == terms
|
||||
end
|
||||
|
||||
def self.match_code(terms)
|
||||
/\A#{Setting["proposal_code_prefix"]}-\d\d\d\d-\d\d-(\d*)\z/.match(terms)
|
||||
end
|
||||
|
||||
def likes
|
||||
cached_votes_up
|
||||
end
|
||||
|
||||
def dislikes
|
||||
cached_votes_down
|
||||
end
|
||||
|
||||
def total_votes
|
||||
cached_votes_total
|
||||
end
|
||||
|
||||
def votes_score
|
||||
cached_votes_score
|
||||
end
|
||||
|
||||
def voters
|
||||
User.active.where(id: votes_for.voters)
|
||||
end
|
||||
|
||||
def editable?
|
||||
total_votes <= Setting["max_votes_for_people_proposal_edit"].to_i
|
||||
end
|
||||
|
||||
def editable_by?(user)
|
||||
author_id == user.id && editable?
|
||||
end
|
||||
|
||||
def votable_by?(user)
|
||||
user && user.level_two_or_three_verified?
|
||||
end
|
||||
|
||||
def register_vote(user, vote_value)
|
||||
vote_by(voter: user, vote: vote_value) if votable_by?(user)
|
||||
end
|
||||
|
||||
def code
|
||||
"#{Setting["proposal_code_prefix"]}-#{created_at.strftime("%Y-%m")}-#{id}"
|
||||
end
|
||||
|
||||
def after_commented
|
||||
save # update cache when it has a new comment
|
||||
end
|
||||
|
||||
def calculate_hot_score
|
||||
self.hot_score = ScoreCalculator.hot_score(self)
|
||||
end
|
||||
|
||||
def calculate_confidence_score
|
||||
self.confidence_score = ScoreCalculator.confidence_score(total_votes, total_votes)
|
||||
end
|
||||
|
||||
def after_hide
|
||||
tags.each{ |t| t.decrement_custom_counter_for("LegislationPeopleProposal") }
|
||||
end
|
||||
|
||||
def after_restore
|
||||
tags.each{ |t| t.increment_custom_counter_for("LegislationPeopleProposal") }
|
||||
end
|
||||
|
||||
def contact_info
|
||||
[phone, email, website].compact
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def set_responsible_name
|
||||
if author && author.document_number?
|
||||
self.responsible_name = author.document_number
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,9 +4,6 @@ class Legislation::Process < ApplicationRecord
|
||||
include Milestoneable
|
||||
include Imageable
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
|
||||
acts_as_paranoid column: :hidden_at
|
||||
acts_as_taggable_on :customs
|
||||
@@ -20,7 +17,8 @@ class Legislation::Process < ApplicationRecord
|
||||
include Globalizable
|
||||
|
||||
PHASES_AND_PUBLICATIONS = %i[homepage_phase draft_phase debate_phase allegations_phase
|
||||
proposals_phase draft_publication result_publication].freeze
|
||||
proposals_phase people_proposals_phase draft_publication
|
||||
result_publication].freeze
|
||||
|
||||
CSS_HEX_COLOR = /\A#?(?:[A-F0-9]{3}){1,2}\z/i
|
||||
|
||||
@@ -34,6 +32,8 @@ class Legislation::Process < ApplicationRecord
|
||||
foreign_key: "legislation_process_id", dependent: :destroy
|
||||
has_many :proposals, -> { order(:id) }, class_name: "Legislation::Proposal",
|
||||
foreign_key: "legislation_process_id", dependent: :destroy
|
||||
has_many :people_proposals, -> { order(:id) }, class_name: "Legislation::PeopleProposal",
|
||||
foreign_key: "legislation_process_id", dependent: :destroy
|
||||
|
||||
validates_translation :title, presence: true
|
||||
validates :start_date, presence: true
|
||||
@@ -45,6 +45,8 @@ class Legislation::Process < ApplicationRecord
|
||||
validates :allegations_start_date, presence: true, if: :allegations_end_date?
|
||||
validates :allegations_end_date, presence: true, if: :allegations_start_date?
|
||||
validates :proposals_phase_end_date, presence: true, if: :proposals_phase_start_date?
|
||||
validates :people_proposals_phase_end_date, presence: true,
|
||||
if: :people_proposals_phase_start_date?
|
||||
validate :valid_date_ranges
|
||||
validates :background_color, format: { allow_blank: true, with: CSS_HEX_COLOR }
|
||||
validates :font_color, format: { allow_blank: true, with: CSS_HEX_COLOR }
|
||||
@@ -84,6 +86,11 @@ class Legislation::Process < ApplicationRecord
|
||||
proposals_phase_end_date, proposals_phase_enabled)
|
||||
end
|
||||
|
||||
def people_proposals_phase
|
||||
Legislation::Process::Phase.new(people_proposals_phase_start_date,
|
||||
people_proposals_phase_end_date, people_proposals_phase_enabled)
|
||||
end
|
||||
|
||||
def draft_publication
|
||||
Legislation::Process::Publication.new(draft_publication_date, draft_publication_enabled)
|
||||
end
|
||||
|
||||
@@ -14,9 +14,6 @@ class Legislation::Proposal < ApplicationRecord
|
||||
include Imageable
|
||||
include Randomizable
|
||||
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
accepts_nested_attributes_for :documents, allow_destroy: true
|
||||
|
||||
acts_as_votable
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
class Milestone < ApplicationRecord
|
||||
include Imageable
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
|
||||
translates :title, :description, touch: true
|
||||
include Globalizable
|
||||
|
||||
@@ -49,7 +49,19 @@ class Poll < ApplicationRecord
|
||||
scope :not_budget, -> { where(budget_id: nil) }
|
||||
scope :created_by_admin, -> { where(related_type: nil) }
|
||||
|
||||
scope :sort_for_list, -> { joins(:translations).order(:geozone_restricted, :starts_at, "poll_translations.name") }
|
||||
def self.sort_for_list
|
||||
all.sort do |poll, another_poll|
|
||||
if poll.geozone_restricted? == another_poll.geozone_restricted?
|
||||
[poll.starts_at, poll.name] <=> [another_poll.starts_at, another_poll.name]
|
||||
else
|
||||
if poll.geozone_restricted?
|
||||
1
|
||||
else
|
||||
-1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.overlaping_with(poll)
|
||||
where("? < ends_at and ? >= starts_at", poll.starts_at.beginning_of_day,
|
||||
|
||||
@@ -12,7 +12,7 @@ class Poll
|
||||
end
|
||||
|
||||
def self.available
|
||||
where(polls: { id: Poll.current_or_recounting }).joins(polls: :translations)
|
||||
where(polls: { id: Poll.current_or_recounting }).joins(:polls)
|
||||
end
|
||||
|
||||
def assignment_on_poll(poll)
|
||||
|
||||
@@ -7,7 +7,13 @@ class Poll
|
||||
|
||||
validates :user_id, presence: true, uniqueness: true
|
||||
|
||||
delegate :name, :email, to: :user
|
||||
def name
|
||||
user&.name || I18n.t("shared.author_info.author_deleted")
|
||||
end
|
||||
|
||||
def email
|
||||
user&.email || I18n.t("shared.author_info.email_deleted")
|
||||
end
|
||||
|
||||
def voting_days_assigned_polls
|
||||
officer_assignments.voting_days.includes(booth_assignment: :poll).
|
||||
|
||||
@@ -6,9 +6,6 @@ class Poll::Question::Answer < ApplicationRecord
|
||||
translates :description, touch: true
|
||||
include Globalizable
|
||||
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
accepts_nested_attributes_for :documents, allow_destroy: true
|
||||
|
||||
belongs_to :question, class_name: "Poll::Question", foreign_key: "question_id"
|
||||
|
||||
@@ -15,9 +15,6 @@ class Proposal < ApplicationRecord
|
||||
include Mappable
|
||||
include Notifiable
|
||||
include Documentable
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
include EmbedVideosHelper
|
||||
include Relationable
|
||||
include Milestoneable
|
||||
|
||||
@@ -3,9 +3,12 @@ class Setting < ApplicationRecord
|
||||
|
||||
default_scope { order(id: :asc) }
|
||||
|
||||
def prefix
|
||||
key.split(".").first
|
||||
end
|
||||
|
||||
def type
|
||||
prefix = key.split(".").first
|
||||
if %w[feature process proposals map html homepage].include? prefix
|
||||
if %w[feature process proposals map html homepage uploads].include? prefix
|
||||
prefix
|
||||
else
|
||||
"configuration"
|
||||
@@ -16,6 +19,14 @@ class Setting < ApplicationRecord
|
||||
value.present?
|
||||
end
|
||||
|
||||
def content_type?
|
||||
key.split(".").last == "content_types"
|
||||
end
|
||||
|
||||
def content_type_group
|
||||
key.split(".").second
|
||||
end
|
||||
|
||||
class << self
|
||||
def [](key)
|
||||
where(key: key).pluck(:value).first.presence
|
||||
@@ -40,5 +51,132 @@ class Setting < ApplicationRecord
|
||||
setting = where(key: key).first
|
||||
setting.destroy if setting.present?
|
||||
end
|
||||
|
||||
def accepted_content_types_for(group)
|
||||
mime_content_types = Setting["uploads.#{group}.content_types"]&.split(" ") || []
|
||||
Setting.mime_types[group].select { |_, content_type| mime_content_types.include?(content_type) }.keys
|
||||
end
|
||||
|
||||
def mime_types
|
||||
{
|
||||
"images" => {
|
||||
"jpg" => "image/jpeg",
|
||||
"png" => "image/png",
|
||||
"gif" => "image/gif"
|
||||
},
|
||||
"documents" => {
|
||||
"pdf" => "application/pdf",
|
||||
"doc" => "application/msword",
|
||||
"docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
"xls" => "application/x-ole-storage",
|
||||
"xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
"csv" => "text/plain",
|
||||
"zip" => "application/zip"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def defaults
|
||||
{
|
||||
"feature.featured_proposals": nil,
|
||||
"feature.facebook_login": true,
|
||||
"feature.google_login": true,
|
||||
"feature.twitter_login": true,
|
||||
"feature.public_stats": true,
|
||||
"feature.signature_sheets": true,
|
||||
"feature.user.recommendations": true,
|
||||
"feature.user.recommendations_on_debates": true,
|
||||
"feature.user.recommendations_on_proposals": true,
|
||||
"feature.user.skip_verification": "true",
|
||||
"feature.community": true,
|
||||
"feature.map": nil,
|
||||
"feature.allow_attached_documents": true,
|
||||
"feature.allow_images": true,
|
||||
"feature.help_page": true,
|
||||
"feature.valuation_comment_notification": true,
|
||||
"homepage.widgets.feeds.debates": true,
|
||||
"homepage.widgets.feeds.processes": true,
|
||||
"homepage.widgets.feeds.proposals": true,
|
||||
# Code to be included at the top (inside <body>) of every page
|
||||
"html.per_page_code_body": "",
|
||||
# Code to be included at the top (inside <head>) of every page (useful for tracking)
|
||||
"html.per_page_code_head": "",
|
||||
"map.latitude": 51.48,
|
||||
"map.longitude": 0.0,
|
||||
"map.zoom": 10,
|
||||
"process.debates": true,
|
||||
"process.proposals": true,
|
||||
"process.polls": true,
|
||||
"process.budgets": true,
|
||||
"process.legislation": true,
|
||||
"proposals.successful_proposal_id": nil,
|
||||
"proposals.poll_short_title": nil,
|
||||
"proposals.poll_description": nil,
|
||||
"proposals.poll_link": nil,
|
||||
"proposals.email_short_title": nil,
|
||||
"proposals.email_description": nil,
|
||||
"proposals.poster_short_title": nil,
|
||||
"proposals.poster_description": nil,
|
||||
# Images and Documents
|
||||
"uploads.images.title.min_length": 4,
|
||||
"uploads.images.title.max_length": 80,
|
||||
"uploads.images.min_width": 0,
|
||||
"uploads.images.min_height": 475,
|
||||
"uploads.images.max_size": 1,
|
||||
"uploads.images.content_types": "image/jpeg",
|
||||
"uploads.documents.max_amount": 3,
|
||||
"uploads.documents.max_size": 3,
|
||||
"uploads.documents.content_types": "application/pdf",
|
||||
# Names for the moderation console, as a hint for moderators
|
||||
# to know better how to assign users with official positions
|
||||
"official_level_1_name": I18n.t("seeds.settings.official_level_1_name"),
|
||||
"official_level_2_name": I18n.t("seeds.settings.official_level_2_name"),
|
||||
"official_level_3_name": I18n.t("seeds.settings.official_level_3_name"),
|
||||
"official_level_4_name": I18n.t("seeds.settings.official_level_4_name"),
|
||||
"official_level_5_name": I18n.t("seeds.settings.official_level_5_name"),
|
||||
"max_ratio_anon_votes_on_debates": 50,
|
||||
"max_votes_for_debate_edit": 1000,
|
||||
"max_votes_for_proposal_edit": 1000,
|
||||
"max_votes_for_people_proposal_edit": 1000,
|
||||
"comments_body_max_length": 1000,
|
||||
"proposal_code_prefix": "CONSUL",
|
||||
"votes_for_proposal_success": 10000,
|
||||
"months_to_archive_proposals": 12,
|
||||
# Users with this email domain will automatically be marked as level 1 officials
|
||||
# Emails under the domain's subdomains will also be included
|
||||
"email_domain_for_officials": "",
|
||||
"facebook_handle": nil,
|
||||
"instagram_handle": nil,
|
||||
"telegram_handle": nil,
|
||||
"twitter_handle": nil,
|
||||
"twitter_hashtag": nil,
|
||||
"youtube_handle": nil,
|
||||
"url": "http://example.com", # Public-facing URL of the app.
|
||||
# CONSUL installation's organization name
|
||||
"org_name": "CONSUL",
|
||||
"meta_title": nil,
|
||||
"meta_description": nil,
|
||||
"meta_keywords": nil,
|
||||
"proposal_notification_minimum_interval_in_days": 3,
|
||||
"direct_message_max_per_day": 3,
|
||||
"mailer_from_name": "CONSUL",
|
||||
"mailer_from_address": "noreply@consul.dev",
|
||||
"min_age_to_participate": 16,
|
||||
"hot_score_period_in_days": 31,
|
||||
"related_content_score_threshold": -0.3,
|
||||
"featured_proposals_number": 3,
|
||||
"dashboard.emails": nil
|
||||
}
|
||||
end
|
||||
|
||||
def reset_defaults
|
||||
defaults.each { |name, value| self[name] = value }
|
||||
end
|
||||
|
||||
def add_new_settings
|
||||
defaults.each do |name, value|
|
||||
self[name] = value unless find_by(key: name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,6 +23,7 @@ class User < ApplicationRecord
|
||||
has_many :identities, dependent: :destroy
|
||||
has_many :debates, -> { with_hidden }, foreign_key: :author_id
|
||||
has_many :proposals, -> { with_hidden }, foreign_key: :author_id
|
||||
has_many :people_proposals, -> { with_hidden }, foreign_key: :author_id
|
||||
has_many :budget_investments, -> { with_hidden }, foreign_key: :author_id, class_name: "Budget::Investment"
|
||||
has_many :comments, -> { with_hidden }
|
||||
has_many :failed_census_calls
|
||||
@@ -131,9 +132,7 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
def headings_voted_within_group(group)
|
||||
Budget::Heading.joins(:translations)
|
||||
.order("name")
|
||||
.where(id: voted_investments.by_group(group).pluck(:heading_id))
|
||||
Budget::Heading.where(id: voted_investments.by_group(group).pluck(:heading_id))
|
||||
end
|
||||
|
||||
def voted_investments
|
||||
|
||||
@@ -141,8 +141,8 @@
|
||||
<% end %>
|
||||
|
||||
<% if feature?(:debates) %>
|
||||
<li <%= "class=is-active" if controller_name == "debates" %>>
|
||||
<%= link_to t("admin.menu.hidden_debates"), admin_debates_path %>
|
||||
<li <%= "class=is-active" if controller_name == "hidden_debates" %>>
|
||||
<%= link_to t("admin.menu.hidden_debates"), admin_hidden_debates_path %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
@@ -152,8 +152,8 @@
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<li <%= "class=is-active" if controller_name == "comments" %>>
|
||||
<%= link_to t("admin.menu.hidden_comments"), admin_comments_path %>
|
||||
<li <%= "class=is-active" if controller_name == "hidden_comments" %>>
|
||||
<%= link_to t("admin.menu.hidden_comments"), admin_hidden_comments_path %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=is-active" if controller_name == "proposal_notifications" %>>
|
||||
|
||||
15
app/views/admin/administrators/edit.html.erb
Normal file
15
app/views/admin/administrators/edit.html.erb
Normal file
@@ -0,0 +1,15 @@
|
||||
<%= back_link_to admin_administrators_path %>
|
||||
|
||||
<h2><%= t("admin.administrators.form.edit_title") %></h2>
|
||||
|
||||
<div class="callout highlight">
|
||||
<strong><%= @administrator.name %></strong><br>
|
||||
<%= @administrator.email %>
|
||||
</div>
|
||||
|
||||
<div class="margin-top">
|
||||
<%= form_for [:admin, @administrator] do |f| %>
|
||||
<%= f.text_field :description %>
|
||||
<%= f.submit class: "button success" %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -11,6 +11,7 @@
|
||||
<th scope="col" class="text-center"><%= t("admin.administrators.index.id") %></th>
|
||||
<th scope="col"><%= t("admin.administrators.index.name") %></th>
|
||||
<th scope="col"><%= t("admin.administrators.index.email") %></th>
|
||||
<th scope="col"><%= t("admin.administrators.index.description") %></th>
|
||||
<th scope="col" class="small-3"><%= t("admin.shared.actions") %></th>
|
||||
</thead>
|
||||
<% @administrators.each do |administrator| %>
|
||||
@@ -24,13 +25,18 @@
|
||||
<td>
|
||||
<%= administrator.email %>
|
||||
</td>
|
||||
<td>
|
||||
<%= administrator.description %>
|
||||
</td>
|
||||
<td>
|
||||
<% if administrator.persisted? %>
|
||||
<%= link_to t("admin.actions.edit"),
|
||||
edit_admin_administrator_path(administrator),
|
||||
class: "button hollow" %>
|
||||
<%= link_to t("admin.administrators.administrator.delete"),
|
||||
admin_administrator_path(administrator),
|
||||
method: :delete,
|
||||
class: "button hollow alert expanded"
|
||||
%>
|
||||
class: "button hollow alert" %>
|
||||
<% else %>
|
||||
<%= link_to t("admin.administrators.administrator.add"),
|
||||
{ controller: "admin/administrators", action: :create,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
admin_budget_budget_investments_path(csv_params),
|
||||
class: "float-right small clear" %>
|
||||
|
||||
|
||||
<% if params[:advanced_filters].include?("winners") %>
|
||||
<% if display_calculate_winners_button?(@budget) %>
|
||||
<%= link_to calculate_winner_button_text(@budget),
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
</td>
|
||||
<td class="small">
|
||||
<% if investment.administrator.present? %>
|
||||
<span title="<%= t("admin.budget_investments.index.assigned_admin") %>">
|
||||
<%= investment.administrator.name %>
|
||||
</span>
|
||||
<span title="<%= t("admin.budget_investments.index.assigned_admin") %>">
|
||||
<%= investment.administrator.description_or_name %>
|
||||
</span>
|
||||
<% else %>
|
||||
<%= t("admin.budget_investments.index.no_admin_assigned") %>
|
||||
<% end %>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
<div class="small-12 medium-6">
|
||||
<%= f.select(:administrator_id,
|
||||
@admins.collect{ |a| [a.name_and_email, a.id ] },
|
||||
@admins.collect{ |a| [a.description_or_name_and_email, a.id ] },
|
||||
{ include_blank: t("admin.budget_investments.edit.undefined") }) %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -105,6 +105,13 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small-12 column">
|
||||
<%= f.text_field :milestone_tag_list,
|
||||
value: @investment.milestone_tag_list.sort.join(", "),
|
||||
label: t("admin.budget_investments.edit.milestone_tags") %>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="small-12 column margin-top">
|
||||
<%= f.submit(class: "button", value: t("admin.budget_investments.edit.submit_button")) %>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<h2><%= t("admin.comments.index.title") %></h2>
|
||||
<h2><%= t("admin.hidden_comments.index.title") %></h2>
|
||||
<p><%= t("admin.shared.moderated_content") %></p>
|
||||
|
||||
<%= render "shared/filter_subnav", i18n_namespace: "admin.comments.index" %>
|
||||
|
||||
<%= render "shared/filter_subnav", i18n_namespace: "admin.hidden_comments.index" %>
|
||||
|
||||
<% if @comments.any? %>
|
||||
<h3 class="margin"><%= page_entries_info @comments %></h3>
|
||||
@@ -17,20 +18,20 @@
|
||||
<td>
|
||||
<%= text_with_links comment.body %><br>
|
||||
<% if comment.commentable.hidden? %>
|
||||
(<%= t("admin.comments.index.hidden_#{comment.commentable_type.downcase}") %>: <%= comment.commentable.title %>)
|
||||
(<%= t("admin.hidden_comments.index.hidden_#{comment.commentable_type.downcase}") %>: <%= comment.commentable.title %>)
|
||||
<% else %>
|
||||
<%= link_to comment.commentable.title, commentable_path(comment) %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<%= link_to t("admin.actions.restore"),
|
||||
restore_admin_comment_path(comment, request.query_parameters),
|
||||
restore_admin_hidden_comment_path(comment, request.query_parameters),
|
||||
method: :put,
|
||||
data: { confirm: t("admin.actions.confirm") },
|
||||
class: "button hollow warning" %>
|
||||
<% unless comment.confirmed_hide? %>
|
||||
<%= link_to t("admin.actions.confirm_hide"),
|
||||
confirm_hide_admin_comment_path(comment, request.query_parameters),
|
||||
confirm_hide_admin_hidden_comment_path(comment, request.query_parameters),
|
||||
method: :put,
|
||||
class: "button" %>
|
||||
<% end %>
|
||||
@@ -43,6 +44,6 @@
|
||||
<%= paginate @comments %>
|
||||
<% else %>
|
||||
<div class="callout primary margin">
|
||||
<%= t("admin.comments.index.no_hidden_comments") %>
|
||||
<%= t("admin.hidden_comments.index.no_hidden_comments") %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -1,7 +1,8 @@
|
||||
<h2><%= t("admin.debates.index.title") %></h2>
|
||||
<h2><%= t("admin.hidden_debates.index.title") %></h2>
|
||||
<p><%= t("admin.shared.moderated_content") %></p>
|
||||
|
||||
<%= render "shared/filter_subnav", i18n_namespace: "admin.debates.index" %>
|
||||
|
||||
<%= render "shared/filter_subnav", i18n_namespace: "admin.hidden_debates.index" %>
|
||||
|
||||
<% if @debates.any? %>
|
||||
<h3 class="margin"><%= page_entries_info @debates %></h3>
|
||||
@@ -25,13 +26,13 @@
|
||||
</td>
|
||||
<td class="align-top">
|
||||
<%= link_to t("admin.actions.restore"),
|
||||
restore_admin_debate_path(debate, request.query_parameters),
|
||||
restore_admin_hidden_debate_path(debate, request.query_parameters),
|
||||
method: :put,
|
||||
data: { confirm: t("admin.actions.confirm") },
|
||||
class: "button hollow warning" %>
|
||||
<% unless debate.confirmed_hide? %>
|
||||
<%= link_to t("admin.actions.confirm_hide"),
|
||||
confirm_hide_admin_debate_path(debate, request.query_parameters),
|
||||
confirm_hide_admin_hidden_debate_path(debate, request.query_parameters),
|
||||
method: :put,
|
||||
class: "button" %>
|
||||
<% end %>
|
||||
@@ -44,6 +45,6 @@
|
||||
<%= paginate @debates %>
|
||||
<% else %>
|
||||
<div class="callout primary margin">
|
||||
<%= t("admin.debates.index.no_hidden_debates") %>
|
||||
<%= t("admin.hidden_debates.index.no_hidden_debates") %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -4,6 +4,14 @@
|
||||
polymorphic_path([:admin, *resource_hierarchy_for(milestoneable.progress_bars.new)]),
|
||||
class: "button hollow float-right" %>
|
||||
|
||||
<% if milestoneable.milestone_tag_list.any? %>
|
||||
<div>
|
||||
<strong>
|
||||
<%= t("admin.milestones.index.milestone_tags") %>:
|
||||
</strong> <%= milestoneable.milestone_tag_list.sort.join(", ") %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if milestoneable.milestones.any? %>
|
||||
<table>
|
||||
<thead>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<%= form_tag admin_update_content_types_path, method: :put, id: "edit_#{dom_id(setting)}" do %>
|
||||
<%= hidden_field_tag "id", setting.id %>
|
||||
|
||||
<div class="small-12 medium-6 large-8 column">
|
||||
<% group = setting.content_type_group %>
|
||||
<% Setting.mime_types[group].each do |content_type, mime_type_value| %>
|
||||
<span class="content-type">
|
||||
<%= check_box_tag content_type,
|
||||
setting.value.split(" ").include?(mime_type_value),
|
||||
setting.value.split(" ").include?(mime_type_value) %>
|
||||
<%= label_tag content_type, content_type.upcase %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 large-4 column">
|
||||
<%= submit_tag t("admin.settings.index.update_setting"), class: "button hollow expanded" %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -0,0 +1,6 @@
|
||||
<%= form_for(feature, url: admin_setting_path(feature), html: { id: "edit_#{dom_id(feature)}"}) do |f| %>
|
||||
<%= f.hidden_field :value, id: dom_id(feature), value: (feature.enabled? ? "" : "active") %>
|
||||
<%= f.submit(t("admin.settings.index.features.#{feature.enabled? ? "disable" : "enable"}"),
|
||||
class: "button expanded #{feature.enabled? ? "hollow alert" : "success"}",
|
||||
data: {confirm: t("admin.actions.confirm")}) %>
|
||||
<% end %>
|
||||
@@ -32,13 +32,7 @@
|
||||
</td>
|
||||
|
||||
<td class="text-right">
|
||||
<%= form_for(feature, url: admin_setting_path(feature), html: { id: "edit_#{dom_id(feature)}"}) do |f| %>
|
||||
|
||||
<%= f.hidden_field :value, id: dom_id(feature), value: (feature.enabled? ? "" : "active") %>
|
||||
<%= f.submit(t("admin.settings.index.features.#{feature.enabled? ? "disable" : "enable"}"),
|
||||
class: "button expanded #{feature.enabled? ? "hollow alert" : "success"}",
|
||||
data: {confirm: t("admin.actions.confirm")}) %>
|
||||
<% end %>
|
||||
<%= render "admin/settings/featured_settings_form", feature: feature %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
<% end %>
|
||||
</li>
|
||||
|
||||
<li class="tabs-title" id="images-and-documents-tab">
|
||||
<%= link_to "#tab-images-and-documents" do %>
|
||||
<%= t("admin.settings.index.images_and_documents") %>
|
||||
<% end %>
|
||||
</li>
|
||||
|
||||
<li class="tabs-title" id="proposals-tab">
|
||||
<%= link_to "#tab-proposals" do %>
|
||||
<%= t("admin.settings.index.dashboard.title") %>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<h2><%= t("admin.settings.index.images_and_documents") %></h2>
|
||||
|
||||
<%= render "settings_table", settings: @uploads_settings %>
|
||||
8
app/views/admin/settings/_settings_form.html.erb
Normal file
8
app/views/admin/settings/_settings_form.html.erb
Normal file
@@ -0,0 +1,8 @@
|
||||
<%= form_for(setting, url: admin_setting_path(setting), html: { id: "edit_#{dom_id(setting)}"}) do |f| %>
|
||||
<div class="small-12 medium-6 large-8 column">
|
||||
<%= f.text_area :value, label: false, id: dom_id(setting), lines: 1 %>
|
||||
</div>
|
||||
<div class="small-12 medium-6 large-4 column">
|
||||
<%= f.submit(t("admin.settings.index.update_setting"), class: "button hollow expanded") %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -16,13 +16,10 @@
|
||||
</span>
|
||||
</td>
|
||||
<td class="small-6">
|
||||
<%= form_for(setting, url: admin_setting_path(setting), html: { id: "edit_#{dom_id(setting)}"}) do |f| %>
|
||||
<div class="small-12 medium-6 large-8 column">
|
||||
<%= f.text_area :value, label: false, id: dom_id(setting), lines: 1 %>
|
||||
</div>
|
||||
<div class="small-12 medium-6 large-4 column">
|
||||
<%= f.submit(t("admin.settings.index.update_setting"), class: "button hollow expanded") %>
|
||||
</div>
|
||||
<% if setting.content_type? %>
|
||||
<%= render "admin/settings/content_types_settings_form", setting: setting %>
|
||||
<% else %>
|
||||
<%= render "admin/settings/settings_form", setting: setting %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
<%= render "map_configuration_tab" %>
|
||||
</div>
|
||||
|
||||
<div class="tabs-panel" id="tab-images-and-documents">
|
||||
<%= render "images_and_documents_tab" %>
|
||||
</div>
|
||||
|
||||
<div class="tabs-panel" id="tab-proposals">
|
||||
<%= render "proposals_dashboard" %>
|
||||
</div>
|
||||
|
||||
35
app/views/budgets/_finished.html.erb
Normal file
35
app/views/budgets/_finished.html.erb
Normal file
@@ -0,0 +1,35 @@
|
||||
<div class="row margin-top">
|
||||
<div class="small-12 medium-9 column">
|
||||
<h2><%= t("budgets.index.finished_budgets") %></h2>
|
||||
|
||||
<div id="finished_budgets" class="budget-investments-list">
|
||||
<% budgets.each do |budget| %>
|
||||
<div class="budget-investment clear">
|
||||
<div class="panel past-budgets">
|
||||
<div class="row" data-equalizer data-equalizer-on="medium">
|
||||
<div class="small-12 medium-6 column table" data-equalizer-watch>
|
||||
<div class="table-cell align-middle">
|
||||
<h3><%= budget.name %></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 column table" data-equalizer-watch>
|
||||
<div id="budget_<%= budget.id %>_results" class="table-cell align-middle">
|
||||
<% if can?(:read_results, budget) %>
|
||||
<%= link_to t("budgets.index.see_results"),
|
||||
budget_results_path(budget),
|
||||
class: "button" %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to t("budgets.index.milestones"),
|
||||
budget_executions_path(budget),
|
||||
class: "button" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
17
app/views/budgets/_subnav.html.erb
Normal file
17
app/views/budgets/_subnav.html.erb
Normal file
@@ -0,0 +1,17 @@
|
||||
<div class="row margin-top">
|
||||
<div class="small-12 column">
|
||||
<ul class="tabs">
|
||||
<% budget_subnav_items_for(budget).each do |item| %>
|
||||
<% if item[:active] %>
|
||||
<li class="tabs-title is-active">
|
||||
<span class="show-for-sr"><%= t("shared.you_are_in") %></span>
|
||||
|
||||
<%= link_to item[:text], item[:url], class: "is-active" %>
|
||||
</li>
|
||||
<% else %>
|
||||
<li class="tabs-title"><%= link_to item[:text], item[:url] %></li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -25,21 +25,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row margin-top">
|
||||
<div class="small-12 column">
|
||||
<ul class="tabs">
|
||||
<li class="tabs-title">
|
||||
<%= link_to t("budgets.results.link"), budget_results_path(@budget) %>
|
||||
</li>
|
||||
<li class="tabs-title">
|
||||
<%= link_to t("stats.budgets.link"), budget_stats_path(@budget) %>
|
||||
</li>
|
||||
<li class="tabs-title is-active">
|
||||
<%= link_to t("budgets.executions.link"), budget_executions_path(@budget), class: "is-active" %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<%= render "budgets/subnav", budget: @budget %>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-3 large-2 column">
|
||||
@@ -58,13 +44,24 @@
|
||||
<div class="small-12 medium-9 large-10 column">
|
||||
<%= form_tag(budget_executions_path(@budget), method: :get) do %>
|
||||
<div class="small-12 medium-3 column">
|
||||
<%= label_tag :status, t("budgets.executions.filters.label") %>
|
||||
<%= label_tag :milestone_tag, t("budgets.executions.filters.milestone_tag.label") %>
|
||||
<%= select_tag :milestone_tag,
|
||||
options_for_select(
|
||||
options_for_milestone_tags,
|
||||
params[:milestone_tag]
|
||||
),
|
||||
class: "js-submit-on-change",
|
||||
prompt: t("budgets.executions.filters.milestone_tag.all",
|
||||
count: @budget.investments.winners.with_milestones.count) %>
|
||||
</div>
|
||||
<div class="small-12 medium-3 column">
|
||||
<%= label_tag :status, t("budgets.executions.filters.status.label") %>
|
||||
<%= select_tag :status,
|
||||
options_from_collection_for_select(@statuses,
|
||||
:id, lambda { |s| "#{s.name} (#{filters_select_counts(s.id)})" },
|
||||
params[:status]),
|
||||
class: "js-submit-on-change",
|
||||
prompt: t("budgets.executions.filters.all",
|
||||
prompt: t("budgets.executions.filters.status.all",
|
||||
count: @budget.investments.winners.with_milestones.count) %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if current_budget.finished? %>
|
||||
<% if can?(:read_results, current_budget) %>
|
||||
<%= link_to t("budgets.show.see_results"),
|
||||
budget_results_path(current_budget, heading_id: current_budget.headings.first),
|
||||
class: "button margin-top expanded" %>
|
||||
@@ -126,38 +126,7 @@
|
||||
</div>
|
||||
|
||||
<% if @finished_budgets.present? %>
|
||||
<div class="row margin-top">
|
||||
<div class="small-12 medium-9 column">
|
||||
<h2><%= t("budgets.index.finished_budgets") %></h2>
|
||||
|
||||
<div id="finished_budgets" class="budget-investments-list">
|
||||
<% @finished_budgets.each do |budget| %>
|
||||
<div class="budget-investment clear">
|
||||
<div class="panel past-budgets">
|
||||
<div class="row" data-equalizer data-equalizer-on="medium">
|
||||
<div class="small-12 medium-6 column table" data-equalizer-watch>
|
||||
<div class="table-cell align-middle">
|
||||
<h3><%= budget.name %></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 column table" data-equalizer-watch>
|
||||
<div id="budget_<%= budget.id %>_results" class="table-cell align-middle">
|
||||
<%= link_to t("budgets.index.see_results"),
|
||||
budget_results_path(budget.id),
|
||||
class: "button" %>
|
||||
<%= link_to t("budgets.index.milestones"),
|
||||
budget_executions_path(budget.id),
|
||||
class: "button" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%= render "finished", budgets: @finished_budgets %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
verify_account: link_to(t("votes.verify_account"), verification_path),
|
||||
signin: link_to(t("votes.signin"), new_user_session_path),
|
||||
signup: link_to(t("votes.signup"), new_user_registration_path),
|
||||
supported_headings: (current_user && current_user.headings_voted_within_group(investment.group).map(&:name).to_sentence)
|
||||
supported_headings: (current_user && current_user.headings_voted_within_group(investment.group).map(&:name).sort.to_sentence)
|
||||
).html_safe %>
|
||||
</small>
|
||||
</p>
|
||||
|
||||
@@ -24,22 +24,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row margin-top">
|
||||
<div class="small-12 column">
|
||||
<ul class="tabs">
|
||||
<li class="tabs-title is-active">
|
||||
<span class="show-for-sr"><%= t("shared.you_are_in") %></span>
|
||||
<%= link_to t("budgets.results.link"), budget_results_path(@budget), class: "is-active" %>
|
||||
</li>
|
||||
<li class="tabs-title">
|
||||
<%= link_to t("stats.budgets.link"), budget_stats_path(@budget) %>
|
||||
</li>
|
||||
<li class="tabs-title">
|
||||
<%= link_to t("budgets.executions.link"), budget_executions_path(@budget) %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<%= render "budgets/subnav", budget: @budget %>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-3 large-2 column">
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if @budget.finished? %>
|
||||
<% if can?(:read_results, @budget) %>
|
||||
<%= link_to t("budgets.show.see_results"),
|
||||
budget_results_path(@budget),
|
||||
class: "button margin-top expanded" %>
|
||||
|
||||
@@ -21,22 +21,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row margin-top">
|
||||
<div class="small-12 column">
|
||||
<ul class="tabs">
|
||||
<li class="tabs-title">
|
||||
<span class="show-for-sr"><%= t("shared.you_are_in") %></span>
|
||||
<%= link_to t("budgets.results.link"), budget_results_path(@budget) %>
|
||||
</li>
|
||||
<li class="tabs-title is-active">
|
||||
<%= link_to t("stats.budgets.link"), budget_stats_path(@budget), class: "is-active" %>
|
||||
</li>
|
||||
<li class="tabs-title">
|
||||
<%= link_to t("budgets.executions.link"), budget_executions_path(@budget) %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<%= render "budgets/subnav", budget: @budget %>
|
||||
|
||||
<div class="row margin">
|
||||
<div class="small-12 medium-3 column sidebar">
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
<% allow_votes = local_assigns.fetch(:allow_votes, true) %>
|
||||
<% allow_actions = local_assigns.fetch(:allow_actions, true) %>
|
||||
<% allow_comments = local_assigns.fetch(:allow_comments, true) %>
|
||||
<% cache [locale_and_user_status(comment), comment, commentable_cache_key(comment.commentable), comment.author, (comment_flags[comment.id] if comment_flags)] do %>
|
||||
<% admin_layout = local_assigns.fetch(:admin_layout, false) %>
|
||||
<% cache [locale_and_user_status(comment), comment, commentable_cache_key(comment.commentable), comment.author, (comment_flags[comment.id] if comment_flags), (admin_layout if admin_layout)] do %>
|
||||
<ul id="<%= dom_id(comment) %>" class="comment no-bullet small-12">
|
||||
<li class="comment-body">
|
||||
<% if comment.hidden? || comment.user.hidden? %>
|
||||
@@ -30,7 +31,14 @@
|
||||
<div class="comment-info">
|
||||
|
||||
<% if comment.as_administrator? %>
|
||||
<span class="user-name"><%= t("comments.comment.admin") %> #<%= comment.administrator_id %></span>
|
||||
<span class="user-name">
|
||||
<%= t("comments.comment.admin") %>
|
||||
<% if admin_layout %>
|
||||
<%= Administrator.find(comment.administrator_id).description_or_name %>
|
||||
<% else %>
|
||||
#<%= comment.administrator_id %>
|
||||
<% end %>
|
||||
</span>
|
||||
<% elsif comment.as_moderator? %>
|
||||
<span class="user-name"><%= t("comments.comment.moderator") %> #<%= comment.moderator_id %></span>
|
||||
<% else %>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<% commentable = comment_tree.commentable %>
|
||||
<% valuation = local_assigns.fetch(:valuation, false) %>
|
||||
<% allow_comments = local_assigns.fetch(:allow_comments, true) %>
|
||||
<% cache [locale_and_user_status, comment_tree.order, commentable_cache_key(commentable), comment_tree.comments, comment_tree.comment_authors, commentable.comments_count, comment_flags] do %>
|
||||
<% admin_layout = local_assigns.fetch(:admin_layout, false) %>
|
||||
<% cache [locale_and_user_status, comment_tree.order, commentable_cache_key(commentable), comment_tree.comments, comment_tree.comment_authors, commentable.comments_count, comment_flags, admin_layout] do %>
|
||||
<section class="expanded comments">
|
||||
<div class="row">
|
||||
<div id="comments" class="small-12 column">
|
||||
@@ -46,7 +47,8 @@
|
||||
valuation: valuation,
|
||||
allow_votes: !valuation,
|
||||
allow_actions: !valuation,
|
||||
allow_comments: allow_comments } %>
|
||||
allow_comments: allow_comments,
|
||||
admin_layout: admin_layout } %>
|
||||
<% end %>
|
||||
<%= paginate comment_tree.root_comments %>
|
||||
</div>
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
<h2 class="sidebar-title"><%= t("shared.tags_cloud.districts") %></h2>
|
||||
<br>
|
||||
<%= link_to map_proposals_path, id: "map", title: t("shared.tags_cloud.districts_list") do %>
|
||||
<%= image_tag(image_path_for("map.jpg", alt: t("shared.tags_cloud.districts_list")) %>
|
||||
<%= image_tag(image_path_for("map.jpg", alt: t("shared.tags_cloud.districts_list"))) %>
|
||||
<% end %>
|
||||
|
||||
19
app/views/mailer/evaluation_comment.html.erb
Normal file
19
app/views/mailer/evaluation_comment.html.erb
Normal file
@@ -0,0 +1,19 @@
|
||||
<td style="padding-bottom: 20px; padding-left: 10px;">
|
||||
|
||||
<h1 style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;">
|
||||
<%= t("mailers.evaluation_comment.title", investment: @email.commentable.title) %>
|
||||
</h1>
|
||||
|
||||
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
|
||||
<%= t("mailers.evaluation_comment.hi") %> <strong><%= @email_to.name %></strong>,
|
||||
</p>
|
||||
|
||||
<p style="font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-weight: normal;line-height: 24px;">
|
||||
<%= t("mailers.evaluation_comment.new_comment_by_html", commenter: @email.comment.author.name, investment: valuation_comments_link(@email.commentable)) %>
|
||||
</p>
|
||||
|
||||
<%= t("mailers.evaluation_comment.commenter_info", commenter: @email.comment.author.name, time: l(@email.comment.created_at)) %>
|
||||
<div style="border-left: 2px solid #DEE0E3;font-family: 'Open Sans','Helvetica Neue',arial,sans-serif;font-size: 14px;font-style: italic;font-weight: normal;line-height: 24px;margin-left: 20px;padding: 10px;">
|
||||
<%= simple_format text_with_links(@email.comment.body), {}, sanitize: false %>
|
||||
</div>
|
||||
</td>
|
||||
43
app/views/proposals/_support_status.html.erb
Normal file
43
app/views/proposals/_support_status.html.erb
Normal file
@@ -0,0 +1,43 @@
|
||||
<% if proposal.selected? %>
|
||||
<div class="callout success">
|
||||
<strong><%= t("proposals.proposal.selected") %></strong>
|
||||
</div>
|
||||
<% else %>
|
||||
<div id="proposal_sticky" data-sticky-container>
|
||||
<div class="sticky fixed-mobile-content"
|
||||
data-sticky
|
||||
data-stick-to="bottom"
|
||||
data-sticky-on="small"
|
||||
data-top-anchor="0"
|
||||
data-btm-anchor="sticky_stop"
|
||||
data-check-every="0">
|
||||
<div class="fixed-mobile-content">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("votes.supports") %></h2>
|
||||
|
||||
<div id="<%= dom_id(proposal) %>_votes">
|
||||
<% if proposal.draft? %>
|
||||
<div class="callout primary">
|
||||
<p class="text-center small"><strong><%= t("proposals.show.draft") %></strong></p>
|
||||
</div>
|
||||
<% elsif proposal.successful? %>
|
||||
<div class="supports text-center">
|
||||
<%= render "supports", proposal: proposal %>
|
||||
</div>
|
||||
<% elsif proposal.archived? %>
|
||||
<div class="padding text-center">
|
||||
<p>
|
||||
<strong><%= t("proposals.proposal.supports", count: proposal.total_votes) %></strong>
|
||||
</p>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "votes", { proposal: proposal, vote_url: vote_proposal_path(proposal, value: "yes") } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="sticky_stop"></div>
|
||||
<% end %>
|
||||
@@ -2,12 +2,12 @@
|
||||
<% provide :title do %><%= @proposal.title %><% end %>
|
||||
<% content_for :meta_description do %><%= @proposal.summary %><% end %>
|
||||
<% provide :social_media_meta_tags do %>
|
||||
<%= render "shared/social_media_meta_tags",
|
||||
social_url: proposal_url(@proposal),
|
||||
social_title: @proposal.title,
|
||||
social_description: @proposal.summary,
|
||||
twitter_image_url: (@proposal.image.present? ? @proposal.image_url(:thumb) : nil),
|
||||
og_image_url: (@proposal.image.present? ? @proposal.image_url(:thumb) : nil) %>
|
||||
<%= render "shared/social_media_meta_tags",
|
||||
social_url: proposal_url(@proposal),
|
||||
social_title: @proposal.title,
|
||||
social_description: @proposal.summary,
|
||||
twitter_image_url: (@proposal.image.present? ? @proposal.image_url(:thumb) : nil),
|
||||
og_image_url: (@proposal.image.present? ? @proposal.image_url(:thumb) : nil) %>
|
||||
<% end %>
|
||||
<% content_for :canonical do %>
|
||||
<%= render "shared/canonical", href: proposal_url(@proposal) %>
|
||||
@@ -62,50 +62,7 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @proposal.selected? %>
|
||||
<div class="callout success">
|
||||
<strong><%= t("proposals.proposal.selected") %></strong>
|
||||
</div>
|
||||
<% else %>
|
||||
<div id="proposal_sticky" data-sticky-container>
|
||||
<div class="sticky fixed-mobile-content"
|
||||
data-sticky
|
||||
data-stick-to="bottom"
|
||||
data-sticky-on="small"
|
||||
data-top-anchor="0"
|
||||
data-btm-anchor="sticky_stop"
|
||||
data-check-every="0">
|
||||
<div class="fixed-mobile-content">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("votes.supports") %></h2>
|
||||
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
<% if @proposal.draft? %>
|
||||
<div class="callout primary">
|
||||
<p class=text-center><strong><%= t(".draft") %></strong></p>
|
||||
</div>
|
||||
<% elsif @proposal.successful? %>
|
||||
<div class="supports text-center">
|
||||
<%= render "supports", proposal: @proposal %>
|
||||
</div>
|
||||
<% elsif @proposal.archived? %>
|
||||
<div class="padding text-center">
|
||||
<p>
|
||||
<strong><%= t("proposals.proposal.supports", count: @proposal.total_votes) %></strong>
|
||||
</p>
|
||||
<p><%= t("proposals.proposal.archived") %></p>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "votes",
|
||||
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: "yes") } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="sticky_stop"></div>
|
||||
<% end %>
|
||||
<%= render "proposals/support_status", proposal: @proposal %>
|
||||
|
||||
<%= render "proposals/social_share", proposal: @proposal, share_title: t("proposals.show.share") %>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"<%= t("stats.index.visits") %>" : "<%= number_with_delimiter(@visits) %>",
|
||||
"<%= t("stats.index.debates") %>" : <%= number_with_delimiter(@debates) %>",
|
||||
"<%= t("stats.index.debates") %>" : "<%= number_with_delimiter(@debates) %>",
|
||||
"<%= t("stats.index.proposals") %>" : "<%= number_with_delimiter(@proposals) %>",
|
||||
"<%= t("stats.index.comments") %>" : "<%= number_with_delimiter(@comments) %>",
|
||||
"<%= t("stats.index.proposal_votes") %>" : "<%= number_with_delimiter(@proposal_votes) %>",
|
||||
@@ -9,4 +9,4 @@
|
||||
"<%= t("stats.index.votes") %>" : "<%= number_with_delimiter(@votes) %>",
|
||||
"<%= t("stats.index.verified_users") %>" : "<%= number_with_delimiter(@verified_users) %>",
|
||||
"<%= t("stats.index.unverified_users") %>" : "<%= number_with_delimiter(@unverified_users) %>"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<h2><%= t("valuation.budget_investments.valuation_comments") %></h2>
|
||||
<% unless @comment_tree.nil? %>
|
||||
<%= render partial: "/comments/comment_tree", locals: { comment_tree: @comment_tree,
|
||||
comment_flags: @comment_flags,
|
||||
display_comments_count: false,
|
||||
valuation: true,
|
||||
allow_comments: !@budget.finished? } %>
|
||||
<%= render partial: "/comments/comment_tree", locals: {
|
||||
comment_tree: @comment_tree,
|
||||
comment_flags: @comment_flags,
|
||||
display_comments_count: false,
|
||||
valuation: true,
|
||||
allow_comments: !@budget.finished?,
|
||||
admin_layout: true } %>
|
||||
<% end %>
|
||||
|
||||
@@ -45,11 +45,19 @@ namespace :deploy do
|
||||
#before :starting, "rvm1:install:ruby" # install Ruby and create gemset
|
||||
#before :starting, "install_bundler_gem" # install bundler gem
|
||||
|
||||
after "deploy:migrate", "add_new_settings"
|
||||
after :publishing, "deploy:restart"
|
||||
after :published, "delayed_job:restart"
|
||||
after :published, "refresh_sitemap"
|
||||
|
||||
after :finishing, "deploy:cleanup"
|
||||
|
||||
|
||||
desc "Deploys and runs the tasks needed to upgrade to a new release"
|
||||
task :upgrade do
|
||||
after "add_new_settings", "execute_release_tasks"
|
||||
invoke "deploy"
|
||||
end
|
||||
end
|
||||
|
||||
task :install_bundler_gem do
|
||||
@@ -67,3 +75,23 @@ task :refresh_sitemap do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
task :add_new_settings do
|
||||
on roles(:db) do
|
||||
within release_path do
|
||||
with rails_env: fetch(:rails_env) do
|
||||
execute :rake, "settings:add_new_settings"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
task :execute_release_tasks do
|
||||
on roles(:app) do
|
||||
within release_path do
|
||||
with rails_env: fetch(:rails_env) do
|
||||
execute :rake, "consul:execute_release_tasks"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,6 +48,7 @@ Rails.application.configure do
|
||||
# config.action_cable.url = 'wss://example.com/cable'
|
||||
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
|
||||
|
||||
|
||||
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
||||
config.force_ssl = true
|
||||
|
||||
|
||||
@@ -115,9 +115,12 @@ ignore_missing:
|
||||
- "activerecord.errors.models.direct_message.*"
|
||||
- "errors.messages.blank"
|
||||
- "errors.messages.taken"
|
||||
- "errors.messages.too_short"
|
||||
- "errors.messages.too_long"
|
||||
- "devise.failure.invalid"
|
||||
- "devise.registrations.destroyed"
|
||||
- "devise.password_expired.*"
|
||||
- "seeds.settings.*"
|
||||
|
||||
## Consider these keys used:
|
||||
ignore_unused:
|
||||
@@ -130,9 +133,9 @@ ignore_unused:
|
||||
- "date.order"
|
||||
- "unauthorized.*"
|
||||
- "admin.officials.level_*"
|
||||
- "admin.comments.index.filter*"
|
||||
- "admin.hidden_comments.index.filter*"
|
||||
- "admin.banners.index.filters.*"
|
||||
- "admin.debates.index.filter*"
|
||||
- "admin.hidden_debates.index.filter*"
|
||||
- "admin.hidden_proposals.index.filter*"
|
||||
- "admin.proposal_notifications.index.filter*"
|
||||
- "admin.budgets.index.filter*"
|
||||
@@ -147,7 +150,7 @@ ignore_unused:
|
||||
- "admin.legislation.processes.proposals.select_order"
|
||||
- "admin.legislation.draft_versions.*.submit_button"
|
||||
- "admin.legislation.questions.*.submit_button"
|
||||
- "admin.comments.index.hidden_*"
|
||||
- "admin.hidden_comments.index.hidden_*"
|
||||
- "admin.settings.index.features.*"
|
||||
- "admin.polls.*.submit_button"
|
||||
- "admin.booths.*.submit_button"
|
||||
@@ -206,7 +209,7 @@ ignore_unused:
|
||||
- admin.stats.polls.expired
|
||||
- "stats.polls.*_percentage"
|
||||
- landings.cambia_tu_ciudad.*
|
||||
- 'seeds.settings.*'
|
||||
- "seeds.settings.*"
|
||||
- "dashboard.polls.*.submit"
|
||||
####
|
||||
## Exclude these keys from the `i18n-tasks eq-base" report:
|
||||
|
||||
@@ -168,8 +168,9 @@ ar:
|
||||
heading_selection_title: "جسب المنطقة"
|
||||
no_winner_investments: "لا يوجد استثمارات فائزة"
|
||||
filters:
|
||||
label: "حالة المشروع الحالية"
|
||||
all: "الكل (%{count})"
|
||||
status:
|
||||
label: "حالة المشروع الحالية"
|
||||
all: "الكل (%{count})"
|
||||
phases:
|
||||
errors:
|
||||
dates_range_invalid: "تاريخ البدأ لا يمكن ان يكون مساو او يتجاوز تاريخ الانتهاء"
|
||||
|
||||
@@ -3,7 +3,7 @@ ar:
|
||||
no_reply: "تم إرسال هذه الرسالة من عنوان بريد إلكتروني لا يقبل الردود."
|
||||
comment:
|
||||
hi: مرحبا
|
||||
new_comment_by_html: هناك تعليق جديد من <b>%{commenter}</b>
|
||||
new_comment_by_html: هناك تعليق جديد من <strong>%{commenter}</strong>
|
||||
subject: تم التعليق على %{commentable}
|
||||
title: تعليق جديد
|
||||
config:
|
||||
@@ -16,7 +16,7 @@ ar:
|
||||
title: أكد حسابك باستخدام الرابط التالي
|
||||
reply:
|
||||
hi: مرحبا
|
||||
new_reply_by_html: وهناك رد جديد من <b>%{commenter}</b> على التعليق الخاص بك
|
||||
new_reply_by_html: وهناك رد جديد من <strong>%{commenter}</strong> على التعليق الخاص بك
|
||||
subject: يوجد رد على تعليقك
|
||||
title: اجابة جديدة على تعليقك
|
||||
unfeasible_spending_proposal:
|
||||
|
||||
@@ -3,7 +3,7 @@ ast:
|
||||
no_reply: "Este mensaje se ha enviado desde una dirección de correo electrónico que no admite respuestas."
|
||||
comment:
|
||||
hi: Hola
|
||||
new_comment_by_html: Hay un nuevo comentario de <b>%{commenter}</b> en
|
||||
new_comment_by_html: Hay un nuevo comentario de <strong>%{commenter}</strong> en
|
||||
subject: Alguien ha comentado en tu %{commentable}
|
||||
title: Nuevo comentario
|
||||
config:
|
||||
@@ -16,7 +16,7 @@ ast:
|
||||
title: Verifica tu cuenta con el siguiente enlace
|
||||
reply:
|
||||
hi: Hola
|
||||
new_reply_by_html: Hay una nueva respuesta de <b>%{commenter}</b> a tu comentario en
|
||||
new_reply_by_html: Hay una nueva respuesta de <strong>%{commenter}</strong> a tu comentario en
|
||||
subject: Alguien ha respondido a tu comentario
|
||||
title: Nueva respuesta a tu comentario
|
||||
unfeasible_spending_proposal:
|
||||
|
||||
@@ -3,7 +3,7 @@ ca:
|
||||
no_reply: "Aquest missatge s'ha enviat des d'una adreça de correu electrònic que no admet respostes."
|
||||
comment:
|
||||
hi: Hola
|
||||
new_comment_by_html: Hi ha un nou comentari de <b>%{commenter}</b> en
|
||||
new_comment_by_html: Hi ha un nou comentari de <strong>%{commenter}</strong> en
|
||||
subject: Algú ha comentat en el teu %{commentable}
|
||||
title: Nou comentari
|
||||
config:
|
||||
@@ -16,7 +16,7 @@ ca:
|
||||
title: Verifica el teu compte amb el següent enllaç
|
||||
reply:
|
||||
hi: Hola
|
||||
new_reply_by_html: Hi ha una nova resposta de <b>%{commenter}</b> al teu comentari en
|
||||
new_reply_by_html: Hi ha una nova resposta de <strong>%{commenter}</strong> al teu comentari en
|
||||
subject: Algú ha respost al teu comentari
|
||||
title: Nova resposta al teu comentari
|
||||
unfeasible_spending_proposal:
|
||||
|
||||
@@ -182,8 +182,9 @@ de:
|
||||
heading_selection_title: "Nach Bezirk"
|
||||
no_winner_investments: "Keine erfolgreichen Ausgabenvorschläge in diesem Status"
|
||||
filters:
|
||||
label: "Aktueller Stand des Projekts"
|
||||
all: "Alle (%{count})"
|
||||
status:
|
||||
label: "Aktueller Stand des Projekts"
|
||||
all: "Alle (%{count})"
|
||||
phases:
|
||||
errors:
|
||||
dates_range_invalid: "Das Anfangsdatum kann nicht gleich oder später als das Enddatum sein"
|
||||
|
||||
@@ -3,7 +3,7 @@ de:
|
||||
no_reply: "Diese Nachricht wurde von einer E-Mail-Adresse gesendet, die keine Antworten akzeptiert."
|
||||
comment:
|
||||
hi: Hallo
|
||||
new_comment_by_html: Es gibt einen neuen Kommentar von <b>%{commenter}</b>
|
||||
new_comment_by_html: Es gibt einen neuen Kommentar von <strong>%{commenter}</strong>
|
||||
subject: Jemand hat Ihre %{commentable} kommentiert.
|
||||
title: Neuer Kommentar
|
||||
config:
|
||||
@@ -16,7 +16,7 @@ de:
|
||||
title: Bestätigen Sie Ihr Konto über den folgenden Link
|
||||
reply:
|
||||
hi: Hallo
|
||||
new_reply_by_html: Es gibt eine neue Antwort von <b>%{commenter}</b> auf Ihren Kommentar
|
||||
new_reply_by_html: Es gibt eine neue Antwort von <strong>%{commenter}</strong> auf Ihren Kommentar
|
||||
subject: Jemand hat auf Ihren Kommentar geantwortet
|
||||
title: Neue Antwort auf Ihren Kommentar
|
||||
unfeasible_spending_proposal:
|
||||
|
||||
@@ -281,6 +281,7 @@ en:
|
||||
tags_placeholder: "Write the tags you want separated by commas (,)"
|
||||
undefined: Undefined
|
||||
user_groups: "Groups"
|
||||
milestone_tags: Milestone tags
|
||||
search_unfeasible: Search unfeasible
|
||||
milestones:
|
||||
index:
|
||||
@@ -297,6 +298,7 @@ en:
|
||||
documents: "Documents"
|
||||
milestone: Milestone
|
||||
new_milestone: Create new milestone
|
||||
milestone_tags: Milestone Tags
|
||||
form:
|
||||
admin_statuses: Manage statuses
|
||||
no_statuses_defined: There are no defined statuses yet
|
||||
@@ -355,7 +357,7 @@ en:
|
||||
notice: "Progress bar updated successfully"
|
||||
delete:
|
||||
notice: "Progress bar deleted successfully"
|
||||
comments:
|
||||
hidden_comments:
|
||||
index:
|
||||
filter: Filter
|
||||
filters:
|
||||
@@ -430,7 +432,7 @@ en:
|
||||
request: Requested resource
|
||||
update:
|
||||
success: The task has been marked as solved.
|
||||
debates:
|
||||
hidden_debates:
|
||||
index:
|
||||
filter: Filter
|
||||
filters:
|
||||
@@ -728,6 +730,7 @@ en:
|
||||
title: Administrators
|
||||
name: Name
|
||||
email: Email
|
||||
description: Description
|
||||
id: Administrator ID
|
||||
no_administrators: There are no administrators.
|
||||
administrator:
|
||||
@@ -736,6 +739,9 @@ en:
|
||||
restricted_removal: "Sorry, you can't remove yourself from the administrators"
|
||||
search:
|
||||
title: "Administrators: User search"
|
||||
form:
|
||||
edit_title: "Edit administrator"
|
||||
updated: "Administrator updated successfully"
|
||||
moderators:
|
||||
index:
|
||||
title: Moderators
|
||||
@@ -875,6 +881,9 @@ en:
|
||||
user_invite:
|
||||
title: "User Invitation"
|
||||
description: "Sent to the person that has been invited to register an account."
|
||||
evaluation_comment:
|
||||
title: "New evaluation comment"
|
||||
description: "Sent to administrators and evaluators related to commented investment"
|
||||
edit_info: "You can edit this email in"
|
||||
message_title: "Message's Title"
|
||||
message_body: "This is a sample of message's content."
|
||||
@@ -882,6 +891,7 @@ en:
|
||||
no_investments: "There aren't any budget investment created. Some example data is needed in order to preview the email."
|
||||
no_comments: "There aren't any comments created. Some example data is needed in order to preview the email."
|
||||
no_replies: "There aren't any replies created. Some example data is needed in order to preview the email."
|
||||
no_evaluation_comments: "There aren't any evaluation comments created. Some example data is needed in order to preview the email."
|
||||
emails_download:
|
||||
index:
|
||||
title: Emails download
|
||||
@@ -1261,6 +1271,7 @@ en:
|
||||
title: Configuration settings
|
||||
update_setting: Update
|
||||
participation_processes: "Participation processes"
|
||||
images_and_documents: "Images and documents"
|
||||
feature_flags: Features
|
||||
features:
|
||||
enabled: "Feature enabled"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user