diff --git a/.coffeelint.json b/.coffeelint.json
new file mode 100644
index 000000000..9b00e8a75
--- /dev/null
+++ b/.coffeelint.json
@@ -0,0 +1,41 @@
+{
+ "arrow_spacing": {
+ "level": "error"
+ },
+ "braces_spacing": {
+ "level": "error",
+ "spaces": 1
+ },
+ "colon_assignment_spacing": {
+ "level": "error",
+ "spacing": {
+ "left": 0,
+ "right": 1
+ }
+ },
+ "eol_last": {
+ "level": "error"
+ },
+ "indentation": {
+ "value": 2
+ },
+ "line_endings": {
+ "level": "error"
+ },
+ "max_line_length": {
+ "value": 100,
+ "level": "error",
+ "limitComments": true
+ },
+ "no_trailing_whitespace": {
+ "level": "error",
+ "allowed_in_comments": false,
+ "allowed_in_empty_lines": false
+ },
+ "space_operators": {
+ "level": "error"
+ },
+ "spacing_after_comma": {
+ "level": "error"
+ }
+}
diff --git a/.erb-lint.yml b/.erb-lint.yml
new file mode 100644
index 000000000..895a9d799
--- /dev/null
+++ b/.erb-lint.yml
@@ -0,0 +1,14 @@
+---
+linters:
+ FinalNewline:
+ enabled: true
+ SpaceAroundErbTag:
+ enabled: true
+ SelfClosingTag:
+ enabled: false
+ Rubocop:
+ enabled: true
+ only:
+ - Layout/EndOfLine
+ - Lint/LiteralAsCondition
+ - Style/PercentLiteralDelimiters
diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE
index abb23cf0a..a8c151f5d 100644
--- a/.github/PULL_REQUEST_TEMPLATE
+++ b/.github/PULL_REQUEST_TEMPLATE
@@ -1,17 +1,17 @@
-References
-===================
-> Add references to related Issues/Pull Requests/Travis Builds/Rollbar errors/etc...
+## References
-Objectives
-===================
-> What are the objectives of this changes? (If there is no related Issue with an explanation)
+> Related Issues/Pull Requests/Travis Builds/Rollbar errors/etc...
+
+## Objectives
+
+> What are the objectives of these changes?
+
+## Visual Changes
-Visual Changes
-===================
> Any visual changes? please attach screenshots (or gifs) showing them.
> If modified views are public (not the admin panel), try them in mobile display (with your browser's developer console) and add screenshots.
-Notes
-===================
+## Notes
+
> Mention rake tasks or actions to be done when deploying this changes to a server (if any).
> Explain any caveats, or important things to notice like deprecations (if any).
diff --git a/.gitignore b/.gitignore
index 0413aaa36..865001781 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,4 @@
public/sitemap.xml
public/system/
/public/ckeditor_assets/
+
diff --git a/.hound.yml b/.hound.yml
index 67a0668db..4e54eebfc 100644
--- a/.hound.yml
+++ b/.hound.yml
@@ -2,3 +2,8 @@ rubocop:
config_file: .rubocop_basic.yml
scss:
config_file: .scss-lint.yml
+coffeescript:
+ config_file: .coffeelint.json
+erblint:
+ enabled: true
+ config_file: .erb-lint.yml
diff --git a/.rubocop_basic.yml b/.rubocop_basic.yml
index cebf55084..1099dcce4 100644
--- a/.rubocop_basic.yml
+++ b/.rubocop_basic.yml
@@ -4,12 +4,11 @@ AllCops:
DisplayCopNames: true
DisplayStyleGuide: true
Include:
- - '**/Rakefile'
- - '**/config.ru'
+ - "**/Rakefile"
+ - "**/config.ru"
Exclude:
- - 'db/**/*'
- - 'config/**/*'
- - 'script/**/*'
+ - "db/migrate/**/*"
+ - "db/schema.rb"
TargetRubyVersion: 2.3
# RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
# to ignore them, so only the ones explicitly set in this file are enabled.
@@ -30,6 +29,12 @@ Layout/TrailingBlankLines:
Layout/TrailingWhitespace:
Enabled: true
+Lint/LiteralAsCondition:
+ Enabled: true
+
+Lint/UselessAssignment:
+ Enabled: true
+
Metrics/LineLength:
Max: 100
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
deleted file mode 100644
index f3a40d8ab..000000000
--- a/.rubocop_todo.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-# This configuration was generated by
-# `rubocop --auto-gen-config`
-# on 2018-02-10 21:25:09 +0100 using RuboCop version 0.52.1.
-# The point is for the user to remove these configuration records
-# one by one as the offenses are removed from the code base.
-# Note that changes in the inspected code, or installation of new
-# versions of RuboCop, may require this file to be generated again.
-
-# Offense count: 10
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle.
-# SupportedStyles: normal, rails
-Layout/IndentationConsistency:
- Exclude:
- - 'spec/features/tracks_spec.rb'
- - 'spec/models/budget/investment_spec.rb'
- - 'spec/models/legislation/draft_version_spec.rb'
- - 'spec/models/proposal_spec.rb'
-
-# Offense count: 1225
-# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
-# URISchemes: http, https
-Metrics/LineLength:
- Max: 248
-
-# Offense count: 4
-# Cop supports --auto-correct.
-Performance/RedundantMatch:
- Exclude:
- - 'app/controllers/valuation/budget_investments_controller.rb'
- - 'app/controllers/valuation/spending_proposals_controller.rb'
-
-# Offense count: 11
-RSpec/DescribeClass:
- Exclude:
- - 'spec/customization_engine_spec.rb'
- - 'spec/i18n_spec.rb'
- - 'spec/lib/acts_as_paranoid_aliases_spec.rb'
- - 'spec/lib/cache_spec.rb'
- - 'spec/lib/graphql_spec.rb'
- - 'spec/lib/tasks/communities_spec.rb'
- - 'spec/lib/tasks/dev_seed_spec.rb'
- - 'spec/lib/tasks/map_location_spec.rb'
- - 'spec/lib/tasks/settings_spec.rb'
- - 'spec/models/abilities/organization_spec.rb'
- - 'spec/views/welcome/index.html.erb_spec.rb'
-
-# Offense count: 2
-# Configuration parameters: SkipBlocks, EnforcedStyle.
-# SupportedStyles: described_class, explicit
-RSpec/DescribedClass:
- Exclude:
- - 'spec/controllers/concerns/has_filters_spec.rb'
- - 'spec/controllers/concerns/has_orders_spec.rb'
-
-# Offense count: 6
-RSpec/ExpectActual:
- Exclude:
- - 'spec/routing/**/*'
- - 'spec/features/admin/budget_investments_spec.rb'
-
-# Offense count: 830
-# Configuration parameters: AssignmentOnly.
-RSpec/InstanceVariable:
- Enabled: false
-
-# Offense count: 1
-# Configuration parameters: IgnoreSymbolicNames.
-RSpec/VerifiedDoubles:
- Exclude:
- - 'spec/models/verification/management/email_spec.rb'
diff --git a/.scss-lint.yml b/.scss-lint.yml
index dfa46907b..d2d024576 100644
--- a/.scss-lint.yml
+++ b/.scss-lint.yml
@@ -175,7 +175,7 @@ linters:
StringQuotes:
enabled: true
- style: single_quotes
+ style: double_quotes
TrailingSemicolon:
enabled: true
diff --git a/.travis.yml b/.travis.yml
index cb4ffd0ac..0aa683c04 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
language: ruby
addons:
- postgresql: '9.4'
+ postgresql: "9.4"
chrome: stable
rvm:
- 2.3.2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index adfaaac31..63f25531f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,304 @@
# Changelog
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).
+and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
+
+## [v0.19](https://github.com/consul/consul/compare/v0.18.1...v0.19) (2019-02-27)
+
+### Added
+
+- **Admin:** Add cards to custom pages [\#3149](https://github.com/consul/consul/pull/3149)
+- **Design/UX:** Refactor processes header colors and custom pages [\#3249](https://github.com/consul/consul/pull/3249)
+- **Legislation:** Add image to legislation processes and banner colors [\#3152](https://github.com/consul/consul/pull/3152)
+- **Mails:** Configurable email interceptor by environment [\#3251](https://github.com/consul/consul/pull/3251)
+- **Maintenance-Rubocop:** Enable useless assignment rubocop rule [\#3120](https://github.com/consul/consul/pull/3120)
+- **Maintenance-Rubocop:** Fix literal as condition [\#3313](https://github.com/consul/consul/pull/3313)
+- **Milestones:** Manage milestone progress bars [\#3195](https://github.com/consul/consul/pull/3195)
+- **Milestones:** Refactor milestones css [\#3196](https://github.com/consul/consul/pull/3196)
+- **Milestones:** Add progress bar dev seeds [\#3197](https://github.com/consul/consul/pull/3197)
+- **Milestones:** Add progress bars to milestones public view [\#3228](https://github.com/consul/consul/pull/3228)
+- **Multi-language:** Make budgets translatable [\#3296](https://github.com/consul/consul/pull/3296)
+- **Polls:** Add a description for open polls [\#3303](https://github.com/consul/consul/pull/3303)
+- **Translations:** add new Russian translation [\#3204](https://github.com/consul/consul/pull/3204)
+- **Translations:** add new Russian translation [\#3205](https://github.com/consul/consul/pull/3205)
+- **Translations:** add new Russian translation [\#3206](https://github.com/consul/consul/pull/3206)
+- **Translations:** add new Russian translation [\#3207](https://github.com/consul/consul/pull/3207)
+- **Translations:** add new Russian translation [\#3208](https://github.com/consul/consul/pull/3208)
+- **Translations:** add new Russian translation [\#3209](https://github.com/consul/consul/pull/3209)
+- **Translations:** add new Russian translation [\#3210](https://github.com/consul/consul/pull/3210)
+- **Translations:** add new Russian translation [\#3211](https://github.com/consul/consul/pull/3211)
+- **Translations:** add new Russian translation [\#3212](https://github.com/consul/consul/pull/3212)
+- **Translations:** add new Russian translation [\#3213](https://github.com/consul/consul/pull/3213)
+- **Translations:** add new Russian translation [\#3214](https://github.com/consul/consul/pull/3214)
+- **Translations:** add new Russian translation [\#3215](https://github.com/consul/consul/pull/3215)
+- **Translations:** add new Russian translation [\#3216](https://github.com/consul/consul/pull/3216)
+- **Translations:** add new Russian translation [\#3217](https://github.com/consul/consul/pull/3217)
+- **Translations:** add new Russian translation [\#3218](https://github.com/consul/consul/pull/3218)
+- **Translations:** add new Russian translation [\#3219](https://github.com/consul/consul/pull/3219)
+- **Translations:** add new Russian translation [\#3220](https://github.com/consul/consul/pull/3220)
+- **Translations:** add new Russian translation [\#3221](https://github.com/consul/consul/pull/3221)
+- **Translations:** add new Russian translation [\#3222](https://github.com/consul/consul/pull/3222)
+- **Translations:** add new Russian translation [\#3223](https://github.com/consul/consul/pull/3223)
+- **Translations:** add new Russian translation [\#3224](https://github.com/consul/consul/pull/3224)
+- **Translations:** add new Russian translation [\#3225](https://github.com/consul/consul/pull/3225)
+- **Translations:** add new Russian translation [\#3226](https://github.com/consul/consul/pull/3226)
+- **Translations:** New Crowdin translations [\#3305](https://github.com/consul/consul/pull/3305)
+- **Translations:** Add locales for Indonesian, Russian, Slovak and Somali [\#3309](https://github.com/consul/consul/pull/3309)
+- **Translations:** Remove untranslated locales [\#3310](https://github.com/consul/consul/pull/3310)
+
+### Changed
+
+- **Admin:** Admin tables order - sorting [\#3148](https://github.com/consul/consul/pull/3148)
+- **Admin:** Hide polls results and stats to admins [\#3229](https://github.com/consul/consul/pull/3229)
+- **Admin:** Allow change map image from admin [\#3230](https://github.com/consul/consul/pull/3230)
+- **Admin:** Allow admins delete poll answer documents [\#3231](https://github.com/consul/consul/pull/3231)
+- **Admin:** Admin polls list [\#3253](https://github.com/consul/consul/pull/3253)
+- **Admin:** Show all system emails in Admin section [\#3326](https://github.com/consul/consul/pull/3326)
+- **Admin:** Improve Admin settings section [\#3328](https://github.com/consul/consul/pull/3328)
+- **Budgets:** Show current phase as selected on phase select on admin budgets form [\#3203](https://github.com/consul/consul/pull/3203)
+- **Budgets:** Do not display alert when supporting in a group with a single heading [\#3278](https://github.com/consul/consul/pull/3278)
+- **Budgets:** Include heading names in "headings limit reached" alert [\#3290](https://github.com/consul/consul/pull/3290)
+- **Budgets:** Consider having valuator group as having valuator [\#3314](https://github.com/consul/consul/pull/3314)
+- **Budgets:** Show all investments in the map [\#3318](https://github.com/consul/consul/pull/3318)
+- **Design/UX:** Improve UI of budgets index page [\#3250](https://github.com/consul/consul/pull/3250)
+- **Design/UX:** Allow select column width for widget cards [\#3252](https://github.com/consul/consul/pull/3252)
+- **Design/UX:** Change layout on homepage if feed debates and proposals are enabled [\#3269](https://github.com/consul/consul/pull/3269)
+- **Design/UX:** Improve color picker on admin legislation process [\#3277](https://github.com/consul/consul/pull/3277)
+- **Design/UX:** Removes next/incoming filters [\#3280](https://github.com/consul/consul/pull/3280)
+- **Design/UX:** Add sorting icons to sortable tables [\#3324](https://github.com/consul/consul/pull/3324)
+- **Design/UX:** Improve UX on admin section [\#3329](https://github.com/consul/consul/pull/3329)
+- **Legislation:** Remove help and recommendations on legislation proposal new form [\#3200](https://github.com/consul/consul/pull/3200)
+- **Legislation:** Sort Legislation Processes by descending start date [\#3202](https://github.com/consul/consul/pull/3202)
+- **Maps:** Always show markers on budgets index map [\#3267](https://github.com/consul/consul/pull/3267)
+- **Maintenance-Refactorings:** Add pending specs proposal notification limits [\#3174](https://github.com/consul/consul/pull/3174)
+- **Maintenance-Refactorings:** Refactors images attributes [\#3170](https://github.com/consul/consul/pull/3170)
+- **Maintenance-Refactorings:** Use find instead of find\_by\_id [\#3234](https://github.com/consul/consul/pull/3234)
+- **Maintenance-Refactorings:** LegacyLegislation migration cleanup [\#3275](https://github.com/consul/consul/pull/3275)
+- **Maintenance-Refactorings:** Replace sccs lint string quotes to double quotes [\#3281](https://github.com/consul/consul/pull/3281)
+- **Maintenance-Refactorings:** Change single quotes to double quotes in folder /spec [\#3287](https://github.com/consul/consul/pull/3287)
+- **Maintenance-Refactorings:** Reuse image attributes in legislation processes [\#3319](https://github.com/consul/consul/pull/3319)
+- **Newsletters:** Send newsletter emails in order [\#3274](https://github.com/consul/consul/pull/3274)
+- **Tags:** Set tags max length to 160 [\#3264](https://github.com/consul/consul/pull/3264)
+- **Translations:** Update budgets confirm group es translation [\#3198](https://github.com/consul/consul/pull/3198)
+- **Votes:** Use votes score instead of total votes on debates and legislation proposals [\#3291](https://github.com/consul/consul/pull/3291)
+
+### Fixed
+
+- **Budgets:** Show unfeasible and unselected investments for finished budgets [\#3272](https://github.com/consul/consul/pull/3272)
+- **Design/UX:** Fix UI details for a better UX and design [\#3323](https://github.com/consul/consul/pull/3323)
+- **Design/UX:** Budgets UI minor fixes [\#3268](https://github.com/consul/consul/pull/3268)
+- **Polls:** Delete Booth Shifts with associated data [\#3292](https://github.com/consul/consul/pull/3292)
+- **Proposals:** Fix random proposals order in the same session [\#3321](https://github.com/consul/consul/pull/3321)
+- **Tags:** Fix valuation tags being overwritten [\#3330](https://github.com/consul/consul/pull/3330)
+- **Translations:** Fix i18n and UI minor details [\#3191](https://github.com/consul/consul/pull/3191)
+- **Translations:** Return a String in I18n method 'pluralize' [\#3307](https://github.com/consul/consul/pull/3307)
+
+## [0.18.1](https://github.com/consul/consul/compare/v0.18...v0.18.1) (2019-01-17)
+
+### Added
+
+- **Legislation:** Legislation process homepage phase [\#3188](https://github.com/consul/consul/pull/3188)
+- **Legislation:** Show documents on processes proposals phase [\#3136](https://github.com/consul/consul/pull/3136)
+- **Maintenance-Refactorings:** Remove semicolons from controllers [\#3160](https://github.com/consul/consul/pull/3160)
+- **Maintenance-Refactorings:** Remove before action not used [\#3167](https://github.com/consul/consul/pull/3167)
+- **Maintenance-Rubocop:** Enable double quotes rubocop rule [\#3175](https://github.com/consul/consul/pull/3175)
+- **Maintenance-Rubocop:** Enable line length rubocop rule [\#3165](https://github.com/consul/consul/pull/3165)
+- **Maintenance-Rubocop:** Add rubocop rule to indent private methods [\#3134](https://github.com/consul/consul/pull/3134)
+
+### Changed
+
+- **Admin:** Improve CRUD budgets and content blocks [\#3173](https://github.com/consul/consul/pull/3173)
+- **Design/UX:** new CRUD budgets, content blocks and heading map [\#3150](https://github.com/consul/consul/pull/3150)
+- **Design/UX:** Processes key dates [\#3137](https://github.com/consul/consul/pull/3137)
+
+### Fixed
+
+- **Admin:** checks for deleted proposals [\#3154](https://github.com/consul/consul/pull/3154)
+- **Admin:** Add default order for admin budget investments list [\#3151](https://github.com/consul/consul/pull/3151)
+- **Budgets:** Bug Management Cannot create Budget Investment without a map location [\#3133](https://github.com/consul/consul/pull/3133)
+
+## [0.18.0](https://github.com/consul/consul/compare/v0.17...v0.18) (2018-12-27)
+
+### Added
+
+- **Admin:** Admin poll questions index [\#3123](https://github.com/consul/consul/pull/3123)
+- **Budgets:** Added feature to add content block to headings in sidebar [\#3043](https://github.com/consul/consul/pull/3043)
+- **Budgets:** Add map to sidebar on Heading's page [\#3038](https://github.com/consul/consul/pull/3038)
+- **Budgets:** Budget executions [\#3023](https://github.com/consul/consul/pull/3023)
+- **Budgets:** Budget execution list [\#2864](https://github.com/consul/consul/pull/2864)
+- **Design/UX:** Administrator ID [\#3056](https://github.com/consul/consul/pull/3056)
+- **Legislation:** Draft phase on legislation processes [\#3105](https://github.com/consul/consul/pull/3105)
+- **Legislation:** add homepage for legislation processes [\#3091](https://github.com/consul/consul/pull/3091)
+- **Legislation:** Adds draft phase functionality in legislation processes [\#3048](https://github.com/consul/consul/pull/3048)
+- **Maintenance:** Widgets dev seeds [\#3104](https://github.com/consul/consul/pull/3104)
+- **Maintenance:** Add web sections to seeds [\#3037](https://github.com/consul/consul/pull/3037)
+- **Maintenance-Rubocop:** Apply Rubocop not\_to rule [\#3118](https://github.com/consul/consul/pull/3118)
+- **Maintenance-Rubocop:** Add not\_to Rubocop rule [\#3112](https://github.com/consul/consul/pull/3112)
+- **Maintenance-Rubocop:** Add a "Reviewed by Hound" badge [\#3093](https://github.com/consul/consul/pull/3093)
+- **Maintenance-Specs:** Add missing feature spec: Proposal Notifications In-app notifications from the proposal's author group notifications for the same proposal [\#3066](https://github.com/consul/consul/pull/3066)
+- **Maintenance-Specs:** Add missing feature spec: Admin poll questions Create from successful proposal show [\#3065](https://github.com/consul/consul/pull/3065)
+- **Maintenance-Specs:** Add missing feature spec Admin budget investments Edit Do not display valuators of an assigned group [\#3064](https://github.com/consul/consul/pull/3064)
+- **Milestones:** Edit only existing languages in milestones summary [\#3103](https://github.com/consul/consul/pull/3103)
+- **Milestones:** Update milestone status texts [\#3102](https://github.com/consul/consul/pull/3102)
+- **Milestones:** Fix milestone validation [\#3101](https://github.com/consul/consul/pull/3101)
+- **Milestones:** Add milestones to legislation processes [\#3100](https://github.com/consul/consul/pull/3100)
+- **Milestones:** Add milestones to proposals [\#3099](https://github.com/consul/consul/pull/3099)
+- **Milestones:** Fix budget investment milestone translations migration [\#3097](https://github.com/consul/consul/pull/3097)
+- **Milestones:** Make milestones code reusable [\#3095](https://github.com/consul/consul/pull/3095)
+- **Milestones:** Make milestones controller polymorphic [\#3083](https://github.com/consul/consul/pull/3083)
+- **Milestones:** Make milestones polymorphic [\#3057](https://github.com/consul/consul/pull/3057)
+- **Polls:** Polls voted by [\#3089](https://github.com/consul/consul/pull/3089)
+- **Proposals:** Featured proposals [\#3081](https://github.com/consul/consul/pull/3081)
+- **Translations:** Added Slovenian translations [\#3062](https://github.com/consul/consul/pull/3062)
+- **Translations:** New Crowdin translations [\#3050](https://github.com/consul/consul/pull/3050)
+- **Translations:** Maintain translations for other languages after updatin main language [\#3046](https://github.com/consul/consul/pull/3046)
+- **Translations:** New Crowdin translations [\#3005](https://github.com/consul/consul/pull/3005)
+- **Translations:** Update i18n from Crowdin [\#2998](https://github.com/consul/consul/pull/2998)
+
+### Changed
+
+- **Admin:** Improve action buttons aspect for small screens [\#3027](https://github.com/consul/consul/pull/3027)
+- **Admin:** Improve visualization for small resolution [\#3025](https://github.com/consul/consul/pull/3025)
+- **Admin:** Budgets admin [\#3012](https://github.com/consul/consul/pull/3012)
+- **Budgets:** Budget investments social share [\#3053](https://github.com/consul/consul/pull/3053)
+- **Design/UX:** Documents title [\#3131](https://github.com/consul/consul/pull/3131)
+- **Design/UX:** Proposal create question [\#3122](https://github.com/consul/consul/pull/3122)
+- **Design/UX:** Budget investments price explanation [\#3121](https://github.com/consul/consul/pull/3121)
+- **Design/UX:** Change CRUD for budget groups and headings [\#3106](https://github.com/consul/consul/pull/3106)
+- **Design/UX:** UI design [\#3080](https://github.com/consul/consul/pull/3080)
+- **Design/UX:** Budgets unselected message [\#3033](https://github.com/consul/consul/pull/3033)
+- **Design/UX:** Hide Featured section on Home Page if there are no cards [\#2899](https://github.com/consul/consul/pull/2899)
+- **Maintenance:** Simplify pull request template [\#3088](https://github.com/consul/consul/pull/3088)
+- **Maintenance:** Removes references to deleted general terms page [\#3079](https://github.com/consul/consul/pull/3079)
+- **Maintenance:** Pages texts [\#3042](https://github.com/consul/consul/pull/3042)
+- **Maintenance:** Removed icon\_home and fixed corresponding test [\##2970](https://github.com/consul/consul/pull/2970)
+- **Maintenance-Gems:** \[Security\] Bump rails from 4.2.10 to 4.2.11 [\#3070](https://github.com/consul/consul/pull/3070)
+- **Maintenance-Gems:** Bump database\_cleaner from 1.6.2 to 1.7.0 [\#3014](https://github.com/consul/consul/pull/3014)
+- **Maintenance-Gems:** Bump rspec-rails from 3.7.2 to 3.8.1 [\#3003](https://github.com/consul/consul/pull/3003)
+- **Maintenance-Gems:** Bump uglifier from 4.1.3 to 4.1.19 [\#3002](https://github.com/consul/consul/pull/3002)
+- **Maintenance-Gems:** \[Security\] Bump rack from 1.6.10 to 1.6.11 [\#3000](https://github.com/consul/consul/pull/3000)
+- **Maintenance-Gems:** Bump knapsack\_pro from 0.53.0 to 1.1.0 [\#2999](https://github.com/consul/consul/pull/2999)
+- **Maintenance-Gems:** Bump letter\_opener\_web from 1.3.2 to 1.3.4 [\#2957](https://github.com/consul/consul/pull/2957)
+- **Maintenance-Gems:** Bump rollbar from 2.15.5 to 2.18.0 [\#2923](https://github.com/consul/consul/pull/2923)
+- **Maintenance-Gems:** Bump cancancan from 2.1.2 to 2.3.0 [\#2901](https://github.com/consul/consul/pull/2901)
+- **Maintenance-Refactorings:** Remove custom "toda la ciudad" code [\#3111](https://github.com/consul/consul/pull/3111)
+- **Maintenance-Refactorings:** Refactor legislation process subnav [\#3074](https://github.com/consul/consul/pull/3074)
+- **Maintenance-Refactorings:** Rename Admin::Proposals to Admin::HiddenProposals [\#3073](https://github.com/consul/consul/pull/3073)
+- **Maintenance-Refactorings:** Budget investment show [\#3041](https://github.com/consul/consul/pull/3041)
+- **Proposals:** Optimize task reset\_hot\_score [\#3116](https://github.com/consul/consul/pull/3116)
+- **Proposals:** New algorithm for filter 'most active' [\#3098](https://github.com/consul/consul/pull/3098)
+- **Translations:** Bring back date order translations [\#3127](https://github.com/consul/consul/pull/3127)
+- **Translations:** i18n remove date.order key [\#3007](https://github.com/consul/consul/pull/3007)
+
+### Fixed
+
+- **Admin:** Fix pagination after selecting/unselecting budget investment [\#3034](https://github.com/consul/consul/pull/3034)
+- **Admin:** Admin menu link [\#3032](https://github.com/consul/consul/pull/3032)
+- **Design/UX:** Honeypot on users sign up form [\#3124](https://github.com/consul/consul/pull/3124)
+- **Design/UX:** Fix scroll jump voting investments [\#3113](https://github.com/consul/consul/pull/3113)
+- **Design/UX:** Globalize tabs [\#3054](https://github.com/consul/consul/pull/3054)
+- **Design/UX:** Help feature [\#3040](https://github.com/consul/consul/pull/3040)
+- **Design/UX:** Fix misleading title on account creation confirmation page (en, fr) [\#2944](https://github.com/consul/consul/pull/2944)
+- **Legislation:** Fixes legislation processes key dates active class [\#3020](https://github.com/consul/consul/pull/3020)
+- **Maintenance:** Fix scope warning [\#3071](https://github.com/consul/consul/pull/3071)
+- **Maintenance** Admin poll officers [\#3055](https://github.com/consul/consul/pull/3055)
+- **Maintenance-Rubocop:** Remove trailing whitespace [\#3094](https://github.com/consul/consul/pull/3094)
+- **Maintenance-Specs:** Fix flaky spec checking price without currency symbol [\#3115](https://github.com/consul/consul/pull/3115)
+- **Maintenance-Specs:** Fix flaky localization specs [\#3096](https://github.com/consul/consul/pull/3096)
+- **Maintenance-Specs:** Add frozen time condition to proposals phase spec [\#3090](https://github.com/consul/consul/pull/3090)
+- **Maintenance-Specs:** Fix flaky spec: Legislation Proposals Each user has a different and consistent random proposals order [\#3085](https://github.com/consul/consul/pull/3085)
+- **Maintenance-Specs:** Fix flaky spec: Each user has a different and consistent random proposals order [\#3076](https://github.com/consul/consul/pull/3076)
+- **Maintenance-Specs:** Fix flaky spec: Welcome screen is not shown to organizations [\#3072](https://github.com/consul/consul/pull/3072)
+- **Maintenance-Specs:** Fix failing spec: Budget::Investment Reclassification store\_reclassified\_votes stores the votes for a reclassified investment [\#3067](https://github.com/consul/consul/pull/3067)
+- **Maintenance-Specs:** Fix failing spec: Poll::Shift officer\_assignments creates and destroy corresponding officer\_assignments [\#3061](https://github.com/consul/consul/pull/3061)
+- **Maintenance-Specs:** Update debates\_spec.rb [\#3029](https://github.com/consul/consul/pull/3029)
+- **Maintenance-Specs:** Fix flaky spec: Admin budget investment mark/unmark visible to valuators [\#3008](https://github.com/consul/consul/pull/3008)
+- **Polls:** Fix poll results accuracy [\#3030](https://github.com/consul/consul/pull/3030)
+- **Translations:** Legislation dates [\#3039](https://github.com/consul/consul/pull/3039)
+- **Translations:** Fixes english translations [\#3011](https://github.com/consul/consul/pull/3011)
+- **Translations:** i18n remove duplicate locale folders [\#3006](https://github.com/consul/consul/pull/3006)
+- **Valuation:** Fix crash in valuation when there are no budgets [\#3128](https://github.com/consul/consul/pull/3128)
+
+## [0.17.0](https://github.com/consul/consul/compare/v0.16...v0.17) - 2018-10-31
+
+### Added
+- **Multi-language:** Migrate globalize data [\#2986](https://github.com/consul/consul/pull/2986)
+- **Multi-language:** Update custom pages translations [\#2952](https://github.com/consul/consul/pull/2952)
+- **Multi-language:** Make homepage content translatable [\#2924](https://github.com/consul/consul/pull/2924)
+- **Multi-language:** Make collaborative legislation translatable [\#2912](https://github.com/consul/consul/pull/2912)
+- **Multi-language:** Make admin notifications translatable [\#2910](https://github.com/consul/consul/pull/2910)
+- **Multi-language:** Refactor translatable specs [\#2903](https://github.com/consul/consul/pull/2903)
+- **Multi-language:** Refactor code shared by admin-translatable resources [\#2896](https://github.com/consul/consul/pull/2896)
+- **Multi-language:** Change Translatable implementation to accommodate new requirements [\#2886](https://github.com/consul/consul/pull/2886)
+- **Multi-language:** Make banners translatable [\#2865](https://github.com/consul/consul/pull/2865)
+- **Multi-language:** Fix translatable bugs [\#2985](https://github.com/consul/consul/pull/2985)
+- **Multi-language:** Make polls translatable [\#2914](https://github.com/consul/consul/pull/2914)
+- **Multi-language:** Updates translatable custom pages [\#2913](https://github.com/consul/consul/pull/2913)
+- **Translations:** Add all available languages [\#2964](https://github.com/consul/consul/pull/2964)
+- **Translations:** Fix locale folder names [\#2963](https://github.com/consul/consul/pull/2963)
+- **Translations:** Update translations from Crowdin [\#2961](https://github.com/consul/consul/pull/2961)
+- **Translations:** Display language name or language key [\#2949](https://github.com/consul/consul/pull/2949)
+- **Translations:** Avoid InvalidPluralizationData exception when missing translations [\#2936](https://github.com/consul/consul/pull/2936)
+- **Translations:** Changes allegations dates label [\#2915](https://github.com/consul/consul/pull/2915)
+- **Maintenance-Rubocop:** Add Hound basic configuration [\#2987](https://github.com/consul/consul/pull/2987)
+- **Maintenance-Rubocop:** Update rubocop rules [\#2925](https://github.com/consul/consul/pull/2925)
+- **Maintenance-Rubocop:** Fix Rubocop warnings for Admin controllers [\#2880](https://github.com/consul/consul/pull/2880)
+- **Design/UX:** Adds status icons on polls poll group [\#2860](https://github.com/consul/consul/pull/2860)
+- **Design/UX:** Feature help page [\#2933](https://github.com/consul/consul/pull/2933)
+- **Design/UX:** Adds enable help page task [\#2960](https://github.com/consul/consul/pull/2960)
+- **Budgets:** Allow select winner legislation proposals [\#2950](https://github.com/consul/consul/pull/2950)
+- **Legislation-Proposals:** Add legislation proposal's categories [\#2948](https://github.com/consul/consul/pull/2948)
+- **Legislation-Proposals:** Admin permissions in legislation proposals [\#2945](https://github.com/consul/consul/pull/2945)
+- **Legislation-Proposals:** Random legislation proposal's order & pagination [\#2942](https://github.com/consul/consul/pull/2942)
+- **Legislation-Proposals:** Legislation proposals imageable [\#2922](https://github.com/consul/consul/pull/2922)
+- **CKeditor:** Bring back CKEditor images button [\#2977](https://github.com/consul/consul/pull/2977)
+- **CKeditor:** Ckeditor4 update [\#2876](https://github.com/consul/consul/pull/2876)
+- **Installation:** Add placeholder configuration for SMTP [\#2900](https://github.com/consul/consul/pull/2900)
+
+### Changed
+- **Newsletters:** Newsletter updates [\#2992](https://github.com/consul/consul/pull/2992)
+- **Maintenance-Gems:** \[Security\] Bump rubyzip from 1.2.1 to 1.2.2 [\#2879](https://github.com/consul/consul/pull/2879)
+- **Maintenance-Gems:** \[Security\] Bump nokogiri from 1.8.2 to 1.8.4 [\#2878](https://github.com/consul/consul/pull/2878)
+- **Maintenance-Gems:** \[Security\] Bump ffi from 1.9.23 to 1.9.25 [\#2877](https://github.com/consul/consul/pull/2877)
+- **Maintenance-Gems:** Bump jquery-rails from 4.3.1 to 4.3.3 [\#2929](https://github.com/consul/consul/pull/2929)
+- **Maintenance-Gems:** Bump browser from 2.5.2 to 2.5.3 [\#2928](https://github.com/consul/consul/pull/2928)
+- **Maintenance-Gems:** Bump delayed\_job\_active\_record from 4.1.2 to 4.1.3 [\#2927](https://github.com/consul/consul/pull/2927)
+- **Maintenance-Gems:** Bump rubocop-rspec from 1.24.0 to 1.26.0 [\#2926](https://github.com/consul/consul/pull/2926)
+- **Maintenance-Gems:** Bump paranoia from 2.4.0 to 2.4.1 [\#2909](https://github.com/consul/consul/pull/2909)
+- **Maintenance-Gems:** Bump ancestry from 3.0.1 to 3.0.2 [\#2908](https://github.com/consul/consul/pull/2908)
+- **Maintenance-Gems:** Bump i18n-tasks from 0.9.20 to 0.9.25 [\#2906](https://github.com/consul/consul/pull/2906)
+- **Maintenance-Gems:** Bump coveralls from 0.8.21 to 0.8.22 [\#2905](https://github.com/consul/consul/pull/2905)
+- **Maintenance-Gems:** Bump scss\_lint from 0.54.0 to 0.55.0 [\#2895](https://github.com/consul/consul/pull/2895)
+- **Maintenance-Gems:** Bump unicorn from 5.4.0 to 5.4.1 [\#2894](https://github.com/consul/consul/pull/2894)
+- **Maintenance-Gems:** Bump mdl from 0.4.0 to 0.5.0 [\#2892](https://github.com/consul/consul/pull/2892)
+- **Maintenance-Gems:** Bump savon from 2.11.2 to 2.12.0 [\#2891](https://github.com/consul/consul/pull/2891)
+- **Maintenance-Gems:** Bump capistrano-rails from 1.3.1 to 1.4.0 [\#2884](https://github.com/consul/consul/pull/2884)
+- **Maintenance-Gems:** Bump autoprefixer-rails from 8.2.0 to 9.1.4 [\#2881](https://github.com/consul/consul/pull/2881)
+- **Maintenance-Gems:** Upgrade gem coffee-rails to version 4.2.2 [\#2837](https://github.com/consul/consul/pull/2837)
+- **Maintenance-Refactorings:** Adds custom javascripts folder [\#2921](https://github.com/consul/consul/pull/2921)
+- **Maintenance-Refactorings:** Test suite maintenance [\#2888](https://github.com/consul/consul/pull/2888)
+- **Maintenance-Refactorings:** Replace `.all.each` with `.find\_each` to reduce memory usage [\#2887](https://github.com/consul/consul/pull/2887)
+- **Maintenance-Refactorings:** Split factories [\#2838](https://github.com/consul/consul/pull/2838)
+- **Maintenance-Refactorings:** Change spelling for constant to TITLE\_LENGTH\_RANGE [\#2966](https://github.com/consul/consul/pull/2966)
+- **Maintenance-Refactorings:** Remove described class cop [\#2990](https://github.com/consul/consul/pull/2990)
+- **Maintenance-Refactorings:** Ease customization in processes controller [\#2982](https://github.com/consul/consul/pull/2982)
+- **Maintenance-Refactorings:** Fix a misleading comment [\#2844](https://github.com/consul/consul/pull/2844)
+- **Maintenance-Refactorings:** Simplify legislation proposals customization [\#2946](https://github.com/consul/consul/pull/2946)
+- **Social-Share:** Improves social share messages for proposals [\#2994](https://github.com/consul/consul/pull/2994)
+
+### Fixed
+- **Maintenance-Specs:** Fix flaky specs: proposals and legislation Voting comments Update [\#2989](https://github.com/consul/consul/pull/2989)
+- **Maintenance-Specs:** Fix flaky spec: Admin legislation questions Update Valid legislation question [\#2976](https://github.com/consul/consul/pull/2976)
+- **Maintenance-Specs:** Fix flaky spec: Admin feature flags Enable a disabled feature [\#2967](https://github.com/consul/consul/pull/2967)
+- **Maintenance-Specs:** Fix flaky spec for translations [\#2962](https://github.com/consul/consul/pull/2962)
+- **Maintenance-Specs:** Fix flaky spec: Admin legislation draft versions Update Valid legislation draft version [\#2995](https://github.com/consul/consul/pull/2995)
+- **Maintenance-Specs:** Fix pluralization spec when using different default locale [\#2973](https://github.com/consul/consul/pull/2973)
+- **Maintenance-Specs:** Fix time related specs [\#2911](https://github.com/consul/consul/pull/2911)
+- **Design/UX:** UI design [\#2983](https://github.com/consul/consul/pull/2983)
+- **Design/UX:** Custom fonts [\#2916](https://github.com/consul/consul/pull/2916)
+- **Design/UX:** Show active tab in custom info texts [\#2898](https://github.com/consul/consul/pull/2898)
+- **Design/UX:** Fix navigation menu under Legislation::Proposal show view [\#2835](https://github.com/consul/consul/pull/2835)
+- **Social-Share:** Fix bug in facebook share link [\#2852](https://github.com/consul/consul/pull/2852)
## [0.16.0](https://github.com/consul/consul/compare/v0.15...v0.16) - 2018-07-16
@@ -416,7 +713,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Rails 4.2.6
- Ruby 2.2.3
-[Unreleased]: https://github.com/consul/consul/compare/v0.16...consul:master
+[Unreleased]: https://github.com/consul/consul/compare/v0.18...consul:master
+[0.18.0]: https://github.com/consul/consul/compare/v0.17...v.018
+[0.17.0]: https://github.com/consul/consul/compare/v0.16...v.017
[0.16.0]: https://github.com/consul/consul/compare/v0.15...v.016
[0.15.0]: https://github.com/consul/consul/compare/v0.14...v0.15
[0.14.0]: https://github.com/consul/consul/compare/v0.13...v0.14
diff --git a/Capfile b/Capfile
index ea11eb9b6..cef760291 100644
--- a/Capfile
+++ b/Capfile
@@ -1,22 +1,22 @@
# Load DSL and set up stages
-require 'capistrano/setup'
+require "capistrano/setup"
# Include default deployment tasks
-require 'capistrano/deploy'
+require "capistrano/deploy"
require "capistrano/bundler"
-require 'capistrano/rails/assets'
-require 'capistrano/rails/migrations'
-#require 'capistrano/passenger'
-require 'capistrano/delayed_job'
-require 'whenever/capistrano'
-require 'rvm1/capistrano3'
+require "capistrano/rails/assets"
+require "capistrano/rails/migrations"
+#require "capistrano/passenger"
+require "capistrano/delayed_job"
+require "whenever/capistrano"
+require "rvm1/capistrano3"
#SCM: Git
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
-Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
-Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }
-Dir.glob('lib/capistrano/**/*.rb').each { |r| import r }
+Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
+Dir.glob("lib/capistrano/tasks/*.cap").each { |r| import r }
+Dir.glob("lib/capistrano/**/*.rb").each { |r| import r }
diff --git a/Gemfile b/Gemfile
index 1ee905d34..3924093fd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,103 +1,104 @@
-source 'https://rubygems.org'
+source "https://rubygems.org"
-gem 'rails', '4.2.10'
+gem "rails", "4.2.11.1"
-gem 'acts-as-taggable-on', '~> 5.0.0'
-gem 'acts_as_votable', '~> 0.11.1'
-gem 'ahoy_matey', '~> 1.6.0'
-gem 'ancestry', '~> 3.0.2'
-gem 'autoprefixer-rails', '~> 9.1.4'
-gem 'best_in_place', '~> 3.0.1'
-gem 'browser', '~> 2.5.3'
-gem 'cancancan', '~> 2.1.2'
-gem 'ckeditor', '~> 4.2.3'
-gem 'cocoon', '~> 1.2.9'
-gem 'coffee-rails', '~> 4.2.2'
-gem 'daemons', '~> 1.2.4'
-gem 'dalli', '~> 2.7.6'
-gem 'delayed_job_active_record', '~> 4.1.3'
-gem 'devise', '~> 3.5.7'
-gem 'devise-async', '~> 0.10.2'
-gem 'devise_security_extension', '~> 0.10.0'
-gem 'faker', '~> 1.8.7'
-gem 'foundation-rails', '~> 6.4.3.0'
-gem 'foundation_rails_helper', '~> 2.0.0'
-gem 'graphiql-rails', '~> 1.4.1'
-gem 'graphql', '~> 1.7.8'
-gem 'groupdate', '~> 3.2.0'
-gem 'initialjs-rails', '~> 0.2.0.5'
-gem 'invisible_captcha', '~> 0.10.0'
-gem 'jquery-fileupload-rails'
-gem 'jquery-rails', '~> 4.3.3'
-gem 'jquery-ui-rails', '~> 6.0.1'
-gem 'kaminari', '~> 1.1.1'
-gem 'newrelic_rpm', '~> 4.1.0.333'
-gem 'omniauth', '~> 1.8.1'
-gem 'omniauth-facebook', '~> 4.0.0'
-gem 'omniauth-google-oauth2', '~> 0.4.0'
-gem 'omniauth-twitter', '~> 1.4.0'
-gem 'paperclip', '~> 5.2.1'
-gem 'paranoia', '~> 2.4.1'
-gem 'pg', '~> 0.21.0'
-gem 'pg_search', '~> 2.0.1'
-gem 'redcarpet', '~> 3.4.0'
-gem 'responders', '~> 2.4.0'
-gem 'rinku', '~> 2.0.2', require: 'rails_rinku'
-gem 'rollbar', '~> 2.15.5'
-gem 'sass-rails', '~> 5.0', '>= 5.0.4'
-gem 'savon', '~> 2.12.0'
-gem 'sitemap_generator', '~> 6.0.1'
-gem 'social-share-button', '~> 1.1'
-gem 'sprockets', '~> 3.7.2'
-gem 'turbolinks', '~> 2.5.3'
-gem 'turnout', '~> 2.4.0'
-gem 'uglifier', '~> 4.1.2'
-gem 'unicorn', '~> 5.4.1'
-gem 'whenever', '~> 0.10.0', require: false
-gem 'globalize', '~> 5.0.0'
-gem 'globalize-accessors', '~> 0.2.1'
-gem 'wkhtmltopdf-binary', '~> 0.12.4'
-gem 'wicked_pdf', '~> 1.1.0'
+gem "acts-as-taggable-on", "~> 5.0.0"
+gem "acts_as_votable", "~> 0.11.1"
+gem "ahoy_matey", "~> 1.6.0"
+gem "ancestry", "~> 3.0.2"
+gem "autoprefixer-rails", "~> 9.1.4"
+gem "best_in_place", "~> 3.0.1"
+gem "browser", "~> 2.5.3"
+gem "cancancan", "~> 2.3.0"
+gem "ckeditor", "~> 4.2.3"
+gem "cocoon", "~> 1.2.9"
+gem "coffee-rails", "~> 4.2.2"
+gem "daemons", "~> 1.2.4"
+gem "dalli", "~> 2.7.6"
+gem "delayed_job_active_record", "~> 4.1.3"
+gem "devise", "~> 3.5.7"
+gem "devise-async", "~> 0.10.2"
+gem "devise_security_extension", "~> 0.10.0"
+gem "foundation-rails", "~> 6.4.3.0"
+gem "foundation_rails_helper", "~> 2.0.0"
+gem "graphiql-rails", "~> 1.4.1"
+gem "graphql", "~> 1.7.8"
+gem "groupdate", "~> 3.2.0"
+gem "initialjs-rails", "~> 0.2.0.5"
+gem "invisible_captcha", "~> 0.10.0"
+gem "jquery-fileupload-rails"
+gem "jquery-rails", "~> 4.3.3"
+gem "jquery-ui-rails", "~> 6.0.1"
+gem "kaminari", "~> 1.1.1"
+gem "newrelic_rpm", "~> 4.1.0.333"
+gem "omniauth", "~> 1.8.1"
+gem "omniauth-facebook", "~> 4.0.0"
+gem "omniauth-google-oauth2", "~> 0.4.0"
+gem "omniauth-twitter", "~> 1.4.0"
+gem "paperclip", "~> 5.2.1"
+gem "paranoia", "~> 2.4.1"
+gem "pg", "~> 0.21.0"
+gem "pg_search", "~> 2.0.1"
+gem "redcarpet", "~> 3.4.0"
+gem "responders", "~> 2.4.0"
+gem "rinku", "~> 2.0.2", require: "rails_rinku"
+gem "rollbar", "~> 2.18.0"
+gem "sass-rails", "~> 5.0", ">= 5.0.4"
+gem "savon", "~> 2.12.0"
+gem "sitemap_generator", "~> 6.0.1"
+gem "social-share-button", "~> 1.1"
+gem "sprockets", "~> 3.7.2"
+gem "turbolinks", "~> 2.5.3"
+gem "turnout", "~> 2.4.0"
+gem "uglifier", "~> 4.1.2"
+gem "unicorn", "~> 5.4.1"
+gem "whenever", "~> 0.10.0", require: false
+gem "globalize", "~> 5.0.0"
+gem "globalize-accessors", "~> 0.2.1"
+gem "recipient_interceptor", "~> 0.2.0"
+gem "wkhtmltopdf-binary", "~> 0.12.4"
+gem "wicked_pdf", "~> 1.1.0"
-source 'https://rails-assets.org' do
- gem 'rails-assets-leaflet'
- gem 'rails-assets-markdown-it', '~> 8.2.1'
+source "https://rails-assets.org" do
+ gem "rails-assets-leaflet"
+ gem "rails-assets-markdown-it", "~> 8.2.1"
end
group :development, :test do
- gem 'bullet', '~> 5.7.0'
- gem 'byebug', '~> 10.0.0'
- gem 'factory_bot_rails', '~> 4.8.2'
- gem 'faker', '~> 1.8.7'
- gem 'i18n-tasks', '~> 0.9.25'
- gem 'knapsack_pro', '~> 0.53.0'
- gem 'launchy', '~> 2.4.3'
- gem 'letter_opener_web', '~> 1.3.2'
- gem 'quiet_assets', '~> 1.1.0'
- gem 'spring', '~> 2.0.1'
- gem 'spring-commands-rspec', '~> 1.0.4'
+ gem "bullet", "~> 5.7.0"
+ gem "byebug", "~> 10.0.0"
+ gem "factory_bot_rails", "~> 4.8.2"
+ gem "faker", "~> 1.8.7"
+ gem "i18n-tasks", "~> 0.9.25"
+ gem "knapsack_pro", "~> 1.1.0"
+ gem "launchy", "~> 2.4.3"
+ gem "letter_opener_web", "~> 1.3.4"
+ gem "quiet_assets", "~> 1.1.0"
+ gem "spring", "~> 2.0.1"
+ gem "spring-commands-rspec", "~> 1.0.4"
end
group :test do
- gem 'capybara', '~> 2.17.0'
- gem 'coveralls', '~> 0.8.22', require: false
- gem 'database_cleaner', '~> 1.6.1'
- gem 'email_spec', '~> 2.1.0'
- gem 'rspec-rails', '~> 3.6'
- gem 'selenium-webdriver', '~> 3.10'
+ gem "capybara", "~> 2.17.0"
+ gem "coveralls", "~> 0.8.22", require: false
+ gem "database_cleaner", "~> 1.7.0"
+ gem "email_spec", "~> 2.1.0"
+ gem "rspec-rails", "~> 3.8"
+ gem "selenium-webdriver", "~> 3.10"
end
group :development do
- gem 'capistrano', '~> 3.10.1', require: false
- gem 'capistrano-bundler', '~> 1.2', require: false
- gem 'capistrano-rails', '~> 1.4.0', require: false
- gem 'capistrano3-delayed-job', '~> 1.7.3'
- gem 'mdl', '~> 0.5.0', require: false
- gem 'rubocop', '~> 0.54.0', require: false
- gem 'rubocop-rspec', '~> 1.26.0', require: false
- gem 'rvm1-capistrano3', '~> 1.4.0', require: false
- gem 'scss_lint', '~> 0.55.0', require: false
- gem 'web-console', '~> 3.3.0'
+ gem "capistrano", "~> 3.10.1", require: false
+ gem "capistrano-bundler", "~> 1.2", require: false
+ gem "capistrano-rails", "~> 1.4.0", require: false
+ gem "capistrano3-delayed-job", "~> 1.7.3"
+ gem "erb_lint", require: false
+ gem "mdl", "~> 0.5.0", require: false
+ gem "rubocop", "~> 0.54.0", require: false
+ gem "rubocop-rspec", "~> 1.26.0", require: false
+ gem "rvm1-capistrano3", "~> 1.4.0", require: false
+ gem "scss_lint", "~> 0.55.0", require: false
+ gem "web-console", "~> 3.3.0"
end
-eval_gemfile './Gemfile_custom'
+eval_gemfile "./Gemfile_custom"
diff --git a/Gemfile.lock b/Gemfile.lock
index e85a03d81..d1e2865ca 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -2,36 +2,36 @@ GEM
remote: https://rubygems.org/
remote: https://rails-assets.org/
specs:
- actionmailer (4.2.10)
- actionpack (= 4.2.10)
- actionview (= 4.2.10)
- activejob (= 4.2.10)
+ actionmailer (4.2.11.1)
+ actionpack (= 4.2.11.1)
+ actionview (= 4.2.11.1)
+ activejob (= 4.2.11.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
- actionpack (4.2.10)
- actionview (= 4.2.10)
- activesupport (= 4.2.10)
+ actionpack (4.2.11.1)
+ actionview (= 4.2.11.1)
+ activesupport (= 4.2.11.1)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (4.2.10)
- activesupport (= 4.2.10)
+ actionview (4.2.11.1)
+ activesupport (= 4.2.11.1)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (4.2.10)
- activesupport (= 4.2.10)
+ activejob (4.2.11.1)
+ activesupport (= 4.2.11.1)
globalid (>= 0.3.0)
- activemodel (4.2.10)
- activesupport (= 4.2.10)
+ activemodel (4.2.11.1)
+ activesupport (= 4.2.11.1)
builder (~> 3.1)
- activerecord (4.2.10)
- activemodel (= 4.2.10)
- activesupport (= 4.2.10)
+ activerecord (4.2.11.1)
+ activemodel (= 4.2.11.1)
+ activesupport (= 4.2.11.1)
arel (~> 6.0)
- activesupport (4.2.10)
+ activesupport (4.2.11.1)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
@@ -71,13 +71,21 @@ GEM
best_in_place (3.0.3)
actionpack (>= 3.2)
railties (>= 3.2)
+ better_html (1.0.13)
+ actionview (>= 4.0)
+ activesupport (>= 4.0)
+ ast (~> 2.0)
+ erubi (~> 1.4)
+ html_tokenizer (~> 0.0.6)
+ parser (>= 2.4)
+ smart_properties
browser (2.5.3)
builder (3.2.3)
bullet (5.7.1)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11.0)
byebug (10.0.0)
- cancancan (2.1.2)
+ cancancan (2.3.0)
capistrano (3.10.1)
airbrussh (>= 1.0.0)
i18n
@@ -116,7 +124,7 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
- concurrent-ruby (1.0.5)
+ concurrent-ruby (1.1.5)
coveralls (0.8.22)
json (>= 1.8, < 3)
simplecov (~> 0.16.1)
@@ -126,7 +134,7 @@ GEM
crass (1.0.4)
daemons (1.2.6)
dalli (2.7.6)
- database_cleaner (1.6.2)
+ database_cleaner (1.7.0)
debug_inspector (0.0.3)
delayed_job (4.1.5)
activesupport (>= 3.0, < 5.3)
@@ -151,6 +159,13 @@ GEM
htmlentities (~> 4.3.3)
launchy (~> 2.1)
mail (~> 2.6)
+ erb_lint (0.0.28)
+ activesupport
+ better_html (~> 1.0.7)
+ html_tokenizer
+ rainbow
+ rubocop (~> 0.51)
+ smart_properties
errbase (0.0.3)
erubi (1.7.1)
erubis (2.7.0)
@@ -176,7 +191,7 @@ GEM
railties (>= 4.1)
tzinfo (~> 1.2, >= 1.2.2)
geocoder (1.4.4)
- globalid (0.4.1)
+ globalid (0.4.2)
activesupport (>= 4.2.0)
globalize (5.0.1)
activemodel (>= 4.2.0, < 4.3)
@@ -192,6 +207,7 @@ GEM
builder (>= 2.1.2)
hashie (3.5.7)
highline (2.0.0)
+ html_tokenizer (0.0.7)
htmlentities (4.3.4)
httpi (2.4.4)
rack
@@ -236,21 +252,21 @@ GEM
kaminari-core (= 1.1.1)
kaminari-core (1.1.1)
kgio (2.11.2)
- knapsack_pro (0.53.0)
+ knapsack_pro (1.1.0)
rake
kramdown (1.17.0)
launchy (2.4.3)
addressable (~> 2.3)
letter_opener (1.6.0)
launchy (~> 2.2)
- letter_opener_web (1.3.2)
+ letter_opener_web (1.3.4)
actionmailer (>= 3.2)
letter_opener (~> 1.0)
railties (>= 3.2)
- loofah (2.2.2)
+ loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
- mail (2.7.0)
+ mail (2.7.1)
mini_mime (>= 0.1.1)
mdl (0.5.0)
kramdown (~> 1.12, >= 1.12.0)
@@ -260,21 +276,21 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mimemagic (0.3.2)
- mini_mime (1.0.0)
- mini_portile2 (2.3.0)
+ mini_mime (1.0.1)
+ mini_portile2 (2.4.0)
minitest (5.11.3)
mixlib-cli (1.7.0)
mixlib-config (2.2.13)
tomlrb
- multi_json (1.12.2)
+ multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (5.0.2)
newrelic_rpm (4.1.0.333)
- nokogiri (1.8.4)
- mini_portile2 (~> 2.3.0)
+ nokogiri (1.10.1)
+ mini_portile2 (~> 2.4.0)
nori (2.6.0)
oauth (0.5.3)
oauth2 (1.4.0)
@@ -320,26 +336,26 @@ GEM
activesupport (>= 4.2)
arel (>= 6)
powerpack (0.1.2)
- public_suffix (3.0.1)
+ public_suffix (3.0.3)
quiet_assets (1.1.0)
railties (>= 3.1, < 5.0)
- rack (1.6.10)
+ rack (1.6.11)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (5.0.1)
rack
rack-test (0.6.3)
rack (>= 1.0)
- rails (4.2.10)
- actionmailer (= 4.2.10)
- actionpack (= 4.2.10)
- actionview (= 4.2.10)
- activejob (= 4.2.10)
- activemodel (= 4.2.10)
- activerecord (= 4.2.10)
- activesupport (= 4.2.10)
+ rails (4.2.11.1)
+ actionmailer (= 4.2.11.1)
+ actionpack (= 4.2.11.1)
+ actionview (= 4.2.11.1)
+ activejob (= 4.2.11.1)
+ activemodel (= 4.2.11.1)
+ activerecord (= 4.2.11.1)
+ activesupport (= 4.2.11.1)
bundler (>= 1.3.0, < 2.0)
- railties (= 4.2.10)
+ railties (= 4.2.11.1)
sprockets-rails
rails-assets-leaflet (1.1.0)
rails-assets-markdown-it (8.2.2)
@@ -351,14 +367,16 @@ GEM
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.4)
loofah (~> 2.2, >= 2.2.2)
- railties (4.2.10)
- actionpack (= 4.2.10)
- activesupport (= 4.2.10)
+ railties (4.2.11.1)
+ actionpack (= 4.2.11.1)
+ activesupport (= 4.2.11.1)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
raindrops (0.19.0)
- rake (12.3.1)
+ rake (12.3.2)
+ recipient_interceptor (0.2.0)
+ mail
redcarpet (3.4.0)
referer-parser (0.3.0)
request_store (1.3.2)
@@ -366,25 +384,25 @@ GEM
actionpack (>= 4.2.0, < 5.3)
railties (>= 4.2.0, < 5.3)
rinku (2.0.4)
- rollbar (2.15.5)
+ rollbar (2.18.0)
multi_json
- rspec-core (3.7.1)
- rspec-support (~> 3.7.0)
- rspec-expectations (3.7.0)
+ rspec-core (3.8.0)
+ rspec-support (~> 3.8.0)
+ rspec-expectations (3.8.2)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.7.0)
- rspec-mocks (3.7.0)
+ rspec-support (~> 3.8.0)
+ rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.7.0)
- rspec-rails (3.7.2)
+ rspec-support (~> 3.8.0)
+ rspec-rails (3.8.1)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
- rspec-core (~> 3.7.0)
- rspec-expectations (~> 3.7.0)
- rspec-mocks (~> 3.7.0)
- rspec-support (~> 3.7.0)
- rspec-support (3.7.0)
+ rspec-core (~> 3.8.0)
+ rspec-expectations (~> 3.8.0)
+ rspec-mocks (~> 3.8.0)
+ rspec-support (~> 3.8.0)
+ rspec-support (3.8.0)
rubocop (0.54.0)
parallel (~> 1.10)
parser (>= 2.5)
@@ -429,6 +447,7 @@ GEM
simplecov-html (0.10.2)
sitemap_generator (6.0.1)
builder (~> 3.0)
+ smart_properties (1.13.1)
social-share-button (1.1.0)
coffee-rails
socksify (1.7.1)
@@ -468,7 +487,7 @@ GEM
tilt (>= 1.4, < 3)
tzinfo (1.2.5)
thread_safe (~> 0.1)
- uglifier (4.1.3)
+ uglifier (4.1.19)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.4.0)
unicorn (5.4.1)
@@ -506,7 +525,7 @@ DEPENDENCIES
browser (~> 2.5.3)
bullet (~> 5.7.0)
byebug (~> 10.0.0)
- cancancan (~> 2.1.2)
+ cancancan (~> 2.3.0)
capistrano (~> 3.10.1)
capistrano-bundler (~> 1.2)
capistrano-rails (~> 1.4.0)
@@ -518,12 +537,13 @@ DEPENDENCIES
coveralls (~> 0.8.22)
daemons (~> 1.2.4)
dalli (~> 2.7.6)
- database_cleaner (~> 1.6.1)
+ database_cleaner (~> 1.7.0)
delayed_job_active_record (~> 4.1.3)
devise (~> 3.5.7)
devise-async (~> 0.10.2)
devise_security_extension (~> 0.10.0)
email_spec (~> 2.1.0)
+ erb_lint
factory_bot_rails (~> 4.8.2)
faker (~> 1.8.7)
foundation-rails (~> 6.4.3.0)
@@ -540,9 +560,9 @@ DEPENDENCIES
jquery-rails (~> 4.3.3)
jquery-ui-rails (~> 6.0.1)
kaminari (~> 1.1.1)
- knapsack_pro (~> 0.53.0)
+ knapsack_pro (~> 1.1.0)
launchy (~> 2.4.3)
- letter_opener_web (~> 1.3.2)
+ letter_opener_web (~> 1.3.4)
mdl (~> 0.5.0)
newrelic_rpm (~> 4.1.0.333)
omniauth (~> 1.8.1)
@@ -554,14 +574,15 @@ DEPENDENCIES
pg (~> 0.21.0)
pg_search (~> 2.0.1)
quiet_assets (~> 1.1.0)
- rails (= 4.2.10)
+ rails (= 4.2.11.1)
rails-assets-leaflet!
rails-assets-markdown-it (~> 8.2.1)!
+ recipient_interceptor (~> 0.2.0)
redcarpet (~> 3.4.0)
responders (~> 2.4.0)
rinku (~> 2.0.2)
- rollbar (~> 2.15.5)
- rspec-rails (~> 3.6)
+ rollbar (~> 2.18.0)
+ rspec-rails (~> 3.8)
rubocop (~> 0.54.0)
rubocop-rspec (~> 1.26.0)
rvm1-capistrano3 (~> 1.4.0)
@@ -584,4 +605,4 @@ DEPENDENCIES
wkhtmltopdf-binary (~> 0.12.4)
BUNDLED WITH
- 1.16.2
+ 1.17.1
diff --git a/README.md b/README.md
index f845ccd0e..9cb539e31 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@ Citizen Participation and Open Government Application
[](https://coveralls.io/github/consul/consul?branch=master)
[](https://crowdin.com/project/consul)
[](http://www.gnu.org/licenses/agpl-3.0)
+[](https://houndci.com)
[](https://www.w3.org/WAI/eval/Overview)
[](https://rocketvalidator.com/opensource)
@@ -78,4 +79,4 @@ Code published under AFFERO GPL v3 (see [LICENSE-AGPLv3.txt](LICENSE-AGPLv3.txt)
## Contributions
-See [CONTRIBUTING.md](CONTRIBUTING.md)
\ No newline at end of file
+See [CONTRIBUTING.md](CONTRIBUTING.md)
diff --git a/Rakefile b/Rakefile
index 13a99536b..b99dafeef 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,7 +1,7 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
-require File.expand_path('../config/application', __FILE__)
+require File.expand_path("../config/application", __FILE__)
-Rails.application.load_tasks
+Rails.application.load_tasks if Rake::Task.tasks.empty?
KnapsackPro.load_tasks if defined?(KnapsackPro)
diff --git a/app/assets/images/budget_execution_no_image.jpg b/app/assets/images/budget_execution_no_image.jpg
new file mode 100644
index 000000000..7de0e0a2c
Binary files /dev/null and b/app/assets/images/budget_execution_no_image.jpg differ
diff --git a/app/assets/images/language_select.png b/app/assets/images/language_select.png
deleted file mode 100644
index e0c4e6411..000000000
Binary files a/app/assets/images/language_select.png and /dev/null differ
diff --git a/app/assets/images/map.jpg b/app/assets/images/map.jpg
index 0b3ad3516..b35490b52 100644
Binary files a/app/assets/images/map.jpg and b/app/assets/images/map.jpg differ
diff --git a/app/assets/javascripts/advanced_search.js.coffee b/app/assets/javascripts/advanced_search.js.coffee
index e768e09a3..fbbc77ce0 100644
--- a/app/assets/javascripts/advanced_search.js.coffee
+++ b/app/assets/javascripts/advanced_search.js.coffee
@@ -1,42 +1,42 @@
App.AdvancedSearch =
advanced_search_terms: ->
- $('#js-advanced-search').data('advanced-search-terms')
+ $("#js-advanced-search").data("advanced-search-terms")
toggle_form: (event) ->
event.preventDefault()
- $('#js-advanced-search').slideToggle()
+ $("#js-advanced-search").slideToggle()
toggle_date_options: ->
- if $('#js-advanced-search-date-min').val() == 'custom'
- $('#js-custom-date').show()
+ if $("#js-advanced-search-date-min").val() == "custom"
+ $("#js-custom-date").show()
$( ".js-calendar" ).datepicker( "option", "disabled", false )
else
- $('#js-custom-date').hide()
+ $("#js-custom-date").hide()
$( ".js-calendar" ).datepicker( "option", "disabled", true )
init_calendar: ->
- locale = $('#js-locale').data('current-locale')
- if locale == 'en'
- locale = ''
+ locale = $("#js-locale").data("current-locale")
+ if locale == "en"
+ locale = ""
- $('.js-calendar').datepicker
+ $(".js-calendar").datepicker
regional: locale
maxDate: "+0d"
- $('.js-calendar-full').datepicker
+ $(".js-calendar-full").datepicker
regional: locale
initialize: ->
App.AdvancedSearch.init_calendar()
if App.AdvancedSearch.advanced_search_terms()
- $('#js-advanced-search').show()
+ $("#js-advanced-search").show()
App.AdvancedSearch.toggle_date_options()
- $('#js-advanced-search-title').on
+ $("#js-advanced-search-title").on
click: (event) ->
App.AdvancedSearch.toggle_form(event)
- $('#js-advanced-search-date-min').on
+ $("#js-advanced-search-date-min").on
change: ->
App.AdvancedSearch.toggle_date_options()
diff --git a/app/assets/javascripts/allow_participation.js.coffee b/app/assets/javascripts/allow_participation.js.coffee
index da6bf47bb..9482826ca 100644
--- a/app/assets/javascripts/allow_participation.js.coffee
+++ b/app/assets/javascripts/allow_participation.js.coffee
@@ -2,7 +2,7 @@ App.AllowParticipation =
initialize: ->
$(document).on {
- 'mouseenter focus': ->
+ "mouseenter focus": ->
$(this).find(".js-participation-not-allowed").show()
$(this).find(".js-participation-allowed").hide()
mouseleave: ->
diff --git a/app/assets/javascripts/annotatable.js.coffee b/app/assets/javascripts/annotatable.js.coffee
index 49757f16a..90cabb9e4 100644
--- a/app/assets/javascripts/annotatable.js.coffee
+++ b/app/assets/javascripts/annotatable.js.coffee
@@ -2,18 +2,18 @@ _t = (key) -> new Gettext().gettext(key)
App.Annotatable =
initialize: ->
- current_user_id = $('html').data('current-user-id')
+ current_user_id = $("html").data("current-user-id")
if current_user_id == ""
annotator.ui.editor.Editor.template = [
'
'
- ].join('\n')
+ " #{_t("Cancel")}",
+ " ",
+ " ",
+ ""
+ ].join("\n")
$("[data-annotatable-type]").each ->
$this = $(this)
@@ -23,7 +23,7 @@ App.Annotatable =
app = new annotator.App()
.include ->
beforeAnnotationCreated: (ann) ->
- ann[ann_type + "_id"] = ann_id
+ ann["#{ann_type}_id"] = ann_id
ann.permissions = ann.permissions || {}
ann.permissions.admin = []
.include(annotator.ui.main, { element: this })
@@ -34,5 +34,5 @@ App.Annotatable =
app.ident.identity = current_user_id
options = {}
- options[ann_type + "_id"] = ann_id
+ options["#{ann_type}_id"] = ann_id
app.annotations.load(options)
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 82b40edc9..02230370a 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -87,6 +87,7 @@
//= require clipboard_button
//= require best_in_place_initialize
//= require send_admin_notification_alert
+//= require settings
var initialize_modules = function() {
App.Answers.initialize();
@@ -137,12 +138,13 @@ var initialize_modules = function() {
App.ClipboardButton.initialize();
App.BestInPlace.initialize();
App.SendAdminNotificationAlert.initialize();
+ App.Settings.initialize();
};
$(function(){
Turbolinks.enableProgressBar();
$(document).ready(initialize_modules);
- $(document).on('page:load', initialize_modules);
- $(document).on('ajax:complete', initialize_modules);
+ $(document).on("page:load", initialize_modules);
+ $(document).on("ajax:complete", initialize_modules);
});
diff --git a/app/assets/javascripts/banners.js.coffee b/app/assets/javascripts/banners.js.coffee
index d38587083..b136d19a0 100644
--- a/app/assets/javascripts/banners.js.coffee
+++ b/app/assets/javascripts/banners.js.coffee
@@ -7,37 +7,26 @@ App.Banners =
$(selector).removeClass($(selector).attr("class"), true)
.addClass(style, true)
- update_background_color: (selector, text_selector, background_color) ->
- $(selector).css('background-color', background_color);
- $(text_selector).val(background_color);
+ update_background_color: (selector, background_color) ->
+ $(selector).css("background-color", background_color)
- update_font_color: (selector, text_selector, font_color) ->
- $(selector).css('color', font_color);
- $(text_selector).val(font_color);
+ update_font_color: (selector, font_color) ->
+ $(selector).css("color", font_color)
initialize: ->
- $('[data-js-banner-title]').on
+ $("[data-js-banner-title]").on
change: ->
App.Banners.update_banner("#js-banner-title", $(this).val())
- $('[data-js-banner-description]').on
+ $("[data-js-banner-description]").on
change: ->
App.Banners.update_banner("#js-banner-description", $(this).val())
- $("#banner_background_color_picker").on
+ $("[name='banner[background_color]']").on
change: ->
- App.Banners.update_background_color("#js-banner-background", "#banner_background_color", $(this).val());
+ App.Banners.update_background_color("#js-banner-background", $(this).val())
- $("#banner_background_color").on
+ $("[name='banner[font_color]']").on
change: ->
- App.Banners.update_background_color("#js-banner-background", "#banner_background_color_picker", $(this).val());
-
- $("#banner_font_color_picker").on
- change: ->
- App.Banners.update_font_color("#js-banner-title", "#banner_font_color", $(this).val());
- App.Banners.update_font_color("#js-banner-description", "#banner_font_color", $(this).val());
-
- $("#banner_font_color").on
- change: ->
- App.Banners.update_font_color("#js-banner-title", "#banner_font_color_picker", $(this).val());
- App.Banners.update_font_color("#js-banner-description", "#banner_font_color_picker", $(this).val());
+ App.Banners.update_font_color("#js-banner-title", $(this).val())
+ App.Banners.update_font_color("#js-banner-description", $(this).val())
diff --git a/app/assets/javascripts/best_in_place_initialize.js.coffee b/app/assets/javascripts/best_in_place_initialize.js.coffee
index 2caaea1f1..0b833b921 100644
--- a/app/assets/javascripts/best_in_place_initialize.js.coffee
+++ b/app/assets/javascripts/best_in_place_initialize.js.coffee
@@ -1,3 +1,3 @@
App.BestInPlace =
initialize: ->
- $('.best_in_place').best_in_place();
+ $(".best_in_place").best_in_place()
diff --git a/app/assets/javascripts/check_all_none.js.coffee b/app/assets/javascripts/check_all_none.js.coffee
index f49801a73..f0507b277 100644
--- a/app/assets/javascripts/check_all_none.js.coffee
+++ b/app/assets/javascripts/check_all_none.js.coffee
@@ -1,13 +1,10 @@
App.CheckAllNone =
initialize: ->
- $('[data-check-all]').on 'click', ->
- target_name = $(this).data('check-all')
- $("[name='" + target_name + "']").prop('checked', true)
-
- $('[data-check-none]').on 'click', ->
- target_name = $(this).data('check-none')
- $("[name='" + target_name + "']").prop('checked', false)
-
-
+ $("[data-check-all]").on "click", ->
+ target_name = $(this).data("check-all")
+ $("[name='#{target_name}']").prop("checked", true)
+ $("[data-check-none]").on "click", ->
+ target_name = $(this).data("check-none")
+ $("[name='#{target_name}']").prop("checked", false)
diff --git a/app/assets/javascripts/checkbox_toggle.js.coffee b/app/assets/javascripts/checkbox_toggle.js.coffee
index 096ce7e25..f20476f8d 100644
--- a/app/assets/javascripts/checkbox_toggle.js.coffee
+++ b/app/assets/javascripts/checkbox_toggle.js.coffee
@@ -1,12 +1,10 @@
App.CheckboxToggle =
initialize: ->
- $('[data-checkbox-toggle]').on 'change', ->
+ $("[data-checkbox-toggle]").on "change", ->
$this = $(this)
- $target = $($this.data('checkbox-toggle'))
- if $this.is(':checked')
+ $target = $($this.data("checkbox-toggle"))
+ if $this.is(":checked")
$target.show()
else
$target.hide()
-
-
diff --git a/app/assets/javascripts/ckeditor/config.js b/app/assets/javascripts/ckeditor/config.js
index dc8ae5149..78be62b99 100644
--- a/app/assets/javascripts/ckeditor/config.js
+++ b/app/assets/javascripts/ckeditor/config.js
@@ -22,7 +22,7 @@ CKEDITOR.editorConfig = function( config )
// Rails CSRF token
config.filebrowserParams = function(){
var csrf_token, csrf_param, meta,
- metas = document.getElementsByTagName('meta'),
+ metas = document.getElementsByTagName("meta"),
params = new Object();
for ( var i = 0 ; i < metas.length ; i++ ){
@@ -61,47 +61,47 @@ CKEDITOR.editorConfig = function( config )
};
// Integrate Rails CSRF token into file upload dialogs (link, image, attachment and flash)
- CKEDITOR.on( 'dialogDefinition', function( ev ){
+ CKEDITOR.on( "dialogDefinition", function( ev ){
// Take the dialog name and its definition from the event data.
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
var content, upload;
- if (CKEDITOR.tools.indexOf(['link', 'image', 'attachment', 'flash'], dialogName) > -1) {
- content = (dialogDefinition.getContents('Upload') || dialogDefinition.getContents('upload'));
- upload = (content == null ? null : content.get('upload'));
+ if (CKEDITOR.tools.indexOf(["link", "image", "attachment", "flash"], dialogName) > -1) {
+ content = (dialogDefinition.getContents("Upload") || dialogDefinition.getContents("upload"));
+ upload = (content == null ? null : content.get("upload"));
- if (upload && upload.filebrowser && upload.filebrowser['params'] === undefined) {
- upload.filebrowser['params'] = config.filebrowserParams();
- upload.action = config.addQueryString(upload.action, upload.filebrowser['params']);
+ if (upload && upload.filebrowser && upload.filebrowser["params"] === undefined) {
+ upload.filebrowser["params"] = config.filebrowserParams();
+ upload.action = config.addQueryString(upload.action, upload.filebrowser["params"]);
}
}
});
// Toolbar groups configuration.
config.toolbar = [
- { name: 'document', groups: [ 'mode', 'document', 'doctools' ], items: [ 'Source'] },
- { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
- // { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ], items: [ 'Find', 'Replace', '-', 'SelectAll', '-', 'Scayt' ] },
- // { name: 'forms', items: [ 'Form', 'Checkbox', 'Radio', 'TextField', 'Textarea', 'Select', 'Button', 'ImageButton', 'HiddenField' ] },
- { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
- { name: 'insert', items: [ 'Image', 'Flash', 'Table', 'HorizontalRule', 'SpecialChar' ] },
- { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
- '/',
- { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] },
- { name: 'colors', items: [ 'TextColor', 'BGColor' ] },
- { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] }
+ { name: "document", groups: [ "mode", "document", "doctools" ], items: [ "Source"] },
+ { name: "clipboard", groups: [ "clipboard", "undo" ], items: [ "Cut", "Copy", "Paste", "PasteText", "PasteFromWord", "-", "Undo", "Redo" ] },
+ // { name: "editing", groups: [ "find", "selection", "spellchecker" ], items: [ "Find", "Replace", "-", "SelectAll", "-", "Scayt" ] },
+ // { name: "forms", items: [ "Form", "Checkbox", "Radio", "TextField", "Textarea", "Select", "Button", "ImageButton", "HiddenField" ] },
+ { name: "links", items: [ "Link", "Unlink", "Anchor" ] },
+ { name: "insert", items: [ "Image", "Flash", "Table", "HorizontalRule", "SpecialChar" ] },
+ { name: "paragraph", groups: [ "list", "indent", "blocks", "align", "bidi" ], items: [ "NumberedList", "BulletedList", "-", "Outdent", "Indent", "-", "Blockquote", "CreateDiv", "-", "JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock" ] },
+ "/",
+ { name: "styles", items: [ "Styles", "Format", "Font", "FontSize" ] },
+ { name: "colors", items: [ "TextColor", "BGColor" ] },
+ { name: "basicstyles", groups: [ "basicstyles", "cleanup" ], items: [ "Bold", "Italic", "Underline", "Strike", "Subscript", "Superscript", "-", "RemoveFormat" ] }
];
config.toolbar_mini = [
- { name: 'paragraph', groups: [ 'list' ], items: [ 'NumberedList', 'BulletedList' ] },
- { name: 'links', items: [ 'Link', 'Unlink' ] },
- { name: 'styles', items: [ 'Format' ] },
- { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike' ] }
+ { name: "paragraph", groups: [ "list" ], items: [ "NumberedList", "BulletedList" ] },
+ { name: "links", items: [ "Link", "Unlink" ] },
+ { name: "styles", items: [ "Format" ] },
+ { name: "basicstyles", groups: [ "basicstyles", "cleanup" ], items: [ "Bold", "Italic", "Underline", "Strike" ] }
];
config.toolbar_admin = config.toolbar_mini.concat([
- { name: 'insert', items: [ 'Image' ] }
+ { name: "insert", items: [ "Image", "Table" ] }
]);
config.toolbar = "mini";
diff --git a/app/assets/javascripts/ckeditor/loader.js.erb b/app/assets/javascripts/ckeditor/loader.js.erb
index 66e1d8347..a01df8811 100644
--- a/app/assets/javascripts/ckeditor/loader.js.erb
+++ b/app/assets/javascripts/ckeditor/loader.js.erb
@@ -1,3 +1,3 @@
//= require ckeditor/init
-CKEDITOR.config.customConfig = '<%= javascript_path 'ckeditor/config.js' %>';
+CKEDITOR.config.customConfig = "<%= javascript_path 'ckeditor/config.js' %>";
diff --git a/app/assets/javascripts/ckeditor/reinit.js b/app/assets/javascripts/ckeditor/reinit.js
index fe8e8cff3..7d2d4233c 100644
--- a/app/assets/javascripts/ckeditor/reinit.js
+++ b/app/assets/javascripts/ckeditor/reinit.js
@@ -1,7 +1,7 @@
-$(document).bind('page:change', function() {
+$(document).bind("page:change", function() {
if (typeof(CKEDITOR) != "undefined"){
for(name in CKEDITOR.instances){
try{CKEDITOR.replace(name);}catch(err){};
}
}
-});
\ No newline at end of file
+});
diff --git a/app/assets/javascripts/clipboard_button.js.coffee b/app/assets/javascripts/clipboard_button.js.coffee
index 292492d1b..05b6d9867 100644
--- a/app/assets/javascripts/clipboard_button.js.coffee
+++ b/app/assets/javascripts/clipboard_button.js.coffee
@@ -1,4 +1,4 @@
App.ClipboardButton =
initialize: ->
- clipboard = new ClipboardJS('.js-clipboard');
- console.log(clipboard);
+ clipboard = new ClipboardJS(".js-clipboard")
+ console.log(clipboard)
diff --git a/app/assets/javascripts/comments.js.coffee b/app/assets/javascripts/comments.js.coffee
index 94845ca78..370ab7a53 100644
--- a/app/assets/javascripts/comments.js.coffee
+++ b/app/assets/javascripts/comments.js.coffee
@@ -21,12 +21,12 @@ App.Comments =
reset_and_hide_form: (id) ->
form_container = $("#js-comment-form-#{id}")
input = form_container.find("form textarea")
- input.val('')
+ input.val("")
form_container.hide()
reset_form: (id) ->
input = $("#js-comment-form-#{id} form textarea")
- input.val('')
+ input.val("")
toggle_form: (id) ->
$("#js-comment-form-#{id}").toggle()
@@ -39,21 +39,21 @@ App.Comments =
$(arrow).removeClass("icon-arrow-down").addClass("icon-arrow-right")
initialize: ->
- $('body .js-add-comment-link').each ->
+ $("body .js-add-comment-link").each ->
$this = $(this)
- unless $this.data('initialized') is 'yes'
- $this.on('click', ->
+ unless $this.data("initialized") is "yes"
+ $this.on("click", ->
id = $(this).data().id
App.Comments.toggle_form(id)
false
- ).data 'initialized', 'yes'
+ ).data "initialized", "yes"
- $('body .js-toggle-children').each ->
- $(this).on('click', ->
+ $("body .js-toggle-children").each ->
+ $(this).on("click", ->
children_container_id = "#{$(this).data().id}_children"
- $("##{children_container_id}").toggle('slow')
+ $("##{children_container_id}").toggle("slow")
App.Comments.toggle_arrow(children_container_id)
- $(this).children('.js-child-toggle').toggle()
+ $(this).children(".js-child-toggle").toggle()
false
)
diff --git a/app/assets/javascripts/dashboard_graphs.js b/app/assets/javascripts/dashboard_graphs.js
index 6bad63d21..22a52f3e9 100644
--- a/app/assets/javascripts/dashboard_graphs.js
+++ b/app/assets/javascripts/dashboard_graphs.js
@@ -70,7 +70,7 @@
ProposalGraph.prototype.parseData = function(data) {
var key;
-
+
this.xColumnValues = [ ];
this.progressColumnValues = [ this.progressLabel ];
@@ -101,7 +101,7 @@
ProposalGraph.prototype.parseSuccessfulProposalData = function(data) {
var key;
-
+
this.successfulColumnValues = [ this.successLabel ];
for (key in data) {
@@ -152,7 +152,7 @@
maximumValue = this.maximumValue === 0 ? this.proposalSuccess : Math.round(this.maximumValue * 1.10);
this.formatXColumnValues();
-
+
colors[this.progressColumnValues[0]] = '#004a83';
colors[this.successfulColumnValues[0]] = '#ff7f0e';
@@ -191,7 +191,7 @@
},
min: (this.maximumValue === 0 ? Math.round(this.proposalSuccess * 0.10) : 0),
max: maximumValue,
- label: {
+ label: {
text: this.supportsLabel,
position: 'outer-middle'
}
@@ -214,7 +214,7 @@
},
tooltip: {
format: {
- title: function (d) {
+ title: function (d) {
var achievement = this.achievements.find(function (element) {
return element.value === this.xColumnValues[d + 1];
}.bind(this));
@@ -283,10 +283,10 @@
}
return group;
- }
+ };
ProposalGraph.prototype.isDailyGrouped = function() {
- return this.groupBy === undefined || this.groupBy === '' || this.groupBy === null
+ return this.groupBy === undefined || this.groupBy === '' || this.groupBy === null;
};
$(document).ready(function () {
diff --git a/app/assets/javascripts/documentable.js.coffee b/app/assets/javascripts/documentable.js.coffee
index a61458150..035371834 100644
--- a/app/assets/javascripts/documentable.js.coffee
+++ b/app/assets/javascripts/documentable.js.coffee
@@ -2,16 +2,16 @@ App.Documentable =
initialize: ->
- inputFiles = $('.js-document-attachment')
+ inputFiles = $(".js-document-attachment")
$.each inputFiles, (index, input) ->
App.Documentable.initializeDirectUploadInput(input)
- $('#nested-documents').on 'cocoon:after-remove', (e, insertedItem) ->
+ $("#nested-documents").on "cocoon:after-remove", (e, insertedItem) ->
App.Documentable.unlockUploads()
- $('#nested-documents').on 'cocoon:after-insert', (e, nested_document) ->
- input = $(nested_document).find('.js-document-attachment')
- input["lockUpload"] = $(nested_document).closest('#nested-documents').find('.document:visible').length >= $('#nested-documents').data('max-documents-allowed')
+ $("#nested-documents").on "cocoon:after-insert", (e, nested_document) ->
+ input = $(nested_document).find(".js-document-attachment")
+ input["lockUpload"] = $(nested_document).closest("#nested-documents").find(".document:visible").length >= $("#nested-documents").data("max-documents-allowed")
App.Documentable.initializeDirectUploadInput(input)
App.Documentable.lockUploads() if input["lockUpload"]
@@ -30,7 +30,7 @@ App.Documentable =
add: (e, data) ->
data = App.Documentable.buildFileUploadData(e, data)
App.Documentable.clearProgressBar(data)
- App.Documentable.setProgressBar(data, 'uploading')
+ App.Documentable.setProgressBar(data, "uploading")
data.submit()
change: (e, data) ->
@@ -40,26 +40,26 @@ App.Documentable =
fail: (e, data) ->
$(data.cachedAttachmentField).val("")
App.Documentable.clearFilename(data)
- App.Documentable.setProgressBar(data, 'errors')
+ App.Documentable.setProgressBar(data, "errors")
App.Documentable.clearInputErrors(data)
App.Documentable.setInputErrors(data)
$(data.destroyAttachmentLinkContainer).find("a.delete:not(.remove-nested)").remove()
- $(data.addAttachmentLabel).addClass('error')
+ $(data.addAttachmentLabel).addClass("error")
$(data.addAttachmentLabel).show()
done: (e, data) ->
$(data.cachedAttachmentField).val(data.result.cached_attachment)
App.Documentable.setTitleFromFile(data, data.result.filename)
- App.Documentable.setProgressBar(data, 'complete')
+ App.Documentable.setProgressBar(data, "complete")
App.Documentable.setFilename(data, data.result.filename)
App.Documentable.clearInputErrors(data)
$(data.addAttachmentLabel).hide()
- $(data.wrapper).find(".attachment-actions").removeClass('small-12').addClass('small-6 float-right')
- $(data.wrapper).find(".attachment-actions .action-remove").removeClass('small-3').addClass('small-12')
+ $(data.wrapper).find(".attachment-actions").removeClass("small-12").addClass("small-6 float-right")
+ $(data.wrapper).find(".attachment-actions .action-remove").removeClass("small-3").addClass("small-12")
destroyAttachmentLink = $(data.result.destroy_link)
$(data.destroyAttachmentLinkContainer).html(destroyAttachmentLink)
- $(destroyAttachmentLink).on 'click', (e) ->
+ $(destroyAttachmentLink).on "click", (e) ->
e.preventDefault()
e.stopPropagation()
App.Documentable.doDeleteCachedAttachmentRequest(this.href, data)
@@ -69,7 +69,7 @@ App.Documentable =
progress: (e, data) ->
progress = parseInt(data.loaded / data.total * 100, 10)
- $(data.progressBar).find('.loading-bar').css 'width', progress + '%'
+ $(data.progressBar).find(".loading-bar").css "width", "#{progress}%"
return
buildFileUploadData: (e, data) ->
@@ -77,53 +77,53 @@ App.Documentable =
return data
buildData: (data, input) ->
- wrapper = $(input).closest('.direct-upload')
+ wrapper = $(input).closest(".direct-upload")
data.input = input
data.wrapper = wrapper
- data.progressBar = $(wrapper).find('.progress-bar-placeholder')
- data.errorContainer = $(wrapper).find('.attachment-errors')
- data.fileNameContainer = $(wrapper).find('p.file-name')
- data.destroyAttachmentLinkContainer = $(wrapper).find('.action-remove')
- data.addAttachmentLabel = $(wrapper).find('.action-add label')
+ data.progressBar = $(wrapper).find(".progress-bar-placeholder")
+ data.errorContainer = $(wrapper).find(".attachment-errors")
+ data.fileNameContainer = $(wrapper).find("p.file-name")
+ data.destroyAttachmentLinkContainer = $(wrapper).find(".action-remove")
+ data.addAttachmentLabel = $(wrapper).find(".action-add label")
data.cachedAttachmentField = $(wrapper).find("input[name$='[cached_attachment]']")
data.titleField = $(wrapper).find("input[name$='[title]']")
- $(wrapper).find('.progress-bar-placeholder').css('display', 'block')
+ $(wrapper).find(".progress-bar-placeholder").css("display", "block")
return data
clearFilename: (data) ->
- $(data.fileNameContainer).text('')
+ $(data.fileNameContainer).text("")
$(data.fileNameContainer).hide()
clearInputErrors: (data) ->
- $(data.errorContainer).find('small.error').remove()
+ $(data.errorContainer).find("small.error").remove()
clearProgressBar: (data) ->
- $(data.progressBar).find('.loading-bar').removeClass('complete errors uploading').css('width', "0px")
+ $(data.progressBar).find(".loading-bar").removeClass("complete errors uploading").css("width", "0px")
setFilename: (data, file_name) ->
$(data.fileNameContainer).text(file_name)
$(data.fileNameContainer).show()
setProgressBar: (data, klass) ->
- $(data.progressBar).find('.loading-bar').addClass(klass)
+ $(data.progressBar).find(".loading-bar").addClass(klass)
setTitleFromFile: (data, title) ->
if $(data.titleField).val() == ""
$(data.titleField).val(title)
setInputErrors: (data) ->
- errors = '' + data.jqXHR.responseJSON.errors + ''
+ errors = "#{data.jqXHR.responseJSON.errors}"
$(data.errorContainer).append(errors)
lockUploads: ->
- $('#new_document_link').addClass('hide')
+ $("#new_document_link").addClass("hide")
unlockUploads: ->
- $('#max-documents-notice').addClass('hide')
- $('#new_document_link').removeClass('hide')
+ $("#max-documents-notice").addClass("hide")
+ $("#new_document_link").removeClass("hide")
showNotice: ->
- $('#max-documents-notice').removeClass('hide')
+ $("#max-documents-notice").removeClass("hide")
doDeleteCachedAttachmentRequest: (url, data) ->
$.ajax
@@ -140,21 +140,21 @@ App.Documentable =
App.Documentable.clearProgressBar(data)
App.Documentable.unlockUploads()
- $(data.wrapper).find(".attachment-actions").addClass('small-12').removeClass('small-6 float-right')
- $(data.wrapper).find(".attachment-actions .action-remove").addClass('small-3').removeClass('small-12')
+ $(data.wrapper).find(".attachment-actions").addClass("small-12").removeClass("small-6 float-right")
+ $(data.wrapper).find(".attachment-actions .action-remove").addClass("small-3").removeClass("small-12")
- if $(data.input).data('nested-document') == true
+ if $(data.input).data("nested-document") == true
$(data.wrapper).remove()
else
- $(data.wrapper).find('a.remove-cached-attachment').remove()
+ $(data.wrapper).find("a.remove-cached-attachment").remove()
initializeRemoveCachedDocumentLink: (input, data) ->
wrapper = $(input).closest(".direct-upload")
- remove_document_link = $(wrapper).find('a.remove-cached-attachment')
- $(remove_document_link).on 'click', (e) ->
+ remove_document_link = $(wrapper).find("a.remove-cached-attachment")
+ $(remove_document_link).on "click", (e) ->
e.preventDefault()
e.stopPropagation()
App.Documentable.doDeleteCachedAttachmentRequest(this.href, data)
removeDocument: (id) ->
- $('#' + id).remove()
+ $("##{id}").remove()
diff --git a/app/assets/javascripts/embed_video.js.coffee b/app/assets/javascripts/embed_video.js.coffee
index 0825d1b80..6f7ef12a4 100644
--- a/app/assets/javascripts/embed_video.js.coffee
+++ b/app/assets/javascripts/embed_video.js.coffee
@@ -1,6 +1,6 @@
App.EmbedVideo =
initialize: ->
- $('#js-embedded-video').each ->
+ $("#js-embedded-video").each ->
code = $(this).data("video-code")
- $('#js-embedded-video').html(code)
+ $("#js-embedded-video").html(code)
diff --git a/app/assets/javascripts/fixed_bar.js.coffee b/app/assets/javascripts/fixed_bar.js.coffee
index 5421d79e9..f1ba7550f 100644
--- a/app/assets/javascripts/fixed_bar.js.coffee
+++ b/app/assets/javascripts/fixed_bar.js.coffee
@@ -1,13 +1,13 @@
App.FixedBar =
initialize: ->
- $('[data-fixed-bar]').each ->
+ $("[data-fixed-bar]").each ->
$this = $(this)
fixedBarTopPosition = $this.offset().top
- $(window).on 'scroll', ->
+ $(window).on "scroll", ->
if $(window).scrollTop() > fixedBarTopPosition
- $this.addClass('is-fixed')
- $("#check-ballot").css({ 'display': "inline-block" })
+ $this.addClass("is-fixed")
+ $("#check-ballot").css({ "display": "inline-block" })
else
- $this.removeClass('is-fixed')
+ $this.removeClass("is-fixed")
$("#check-ballot").hide()
diff --git a/app/assets/javascripts/flaggable.js.coffee b/app/assets/javascripts/flaggable.js.coffee
index 7ada75686..411723368 100644
--- a/app/assets/javascripts/flaggable.js.coffee
+++ b/app/assets/javascripts/flaggable.js.coffee
@@ -1,4 +1,4 @@
App.Flaggable =
update: (resource_id, button) ->
- $("#" + resource_id + " .js-flag-actions").html(button).foundation()
+ $("##{resource_id} .js-flag-actions").html(button).foundation()
diff --git a/app/assets/javascripts/followable.js.coffee b/app/assets/javascripts/followable.js.coffee
index 9fa9aa319..5fad5f563 100644
--- a/app/assets/javascripts/followable.js.coffee
+++ b/app/assets/javascripts/followable.js.coffee
@@ -1,8 +1,8 @@
App.Followable =
update: (followable_id, button, notice) ->
- $("#" + followable_id + " .js-follow").html(button)
- if ($('[data-alert]').length > 0)
- $('[data-alert]').replaceWith(notice)
+ $("##{followable_id} .js-follow").html(button)
+ if ($("[data-alert]").length > 0)
+ $("[data-alert]").replaceWith(notice)
else
$("body").append(notice)
diff --git a/app/assets/javascripts/forms.js.coffee b/app/assets/javascripts/forms.js.coffee
index edf4c525f..34ea71916 100644
--- a/app/assets/javascripts/forms.js.coffee
+++ b/app/assets/javascripts/forms.js.coffee
@@ -1,30 +1,60 @@
App.Forms =
disableEnter: ->
- $('form.js-enter-disabled').on('keyup keypress', (event) ->
+ $("form.js-enter-disabled").on("keyup keypress", (event) ->
if event.which == 13
e.preventDefault()
)
submitOnChange: ->
- $('.js-submit-on-change').unbind('change').on('change', ->
- $(this).closest('form').submit()
+ $(".js-submit-on-change").unbind("change").on("change", ->
+ $(this).closest("form").submit()
false
)
toggleLink: ->
- $('.js-toggle-link').unbind('click').on('click', ->
- $($(this).data('toggle-selector')).toggle("down")
- if $(this).data('toggle-text') isnt undefined
+ $(".js-toggle-link").unbind("click").on("click", ->
+ $($(this).data("toggle-selector")).toggle("down")
+ if $(this).data("toggle-text") isnt undefined
toggle_txt = $(this).text()
- $(this).text( $(this).data('toggle-text') )
- $(this).data('toggle-text', toggle_txt)
+ $(this).text( $(this).data("toggle-text") )
+ $(this).data("toggle-text", toggle_txt)
false
)
+ synchronizeInputs: ->
+ progress_bar = "[name='progress_bar[percentage]']"
+ process_background = "[name='legislation_process[background_color]']"
+ process_font = ", [name='legislation_process[font_color]']"
+ processes = process_background + process_font
+ banners = "[name='banner[background_color]'], [name='banner[font_color]']"
+
+ inputs = $("#{progress_bar}, #{processes}, #{banners}")
+ inputs.on
+ input: ->
+ $("[name='#{this.name}']").val($(this).val())
+
+ inputs.trigger("input")
+
+ hideOrShowFieldsAfterSelection: ->
+ $("[name='progress_bar[kind]']").on
+ change: ->
+ title_field = $("[name^='progress_bar'][name$='[title]']").parent()
+
+ if this.value == "primary"
+ title_field.hide()
+ $("#globalize_locales").hide()
+ else
+ title_field.show()
+ $("#globalize_locales").show()
+
+ $("[name='progress_bar[kind]']").change()
+
initialize: ->
App.Forms.disableEnter()
App.Forms.submitOnChange()
App.Forms.toggleLink()
+ App.Forms.synchronizeInputs()
+ App.Forms.hideOrShowFieldsAfterSelection()
false
diff --git a/app/assets/javascripts/gettext.js.coffee b/app/assets/javascripts/gettext.js.coffee
index 05df572a5..52ae42375 100644
--- a/app/assets/javascripts/gettext.js.coffee
+++ b/app/assets/javascripts/gettext.js.coffee
@@ -21,7 +21,7 @@ i18n = {
window.Gettext = (key) ->
gettext: (key) ->
- locale_id = $('html').attr('lang')
+ locale_id = $("html").attr("lang")
locale = i18n[locale_id]
if locale && locale[key]
return locale[key]
diff --git a/app/assets/javascripts/globalize.js.coffee b/app/assets/javascripts/globalize.js.coffee
index 374d2b299..1238402a2 100644
--- a/app/assets/javascripts/globalize.js.coffee
+++ b/app/assets/javascripts/globalize.js.coffee
@@ -6,7 +6,7 @@ App.Globalize =
if $(this).data("locale") == locale
$(this).show()
App.Globalize.highlight_locale($(this))
- $(".js-globalize-locale option:selected").removeAttr("selected");
+ $(".js-globalize-locale option:selected").removeAttr("selected")
return
display_translations: (locale) ->
@@ -15,46 +15,65 @@ App.Globalize =
$(this).show()
else
$(this).hide()
- $('.js-delete-language').hide()
- $('#delete-' + locale).show()
+ $(".js-delete-language").hide()
+ $("#js_delete_#{locale}").show()
highlight_locale: (element) ->
- $('.js-globalize-locale-link').removeClass('is-active');
- element.addClass('is-active');
+ $(".js-globalize-locale-link").removeClass("is-active")
+ element.addClass("is-active")
remove_language: (locale) ->
- $(".js-globalize-attribute[data-locale=" + locale + "]").each ->
- $(this).val('').hide()
- if CKEDITOR.instances[$(this).attr('id')]
- CKEDITOR.instances[$(this).attr('id')].setData('')
- $(".js-globalize-locale-link[data-locale=" + locale + "]").hide()
+ $(".js-globalize-attribute[data-locale=#{locale}]").each ->
+ $(this).val("").hide()
+ if CKEDITOR.instances[$(this).attr("id")]
+ CKEDITOR.instances[$(this).attr("id")].setData("")
+ $(".js-globalize-locale-link[data-locale=#{locale}]").hide()
next = $(".js-globalize-locale-link:visible").first()
App.Globalize.highlight_locale(next)
App.Globalize.display_translations(next.data("locale"))
App.Globalize.disable_locale(locale)
enable_locale: (locale) ->
- $("#enabled_translations_" + locale).val(1)
+ App.Globalize.destroy_locale_field(locale).val(false)
+ App.Globalize.site_customization_enable_locale_field(locale).val(1)
disable_locale: (locale) ->
- $("#enabled_translations_" + locale).val(0)
+ App.Globalize.destroy_locale_field(locale).val(true)
+ App.Globalize.site_customization_enable_locale_field(locale).val(0)
+
+ enabled_locales: ->
+ $.map(
+ $(".js-globalize-locale-link:visible"),
+ (element) -> $(element).data("locale")
+ )
+
+ destroy_locale_field: (locale) ->
+ $("input[id$=_destroy][data-locale=#{locale}]")
+
+ site_customization_enable_locale_field: (locale) ->
+ $("#enabled_translations_#{locale}")
refresh_visible_translations: ->
- locale = $('.js-globalize-locale-link.is-active').data("locale")
+ locale = $(".js-globalize-locale-link.is-active").data("locale")
App.Globalize.display_translations(locale)
initialize: ->
- $('.js-globalize-locale').on 'change', ->
+ $(".js-globalize-locale").on "change", ->
App.Globalize.display_translations($(this).val())
App.Globalize.display_locale($(this).val())
- $('.js-globalize-locale-link').on 'click', ->
+ $(".js-globalize-locale-link").on "click", ->
locale = $(this).data("locale")
App.Globalize.display_translations(locale)
App.Globalize.highlight_locale($(this))
- $('.js-delete-language').on 'click', ->
+ $(".js-delete-language").on "click", ->
locale = $(this).data("locale")
$(this).hide()
App.Globalize.remove_language(locale)
+ $(".js-add-fields-container").on "cocoon:after-insert", ->
+ $.each(
+ App.Globalize.enabled_locales(),
+ (index, locale) -> App.Globalize.enable_locale(locale)
+ )
diff --git a/app/assets/javascripts/ie_alert.js.coffee b/app/assets/javascripts/ie_alert.js.coffee
index cab566b73..30c7620ce 100644
--- a/app/assets/javascripts/ie_alert.js.coffee
+++ b/app/assets/javascripts/ie_alert.js.coffee
@@ -1,9 +1,9 @@
App.IeAlert =
set_cookie_and_hide: (event) ->
event.preventDefault()
- $.cookie('ie_alert_closed', 'true', { path: '/', expires: 365 })
- $('.ie-callout').remove()
+ $.cookie("ie_alert_closed", "true", { path: "/", expires: 365 })
+ $(".ie-callout").remove()
initialize: ->
- $('.ie-callout-close-js').on 'click', (event) ->
+ $(".ie-callout-close-js").on "click", (event) ->
App.IeAlert.set_cookie_and_hide(event)
diff --git a/app/assets/javascripts/imageable.js.coffee b/app/assets/javascripts/imageable.js.coffee
index e029dff52..bdb71f4f9 100644
--- a/app/assets/javascripts/imageable.js.coffee
+++ b/app/assets/javascripts/imageable.js.coffee
@@ -1,20 +1,20 @@
App.Imageable =
initialize: ->
- inputFiles = $('.js-image-attachment')
+ inputFiles = $(".js-image-attachment")
$.each inputFiles, (index, input) ->
App.Imageable.initializeDirectUploadInput(input)
- $('#nested-image').on 'cocoon:after-remove', (e, item) ->
- $("#new_image_link").removeClass('hide')
+ $("#nested-image").on "cocoon:after-remove", (e, item) ->
+ $("#new_image_link").removeClass("hide")
- $('#nested-image').on 'cocoon:before-insert', (e, nested_image) ->
+ $("#nested-image").on "cocoon:before-insert", (e, nested_image) ->
if $(".js-image-attachment").length > 0
- $(".js-image-attachment").closest('.image').remove()
+ $(".js-image-attachment").closest(".image").remove()
- $('#nested-image').on 'cocoon:after-insert', (e, nested_image) ->
- $("#new_image_link").addClass('hide')
- input = $(nested_image).find('.js-image-attachment')
+ $("#nested-image").on "cocoon:after-insert", (e, nested_image) ->
+ $("#new_image_link").addClass("hide")
+ input = $(nested_image).find(".js-image-attachment")
App.Imageable.initializeDirectUploadInput(input)
initializeDirectUploadInput: (input) ->
@@ -32,7 +32,7 @@ App.Imageable =
add: (e, data) ->
data = App.Imageable.buildFileUploadData(e, data)
App.Imageable.clearProgressBar(data)
- App.Imageable.setProgressBar(data, 'uploading')
+ App.Imageable.setProgressBar(data, "uploading")
data.submit()
change: (e, data) ->
@@ -42,35 +42,35 @@ App.Imageable =
fail: (e, data) ->
$(data.cachedAttachmentField).val("")
App.Imageable.clearFilename(data)
- App.Imageable.setProgressBar(data, 'errors')
+ App.Imageable.setProgressBar(data, "errors")
App.Imageable.clearInputErrors(data)
App.Imageable.setInputErrors(data)
App.Imageable.clearPreview(data)
$(data.destroyAttachmentLinkContainer).find("a.delete:not(.remove-nested)").remove()
- $(data.addAttachmentLabel).addClass('error')
+ $(data.addAttachmentLabel).addClass("error")
$(data.addAttachmentLabel).show()
done: (e, data) ->
$(data.cachedAttachmentField).val(data.result.cached_attachment)
App.Imageable.setTitleFromFile(data, data.result.filename)
- App.Imageable.setProgressBar(data, 'complete')
+ App.Imageable.setProgressBar(data, "complete")
App.Imageable.setFilename(data, data.result.filename)
App.Imageable.clearInputErrors(data)
$(data.addAttachmentLabel).hide()
- $(data.wrapper).find(".attachment-actions").removeClass('small-12').addClass('small-6 float-right')
- $(data.wrapper).find(".attachment-actions .action-remove").removeClass('small-3').addClass('small-12')
+ $(data.wrapper).find(".attachment-actions").removeClass("small-12").addClass("small-6 float-right")
+ $(data.wrapper).find(".attachment-actions .action-remove").removeClass("small-3").addClass("small-12")
App.Imageable.setPreview(data)
destroyAttachmentLink = $(data.result.destroy_link)
$(data.destroyAttachmentLinkContainer).html(destroyAttachmentLink)
- $(destroyAttachmentLink).on 'click', (e) ->
+ $(destroyAttachmentLink).on "click", (e) ->
e.preventDefault()
e.stopPropagation()
App.Imageable.doDeleteCachedAttachmentRequest(this.href, data)
progress: (e, data) ->
progress = parseInt(data.loaded / data.total * 100, 10)
- $(data.progressBar).find('.loading-bar').css 'width', progress + '%'
+ $(data.progressBar).find(".loading-bar").css "width", "#{progress}%"
return
buildFileUploadData: (e, data) ->
@@ -78,55 +78,55 @@ App.Imageable =
return data
buildData: (data, input) ->
- wrapper = $(input).closest('.direct-upload')
+ wrapper = $(input).closest(".direct-upload")
data.input = input
data.wrapper = wrapper
- data.progressBar = $(wrapper).find('.progress-bar-placeholder')
- data.preview = $(wrapper).find('.image-preview')
- data.errorContainer = $(wrapper).find('.attachment-errors')
- data.fileNameContainer = $(wrapper).find('p.file-name')
- data.destroyAttachmentLinkContainer = $(wrapper).find('.action-remove')
- data.addAttachmentLabel = $(wrapper).find('.action-add label')
+ data.progressBar = $(wrapper).find(".progress-bar-placeholder")
+ data.preview = $(wrapper).find(".image-preview")
+ data.errorContainer = $(wrapper).find(".attachment-errors")
+ data.fileNameContainer = $(wrapper).find("p.file-name")
+ data.destroyAttachmentLinkContainer = $(wrapper).find(".action-remove")
+ data.addAttachmentLabel = $(wrapper).find(".action-add label")
data.cachedAttachmentField = $(wrapper).find("input[name$='[cached_attachment]']")
data.titleField = $(wrapper).find("input[name$='[title]']")
- $(wrapper).find('.progress-bar-placeholder').css('display', 'block')
+ $(wrapper).find(".progress-bar-placeholder").css("display", "block")
return data
clearFilename: (data) ->
- $(data.fileNameContainer).text('')
+ $(data.fileNameContainer).text("")
$(data.fileNameContainer).hide()
clearInputErrors: (data) ->
- $(data.errorContainer).find('small.error').remove()
+ $(data.errorContainer).find("small.error").remove()
clearProgressBar: (data) ->
- $(data.progressBar).find('.loading-bar').removeClass('complete errors uploading').css('width', "0px")
+ $(data.progressBar).find(".loading-bar").removeClass("complete errors uploading").css("width", "0px")
clearPreview: (data) ->
- $(data.wrapper).find('.image-preview').remove()
+ $(data.wrapper).find(".image-preview").remove()
setFilename: (data, file_name) ->
$(data.fileNameContainer).text(file_name)
$(data.fileNameContainer).show()
setProgressBar: (data, klass) ->
- $(data.progressBar).find('.loading-bar').addClass(klass)
+ $(data.progressBar).find(".loading-bar").addClass(klass)
setTitleFromFile: (data, title) ->
if $(data.titleField).val() == ""
$(data.titleField).val(title)
setInputErrors: (data) ->
- errors = '' + data.jqXHR.responseJSON.errors + ''
+ errors = "#{data.jqXHR.responseJSON.errors}"
$(data.errorContainer).append(errors)
setPreview: (data) ->
- image_preview = ''
+ image_preview = ""
if $(data.preview).length > 0
$(data.preview).replaceWith(image_preview)
else
$(image_preview).insertBefore($(data.wrapper).find(".attachment-actions"))
- data.preview = $(data.wrapper).find('.image-preview')
+ data.preview = $(data.wrapper).find(".image-preview")
doDeleteCachedAttachmentRequest: (url, data) ->
$.ajax
@@ -143,24 +143,24 @@ App.Imageable =
App.Imageable.clearProgressBar(data)
App.Imageable.clearPreview(data)
- $('#new_image_link').removeClass('hide')
+ $("#new_image_link").removeClass("hide")
- $(data.wrapper).find(".attachment-actions").addClass('small-12').removeClass('small-6 float-right')
- $(data.wrapper).find(".attachment-actions .action-remove").addClass('small-3').removeClass('small-12')
+ $(data.wrapper).find(".attachment-actions").addClass("small-12").removeClass("small-6 float-right")
+ $(data.wrapper).find(".attachment-actions .action-remove").addClass("small-3").removeClass("small-12")
- if $(data.input).data('nested-image') == true
+ if $(data.input).data("nested-image") == true
$(data.wrapper).remove()
else
- $(data.wrapper).find('a.remove-cached-attachment').remove()
+ $(data.wrapper).find("a.remove-cached-attachment").remove()
initializeRemoveCachedImageLink: (input, data) ->
wrapper = $(input).closest(".direct-upload")
- remove_image_link = $(wrapper).find('a.remove-cached-attachment')
- $(remove_image_link).on 'click', (e) ->
+ remove_image_link = $(wrapper).find("a.remove-cached-attachment")
+ $(remove_image_link).on "click", (e) ->
e.preventDefault()
e.stopPropagation()
App.Imageable.doDeleteCachedAttachmentRequest(this.href, data)
removeImage: (id) ->
- $('#' + id).remove()
- $("#new_image_link").removeClass('hide')
+ $("##{id}").remove()
+ $("#new_image_link").removeClass("hide")
diff --git a/app/assets/javascripts/investment_report_alert.js.coffee b/app/assets/javascripts/investment_report_alert.js.coffee
index 98b239a55..91dc6ba44 100644
--- a/app/assets/javascripts/investment_report_alert.js.coffee
+++ b/app/assets/javascripts/investment_report_alert.js.coffee
@@ -1,7 +1,7 @@
App.InvestmentReportAlert =
initialize: ->
- $('#js-investment-report-alert').on 'click', ->
- if this.checked && $('#budget_investment_feasibility_unfeasible').is(':checked')
- confirm(this.dataset.alert + "\n" + this.dataset.notFeasibleAlert);
+ $("#js-investment-report-alert").on "click", ->
+ if this.checked && $("#budget_investment_feasibility_unfeasible").is(":checked")
+ confirm("#{this.dataset.alert}\n#{this.dataset.notFeasibleAlert}")
else if this.checked
- confirm(this.dataset.alert);
+ confirm(this.dataset.alert)
diff --git a/app/assets/javascripts/legislation.js.coffee b/app/assets/javascripts/legislation.js.coffee
index 9cf27055a..ec104f2e2 100644
--- a/app/assets/javascripts/legislation.js.coffee
+++ b/app/assets/javascripts/legislation.js.coffee
@@ -1,12 +1,12 @@
App.Legislation =
initialize: ->
- $('form#new_legislation_answer input.button').hide()
- $('form#new_legislation_answer input[type=radio]').on
+ $("form#new_legislation_answer input.button").hide()
+ $("form#new_legislation_answer input[type=radio]").on
click: ->
- $('form#new_legislation_answer').submit()
+ $("form#new_legislation_answer").submit()
- $('form#draft_version_go_to_version input.button').hide()
- $('form#draft_version_go_to_version select').on
+ $("form#draft_version_go_to_version input.button").hide()
+ $("form#draft_version_go_to_version select").on
change: ->
- $('form#draft_version_go_to_version').submit()
+ $("form#draft_version_go_to_version").submit()
diff --git a/app/assets/javascripts/legislation_admin.js.coffee b/app/assets/javascripts/legislation_admin.js.coffee
index f7f9ea17a..c64826224 100644
--- a/app/assets/javascripts/legislation_admin.js.coffee
+++ b/app/assets/javascripts/legislation_admin.js.coffee
@@ -4,13 +4,13 @@ App.LegislationAdmin =
$("input[type='checkbox'][data-disable-date]").on
change: ->
checkbox = $(this)
- parent = $(this).parents('.row:eq(0)')
- date_selector = $(this).data('disable-date')
- parent.find("input[type='text'][id^='" + date_selector + "']").each ->
- if checkbox.is(':checked')
+ parent = $(this).parents(".row:eq(0)")
+ date_selector = $(this).data("disable-date")
+ parent.find("input[type='text'][id^='#{date_selector}']").each ->
+ if checkbox.is(":checked")
$(this).removeAttr("disabled")
else
$(this).val("")
- $("#nested-question-options").on "cocoon:after-insert", ->
+ $("#nested_question_options").on "cocoon:after-insert", ->
App.Globalize.refresh_visible_translations()
diff --git a/app/assets/javascripts/legislation_allegations.js.coffee b/app/assets/javascripts/legislation_allegations.js.coffee
index 9b9c95d8d..98dc36009 100644
--- a/app/assets/javascripts/legislation_allegations.js.coffee
+++ b/app/assets/javascripts/legislation_allegations.js.coffee
@@ -2,24 +2,24 @@ App.LegislationAllegations =
toggle_comments: ->
if !App.LegislationAnnotatable.isMobile()
- $('.draft-allegation').toggleClass('comments-on')
- $('#comments-box').html('').hide()
+ $(".draft-allegation").toggleClass("comments-on")
+ $("#comments-box").html("").hide()
show_comments: ->
if !App.LegislationAnnotatable.isMobile()
- $('.draft-allegation').addClass('comments-on')
+ $(".draft-allegation").addClass("comments-on")
initialize: ->
- $('.js-toggle-allegations .draft-panel').on
+ $(".js-toggle-allegations .draft-panel").on
click: (e) ->
e.preventDefault()
e.stopPropagation()
if !App.LegislationAnnotatable.isMobile()
App.LegislationAllegations.toggle_comments()
- $('.js-toggle-allegations').on
+ $(".js-toggle-allegations").on
click: (e) ->
# Toggle comments when the section title is visible
if !App.LegislationAnnotatable.isMobile()
- if $(this).find('.draft-panel .panel-title:visible').length == 0
+ if $(this).find(".draft-panel .panel-title:visible").length == 0
App.LegislationAllegations.toggle_comments()
diff --git a/app/assets/javascripts/legislation_annotatable.js.coffee b/app/assets/javascripts/legislation_annotatable.js.coffee
index 141bcb858..41ffa0749 100644
--- a/app/assets/javascripts/legislation_annotatable.js.coffee
+++ b/app/assets/javascripts/legislation_annotatable.js.coffee
@@ -6,47 +6,47 @@ App.LegislationAnnotatable =
sel = window.getSelection()
if sel.rangeCount and sel.getRangeAt
range = sel.getRangeAt(0)
- document.designMode = 'on'
+ document.designMode = "on"
if range
sel.removeAllRanges()
sel.addRange range
# Use HiliteColor since some browsers apply BackColor to the whole block
- if !document.execCommand('HiliteColor', false, colour)
- document.execCommand 'BackColor', false, colour
- document.designMode = 'off'
+ if !document.execCommand("HiliteColor", false, colour)
+ document.execCommand "BackColor", false, colour
+ document.designMode = "off"
return
highlight: (colour) ->
if window.getSelection
# IE9 and non-IE
try
- if !document.execCommand('BackColor', false, colour)
+ if !document.execCommand("BackColor", false, colour)
App.LegislationAnnotatable.makeEditableAndHighlight colour
catch ex
App.LegislationAnnotatable.makeEditableAndHighlight colour
else if document.selection and document.selection.createRange
# IE <= 8 case
range = document.selection.createRange()
- range.execCommand 'BackColor', false, colour
+ range.execCommand "BackColor", false, colour
return
remove_highlight: ->
- $('[data-legislation-draft-version-id] span[style]').replaceWith(->
+ $("[data-legislation-draft-version-id] span[style]").replaceWith(->
return $(this).contents()
)
return
renderAnnotationComments: (event) ->
if event.offset
- $("#comments-box").css({top: event.offset - $('.calc-comments').offset().top})
+ $("#comments-box").css({ top: event.offset - $(".calc-comments").offset().top })
if App.LegislationAnnotatable.isMobile()
return
$.ajax
method: "GET"
- url: event.annotation_url + "/annotations/" + event.annotation_id + "/comments"
- dataType: 'script'
+ url: "#{event.annotation_url}/annotations/#{event.annotation_id}/comments"
+ dataType: "script"
onClick: (event) ->
event.preventDefault()
@@ -54,21 +54,21 @@ App.LegislationAnnotatable =
if App.LegislationAnnotatable.isMobile()
annotation_url = $(event.target).closest(".legislation-annotatable").data("legislation-annotatable-base-url")
- window.location.href = annotation_url + "/annotations/" + $(this).data('annotation-id')
+ window.location.href = "#{annotation_url}/annotations/#{$(this).data("annotation-id")}"
return
- $('[data-annotation-id]').removeClass('current-annotation')
+ $("[data-annotation-id]").removeClass("current-annotation")
target = $(this)
- parents = target.parents('.annotator-hl')
+ parents = target.parents(".annotator-hl")
parents_ids = parents.map (_, elem) ->
$(elem).data("annotation-id")
- annotation_id = target.data('annotation-id')
- $('[data-annotation-id="' + annotation_id + '"]').addClass('current-annotation')
+ annotation_id = target.data("annotation-id")
+ $("[data-annotation-id='#{annotation_id}']").addClass("current-annotation")
- $('#comments-box').html('')
+ $("#comments-box").html("")
App.LegislationAllegations.show_comments()
$("#comments-box").show()
@@ -92,24 +92,24 @@ App.LegislationAnnotatable =
return
customShow: (position) ->
- $(@element).html ''
+ $(@element).html ""
# Clean comments section and open it
- $('#comments-box').html ''
+ $("#comments-box").html ""
App.LegislationAllegations.show_comments()
- $('#comments-box').show()
+ $("#comments-box").show()
- annotation_url = $('[data-legislation-annotatable-base-url]').data('legislation-annotatable-base-url')
+ annotation_url = $("[data-legislation-annotatable-base-url]").data("legislation-annotatable-base-url")
$.ajax(
- method: 'GET'
- url: annotation_url + '/annotations/new'
- dataType: 'script').done (->
- $('#new_legislation_annotation #legislation_annotation_quote').val(@annotation.quote)
- $('#new_legislation_annotation #legislation_annotation_ranges').val(JSON.stringify(@annotation.ranges))
- $('#comments-box').css({top: position.top - $('.calc-comments').offset().top})
+ method: "GET"
+ url: "#{annotation_url}/annotations/new"
+ dataType: "script").done (->
+ $("#new_legislation_annotation #legislation_annotation_quote").val(@annotation.quote)
+ $("#new_legislation_annotation #legislation_annotation_ranges").val(JSON.stringify(@annotation.ranges))
+ $("#comments-box").css({ top: position.top - $(".calc-comments").offset().top })
- unless $('[data-legislation-open-phase]').data('legislation-open-phase') == false
- App.LegislationAnnotatable.highlight('#7fff9a')
- $('#comments-box textarea').focus()
+ unless $("[data-legislation-open-phase]").data("legislation-open-phase") == false
+ App.LegislationAnnotatable.highlight("#7fff9a")
+ $("#comments-box textarea").focus()
$("#new_legislation_annotation").on("ajax:complete", (e, data, status, xhr) ->
App.LegislationAnnotatable.app.destroy()
@@ -118,11 +118,11 @@ App.LegislationAnnotatable =
$("#comments-box").html("").hide()
$.ajax
method: "GET"
- url: annotation_url + "/annotations/" + data.responseJSON.id + "/comments"
- dataType: 'script'
+ url: "#{annotation_url}/annotations/#{data.responseJSON.id}/comments"
+ dataType: "script"
else
- $(e.target).find('label').addClass('error')
- $('' + data.responseJSON[0] + '').insertAfter($(e.target).find('textarea'))
+ $(e.target).find("label").addClass("error")
+ $("#{data.responseJSON[0]}").insertAfter($(e.target).find("textarea"))
return true
)
return
@@ -133,17 +133,17 @@ App.LegislationAnnotatable =
scrollToAnchor: ->
annotationsLoaded: (annotations) ->
- anchor = $(location).attr('hash')
- if anchor && anchor.startsWith('#annotation')
+ anchor = $(location).attr("hash")
+ if anchor && anchor.startsWith("#annotation")
ann_id = anchor.split("-")[-1..]
checkExist = setInterval((->
- if $("span[data-annotation-id='" + ann_id + "']").length
- el = $("span[data-annotation-id='" + ann_id + "']")
- el.addClass('current-annotation')
- $('#comments-box').html('')
+ if $("span[data-annotation-id='#{ann_id}']").length
+ el = $("span[data-annotation-id='#{ann_id}']")
+ el.addClass("current-annotation")
+ $("#comments-box").html("")
App.LegislationAllegations.show_comments()
- $('html,body').animate({scrollTop: el.offset().top})
+ $("html,body").animate({ scrollTop: el.offset().top })
$.event.trigger
type: "renderLegislationAnnotation"
annotation_id: ann_id
@@ -164,27 +164,27 @@ App.LegislationAnnotatable =
last_annotation = annotations[annotations.length - 1]
checkExist = setInterval((->
- if $("span[data-annotation-id='" + last_annotation.id + "']").length
+ if $("span[data-annotation-id='#{last_annotation.id}']").length
for annotation in annotations
ann_weight = App.LegislationAnnotatable.propotionalWeight(annotation.weight, max_weight)
- el = $("span[data-annotation-id='" + annotation.id + "']")
- el.addClass('weight-' + ann_weight)
+ el = $("span[data-annotation-id='#{annotation.id}']")
+ el.addClass("weight-#{ann_weight}")
clearInterval checkExist
return
), 100)
initialize: ->
$(document).off("renderLegislationAnnotation").on("renderLegislationAnnotation", App.LegislationAnnotatable.renderAnnotationComments)
- $(document).off('click', '[data-annotation-id]').on('click', '[data-annotation-id]', App.LegislationAnnotatable.onClick)
- $(document).off('click', '[data-cancel-annotation]').on('click', '[data-cancel-annotation]', (e) ->
+ $(document).off("click", "[data-annotation-id]").on("click", "[data-annotation-id]", App.LegislationAnnotatable.onClick)
+ $(document).off("click", "[data-cancel-annotation]").on("click", "[data-cancel-annotation]", (e) ->
e.preventDefault()
- $('#comments-box').html('')
- $('#comments-box').hide()
+ $("#comments-box").html("")
+ $("#comments-box").hide()
App.LegislationAnnotatable.remove_highlight()
return
)
- current_user_id = $('html').data('current-user-id')
+ current_user_id = $("html").data("current-user-id")
$(".legislation-annotatable").each ->
$this = $(this)
diff --git a/app/assets/javascripts/location_changer.js.coffee b/app/assets/javascripts/location_changer.js.coffee
index 54693633d..630cd1b11 100644
--- a/app/assets/javascripts/location_changer.js.coffee
+++ b/app/assets/javascripts/location_changer.js.coffee
@@ -1,8 +1,5 @@
App.LocationChanger =
initialize: ->
- $('.js-location-changer').on 'change', ->
+ $(".js-location-changer").on "change", ->
window.location.assign($(this).val())
-
-
-
diff --git a/app/assets/javascripts/managers.js.coffee b/app/assets/javascripts/managers.js.coffee
index 7d4d702a1..60eab58e9 100644
--- a/app/assets/javascripts/managers.js.coffee
+++ b/app/assets/javascripts/managers.js.coffee
@@ -1,8 +1,8 @@
App.Managers =
generatePassword: ->
- chars = 'aAbcdeEfghiJkmnpqrstuUvwxyz23456789'
- pass = ''
+ chars = "aAbcdeEfghiJkmnpqrstuUvwxyz23456789"
+ pass = ""
x = 0
while x < 12
i = Math.floor(Math.random() * chars.length)
@@ -11,15 +11,15 @@ App.Managers =
return pass
togglePassword: (type) ->
- $('#user_password').prop 'type', type
+ $("#user_password").prop "type", type
initialize: ->
$(".generate-random-value").on "click", (event) ->
password = App.Managers.generatePassword()
- $('#user_password').val(password)
+ $("#user_password").val(password)
$(".show-password").on "click", (event) ->
if $("#user_password").is("input[type='password']")
- App.Managers.togglePassword('text')
+ App.Managers.togglePassword("text")
else
- App.Managers.togglePassword('password')
+ App.Managers.togglePassword("password")
diff --git a/app/assets/javascripts/map.js.coffee b/app/assets/javascripts/map.js.coffee
index 241093d75..bed9019c8 100644
--- a/app/assets/javascripts/map.js.coffee
+++ b/app/assets/javascripts/map.js.coffee
@@ -1,44 +1,45 @@
App.Map =
initialize: ->
- maps = $('*[data-map]')
+ maps = $("*[data-map]")
if maps.length > 0
$.each maps, (index, map) ->
App.Map.initializeMap map
- $('.js-toggle-map').on
- click: ->
- App.Map.toggleMap()
+ $(".js-toggle-map").on
+ click: ->
+ App.Map.toggleMap()
initializeMap: (element) ->
App.Map.cleanInvestmentCoordinates(element)
- mapCenterLatitude = $(element).data('map-center-latitude')
- mapCenterLongitude = $(element).data('map-center-longitude')
- markerLatitude = $(element).data('marker-latitude')
- markerLongitude = $(element).data('marker-longitude')
- zoom = $(element).data('map-zoom')
- mapTilesProvider = $(element).data('map-tiles-provider')
- mapAttribution = $(element).data('map-tiles-provider-attribution')
- latitudeInputSelector = $(element).data('latitude-input-selector')
- longitudeInputSelector = $(element).data('longitude-input-selector')
- zoomInputSelector = $(element).data('zoom-input-selector')
- removeMarkerSelector = $(element).data('marker-remove-selector')
- addMarkerInvestments = $(element).data('marker-investments-coordinates')
- editable = $(element).data('marker-editable')
- marker = null;
+ mapCenterLatitude = $(element).data("map-center-latitude")
+ mapCenterLongitude = $(element).data("map-center-longitude")
+ markerLatitude = $(element).data("marker-latitude")
+ markerLongitude = $(element).data("marker-longitude")
+ zoom = $(element).data("map-zoom")
+ mapTilesProvider = $(element).data("map-tiles-provider")
+ mapAttribution = $(element).data("map-tiles-provider-attribution")
+ latitudeInputSelector = $(element).data("latitude-input-selector")
+ longitudeInputSelector = $(element).data("longitude-input-selector")
+ zoomInputSelector = $(element).data("zoom-input-selector")
+ removeMarkerSelector = $(element).data("marker-remove-selector")
+ addMarkerInvestments = $(element).data("marker-investments-coordinates")
+ editable = $(element).data("marker-editable")
+ marker = null
markerIcon = L.divIcon(
- className: 'map-marker'
- iconSize: [30, 30]
- iconAnchor: [15, 40]
- html: '')
+ className: "map-marker"
+ iconSize: [30, 30]
+ iconAnchor: [15, 40]
+ html: ''
+ )
createMarker = (latitude, longitude) ->
markerLatLng = new (L.LatLng)(latitude, longitude)
marker = L.marker(markerLatLng, { icon: markerIcon, draggable: editable })
if editable
- marker.on 'dragend', updateFormfields
+ marker.on "dragend", updateFormfields
marker.addTo(map)
return marker
@@ -46,7 +47,7 @@ App.Map =
e.preventDefault()
if marker
map.removeLayer(marker)
- marker = null;
+ marker = null
clearFormfields()
return
@@ -66,22 +67,22 @@ App.Map =
return
clearFormfields = ->
- $(latitudeInputSelector).val ''
- $(longitudeInputSelector).val ''
- $(zoomInputSelector).val ''
+ $(latitudeInputSelector).val ""
+ $(longitudeInputSelector).val ""
+ $(zoomInputSelector).val ""
return
openMarkerPopup = (e) ->
marker = e.target
- $.ajax 'investments/' + marker.options['id'] + '/json_data',
- type: 'GET'
- dataType: 'json'
+ $.ajax "/investments/#{marker.options["id"]}/json_data",
+ type: "GET"
+ dataType: "json"
success: (data) ->
e.target.bindPopup(getPopupContent(data)).openPopup()
getPopupContent = (data) ->
- content = "#{data['investment_title']}"
+ content = "#{data["investment_title"]}"
return content
mapCenterLatLng = new (L.LatLng)(mapCenterLatitude, mapCenterLongitude)
@@ -92,27 +93,27 @@ App.Map =
marker = createMarker(markerLatitude, markerLongitude)
if editable
- $(removeMarkerSelector).on 'click', removeMarker
- map.on 'zoomend', updateFormfields
- map.on 'click', moveOrPlaceMarker
+ $(removeMarkerSelector).on "click", removeMarker
+ map.on "zoomend", updateFormfields
+ map.on "click", moveOrPlaceMarker
if addMarkerInvestments
for i in addMarkerInvestments
if App.Map.validCoordinates(i)
marker = createMarker(i.lat, i.long)
- marker.options['id'] = i.investment_id
+ marker.options["id"] = i.investment_id
- marker.on 'click', openMarkerPopup
+ marker.on "click", openMarkerPopup
toggleMap: ->
- $('.map').toggle()
- $('.js-location-map-remove-marker').toggle()
+ $(".map").toggle()
+ $(".js-location-map-remove-marker").toggle()
cleanInvestmentCoordinates: (element) ->
- markers = $(element).attr('data-marker-investments-coordinates')
+ markers = $(element).attr("data-marker-investments-coordinates")
if markers?
clean_markers = markers.replace(/-?(\*+)/g, null)
- $(element).attr('data-marker-investments-coordinates', clean_markers)
+ $(element).attr("data-marker-investments-coordinates", clean_markers)
validCoordinates: (coordinates) ->
App.Map.isNumeric(coordinates.lat) && App.Map.isNumeric(coordinates.long)
diff --git a/app/assets/javascripts/markdown_editor.js.coffee b/app/assets/javascripts/markdown_editor.js.coffee
index 29e74e51c..b3dc7c14e 100644
--- a/app/assets/javascripts/markdown_editor.js.coffee
+++ b/app/assets/javascripts/markdown_editor.js.coffee
@@ -3,15 +3,15 @@ App.MarkdownEditor =
refresh_preview: (element, md) ->
textarea_content = App.MarkdownEditor.find_textarea(element).val()
result = md.render(textarea_content)
- element.find('#markdown-preview').html(result)
+ element.find(".markdown-preview").html(result)
# Multi-locale (translatable) form fields work by hiding inputs of locales
# which are not "active".
find_textarea: (editor) ->
- editor.find('textarea:visible')
+ editor.find("textarea")
initialize: ->
- $('.markdown-editor').each ->
+ $(".markdown-editor").each ->
md = window.markdownit({
html: true,
breaks: true,
@@ -20,25 +20,25 @@ App.MarkdownEditor =
editor = $(this)
- editor.on 'input', ->
+ editor.on "input", ->
App.MarkdownEditor.refresh_preview($(this), md)
- $('.legislation-draft-versions-edit .warning').show()
+ $(".legislation-draft-versions-edit .warning").show()
return
- editor.find('textarea').on 'scroll', ->
- $('#markdown-preview').scrollTop($(this).scrollTop())
+ editor.find("textarea").on "scroll", ->
+ editor.find(".markdown-preview").scrollTop($(this).scrollTop())
- editor.find('.fullscreen-toggle').on 'click', ->
- editor.toggleClass('fullscreen')
- $('.fullscreen-container').toggleClass('medium-8', 'medium-12')
- span = $(this).find('span')
+ editor.find(".fullscreen-toggle").on "click", ->
+ editor.toggleClass("fullscreen")
+ $(".fullscreen-container").toggleClass("medium-8", "medium-12")
+ span = $(this).find("span")
current_html = span.html()
- if(current_html == span.data('open-text'))
- span.html(span.data('closed-text'))
+ if(current_html == span.data("open-text"))
+ span.html(span.data("closed-text"))
else
- span.html(span.data('open-text'))
+ span.html(span.data("open-text"))
- if editor.hasClass('fullscreen')
+ if editor.hasClass("fullscreen")
App.MarkdownEditor.find_textarea(editor).height($(window).height() - 100)
App.MarkdownEditor.refresh_preview(editor, md)
else
diff --git a/app/assets/javascripts/polls.js.coffee b/app/assets/javascripts/polls.js.coffee
index ac2c759ba..d5402d46b 100644
--- a/app/assets/javascripts/polls.js.coffee
+++ b/app/assets/javascripts/polls.js.coffee
@@ -1,16 +1,16 @@
App.Polls =
generateToken: ->
- token = ''
- rand = ''
+ token = ""
+ rand = ""
for n in [0..5]
rand = Math.random().toString(36).substr(2) # remove `0.`
- token = token + rand;
+ token = token + rand
token = token.substring(0, 64)
return token
replaceToken: ->
- for link in $('.js-question-answer')
+ for link in $(".js-question-answer")
token_param = link.search.slice(-6)
if token_param == "token="
link.href = link.href + @token
@@ -22,23 +22,22 @@ App.Polls =
$(".js-question-answer").on
click: =>
token_message = $(".js-token-message")
- if !token_message.is(':visible')
- token_message.html(token_message.html() + "
" + @token + "");
+ if !token_message.is(":visible")
+ token_message.html("#{token_message.html()}
#{@token}")
token_message.show()
false
$(".zoom-link").on "click", (event) ->
element = event.target
- answer = $(element).closest('div.answer')
+ answer = $(element).closest("div.answer")
- if $(answer).hasClass('medium-6')
- $(answer).removeClass("medium-6");
- $(answer).addClass("answer-divider");
- unless $(answer).hasClass('first')
- $(answer).insertBefore($(answer).prev('div.answer'));
+ if $(answer).hasClass("medium-6")
+ $(answer).removeClass("medium-6")
+ $(answer).addClass("answer-divider")
+ unless $(answer).hasClass("first")
+ $(answer).insertBefore($(answer).prev("div.answer"))
else
- $(answer).addClass("medium-6");
- $(answer).removeClass("answer-divider");
- unless $(answer).hasClass('first')
- $(answer).insertAfter($(answer).next('div.answer'));
-
+ $(answer).addClass("medium-6")
+ $(answer).removeClass("answer-divider")
+ unless $(answer).hasClass("first")
+ $(answer).insertAfter($(answer).next("div.answer"))
diff --git a/app/assets/javascripts/polls_admin.js.coffee b/app/assets/javascripts/polls_admin.js.coffee
index ef1dd44f1..343a7c255 100644
--- a/app/assets/javascripts/polls_admin.js.coffee
+++ b/app/assets/javascripts/polls_admin.js.coffee
@@ -4,9 +4,9 @@ App.PollsAdmin =
$("select[class='js-poll-shifts']").on
change: ->
switch ($(this).val())
- when 'vote_collection'
- $("select[class='js-shift-vote-collection-dates']").show();
- $("select[class='js-shift-recount-scrutiny-dates']").hide();
- when 'recount_scrutiny'
- $("select[class='js-shift-recount-scrutiny-dates']").show();
- $("select[class='js-shift-vote-collection-dates']").hide();
+ when "vote_collection"
+ $("select[class='js-shift-vote-collection-dates']").show()
+ $("select[class='js-shift-recount-scrutiny-dates']").hide()
+ when "recount_scrutiny"
+ $("select[class='js-shift-recount-scrutiny-dates']").show()
+ $("select[class='js-shift-vote-collection-dates']").hide()
diff --git a/app/assets/javascripts/prevent_double_submission.js.coffee b/app/assets/javascripts/prevent_double_submission.js.coffee
index 5f080ddfe..c47b40b70 100644
--- a/app/assets/javascripts/prevent_double_submission.js.coffee
+++ b/app/assets/javascripts/prevent_double_submission.js.coffee
@@ -3,35 +3,35 @@ App.PreventDoubleSubmission =
setTimeout ->
buttons.each ->
button = $(this)
- unless button.hasClass('disabled')
- loading = button.data('loading') ? '...'
- button.addClass('disabled').attr('disabled', 'disabled')
- button.data('text', button.val())
+ unless button.hasClass("disabled")
+ loading = button.data("loading") ? "..."
+ button.addClass("disabled").attr("disabled", "disabled")
+ button.data("text", button.val())
button.val(loading)
, 1
reset_buttons: (buttons) ->
buttons.each ->
button = $(this)
- if button.hasClass('disabled')
- button_text = button.data('text')
- button.removeClass('disabled').attr('disabled', null)
+ if button.hasClass("disabled")
+ button_text = button.data("text")
+ button.removeClass("disabled").attr("disabled", null)
if button_text
button.val(button_text)
- button.data('text', null)
+ button.data("text", null)
initialize: ->
- $('form').on('submit', (event) ->
- unless event.target.id == "new_officing_voter" ||
+ $("form").on("submit", (event) ->
+ unless event.target.id == "new_officing_voter" ||
event.target.id == "admin_download_emails"
- buttons = $(this).find(':button, :submit')
+ buttons = $(this).find(":button, :submit")
App.PreventDoubleSubmission.disable_buttons(buttons)
- ).on('ajax:success', (event) ->
- unless event.target.id == "new_officing_voter" ||
+ ).on("ajax:success", (event) ->
+ unless event.target.id == "new_officing_voter" ||
event.target.id == "admin_download_emails"
-
- buttons = $(this).find(':button, :submit')
+
+ buttons = $(this).find(":button, :submit")
App.PreventDoubleSubmission.reset_buttons(buttons)
)
diff --git a/app/assets/javascripts/send_admin_notification_alert.js.coffee b/app/assets/javascripts/send_admin_notification_alert.js.coffee
index 8c1c928e5..c2c9f1195 100644
--- a/app/assets/javascripts/send_admin_notification_alert.js.coffee
+++ b/app/assets/javascripts/send_admin_notification_alert.js.coffee
@@ -1,4 +1,4 @@
App.SendAdminNotificationAlert =
initialize: ->
- $('#js-send-admin_notification-alert').on 'click', ->
- confirm(this.dataset.alert);
+ $("#js-send-admin_notification-alert").on "click", ->
+ confirm(this.dataset.alert)
diff --git a/app/assets/javascripts/send_newsletter_alert.js.coffee b/app/assets/javascripts/send_newsletter_alert.js.coffee
index 3b06a30ff..e8e3e5f2a 100644
--- a/app/assets/javascripts/send_newsletter_alert.js.coffee
+++ b/app/assets/javascripts/send_newsletter_alert.js.coffee
@@ -1,4 +1,4 @@
App.SendNewsletterAlert =
initialize: ->
- $('#js-send-newsletter-alert').on 'click', ->
- confirm(this.dataset.alert);
+ $("#js-send-newsletter-alert").on "click", ->
+ confirm(this.dataset.alert)
diff --git a/app/assets/javascripts/settings.js.coffee b/app/assets/javascripts/settings.js.coffee
new file mode 100644
index 000000000..beb70d7af
--- /dev/null
+++ b/app/assets/javascripts/settings.js.coffee
@@ -0,0 +1,10 @@
+App.Settings =
+
+ initialize: ->
+
+ $("#settings-tabs").on "change.zf.tabs", ->
+ if $("#tab-map-configuration:visible").length
+ map_container = L.DomUtil.get "admin-map"
+ unless map_container is null
+ map_container._leaflet_id = null
+ App.Map.initialize()
diff --git a/app/assets/javascripts/social_share.js.coffee b/app/assets/javascripts/social_share.js.coffee
index 823488fe8..5776fd555 100644
--- a/app/assets/javascripts/social_share.js.coffee
+++ b/app/assets/javascripts/social_share.js.coffee
@@ -3,5 +3,5 @@ App.SocialShare =
initialize: ->
$(".social-share-button a").each ->
element = $(this)
- site = element.data('site')
- element.append("#{site}")
\ No newline at end of file
+ site = element.data("site")
+ element.append("#{site}")
diff --git a/app/assets/javascripts/sortable.js.coffee b/app/assets/javascripts/sortable.js.coffee
index 1af543f6a..61124264e 100644
--- a/app/assets/javascripts/sortable.js.coffee
+++ b/app/assets/javascripts/sortable.js.coffee
@@ -2,8 +2,8 @@ App.Sortable =
initialize: ->
$(".sortable").sortable
update: (event, ui) ->
- new_order = $(this).sortable('toArray', {attribute: 'data-answer-id'});
+ new_order = $(this).sortable("toArray", { attribute: "data-answer-id" })
$.ajax
- url: $('.sortable').data('js-url'),
- data: {ordered_list: new_order},
- type: 'POST'
+ url: $(".sortable").data("js-url"),
+ data: { ordered_list: new_order },
+ type: "POST"
diff --git a/app/assets/javascripts/stat_graphs.js b/app/assets/javascripts/stat_graphs.js
index c5bc5b538..256078a85 100644
--- a/app/assets/javascripts/stat_graphs.js
+++ b/app/assets/javascripts/stat_graphs.js
@@ -9,6 +9,6 @@ var initialize_stats_modules = function() {
$(function(){
$(document).ready(initialize_stats_modules);
- $(document).on('page:load', initialize_stats_modules);
- $(document).on('ajax:complete', initialize_stats_modules);
+ $(document).on("page:load", initialize_stats_modules);
+ $(document).on("ajax:complete", initialize_stats_modules);
});
diff --git a/app/assets/javascripts/stats.js.coffee b/app/assets/javascripts/stats.js.coffee
index 7fcdfb00a..56987c27a 100644
--- a/app/assets/javascripts/stats.js.coffee
+++ b/app/assets/javascripts/stats.js.coffee
@@ -2,8 +2,8 @@
#----------------------------------------------------------------------
buildGraph = (el) ->
- url = $(el).data 'graph'
- conf = bindto: el, data: {x: 'x', url: url, mimeType: 'json'}, axis: { x: {type: 'timeseries',tick: { format: '%Y-%m-%d' } }}
+ url = $(el).data "graph"
+ conf = bindto: el, data: { x: "x", url: url, mimeType: "json" }, axis: { x: { type: "timeseries", tick: { format: "%Y-%m-%d" } } }
graph = c3.generate conf
App.Stats =
diff --git a/app/assets/javascripts/suggest.js.coffee b/app/assets/javascripts/suggest.js.coffee
index de42fd998..854f7ccf1 100644
--- a/app/assets/javascripts/suggest.js.coffee
+++ b/app/assets/javascripts/suggest.js.coffee
@@ -2,24 +2,24 @@ App.Suggest =
initialize: ->
- $('[data-js-suggest-result]').each ->
+ $("[data-js-suggest-result]").each ->
$this = $(this)
callback = ->
$.ajax
- url: $this.data('js-url')
- data: {search: $this.val()},
- type: 'GET',
- dataType: 'html'
+ url: $this.data("js-url")
+ data: { search: $this.val() },
+ type: "GET",
+ dataType: "html"
success: (stHtml) ->
- js_suggest_selector = $this.data('js-suggest')
+ js_suggest_selector = $this.data("js-suggest")
$(js_suggest_selector).html(stHtml)
timer = null
- $this.on 'keyup', ->
+ $this.on "keyup", ->
window.clearTimeout(timer)
timer = window.setTimeout(callback, 1000)
- $this.on 'change', callback
+ $this.on "change", callback
diff --git a/app/assets/javascripts/table_sortable.js.coffee b/app/assets/javascripts/table_sortable.js.coffee
index 331f794a4..cc2b6adaa 100644
--- a/app/assets/javascripts/table_sortable.js.coffee
+++ b/app/assets/javascripts/table_sortable.js.coffee
@@ -1,6 +1,6 @@
App.TableSortable =
getCellValue: (row, index) ->
- $(row).children('td').eq(index).text()
+ $(row).children("td").eq(index).text()
comparer: (index) ->
(a, b) ->
@@ -9,9 +9,9 @@ App.TableSortable =
return if $.isNumeric(valA) and $.isNumeric(valB) then valA - valB else valA.localeCompare(valB)
initialize: ->
- $('table.sortable th').click ->
- table = $(this).parents('table').eq(0)
- rows = table.find('tr:gt(0)').not('tfoot tr').toArray().sort(App.TableSortable.comparer($(this).index()))
+ $("table.sortable th").click ->
+ table = $(this).parents("table").eq(0)
+ rows = table.find("tr:gt(0)").not("tfoot tr").toArray().sort(App.TableSortable.comparer($(this).index()))
@asc = !@asc
if !@asc
rows = rows.reverse()
@@ -20,4 +20,3 @@ App.TableSortable =
table.append rows[i]
i++
return
-
\ No newline at end of file
diff --git a/app/assets/javascripts/tag_autocomplete.js.coffee b/app/assets/javascripts/tag_autocomplete.js.coffee
index be27cd81c..73c1b31f3 100644
--- a/app/assets/javascripts/tag_autocomplete.js.coffee
+++ b/app/assets/javascripts/tag_autocomplete.js.coffee
@@ -7,28 +7,28 @@ App.TagAutocomplete =
return (App.TagAutocomplete.split( term ).pop())
init_autocomplete: ->
- $('.tag-autocomplete').autocomplete
+ $(".tag-autocomplete").autocomplete
source: (request, response) ->
$.ajax
- url: $('.tag-autocomplete').data('js-url'),
- data: {search: App.TagAutocomplete.extractLast( request.term )},
- type: 'GET',
- dataType: 'json'
+ url: $(".tag-autocomplete").data("js-url"),
+ data: { search: App.TagAutocomplete.extractLast( request.term ) },
+ type: "GET",
+ dataType: "json"
success: ( data ) ->
- response( data );
+ response( data )
minLength: 0,
search: ->
- App.TagAutocomplete.extractLast( this.value );
+ App.TagAutocomplete.extractLast( this.value )
focus: ->
- return false;
+ return false
select: ( event, ui ) -> (
- terms = App.TagAutocomplete.split( this.value );
- terms.pop();
- terms.push( ui.item.value );
- terms.push( "" );
- this.value = terms.join( ", " );
- return false;);
+ terms = App.TagAutocomplete.split( this.value )
+ terms.pop()
+ terms.push( ui.item.value )
+ terms.push( "" )
+ this.value = terms.join( ", " )
+ return false;)
initialize: ->
- App.TagAutocomplete.init_autocomplete();
\ No newline at end of file
+ App.TagAutocomplete.init_autocomplete()
diff --git a/app/assets/javascripts/tags.js.coffee b/app/assets/javascripts/tags.js.coffee
index 6e3c7165c..bdabac7fd 100644
--- a/app/assets/javascripts/tags.js.coffee
+++ b/app/assets/javascripts/tags.js.coffee
@@ -1,21 +1,21 @@
App.Tags =
initialize: ->
- $tag_input = $('input.js-tag-list')
+ $tag_input = $("input.js-tag-list")
- $('body .js-add-tag-link').each ->
+ $("body .js-add-tag-link").each ->
$this = $(this)
- unless $this.data('initialized') is 'yes'
- $this.on('click', ->
- name = $(this).text()
- current_tags = $tag_input.val().split(',').filter(Boolean)
+ unless $this.data("initialized") is "yes"
+ $this.on("click", ->
+ name = "\"#{$(this).text()}\""
+ current_tags = $tag_input.val().split(",").filter(Boolean)
if $.inArray(name, current_tags) >= 0
current_tags.splice($.inArray(name, current_tags), 1)
else
current_tags.push name
- $tag_input.val(current_tags.join(','))
+ $tag_input.val(current_tags.join(","))
false
- ).data 'initialized', 'yes'
+ ).data "initialized", "yes"
diff --git a/app/assets/javascripts/tracks.js.coffee b/app/assets/javascripts/tracks.js.coffee
index 74fc305e8..e3f44e7f1 100644
--- a/app/assets/javascripts/tracks.js.coffee
+++ b/app/assets/javascripts/tracks.js.coffee
@@ -4,25 +4,25 @@ App.Tracks =
_paq?
set_custom_var: (id, name, value, scope) ->
- _paq.push(['setCustomVariable', id, name, value, scope])
- _paq.push(['trackPageView'])
+ _paq.push(["setCustomVariable", id, name, value, scope])
+ _paq.push(["trackPageView"])
track_event: ($this) ->
- category = $this.data('track-event-category')
- action = $this.data('track-event-action')
- _paq.push(['trackEvent', category, action])
+ category = $this.data("track-event-category")
+ action = $this.data("track-event-action")
+ _paq.push(["trackEvent", category, action])
initialize: ->
if App.Tracks.tracking_enabled()
- $('[data-track-usertype]').each ->
+ $("[data-track-usertype]").each ->
$this = $(this)
- usertype = $this.data('track-usertype')
+ usertype = $this.data("track-usertype")
App.Tracks.set_custom_var(1, "usertype", usertype, "visit")
- $('[data-track-event-category]').each ->
+ $("[data-track-event-category]").each ->
$this = $(this)
App.Tracks.track_event($this)
- $('[data-track-click]').on 'click', ->
+ $("[data-track-click]").on "click", ->
$this = $(this)
App.Tracks.track_event($this)
diff --git a/app/assets/javascripts/tree_navigator.js.coffee b/app/assets/javascripts/tree_navigator.js.coffee
index 385d1bbbd..bd7192caf 100644
--- a/app/assets/javascripts/tree_navigator.js.coffee
+++ b/app/assets/javascripts/tree_navigator.js.coffee
@@ -1,37 +1,36 @@
App.TreeNavigator =
setNodes: (nodes) ->
- children = nodes.children('ul')
+ children = nodes.children("ul")
if(children.length == 0)
return
children.each ->
- link = $(this).prev('a')
+ link = $(this).prev("a")
$('').insertBefore(link)
App.TreeNavigator.setNodes($(this).children())
initialize: ->
- elem = $('[data-tree-navigator]')
+ elem = $("[data-tree-navigator]")
if(elem.length == 0)
return
- ul = elem.find('ul:eq(0)')
+ ul = elem.find("ul:eq(0)")
if(ul.length && ul.children().length)
App.TreeNavigator.setNodes(ul.children())
- $('[data-tree-navigator] span').on
+ $("[data-tree-navigator] span").on
click: (e) ->
elem = $(this)
- if(elem.hasClass('open'))
- elem.removeClass('open').addClass('closed')
- elem.siblings('ul').hide()
- else if(elem.hasClass('closed'))
- elem.removeClass('closed').addClass('open')
- elem.siblings('ul').show()
+ if(elem.hasClass("open"))
+ elem.removeClass("open").addClass("closed")
+ elem.siblings("ul").hide()
+ else if(elem.hasClass("closed"))
+ elem.removeClass("closed").addClass("open")
+ elem.siblings("ul").show()
- if anchor = $(location).attr('hash')
- if link = elem.find('a[href="' + anchor + '"]')
- link.parents('ul').each ->
+ if anchor = $(location).attr("hash")
+ if link = elem.find("a[href='#{anchor}']")
+ link.parents("ul").each ->
$(this).show()
- $(this).siblings('span').removeClass('closed').addClass('open')
-
+ $(this).siblings("span").removeClass("closed").addClass("open")
diff --git a/app/assets/javascripts/users.js.coffee b/app/assets/javascripts/users.js.coffee
index 2b1bc15de..cae04abaf 100644
--- a/app/assets/javascripts/users.js.coffee
+++ b/app/assets/javascripts/users.js.coffee
@@ -1,5 +1,5 @@
App.Users =
initialize: ->
- $('.initialjs-avatar').initial()
+ $(".initialjs-avatar").initial()
false
diff --git a/app/assets/javascripts/valuation_budget_investment_form.js.coffee b/app/assets/javascripts/valuation_budget_investment_form.js.coffee
index d79ff600e..6e9910cb3 100644
--- a/app/assets/javascripts/valuation_budget_investment_form.js.coffee
+++ b/app/assets/javascripts/valuation_budget_investment_form.js.coffee
@@ -1,22 +1,22 @@
App.ValuationBudgetInvestmentForm =
showFeasibleFields: ->
- $('#valuation_budget_investment_edit_form #unfeasible_fields').hide('down')
- $('#valuation_budget_investment_edit_form #feasible_fields').show()
+ $("#valuation_budget_investment_edit_form #unfeasible_fields").hide("down")
+ $("#valuation_budget_investment_edit_form #feasible_fields").show()
showNotFeasibleFields: ->
- $('#valuation_budget_investment_edit_form #feasible_fields').hide('down')
- $('#valuation_budget_investment_edit_form #unfeasible_fields').show()
+ $("#valuation_budget_investment_edit_form #feasible_fields").hide("down")
+ $("#valuation_budget_investment_edit_form #unfeasible_fields").show()
showAllFields: ->
- $('#valuation_budget_investment_edit_form #feasible_fields').show('down')
- $('#valuation_budget_investment_edit_form #unfeasible_fields').show('down')
+ $("#valuation_budget_investment_edit_form #feasible_fields").show("down")
+ $("#valuation_budget_investment_edit_form #unfeasible_fields").show("down")
showFeasibilityFields: ->
feasibility = $("#valuation_budget_investment_edit_form input[type=radio][name='budget_investment[feasibility]']:checked").val()
- if feasibility == 'feasible'
+ if feasibility == "feasible"
App.ValuationBudgetInvestmentForm.showFeasibleFields()
- else if feasibility == 'unfeasible'
+ else if feasibility == "unfeasible"
App.ValuationBudgetInvestmentForm.showNotFeasibleFields()
@@ -29,4 +29,4 @@ App.ValuationBudgetInvestmentForm =
initialize: ->
App.ValuationBudgetInvestmentForm.showFeasibilityFields()
App.ValuationBudgetInvestmentForm.showFeasibilityFieldsOnChange()
- false
\ No newline at end of file
+ false
diff --git a/app/assets/javascripts/valuation_spending_proposal_form.js.coffee b/app/assets/javascripts/valuation_spending_proposal_form.js.coffee
index fa0bc2106..804077287 100644
--- a/app/assets/javascripts/valuation_spending_proposal_form.js.coffee
+++ b/app/assets/javascripts/valuation_spending_proposal_form.js.coffee
@@ -1,22 +1,22 @@
App.ValuationSpendingProposalForm =
showFeasibleFields: ->
- $('#valuation_spending_proposal_edit_form #not_feasible_fields').hide('down')
- $('#valuation_spending_proposal_edit_form #feasible_fields').show()
+ $("#valuation_spending_proposal_edit_form #not_feasible_fields").hide("down")
+ $("#valuation_spending_proposal_edit_form #feasible_fields").show()
showNotFeasibleFields: ->
- $('#valuation_spending_proposal_edit_form #feasible_fields').hide('down')
- $('#valuation_spending_proposal_edit_form #not_feasible_fields').show()
+ $("#valuation_spending_proposal_edit_form #feasible_fields").hide("down")
+ $("#valuation_spending_proposal_edit_form #not_feasible_fields").show()
showAllFields: ->
- $('#valuation_spending_proposal_edit_form #feasible_fields').show('down')
- $('#valuation_spending_proposal_edit_form #not_feasible_fields').show('down')
+ $("#valuation_spending_proposal_edit_form #feasible_fields").show("down")
+ $("#valuation_spending_proposal_edit_form #not_feasible_fields").show("down")
showFeasibilityFields: ->
feasible = $("#valuation_spending_proposal_edit_form input[type=radio][name='spending_proposal[feasible]']:checked").val()
- if feasible == 'true'
+ if feasible == "true"
App.ValuationSpendingProposalForm.showFeasibleFields()
- else if feasible == 'false'
+ else if feasible == "false"
App.ValuationSpendingProposalForm.showNotFeasibleFields()
@@ -29,4 +29,4 @@ App.ValuationSpendingProposalForm =
initialize: ->
App.ValuationSpendingProposalForm.showFeasibilityFields()
App.ValuationSpendingProposalForm.showFeasibilityFieldsOnChange()
- false
\ No newline at end of file
+ false
diff --git a/app/assets/javascripts/votes.js.coffee b/app/assets/javascripts/votes.js.coffee
index 9176fea1a..003187bca 100644
--- a/app/assets/javascripts/votes.js.coffee
+++ b/app/assets/javascripts/votes.js.coffee
@@ -2,7 +2,7 @@ App.Votes =
hoverize: (votes) ->
$(document).on {
- 'mouseenter focus': ->
+ "mouseenter focus": ->
$("div.participation-not-allowed", this).show()
$("div.participation-allowed", this).hide()
mouseleave: ->
diff --git a/app/assets/javascripts/watch_form_changes.js.coffee b/app/assets/javascripts/watch_form_changes.js.coffee
index eaf125ded..693a68d0e 100644
--- a/app/assets/javascripts/watch_form_changes.js.coffee
+++ b/app/assets/javascripts/watch_form_changes.js.coffee
@@ -1,16 +1,16 @@
App.WatchFormChanges =
forms: ->
- return $('form[data-watch-changes]')
+ return $("form[data-watch-changes]")
msg: ->
- if($('[data-watch-form-message]').length)
- return $('[data-watch-form-message]').data('watch-form-message')
+ if($("[data-watch-form-message]").length)
+ return $("[data-watch-form-message]").data("watch-form-message")
checkChanges: (event) ->
changes = false
App.WatchFormChanges.forms().each ->
form = $(this)
- if form.serialize() != form.data('watchChanges')
+ if form.serialize() != form.data("watchChanges")
changes = true
if changes
return confirm(App.WatchFormChanges.msg())
@@ -21,10 +21,10 @@ App.WatchFormChanges =
if App.WatchFormChanges.forms().length == 0 || App.WatchFormChanges.msg() == undefined
return
- $(document).off('page:before-change').on('page:before-change', (e) -> App.WatchFormChanges.checkChanges(e))
+ $(document).off("page:before-change").on("page:before-change", (e) -> App.WatchFormChanges.checkChanges(e))
App.WatchFormChanges.forms().each ->
form = $(this)
- form.data('watchChanges', form.serialize())
+ form.data("watchChanges", form.serialize())
false
diff --git a/app/assets/stylesheets/_consul_settings.scss b/app/assets/stylesheets/_consul_settings.scss
index 9e8af3615..7ffd8ae4f 100644
--- a/app/assets/stylesheets/_consul_settings.scss
+++ b/app/assets/stylesheets/_consul_settings.scss
@@ -74,7 +74,7 @@ $pdf-secondary: #ff9e00;
$black: #222;
$white: #fff;
-$body-font-family: 'Source Sans Pro', 'Helvetica', 'Arial', sans-serif !important;
+$body-font-family: "Source Sans Pro", "Helvetica", "Arial", sans-serif !important;
$header-font-family: $body-font-family;
@@ -82,24 +82,24 @@ $global-radius: rem-calc(3);
$button-radius: $global-radius;
-$font-family-serif: Georgia, 'Times New Roman', Times, serif;
+$font-family-serif: Georgia, "Times New Roman", Times, serif;
$header-styles: (
small: (
- 'h1': ('font-size': 34),
- 'h2': ('font-size': 24),
- 'h3': ('font-size': 20),
- 'h4': ('font-size': 18),
- 'h5': ('font-size': 16),
- 'h6': ('font-size': 14),
+ "h1": ("font-size": 34),
+ "h2": ("font-size": 24),
+ "h3": ("font-size": 20),
+ "h4": ("font-size": 18),
+ "h5": ("font-size": 16),
+ "h6": ("font-size": 14),
),
medium: (
- 'h1': ('font-size': 44),
- 'h2': ('font-size': 34),
- 'h3': ('font-size': 24),
- 'h4': ('font-size': 19),
- 'h5': ('font-size': 16),
- 'h6': ('font-size': 13),
+ "h1": ("font-size": 44),
+ "h2": ("font-size": 34),
+ "h3": ("font-size": 24),
+ "h4": ("font-size": 19),
+ "h5": ("font-size": 16),
+ "h6": ("font-size": 13),
),
);
diff --git a/app/assets/stylesheets/_settings.scss b/app/assets/stylesheets/_settings.scss
index 296cccde6..305ca3d64 100644
--- a/app/assets/stylesheets/_settings.scss
+++ b/app/assets/stylesheets/_settings.scss
@@ -60,7 +60,7 @@
// 55. Top Bar
// 56. Xy Grid
-@import 'util/util';
+@import "util/util";
// 1. Global
// ---------
@@ -82,7 +82,7 @@ $black: #0a0a0a;
$white: #fefefe;
$body-background: $white;
$body-font-color: $black;
-$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;
+$body-font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;
$body-antialiased: true;
$global-margin: 1rem;
$global-padding: 1rem;
@@ -124,7 +124,7 @@ $grid-column-gutter: (
medium: 30px,
);
$grid-column-align-edge: true;
-$grid-column-alias: 'columns';
+$grid-column-alias: "columns";
$block-grid-max: 8;
// 4. Base Typography
@@ -133,26 +133,26 @@ $block-grid-max: 8;
$header-font-family: $body-font-family;
$header-font-weight: $global-weight-normal;
$header-font-style: normal;
-$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace;
+$font-family-monospace: Consolas, "Liberation Mono", Courier, monospace;
$header-color: inherit;
$header-lineheight: 1.4;
$header-margin-bottom: 0.5rem;
$header-styles: (
small: (
- 'h1': ('font-size': 24),
- 'h2': ('font-size': 20),
- 'h3': ('font-size': 19),
- 'h4': ('font-size': 18),
- 'h5': ('font-size': 17),
- 'h6': ('font-size': 16),
+ "h1": ("font-size": 24),
+ "h2": ("font-size": 20),
+ "h3": ("font-size": 19),
+ "h4": ("font-size": 18),
+ "h5": ("font-size": 17),
+ "h6": ("font-size": 16),
),
medium: (
- 'h1': ('font-size': 48),
- 'h2': ('font-size': 40),
- 'h3': ('font-size': 31),
- 'h4': ('font-size': 25),
- 'h5': ('font-size': 20),
- 'h6': ('font-size': 16),
+ "h1": ("font-size": 48),
+ "h2": ("font-size": 40),
+ "h3": ("font-size": 31),
+ "h4": ("font-size": 25),
+ "h5": ("font-size": 20),
+ "h6": ("font-size": 16),
),
);
$header-text-rendering: optimizeLegibility;
@@ -188,7 +188,7 @@ $blockquote-padding: rem-calc(9 20 0 19);
$blockquote-border: 1px solid $medium-gray;
$cite-font-size: rem-calc(13);
$cite-color: $dark-gray;
-$cite-pseudo-content: '\2014 \0020';
+$cite-pseudo-content: "\2014 \0020";
$keystroke-font: $font-family-monospace;
$keystroke-color: $black;
$keystroke-background: $light-gray;
@@ -271,8 +271,8 @@ $breadcrumbs-item-color-disabled: $medium-gray;
$breadcrumbs-item-margin: 0.75rem;
$breadcrumbs-item-uppercase: true;
$breadcrumbs-item-separator: true;
-$breadcrumbs-item-separator-item: '/';
-$breadcrumbs-item-separator-item-rtl: '\\';
+$breadcrumbs-item-separator-item: "/";
+$breadcrumbs-item-separator-item-rtl: "\\";
$breadcrumbs-item-separator-color: $medium-gray;
// 11. Button
@@ -305,7 +305,7 @@ $button-transition: background-color 0.25s ease-out, color 0.25s ease-out;
$buttongroup-margin: 1rem;
$buttongroup-spacing: 1px;
-$buttongroup-child-selector: '.button';
+$buttongroup-child-selector: ".button";
$buttongroup-expand-max: 6;
$buttongroup-radius-on-each: true;
@@ -511,7 +511,7 @@ $offcanvas-transition-length: 0.5s;
$offcanvas-transition-timing: ease;
$offcanvas-fixed-reveal: true;
$offcanvas-exit-background: rgba($white, 0.25);
-$maincontent-class: 'off-canvas-content';
+$maincontent-class: "off-canvas-content";
// 26. Orbit
// ---------
diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss
index 7b74b2697..17ea18b9d 100644
--- a/app/assets/stylesheets/admin.scss
+++ b/app/assets/stylesheets/admin.scss
@@ -224,6 +224,11 @@ $sidebar-active: #f4fcd0;
label {
color: #fff;
}
+
+ a {
+ color: inherit;
+ white-space: nowrap;
+ }
}
.break {
@@ -251,6 +256,13 @@ $sidebar-active: #f4fcd0;
max-width: none;
}
+ form {
+
+ .input-group-label {
+ height: $line-height * 2;
+ }
+ }
+
.menu.simple {
margin-bottom: $line-height / 2;
@@ -284,10 +296,6 @@ $sidebar-active: #f4fcd0;
.proposal-form {
padding-top: 0;
}
-
- .proposal-show {
- padding-top: rem-calc(54);
- }
}
.is-featured {
@@ -364,6 +372,48 @@ $sidebar-active: #f4fcd0;
color: $text-medium;
}
+.icon-sortable {
+ font-family: "icons";
+ font-size: $small-font-size;
+ padding-right: $line-height / 2;
+ position: relative;
+
+ &::before,
+ &::after {
+ left: 6px;
+ opacity: 0.25;
+ position: absolute;
+ }
+
+ &::before {
+ content: "\57";
+ top: -2px;
+ }
+
+ &::after {
+ content: "\52";
+ bottom: -10px;
+ }
+
+ &.asc {
+
+ &::after {
+ opacity: 1;
+ }
+ }
+
+ &.desc {
+
+ &::before {
+ opacity: 1;
+ }
+ }
+}
+
+code {
+ word-break: break-all;
+}
+
// 02. Sidebar
// -----------
@@ -428,7 +478,7 @@ $sidebar-active: #f4fcd0;
> a::after {
border: 0;
- content: '\61' !important;
+ content: "\61" !important;
font-family: "icons" !important;
height: auto;
position: absolute !important;
@@ -1110,7 +1160,7 @@ table {
}
.map-icon::after {
- content: '';
+ content: "";
width: 14px;
height: 14px;
margin: 8px 0 0 8px;
@@ -1170,7 +1220,7 @@ table {
&.enabled::before,
&.disabled::before {
- font-family: 'icons';
+ font-family: "icons";
left: 0;
position: absolute;
}
@@ -1180,7 +1230,7 @@ table {
&::before {
color: $check;
- content: '\6c';
+ content: "\6c";
}
}
@@ -1189,22 +1239,11 @@ table {
&::before {
color: #000;
- content: '\76';
+ content: "\76";
}
}
}
-.max-headings-label {
- color: $text-medium;
- font-size: $small-font-size;
- margin-left: $line-height / 2;
-}
-
-.current-of-max-headings {
- color: #000;
- font-weight: bold;
-}
-
// 11. Newsletters
// -----------------
diff --git a/app/assets/stylesheets/annotator_overrides.scss b/app/assets/stylesheets/annotator_overrides.scss
index fcc127ecd..0bdb28ade 100644
--- a/app/assets/stylesheets/annotator_overrides.scss
+++ b/app/assets/stylesheets/annotator_overrides.scss
@@ -14,7 +14,7 @@
}
.annotator-adder {
- background-image: image-url('annotator_adder.png');
+ background-image: image-url("annotator_adder.png");
margin-top: -52px;
}
@@ -43,7 +43,7 @@
.annotator-widget::after,
.annotator-editor.annotator-invert-y .annotator-widget::after {
- background-image: image-url('annotator_items.png');
+ background-image: image-url("annotator_items.png");
}
.annotator-editor a,
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 26a57079c..85a9ed041 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -1,23 +1,24 @@
-@import 'social-share-button';
-@import 'foundation_and_overrides';
-@import 'fonts';
-@import 'icons';
-@import 'mixins';
-@import 'admin';
-@import 'layout';
-@import 'participation';
-@import 'pages';
-@import 'dashboard';
-@import 'legislation';
-@import 'legislation_process';
-@import 'community';
-@import 'custom';
-@import 'c3';
-@import 'annotator.min';
-@import 'annotator_overrides';
-@import 'jquery-ui/datepicker';
-@import 'datepicker_overrides';
-@import 'jquery-ui/autocomplete';
-@import 'autocomplete_overrides';
-@import 'jquery-ui/sortable';
-@import 'leaflet';
+@import "social-share-button";
+@import "foundation_and_overrides";
+@import "fonts";
+@import "icons";
+@import "mixins";
+@import "admin";
+@import "layout";
+@import "participation";
+@import "milestones";
+@import "pages";
+@import "dashboard";
+@import "legislation";
+@import "legislation_process";
+@import "community";
+@import "custom";
+@import "c3";
+@import "annotator.min";
+@import "annotator_overrides";
+@import "jquery-ui/datepicker";
+@import "datepicker_overrides";
+@import "jquery-ui/autocomplete";
+@import "autocomplete_overrides";
+@import "jquery-ui/sortable";
+@import "leaflet";
diff --git a/app/assets/stylesheets/dashboard.scss b/app/assets/stylesheets/dashboard.scss
index 62931a13c..0f5202a2a 100644
--- a/app/assets/stylesheets/dashboard.scss
+++ b/app/assets/stylesheets/dashboard.scss
@@ -108,7 +108,7 @@
a {
display: block;
}
-
+
h4,
p {
margin-bottom: 0;
@@ -158,7 +158,7 @@
&::before {
border: 2px solid #fb9497;
color: #fb9497;
- content: '\74';
+ content: "\74";
}
}
@@ -166,8 +166,8 @@
border: 2px solid #00cb96;
border-radius: rem-calc(40);
color: #00cb96;
- content: '\6c';
- font-family: 'icons';
+ content: "\6c";
+ font-family: "icons";
font-size: rem-calc(20);
height: rem-calc(36);
position: absolute;
@@ -185,6 +185,7 @@
h4 {
margin-top: $line-height;
}
+
.resource-description {
min-height: $line-height * 4;
}
@@ -212,8 +213,8 @@
border: 1px solid $border;
border-radius: rem-calc(36);
color: #000;
- content: '\77';
- font-family: 'icons';
+ content: "\77";
+ font-family: "icons";
font-size: rem-calc(24);
height: rem-calc(36);
left: -18px;
@@ -239,7 +240,7 @@
&::before {
color: #000;
- font-family: 'icons';
+ font-family: "icons";
font-size: rem-calc(24);
left: 6px;
position: absolute;
@@ -250,21 +251,21 @@
.goal-supports {
&::before {
- content: '\77';
+ content: "\77";
}
}
.goal-resource {
&::before {
- content: '\74';
+ content: "\74";
}
}
.goal-days {
&::before {
- content: '\67';
+ content: "\67";
}
}
@@ -313,7 +314,7 @@
&::before {
background: linear-gradient(to right, rgba(231, 236, 240, 1) 0%, rgba(251, 251, 251, 1) 90%);
border-left: 4px solid $brand;
- content: '';
+ content: "";
height: rem-calc(48);
left: 0;
padding-left: rem-calc(20);
@@ -431,8 +432,8 @@
&::before {
color: $brand;
- content: '\6d';
- font-family: 'icons';
+ content: "\6d";
+ font-family: "icons";
left: 6px;
position: absolute;
}
@@ -527,7 +528,7 @@
&::before {
background: $pdf-secondary;
- content: '';
+ content: "";
position: absolute;
}
diff --git a/app/assets/stylesheets/datepicker_overrides.scss b/app/assets/stylesheets/datepicker_overrides.scss
index 190784d15..6082592a3 100644
--- a/app/assets/stylesheets/datepicker_overrides.scss
+++ b/app/assets/stylesheets/datepicker_overrides.scss
@@ -23,7 +23,7 @@
thead {
tr th {
- color: $dark;
+ border: 1px solid $brand;
}
}
}
@@ -51,11 +51,11 @@
}
.ui-datepicker-prev::after {
- content: '\62';
+ content: "\62";
}
.ui-datepicker-next::after {
- content: '\63';
+ content: "\63";
}
table {
diff --git a/app/assets/stylesheets/fonts.scss b/app/assets/stylesheets/fonts.scss
index 61429e800..83ce4b078 100644
--- a/app/assets/stylesheets/fonts.scss
+++ b/app/assets/stylesheets/fonts.scss
@@ -8,88 +8,88 @@
// - - - - - - - - - - - - - - - - - - - - - - - - -
@font-face {
- font-family: 'Source Sans Pro';
+ font-family: "Source Sans Pro";
font-style: normal;
font-weight: 300;
- src: font-url('sourcesanspro-light-webfont.eot');
- src: font-url('sourcesanspro-light-webfont.eot?#iefix') format('embedded-opentype'),
- font-url('sourcesanspro-light-webfont.woff2') format('woff2'),
- font-url('sourcesanspro-light-webfont.woff') format('woff'),
- font-url('sourcesanspro-light-webfont.ttf') format('truetype'),
- font-url('sourcesanspro-light-webfont.svg#source_sans_prolight') format('svg');
+ src: font-url("sourcesanspro-light-webfont.eot");
+ src: font-url("sourcesanspro-light-webfont.eot?#iefix") format("embedded-opentype"),
+ font-url("sourcesanspro-light-webfont.woff2") format("woff2"),
+ font-url("sourcesanspro-light-webfont.woff") format("woff"),
+ font-url("sourcesanspro-light-webfont.ttf") format("truetype"),
+ font-url("sourcesanspro-light-webfont.svg#source_sans_prolight") format("svg");
}
@font-face {
- font-family: 'Source Sans Pro';
+ font-family: "Source Sans Pro";
font-style: normal;
font-weight: 400;
- src: font-url('sourcesanspro-regular-webfont.eot');
- src: font-url('sourcesanspro-regular-webfont.eot?#iefix') format('embedded-opentype'),
- font-url('sourcesanspro-regular-webfont.woff2') format('woff2'),
- font-url('sourcesanspro-regular-webfont.woff') format('woff'),
- font-url('sourcesanspro-regular-webfont.ttf') format('truetype'),
- font-url('sourcesanspro-regular-webfont.svg#source_sans_proregular') format('svg');
+ src: font-url("sourcesanspro-regular-webfont.eot");
+ src: font-url("sourcesanspro-regular-webfont.eot?#iefix") format("embedded-opentype"),
+ font-url("sourcesanspro-regular-webfont.woff2") format("woff2"),
+ font-url("sourcesanspro-regular-webfont.woff") format("woff"),
+ font-url("sourcesanspro-regular-webfont.ttf") format("truetype"),
+ font-url("sourcesanspro-regular-webfont.svg#source_sans_proregular") format("svg");
}
@font-face {
- font-family: 'Source Sans Pro';
+ font-family: "Source Sans Pro";
font-style: italic;
font-weight: 400;
- src: font-url('sourcesanspro-italic-webfont.eot');
- src: font-url('sourcesanspro-italic-webfont.eot?#iefix') format('embedded-opentype'),
- font-url('sourcesanspro-italic-webfont.woff2') format('woff2'),
- font-url('sourcesanspro-italic-webfont.woff') format('woff'),
- font-url('sourcesanspro-italic-webfont.ttf') format('truetype'),
- font-url('sourcesanspro-italic-webfont.svg#source_sans_proitalic') format('svg');
+ src: font-url("sourcesanspro-italic-webfont.eot");
+ src: font-url("sourcesanspro-italic-webfont.eot?#iefix") format("embedded-opentype"),
+ font-url("sourcesanspro-italic-webfont.woff2") format("woff2"),
+ font-url("sourcesanspro-italic-webfont.woff") format("woff"),
+ font-url("sourcesanspro-italic-webfont.ttf") format("truetype"),
+ font-url("sourcesanspro-italic-webfont.svg#source_sans_proitalic") format("svg");
}
@font-face {
- font-family: 'Source Sans Pro';
+ font-family: "Source Sans Pro";
font-style: normal;
font-weight: 700;
- src: font-url('sourcesanspro-bold-webfont.eot');
- src: font-url('sourcesanspro-bold-webfont.eot?#iefix') format('embedded-opentype'),
- font-url('sourcesanspro-bold-webfont.woff2') format('woff2'),
- font-url('sourcesanspro-bold-webfont.woff') format('woff'),
- font-url('sourcesanspro-bold-webfont.ttf') format('truetype'),
- font-url('sourcesanspro-bold-webfont.svg#source_sans_probold') format('svg');
+ src: font-url("sourcesanspro-bold-webfont.eot");
+ src: font-url("sourcesanspro-bold-webfont.eot?#iefix") format("embedded-opentype"),
+ font-url("sourcesanspro-bold-webfont.woff2") format("woff2"),
+ font-url("sourcesanspro-bold-webfont.woff") format("woff"),
+ font-url("sourcesanspro-bold-webfont.ttf") format("truetype"),
+ font-url("sourcesanspro-bold-webfont.svg#source_sans_probold") format("svg");
}
// 02. Lato
// - - - - - - - - - - - - - - - - - - - - - - - - -
@font-face {
- font-family: 'Lato';
- src: font-url('lato-light.eot');
- src: font-url('lato-light.eot?#iefix') format('embedded-opentype'),
- font-url('lato-light.woff2') format('woff2'),
- font-url('lato-light.woff') format('woff'),
- font-url('lato-light.ttf') format('truetype'),
- font-url('lato-light.svg#latolight') format('svg');
+ font-family: "Lato";
+ src: font-url("lato-light.eot");
+ src: font-url("lato-light.eot?#iefix") format("embedded-opentype"),
+ font-url("lato-light.woff2") format("woff2"),
+ font-url("lato-light.woff") format("woff"),
+ font-url("lato-light.ttf") format("truetype"),
+ font-url("lato-light.svg#latolight") format("svg");
font-weight: lighter;
font-style: normal;
}
@font-face {
- font-family: 'Lato';
- src: font-url('lato-regular.eot');
- src: font-url('lato-regular.eot?#iefix') format('embedded-opentype'),
- font-url('lato-regular.woff2') format('woff2'),
- font-url('lato-regular.woff') format('woff'),
- font-url('lato-regular.ttf') format('truetype'),
- font-url('lato-regular.svg#latoregular') format('svg');
+ font-family: "Lato";
+ src: font-url("lato-regular.eot");
+ src: font-url("lato-regular.eot?#iefix") format("embedded-opentype"),
+ font-url("lato-regular.woff2") format("woff2"),
+ font-url("lato-regular.woff") format("woff"),
+ font-url("lato-regular.ttf") format("truetype"),
+ font-url("lato-regular.svg#latoregular") format("svg");
font-weight: normal;
font-style: normal;
}
@font-face {
- font-family: 'Lato';
- src: font-url('lato-bold.eot');
- src: font-url('lato-bold.eot?#iefix') format('embedded-opentype'),
- font-url('lato-bold.woff2') format('woff2'),
- font-url('lato-bold.woff') format('woff'),
- font-url('lato-bold.ttf') format('truetype'),
- font-url('lato-bold.svg#latobold') format('svg');
+ font-family: "Lato";
+ src: font-url("lato-bold.eot");
+ src: font-url("lato-bold.eot?#iefix") format("embedded-opentype"),
+ font-url("lato-bold.woff2") format("woff2"),
+ font-url("lato-bold.woff") format("woff"),
+ font-url("lato-bold.ttf") format("truetype"),
+ font-url("lato-bold.svg#latobold") format("svg");
font-weight: bold;
font-style: normal;
}
diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss
index 99e77f57d..c4fa6944e 100644
--- a/app/assets/stylesheets/foundation_and_overrides.scss
+++ b/app/assets/stylesheets/foundation_and_overrides.scss
@@ -1,11 +1,11 @@
-@charset 'utf-8';
+@charset "utf-8";
-@import 'settings';
-@import 'consul_settings';
-@import 'custom_settings';
-@import 'foundation';
+@import "settings";
+@import "consul_settings";
+@import "custom_settings";
+@import "foundation";
-@import 'motion-ui/motion-ui';
+@import "motion-ui/motion-ui";
@include foundation-global-styles;
// @include foundation-xy-grid-classes;
diff --git a/app/assets/stylesheets/icons.scss b/app/assets/stylesheets/icons.scss
index bcfafc135..81f69a1c0 100644
--- a/app/assets/stylesheets/icons.scss
+++ b/app/assets/stylesheets/icons.scss
@@ -1,12 +1,12 @@
@charset "UTF-8";
@font-face {
- font-family: 'icons';
- src: font-url('icons.eot');
- src: font-url('icons.eot?#iefix') format('embedded-opentype'),
- font-url('icons.woff') format('woff'),
- font-url('icons.ttf') format('truetype'),
- font-url('icons.svg#icons') format('svg');
+ font-family: "icons";
+ src: font-url("icons.eot");
+ src: font-url("icons.eot?#iefix") format("embedded-opentype"),
+ font-url("icons.woff") format("woff"),
+ font-url("icons.ttf") format("truetype"),
+ font-url("icons.svg#icons") format("svg");
font-weight: normal;
font-style: normal;
}
@@ -38,263 +38,263 @@
}
.icon-angle-down::before {
- content: '\61';
+ content: "\61";
}
.icon-angle-left::before {
- content: '\62';
+ content: "\62";
}
.icon-angle-right::before {
- content: '\63';
+ content: "\63";
}
.icon-angle-up::before {
- content: '\64';
+ content: "\64";
}
.icon-comments::before {
- content: '\65';
+ content: "\65";
}
.icon-twitter::before {
- content: '\66';
+ content: "\66";
}
.icon-calendar::before {
- content: '\67';
+ content: "\67";
}
.icon-debates::before {
- content: '\69';
+ content: "\69";
}
.icon-unlike::before {
- content: '\6a';
+ content: "\6a";
}
.icon-like::before {
- content: '\6b';
+ content: "\6b";
}
.icon-check::before {
- content: '\6c';
+ content: "\6c";
}
.icon-edit::before {
- content: '\6d';
+ content: "\6d";
}
.icon-user::before {
- content: '\6f';
+ content: "\6f";
}
.icon-settings::before {
- content: '\71';
+ content: "\71";
}
.icon-stats::before {
- content: '\72';
+ content: "\72";
}
.icon-proposals::before {
- content: '\68';
+ content: "\68";
}
.icon-organizations::before {
- content: '\73';
+ content: "\73";
}
.icon-deleted::before {
- content: '\74';
+ content: "\74";
}
.icon-tag::before {
- content: '\75';
+ content: "\75";
}
.icon-eye::before {
- content: '\70';
+ content: "\70";
}
.icon-x::before {
- content: '\76';
+ content: "\76";
}
.icon-flag::before {
- content: '\77';
+ content: "\77";
}
.icon-comment::before {
- content: '\79';
+ content: "\79";
}
.icon-reply::before {
- content: '\7a';
+ content: "\7a";
}
.icon-facebook::before {
- content: '\41';
+ content: "\41";
}
.icon-google-plus::before {
- content: '\42';
+ content: "\42";
}
.icon-search::before {
- content: '\45';
+ content: "\45";
}
.icon-external::before {
- content: '\46';
+ content: "\46";
}
.icon-video::before {
- content: '\44';
+ content: "\44";
}
.icon-document::before {
- content: '\47';
+ content: "\47";
}
.icon-print::before {
- content: '\48';
+ content: "\48";
}
.icon-blog::before {
- content: '\4a';
+ content: "\4a";
}
.icon-box::before {
- content: '\49';
+ content: "\49";
}
.icon-youtube::before {
- content: '\4b';
+ content: "\4b";
}
.icon-letter::before {
- content: '\4c';
+ content: "\4c";
}
.icon-circle::before {
- content: '\43';
+ content: "\43";
}
.icon-circle-o::before {
- content: '\4d';
+ content: "\4d";
}
.icon-help::before {
- content: '\4e';
+ content: "\4e";
}
.icon-budget::before {
- content: '\53';
+ content: "\53";
}
.icon-notification::before {
- content: '\6e';
+ content: "\6e";
}
.icon-no-notification::before {
- content: '\78';
+ content: "\78";
}
.icon-whatsapp::before {
- content: '\50';
+ content: "\50";
}
.icon-zip::before {
- content: '\4f';
+ content: "\4f";
}
.icon-banner::before {
- content: '\51';
+ content: "\51";
}
.icon-arrow-down::before {
- content: '\52';
+ content: "\52";
}
.icon-arrow-left::before {
- content: '\54';
+ content: "\54";
}
.icon-arrow-right::before {
- content: '\55';
+ content: "\55";
}
.icon-check-circle::before {
- content: '\56';
+ content: "\56";
}
.icon-arrow-top::before {
- content: '\57';
+ content: "\57";
}
.icon-checkmark-circle::before {
- content: '\59';
+ content: "\59";
}
.icon-minus-square::before {
- content: '\58';
+ content: "\58";
}
.icon-plus-square::before {
- content: '\5a';
+ content: "\5a";
}
.icon-expand::before {
- content: '\30';
+ content: "\30";
}
.icon-telegram::before {
- content: '\31';
+ content: "\31";
}
.icon-instagram::before {
- content: '\32';
+ content: "\32";
}
.icon-image::before {
- content: '\33';
+ content: "\33";
}
.icon-search-plus::before {
- content: '\34';
+ content: "\34";
}
.icon-search-minus::before {
- content: '\35';
+ content: "\35";
}
.icon-calculator::before {
- content: '\36';
+ content: "\36";
}
.icon-map-marker::before {
- content: '\37';
+ content: "\37";
}
.icon-user-plus::before {
- content: '\38';
+ content: "\38";
}
.icon-file-text-o::before {
- content: '\39';
+ content: "\39";
}
.icon-file-text::before {
- content: '\21';
+ content: "\21";
}
.icon-bars::before {
- content: '\22';
+ content: "\22";
}
.icon-quote-before::before {
- content: '';
+ content: "";
background-size: cover;
display: block;
width: 60px;
@@ -304,7 +304,7 @@
}
.icon-quote-after::before {
- content: '';
+ content: "";
background-size: cover;
display: block;
width: 60px;
@@ -314,7 +314,7 @@
}
.icon-finger::before {
- content: '';
+ content: "";
background-size: cover;
display: inline-block;
width: 50px;
diff --git a/app/assets/stylesheets/layout.scss b/app/assets/stylesheets/layout.scss
index 8172d13ab..ed1322275 100644
--- a/app/assets/stylesheets/layout.scss
+++ b/app/assets/stylesheets/layout.scss
@@ -359,19 +359,34 @@ a {
.tabs-title {
font-size: $base-font-size;
- margin-bottom: 0;
+ margin-right: $line-height;
}
.tabs-title > a {
color: $text-medium;
- margin-bottom: rem-calc(-1);
- margin-right: $line-height;
+ position: relative;
- &[aria-selected='true'],
- &.is-active {
+ &:hover {
+ background: none;
+ color: $brand;
+ text-decoration: none;
+ }
+
+ &[aria-selected="true"],
+ &.is-active {
+ border-bottom: 0;
color: $brand;
- border-bottom: 2px solid $brand;
font-weight: bold;
+
+ &::after {
+ background: $brand;
+ border-bottom: 2px solid $brand;
+ bottom: 0;
+ content: "";
+ left: 0;
+ position: absolute;
+ width: 100%;
+ }
}
}
@@ -419,6 +434,11 @@ a {
text-transform: uppercase;
}
+.help-text {
+ line-height: rem-calc(20);
+ margin-top: 0;
+}
+
// 02. Header
// ----------
@@ -435,6 +455,18 @@ header {
float: left;
height: $line-height * 1.5;
margin-left: $line-height / 2;
+ position: relative;
+
+ &::after {
+ color: #808080;
+ content: "\61";
+ font-family: "icons" !important;
+ font-size: $small-font-size;
+ pointer-events: none;
+ position: absolute;
+ right: 2px;
+ top: 9px;
+ }
}
.external-links {
@@ -469,7 +501,7 @@ header {
a {
color: #fff;
display: inline-block;
- font-family: 'Lato' !important;
+ font-family: "Lato" !important;
font-size: rem-calc(24);
font-weight: lighter;
line-height: $line-height * 2;
@@ -614,7 +646,7 @@ header {
display: inline-block;
&::after {
- content: '|';
+ content: "|";
}
&:last-child::after {
@@ -762,7 +794,7 @@ footer {
color: $text;
.logo a {
- font-family: 'Lato' !important;
+ font-family: "Lato" !important;
text-decoration: none;
&:hover {
@@ -846,6 +878,13 @@ footer {
}
}
+.sidebar-map {
+
+ .map {
+ z-index: 0;
+ }
+}
+
.sidebar-title {
border-top: 2px solid $brand;
display: inline-block;
@@ -867,7 +906,7 @@ footer {
}
.auth-image {
- background: $brand image-url('auth_bg.jpg');
+ background: $brand image-url("auth_bg.jpg");
background-repeat: no-repeat;
background-size: cover;
@@ -881,7 +920,6 @@ footer {
a {
color: #fff;
display: block;
- line-height: rem-calc(80); // Same as logo image height
text-align: center;
@include breakpoint(medium) {
@@ -927,15 +965,11 @@ footer {
label {
color: #fff;
- font-size: $small-font-size;
+ font-size: $tiny-font-size;
font-weight: normal;
}
select {
- background-image: image-url('language_select.png');
- background-origin: border-box;
- background-position: right;
- background-size: 24px 24px;
option {
background: #fff;
@@ -946,14 +980,16 @@ footer {
}
.locale-switcher {
- background-color: transparent;
+ background: #001d33;
border: 0;
+ border-radius: rem-calc(4);
color: #fff;
font-size: $small-font-size;
+ height: $line-height;
margin-bottom: 0;
+ margin-top: $line-height / 4;
outline: none;
- padding-left: rem-calc(3);
- padding-right: $line-height;
+ padding: 0 $line-height / 4;
width: auto;
&:focus {
@@ -1056,6 +1092,7 @@ form {
.callout {
font-size: $small-font-size;
+ overflow: hidden;
a:not(.button) {
font-weight: bold;
@@ -1095,6 +1132,10 @@ form {
.close {
text-decoration: none !important;
}
+
+ .button {
+ margin-bottom: 0;
+ }
}
.no-error {
@@ -1238,7 +1279,7 @@ form {
&::before {
background: $border;
- content: '';
+ content: "";
height: 100%;
left: 7px;
position: absolute;
@@ -1284,14 +1325,14 @@ form {
}
&::before {
- content: '\43';
+ content: "\43";
}
}
&::before {
background: #fff;
color: $brand;
- content: '\4d';
+ content: "\4d";
font-family: "icons" !important;
font-size: $small-font-size;
height: rem-calc(20);
@@ -1446,7 +1487,7 @@ table {
&::before {
color: #45b0e3;
- content: 'f';
+ content: "f";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 0;
@@ -1466,7 +1507,7 @@ table {
width: $line-height * 2 !important;
&::before {
- content: 'f';
+ content: "f";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 50%;
@@ -1489,7 +1530,7 @@ table {
&::before {
color: #3b5998;
- content: 'A';
+ content: "A";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 0;
@@ -1509,7 +1550,7 @@ table {
width: rem-calc(48) !important;
&::before {
- content: 'A';
+ content: "A";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 50%;
@@ -1532,7 +1573,7 @@ table {
&::before {
color: #de4c34;
- content: 'B';
+ content: "B";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 0;
@@ -1552,7 +1593,7 @@ table {
width: $line-height * 2 !important;
&::before {
- content: 'B';
+ content: "B";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 50%;
@@ -1575,7 +1616,7 @@ table {
&::before {
color: #08c;
- content: '1';
+ content: "1";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 0;
@@ -1595,7 +1636,7 @@ table {
width: $line-height * 2 !important;
&::before {
- content: '1';
+ content: "1";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 50%;
@@ -1648,7 +1689,7 @@ table {
width: $line-height * 2;
&::before {
- content: 'f';
+ content: "f";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 50%;
@@ -1673,7 +1714,7 @@ table {
width: rem-calc(48);
&::before {
- content: 'A';
+ content: "A";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 50%;
@@ -1698,7 +1739,7 @@ table {
width: rem-calc(48);
&::before {
- content: 'B';
+ content: "B";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 50%;
@@ -1723,7 +1764,7 @@ table {
width: $line-height * 2;
&::before {
- content: '1';
+ content: "1";
font-family: "icons" !important;
font-size: rem-calc(24);
left: 50%;
@@ -1767,7 +1808,7 @@ table {
top: 24px;
@include breakpoint(medium) {
- content: 'c';
+ content: "c";
}
}
}
@@ -2204,76 +2245,6 @@ table {
// 18. Banners
// -----------
-.banner-style-one {
- background-color: $brand;
-}
-
-.banner-style-two {
- background-color: $budget;
-}
-
-.banner-style-three {
- background-color: #33dadf;
-}
-
-@include breakpoint(large) {
-
- .banner-img-one {
- background-image: image-url('banners/banner1.png');
- }
-
- .banner-img-two {
- background-image: image-url('banners/banner2.png');
- }
-
- .banner-img-three {
- background-image: image-url('banners/banner3.png');
- }
-}
-
-.banner-img-one,
-.banner-img-two,
-.banner-img-three {
- background-position: bottom right;
- background-repeat: no-repeat;
-}
-
-.banner-style-one,
-.banner-style-two,
-.banner-style-three,
-.banner {
- margin: 0;
- margin-bottom: $line-height;
-
- @include breakpoint(large) {
-
- h3 {
- width: 80%;
- }
- }
-
- h2,
- h3,
- a {
- color: #eaeaf2;
- }
-
- h2 {
- padding: $line-height / 2;
- padding-bottom: 0;
- }
-
- h3 {
- padding: $line-height / 2;
- padding-top: 0;
- }
-
- a:hover h2,
- a:hover h3 {
- color: #eaeaf2 !important;
- text-decoration: none;
- }
-}
// 19. Recommendations
// -------------------
@@ -2344,7 +2315,7 @@ table {
}
.card .orbit .orbit-wrapper .truncate {
- background: image-url('truncate.png');
+ background: image-url("truncate.png");
background-repeat: repeat-x;
bottom: 0;
height: rem-calc(20);
@@ -2494,7 +2465,7 @@ table {
border-radius: rem-calc(5);
display: block;
margin: $line-height / 2 0;
- padding: 0 $line-height / 2;
+ padding: $line-height / 2;
position: relative;
.icon-document {
@@ -2627,7 +2598,7 @@ table {
&.score-positive::before,
&.score-negative::before {
- font-family: 'icons';
+ font-family: "icons";
left: 0;
position: absolute;
}
@@ -2637,7 +2608,7 @@ table {
&::before {
color: $color-success;
- content: '\6c';
+ content: "\6c";
}
}
@@ -2646,7 +2617,7 @@ table {
&::before {
color: $color-alert;
- content: '\76';
+ content: "\76";
}
}
}
@@ -2684,10 +2655,22 @@ table {
}
}
+.leaflet-container {
+
+ .leaflet-control-attribution {
+ background: rgba(255, 255, 255, 0.9) !important;
+ }
+
+ a {
+ color: $link !important;
+ }
+}
+
// 24. Homepage
// ------------
-.home-page {
+.home-page,
+.custom-page {
a {
@@ -2794,15 +2777,15 @@ table {
display: inline-block;
height: rem-calc(120);
overflow: hidden;
+ width: 100%;
@include breakpoint(medium) {
height: rem-calc(96);
}
img {
- margin-left: rem-calc(-15);
max-width: none;
- width: rem-calc(120);
+ width: 100%;
}
}
@@ -2827,11 +2810,19 @@ table {
.figure-card {
display: flex;
margin: 0 0 $line-height;
+ overflow: hidden;
position: relative;
+ @include breakpoint(medium down) {
+ min-height: $line-height * 4;
+ }
+
@include breakpoint(medium) {
max-height: rem-calc(185);
- overflow: hidden;
+ }
+
+ @include breakpoint(large) {
+ min-height: rem-calc(185);
}
a {
@@ -2863,8 +2854,16 @@ table {
h3,
.title {
- font-size: rem-calc(24);
- line-height: rem-calc(24);
+ font-size: $base-font-size;
+
+ @include breakpoint(medium) {
+ font-size: rem-calc(20);
+ }
+
+ @include breakpoint(large) {
+ font-size: rem-calc(24);
+ line-height: rem-calc(24);
+ }
}
span {
diff --git a/app/assets/stylesheets/legislation_process.scss b/app/assets/stylesheets/legislation_process.scss
index 30332d49b..474d80bbb 100644
--- a/app/assets/stylesheets/legislation_process.scss
+++ b/app/assets/stylesheets/legislation_process.scss
@@ -24,7 +24,7 @@
&::before {
color: #8aa8be;
- content: '■';
+ content: "■";
padding-right: $line-height / 4;
vertical-align: text-bottom;
}
@@ -44,63 +44,101 @@
// 02. Legislation process navigation
// ----------------------------------
-.legislation-process-categories {
- position: relative;
+.legislation-process-list {
+ border-bottom: 1px solid $border;
+}
- .legislation-process-list {
- border-bottom: 1px solid $medium-gray;
- margin: 0 rem-calc(16) rem-calc(16);
+.key-dates {
+ list-style-type: none;
+ margin: 0 rem-calc(-10);
- ul {
- list-style: none;
- margin: 0 auto;
- margin-bottom: 0;
- padding-left: 0;
+ @include breakpoint(large) {
+ margin: 0;
+ }
+
+ li {
+ border: 1px solid $border;
+ display: block;
+ margin: rem-calc(-1) 0;
+ min-height: $line-height * 3;
+ position: relative;
+ vertical-align: top;
+
+ @include breakpoint(large down) {
+
+ &::after {
+ content: "\63";
+ font-family: "icons" !important;
+ font-size: rem-calc(24);
+ pointer-events: none;
+ position: absolute;
+ right: 12px;
+ top: 12px;
+ }
}
- li {
- border-bottom: 2px solid transparent;
- cursor: pointer;
+ @include breakpoint(large) {
+ background: #fafafa;
display: inline-block;
- margin-bottom: $line-height;
- margin-right: $line-height;
- transition: all 0.4s;
+ border-bottom: 0;
+ border-top-left-radius: rem-calc(6);
+ border-top-right-radius: rem-calc(6);
+ margin-bottom: 0;
+ margin-right: $line-height / 4;
+ margin-top: 0;
- @include breakpoint(medium) {
- margin-bottom: 0;
+ &:hover:not(.is-active) {
+ background: $highlight;
}
- &:hover,
- &:active,
- &:focus {
- border-bottom: 2px solid $brand;
- }
-
- a,
- h4 {
- display: block;
- color: #6d6d6d;
- margin-bottom: 0;
+ &::after {
+ content: "";
}
}
a {
- &:hover,
- &:active {
+ display: block;
+ padding: $line-height / 4 $line-height / 2;
+
+ @include breakpoint(large) {
+ display: inline-block;
+ }
+
+ &:hover {
text-decoration: none;
}
- p {
+ h4 {
margin-bottom: 0;
+ }
+ }
+ }
- @include breakpoint(medium) {
- margin-bottom: rem-calc(16);
- }
+ span {
+ color: $text-medium;
+ font-size: $small-font-size;
+ }
+
+ .is-active {
+ background: $highlight;
+ position: relative;
+
+ @include breakpoint(large) {
+ background: none;
+ border: 1px solid $border;
+ border-bottom: 0;
+
+ &::after {
+ border-bottom: 1px solid #fefefe;
+ bottom: -1px;
+ left: 0;
+ position: absolute;
+ width: 100%;
}
}
- .is-active {
- border-bottom: 2px solid $brand;
+ &::after {
+ content: "";
}
}
}
@@ -430,8 +468,8 @@
cursor: pointer;
position: absolute;
margin-left: rem-calc(-20);
- font-family: 'icons';
- content: '\58';
+ font-family: "icons";
+ content: "\58";
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@@ -440,8 +478,8 @@
cursor: pointer;
position: absolute;
margin-left: rem-calc(-20);
- font-family: 'icons';
- content: '\5a';
+ font-family: "icons";
+ content: "\5a";
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@@ -469,7 +507,7 @@
.anchor::before {
display: none;
- content: '#';
+ content: "#";
color: $text-medium;
position: absolute;
left: 0;
@@ -721,7 +759,7 @@
display: inline-block;
&::after {
- content: '|';
+ content: "|";
color: #838383;
}
}
@@ -742,7 +780,7 @@
&::after {
margin-left: rem-calc(4);
- content: '|';
+ content: "|";
}
}
@@ -792,7 +830,7 @@
&::before {
margin-right: rem-calc(4);
- content: '—';
+ content: "—";
}
}
}
@@ -943,4 +981,4 @@
font-size: rem-calc(20);
margin-top: 0;
}
-}
\ No newline at end of file
+}
diff --git a/app/assets/stylesheets/milestones.scss b/app/assets/stylesheets/milestones.scss
new file mode 100644
index 000000000..ba60057de
--- /dev/null
+++ b/app/assets/stylesheets/milestones.scss
@@ -0,0 +1,127 @@
+$progress-bar-background: #fef0e2;
+$progress-bar-color: #fea230;
+
+.tab-milestones {
+
+ .progress-bars {
+ margin-bottom: $line-height * 2;
+ margin-top: $line-height;
+
+ h5 {
+ font-size: rem-calc(24);
+ }
+
+ .progress {
+ background: $progress-bar-background;
+ border-radius: rem-calc(6);
+ position: relative;
+ }
+
+ .progress-meter {
+ background: $progress-bar-color;
+ border-radius: rem-calc(6);
+ }
+
+ .progress-meter-text {
+ color: #000;
+ right: 12px;
+ text-align: right;
+ transform: translate(0%, -50%);
+ }
+
+ .milestone-progress .row {
+ margin-bottom: $line-height / 2;
+ }
+ }
+}
+
+.tab-milestones .timeline li {
+ margin: 0 auto;
+ position: relative;
+ width: 0;
+
+ @include breakpoint(small only) {
+ width: 100%;
+ }
+
+ &::before {
+ background: $budget;
+ border-radius: rem-calc(20);
+ content: "";
+ height: rem-calc(20);
+ position: absolute;
+ top: 5px;
+ transform: translateX(-50%);
+ width: rem-calc(20);
+ z-index: 2;
+ }
+
+ &::after {
+ background: $light-gray;
+ bottom: 100%;
+ content: "";
+ height: 100%;
+ position: absolute;
+ top: 25px;
+ width: 1px;
+ z-index: 1;
+ }
+
+ .milestone-content {
+ padding: $line-height / 6 $line-height / 2;
+ position: relative;
+
+ @include breakpoint(medium) {
+ width: rem-calc(300);
+ }
+
+ @include breakpoint(large) {
+ width: rem-calc(450);
+ }
+
+ h3 {
+ margin-bottom: 0;
+ }
+
+ .milestone-date {
+ color: $text-medium;
+ font-size: $small-font-size;
+ }
+ }
+
+ &:nth-child(odd) {
+
+ .milestone-content {
+ text-align: right;
+
+ @include breakpoint(medium) {
+ margin-left: rem-calc(-315);
+ }
+
+ @include breakpoint(large) {
+ margin-left: rem-calc(-465);
+ }
+
+ @include breakpoint(small only) {
+ left: 15px;
+ text-align: left;
+ }
+ }
+ }
+
+ &:nth-child(even) {
+
+ .milestone-content {
+ left: 15px;
+ }
+ }
+}
+
+.milestone-status {
+ background: $budget;
+ border-radius: rem-calc(4);
+ color: #fff;
+ display: inline-block;
+ margin-top: $line-height / 6;
+ padding: $line-height / 4 $line-height / 2;
+}
diff --git a/app/assets/stylesheets/mixins.scss b/app/assets/stylesheets/mixins.scss
index ac3c0a923..e1f293c13 100644
--- a/app/assets/stylesheets/mixins.scss
+++ b/app/assets/stylesheets/mixins.scss
@@ -11,7 +11,7 @@
@mixin logo {
color: #fff;
display: inline-block;
- font-family: 'Lato' !important;
+ font-family: "Lato" !important;
font-size: rem-calc(24);
font-weight: lighter;
@@ -19,18 +19,6 @@
line-height: $line-height * 2;
margin-top: 0;
}
-
- img {
- height: 48px;
- width: 48px;
-
- @include breakpoint(medium) {
- height: 80px;
- margin-right: $line-height / 2;
- margin-top: 0;
- width: 80px;
- }
- }
}
// 02. Orbit bullet
diff --git a/app/assets/stylesheets/pages.scss b/app/assets/stylesheets/pages.scss
index efde88d07..3df5ac3c1 100644
--- a/app/assets/stylesheets/pages.scss
+++ b/app/assets/stylesheets/pages.scss
@@ -23,11 +23,6 @@
&.light {
background: #ecf0f1;
}
-
- h1,
- p {
- color: $text;
- }
}
.lead {
diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss
index 559599297..acbe5895b 100644
--- a/app/assets/stylesheets/participation.scss
+++ b/app/assets/stylesheets/participation.scss
@@ -287,7 +287,7 @@
margin: $line-height / 2 0;
&::before {
- content: 'l ';
+ content: "l ";
font-family: "icons" !important;
}
}
@@ -524,118 +524,6 @@
}
}
-.tab-milestones ul {
- margin-top: rem-calc(40);
- position: relative;
-
- li {
- margin: 0 auto;
- position: relative;
- width: 0;
- }
-
- li::before {
- background: $budget;
- border-radius: rem-calc(20);
- content: '';
- height: rem-calc(20);
- position: absolute;
- top: 5px;
- transform: translateX(-50%);
- width: rem-calc(20);
- z-index: 2;
- }
-
- li::after {
- background: $light-gray;
- bottom: 100%;
- content: '';
- height: 100%;
- position: absolute;
- top: 25px;
- width: 1px;
- z-index: 1;
- }
-}
-
-.tab-milestones ul .milestone-content {
- padding: $line-height / 6 $line-height / 2;
- position: relative;
-
- h3 {
- margin-bottom: 0;
- }
-
- .milestone-date {
- color: $text-medium;
- font-size: $small-font-size;
- }
-}
-
-.tab-milestones .timeline ul li:nth-child(odd),
-.tab-milestones .timeline ul li:nth-child(even) {
-
- .milestone-content {
-
- @include breakpoint(medium) {
- width: rem-calc(300);
- }
-
- @include breakpoint(large) {
- width: rem-calc(450);
- }
- }
-}
-
-.tab-milestones .timeline ul li:nth-child(odd) {
-
- .milestone-content {
- text-align: right;
-
- @include breakpoint(medium) {
- margin-left: rem-calc(-315);
- }
-
- @include breakpoint(large) {
- margin-left: rem-calc(-465);
- }
- }
-}
-
-.tab-milestones .timeline ul li:nth-child(even) {
-
- .milestone-content {
- left: 15px;
- }
-}
-
-.tab-milestones {
- @include breakpoint(small only) {
-
- .timeline ul li {
- width: 100%;
-
- &:nth-child(odd),
- &:nth-child(even) {
-
- .milestone-content {
- left: 15px;
- text-align: left;
- }
- }
- }
- }
-}
-
-.milestone-status {
- background: $budget;
- border-radius: rem-calc(4);
- color: #fff;
- display: inline-block;
- margin-top: $line-height / 6;
- padding: $line-height / 4 $line-height / 2;
-}
-
.show-actions-menu {
[class^="icon-"] {
@@ -761,6 +649,10 @@
&.past-budgets {
min-height: 0;
+
+ .button ~ .button {
+ margin-left: $line-height / 2;
+ }
}
}
@@ -842,7 +734,7 @@
}
.truncate {
- background: image-url('truncate.png');
+ background: image-url("truncate.png");
background-repeat: repeat-x;
bottom: 0;
height: rem-calc(24);
@@ -1047,7 +939,7 @@
&::before {
color: $text;
- font-family: 'icons';
+ font-family: "icons";
}
}
@@ -1056,7 +948,7 @@
.button {
&::before {
- content: '\51';
+ content: "\51";
}
}
}
@@ -1066,7 +958,7 @@
.button {
&::before {
- content: '\22';
+ content: "\22";
}
}
}
@@ -1075,8 +967,8 @@
position: relative;
&::before {
- content: '\22';
- font-family: 'icons';
+ content: "\22";
+ font-family: "icons";
left: 0;
position: absolute;
top: 6px;
@@ -1087,20 +979,20 @@
position: relative;
&::before {
- content: '\51';
- font-family: 'icons';
+ content: "\51";
+ font-family: "icons";
left: 0;
position: absolute;
top: 6px;
}
}
- .active {
+ .is-active {
color: $brand;
&::after {
- content: '\6c';
- font-family: 'icons';
+ content: "\6c";
+ font-family: "icons";
font-size: $tiny-font-size;
}
}
@@ -1362,16 +1254,12 @@
display: inline-block;
margin-bottom: $line-height / 2;
- &:hover {
- background: $highlight;
- text-decoration: none;
- }
-
a {
display: block;
padding: $line-height / 2;
&:hover {
+ background: $highlight;
text-decoration: none;
}
}
@@ -1419,8 +1307,8 @@
&::before {
color: #a5a1ff;
- content: '\57';
- font-family: 'icons';
+ content: "\57";
+ font-family: "icons";
font-size: $small-font-size;
position: absolute;
right: -6px;
@@ -1563,8 +1451,8 @@
font-weight: bold;
&::after {
- content: '\56';
- font-family: 'icons';
+ content: "\56";
+ font-family: "icons";
font-size: $small-font-size;
font-weight: normal;
line-height: $line-height;
@@ -1578,7 +1466,6 @@
}
.progress-bar-nav {
- padding: $line-height 0;
position: relative;
z-index: 3;
@@ -1640,7 +1527,7 @@
background-color: #fff;
border: 4px solid $budget;
border-radius: 100%;
- content: '';
+ content: "";
height: 16px;
left: -22px;
position: absolute;
@@ -1681,6 +1568,60 @@
}
}
+.budget-execution {
+ border: 1px solid $border;
+ overflow: hidden;
+ position: relative;
+
+ a {
+ color: $text;
+ display: block;
+
+ img {
+ height: $line-height * 9;
+ min-width: 100%;
+ max-width: none;
+ transition-duration: 0.3s;
+ transition-property: transform;
+ }
+
+ &:hover {
+ text-decoration: none;
+
+ img {
+ transform: scale(1.05);
+ }
+ }
+ }
+
+ h5 {
+ font-size: $base-font-size;
+ margin-bottom: 0;
+ }
+
+ .budget-execution-info {
+ padding: $line-height / 2;
+ }
+
+ .author {
+ color: $text-medium;
+ font-size: $small-font-size;
+ }
+
+ .budget-execution-content {
+ min-height: $line-height * 3;
+ }
+
+ .price {
+ color: $budget;
+ font-size: rem-calc(24);
+ }
+
+ &:hover {
+ box-shadow: 0 0 12px 0 rgba(0, 0, 0, 0.2);
+ }
+}
+
// 07. Proposals successful
// -------------------------
@@ -1728,7 +1669,7 @@
&::after {
color: #1b254c;
- content: '\59';
+ content: "\59";
font-family: "icons" !important;
left: 34px;
position: absolute;
@@ -1832,10 +1773,6 @@
.orbit-slide {
max-height: none !important;
-
- img {
- image-rendering: pixelated;
- }
}
.orbit-caption {
@@ -1925,7 +1862,7 @@
&::after {
color: $color-info;
- content: '\6c';
+ content: "\6c";
}
}
@@ -1934,7 +1871,7 @@
&::after {
color: $color-alert;
- content: '\74';
+ content: "\74";
}
}
@@ -1943,7 +1880,7 @@
&::after {
color: $color-info;
- content: '\6f';
+ content: "\6f";
}
}
@@ -1952,7 +1889,7 @@
&::after {
color: $color-warning;
- content: '\6f';
+ content: "\6f";
}
}
@@ -1961,7 +1898,7 @@
&::after {
color: $color-success;
- content: '\59';
+ content: "\59";
}
}
}
@@ -2027,7 +1964,7 @@
&::after {
background: #92ba48;
border-radius: rem-calc(20);
- content: '\6c';
+ content: "\6c";
color: #fff;
font-family: "icons" !important;
font-size: rem-calc(12);
diff --git a/app/controllers/admin/admin_notifications_controller.rb b/app/controllers/admin/admin_notifications_controller.rb
index 33e99f9ed..430e51f53 100644
--- a/app/controllers/admin/admin_notifications_controller.rb
+++ b/app/controllers/admin/admin_notifications_controller.rb
@@ -63,8 +63,7 @@ class Admin::AdminNotificationsController < Admin::BaseController
private
def admin_notification_params
- attributes = [:title, :body, :link, :segment_recipient,
- *translation_params(AdminNotification)]
+ attributes = [:link, :segment_recipient, translation_params(AdminNotification)]
params.require(:admin_notification).permit(attributes)
end
diff --git a/app/controllers/admin/api/stats_controller.rb b/app/controllers/admin/api/stats_controller.rb
index fe8c72cdd..af8ffb3aa 100644
--- a/app/controllers/admin/api/stats_controller.rb
+++ b/app/controllers/admin/api/stats_controller.rb
@@ -11,7 +11,7 @@ class Admin::Api::StatsController < Admin::Api::BaseController
ds = Ahoy::DataSource.new
if params[:events].present?
- event_types = params[:events].split ','
+ event_types = params[:events].split ","
event_types.each do |event|
ds.add event.titleize, Ahoy::Event.where(name: event).group_by_day(:time).count
end
diff --git a/app/controllers/admin/banners_controller.rb b/app/controllers/admin/banners_controller.rb
index b17c17d1b..1a486bb56 100644
--- a/app/controllers/admin/banners_controller.rb
+++ b/app/controllers/admin/banners_controller.rb
@@ -38,23 +38,22 @@ class Admin::BannersController < Admin::BaseController
private
def banner_params
- attributes = [:title, :description, :target_url,
- :post_started_at, :post_ended_at,
+ attributes = [:target_url, :post_started_at, :post_ended_at,
:background_color, :font_color,
- *translation_params(Banner),
+ translation_params(Banner),
web_section_ids: []]
params.require(:banner).permit(*attributes)
end
def banner_styles
@banner_styles = Setting.all.banner_style.map do |banner_style|
- [banner_style.value, banner_style.key.split('.')[1]]
+ [banner_style.value, banner_style.key.split(".")[1]]
end
end
def banner_imgs
@banner_imgs = Setting.all.banner_img.map do |banner_img|
- [banner_img.value, banner_img.key.split('.')[1]]
+ [banner_img.value, banner_img.key.split(".")[1]]
end
end
diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb
index 7a812104b..a12540871 100644
--- a/app/controllers/admin/base_controller.rb
+++ b/app/controllers/admin/base_controller.rb
@@ -1,5 +1,5 @@
class Admin::BaseController < ApplicationController
- layout 'admin'
+ layout "admin"
before_action :authenticate_user!
skip_authorization_check
diff --git a/app/controllers/admin/budget_groups_controller.rb b/app/controllers/admin/budget_groups_controller.rb
index d8048de48..aa87e2373 100644
--- a/app/controllers/admin/budget_groups_controller.rb
+++ b/app/controllers/admin/budget_groups_controller.rb
@@ -1,23 +1,65 @@
class Admin::BudgetGroupsController < Admin::BaseController
+ include Translatable
include FeatureFlags
feature_flag :budgets
+ before_action :load_budget
+ before_action :load_group, except: [:index, :new, :create]
+
+ def index
+ @groups = @budget.groups.order(:id)
+ end
+
+ def new
+ @group = @budget.groups.new
+ end
+
+ def edit
+ end
+
def create
- @budget = Budget.find(params[:budget_id])
- @budget.groups.create(budget_group_params)
- @groups = @budget.groups.includes(:headings)
+ @group = @budget.groups.new(budget_group_params)
+ if @group.save
+ redirect_to groups_index, notice: t("admin.budget_groups.create.notice")
+ else
+ render :new
+ end
end
def update
- @budget = Budget.find(params[:budget_id])
- @group = @budget.groups.find(params[:id])
- @group.update(budget_group_params)
+ if @group.update(budget_group_params)
+ redirect_to groups_index, notice: t("admin.budget_groups.update.notice")
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ if @group.headings.any?
+ redirect_to groups_index, alert: t("admin.budget_groups.destroy.unable_notice")
+ else
+ @group.destroy
+ redirect_to groups_index, notice: t("admin.budget_groups.destroy.success_notice")
+ end
end
private
+ def load_budget
+ @budget = Budget.includes(:groups).find(params[:budget_id])
+ end
+
+ def load_group
+ @group = @budget.groups.find(params[:id])
+ end
+
+ def groups_index
+ admin_budget_groups_path(@budget)
+ end
+
def budget_group_params
- params.require(:budget_group).permit(:name, :max_votable_headings)
+ valid_attributes = [:max_votable_headings]
+ params.require(:budget_group).permit(*valid_attributes, translation_params(Budget::Group))
end
end
diff --git a/app/controllers/admin/budget_headings_controller.rb b/app/controllers/admin/budget_headings_controller.rb
index 902f256b5..46e46bc62 100644
--- a/app/controllers/admin/budget_headings_controller.rb
+++ b/app/controllers/admin/budget_headings_controller.rb
@@ -1,39 +1,70 @@
class Admin::BudgetHeadingsController < Admin::BaseController
+ include Translatable
include FeatureFlags
feature_flag :budgets
- def create
- @budget = Budget.find(params[:budget_id])
- @budget_group = @budget.groups.find(params[:budget_group_id])
- @budget_group.headings.create(budget_heading_params)
- @headings = @budget_group.headings
+ before_action :load_budget
+ before_action :load_group
+ before_action :load_heading, except: [:index, :new, :create]
+
+ def index
+ @headings = @group.headings.order(:id)
+ end
+
+ def new
+ @heading = @group.headings.new
end
def edit
- @budget = Budget.find(params[:budget_id])
- @budget_group = @budget.groups.find(params[:budget_group_id])
- @heading = Budget::Heading.find(params[:id])
+ end
+
+ def create
+ @heading = @group.headings.new(budget_heading_params)
+ if @heading.save
+ redirect_to headings_index, notice: t("admin.budget_headings.create.notice")
+ else
+ render :new
+ end
end
def update
- @budget = Budget.find(params[:budget_id])
- @budget_group = @budget.groups.find(params[:budget_group_id])
- @heading = Budget::Heading.find(params[:id])
- @heading.assign_attributes(budget_heading_params)
- render :edit unless @heading.save
+ if @heading.update(budget_heading_params)
+ redirect_to headings_index, notice: t("admin.budget_headings.update.notice")
+ else
+ render :edit
+ end
end
def destroy
- @heading = Budget::Heading.find(params[:id])
- @heading.destroy
- @budget = Budget.find(params[:budget_id])
- redirect_to admin_budget_path(@budget)
+ if @heading.can_be_deleted?
+ @heading.destroy
+ redirect_to headings_index, notice: t("admin.budget_headings.destroy.success_notice")
+ else
+ redirect_to headings_index, alert: t("admin.budget_headings.destroy.unable_notice")
+ end
end
private
+ def load_budget
+ @budget = Budget.includes(:groups).find(params[:budget_id])
+ end
+
+ def load_group
+ @group = @budget.groups.find(params[:group_id])
+ end
+
+ def load_heading
+ @heading = @group.headings.find(params[:id])
+ end
+
+ def headings_index
+ admin_budget_group_headings_path(@budget, @group)
+ end
+
def budget_heading_params
- params.require(:budget_heading).permit(:name, :price, :population)
+ valid_attributes = [:price, :population, :allow_custom_content, :latitude, :longitude]
+ params.require(:budget_heading).permit(*valid_attributes, translation_params(Budget::Heading))
end
end
diff --git a/app/controllers/admin/budget_investment_milestones_controller.rb b/app/controllers/admin/budget_investment_milestones_controller.rb
index 49f2df5bf..f354d42fa 100644
--- a/app/controllers/admin/budget_investment_milestones_controller.rb
+++ b/app/controllers/admin/budget_investment_milestones_controller.rb
@@ -1,76 +1,8 @@
-class Admin::BudgetInvestmentMilestonesController < Admin::BaseController
- include Translatable
-
- before_action :load_budget_investment, only: [:index, :new, :create, :edit, :update, :destroy]
- before_action :load_budget_investment_milestone, only: [:edit, :update, :destroy]
- before_action :load_statuses, only: [:index, :new, :create, :edit, :update]
-
- def index
- end
-
- def new
- @milestone = Budget::Investment::Milestone.new
- end
-
- def create
- @milestone = Budget::Investment::Milestone.new(milestone_params)
- @milestone.investment = @investment
- if @milestone.save
- redirect_to admin_budget_budget_investment_path(@investment.budget, @investment),
- notice: t('admin.milestones.create.notice')
- else
- render :new
- end
- end
-
- def edit
- end
-
- def update
- if @milestone.update(milestone_params)
- redirect_to admin_budget_budget_investment_path(@investment.budget, @investment),
- notice: t('admin.milestones.update.notice')
- else
- render :edit
- end
- end
-
- def destroy
- @milestone.destroy
- redirect_to admin_budget_budget_investment_path(@investment.budget, @investment),
- notice: t('admin.milestones.delete.notice')
- end
+class Admin::BudgetInvestmentMilestonesController < Admin::MilestonesController
private
- def milestone_params
- image_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
- documents_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
- attributes = [:title, :description, :publication_date, :budget_investment_id, :status_id,
- *translation_params(Budget::Investment::Milestone),
- image_attributes: image_attributes, documents_attributes: documents_attributes]
-
- params.require(:budget_investment_milestone).permit(*attributes)
+ def milestoneable
+ Budget::Investment.find(params[:budget_investment_id])
end
-
- def load_budget_investment
- @investment = Budget::Investment.find(params[:budget_investment_id])
- end
-
- def load_budget_investment_milestone
- @milestone = get_milestone
- end
-
- def get_milestone
- Budget::Investment::Milestone.find(params[:id])
- end
-
- def resource
- get_milestone
- end
-
- def load_statuses
- @statuses = Budget::Investment::Status.all
- end
-
end
diff --git a/app/controllers/admin/budget_investment_progress_bars_controller.rb b/app/controllers/admin/budget_investment_progress_bars_controller.rb
new file mode 100644
index 000000000..bb4db0d79
--- /dev/null
+++ b/app/controllers/admin/budget_investment_progress_bars_controller.rb
@@ -0,0 +1,8 @@
+class Admin::BudgetInvestmentProgressBarsController < Admin::ProgressBarsController
+
+ private
+
+ def progressable
+ Budget::Investment.find(params[:budget_investment_id])
+ end
+end
diff --git a/app/controllers/admin/budget_investment_statuses_controller.rb b/app/controllers/admin/budget_investment_statuses_controller.rb
deleted file mode 100644
index c3d7a4e16..000000000
--- a/app/controllers/admin/budget_investment_statuses_controller.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-class Admin::BudgetInvestmentStatusesController < Admin::BaseController
-
- before_action :load_status, only: [:edit, :update, :destroy]
-
- def index
- @statuses = Budget::Investment::Status.all
- end
-
- def new
- @status = Budget::Investment::Status.new
- end
-
- def create
- @status = Budget::Investment::Status.new(status_params)
-
- if @status.save
- redirect_to admin_budget_investment_statuses_path,
- notice: t('admin.statuses.create.notice')
- else
- render :new
- end
- end
-
- def edit
- end
-
- def update
- if @status.update(status_params)
- redirect_to admin_budget_investment_statuses_path,
- notice: t('admin.statuses.update.notice')
- else
- render :edit
- end
- end
-
- def destroy
- @status.destroy
- redirect_to admin_budget_investment_statuses_path,
- notice: t('admin.statuses.delete.notice')
- end
-
- private
-
- def load_status
- @status = Budget::Investment::Status.find(params[:id])
- end
-
- def status_params
- params.require(:budget_investment_status).permit([:name, :description])
- end
-end
diff --git a/app/controllers/admin/budget_investments_controller.rb b/app/controllers/admin/budget_investments_controller.rb
index 6797f63d0..1a213c2f2 100644
--- a/app/controllers/admin/budget_investments_controller.rb
+++ b/app/controllers/admin/budget_investments_controller.rb
@@ -21,7 +21,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
format.js
format.csv do
send_data Budget::Investment::Exporter.new(@investments).to_csv,
- filename: 'budget_investments.csv'
+ filename: "budget_investments.csv"
end
end
end
@@ -38,7 +38,6 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
end
def update
- set_valuation_tags
if @investment.update(budget_investment_params)
redirect_to admin_budget_budget_investment_path(@budget,
@investment,
@@ -72,12 +71,13 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
end
def resource_name
- resource_model.parameterize('_')
+ resource_model.parameterize("_")
end
def load_investments
@investments = Budget::Investment.scoped_filter(params, @current_filter)
- @investments = @investments.order_filter(params[:sort_by]) if params[:sort_by].present?
+ .order_filter(params)
+
@investments = @investments.page(params[:page]) unless request.format.csv?
end
@@ -117,11 +117,6 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
@ballot = @budget.balloting? ? query.first_or_create : query.first_or_initialize
end
- def set_valuation_tags
- @investment.set_tag_list_on(:valuation, budget_investment_params[:valuation_tag_list])
- params[:budget_investment] = params[:budget_investment].except(:valuation_tag_list)
- end
-
def parse_valuation_filters
if params[:valuator_or_group_id]
model, id = params[:valuator_or_group_id].split("_")
@@ -133,5 +128,4 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
end
end
end
-
end
diff --git a/app/controllers/admin/budget_phases_controller.rb b/app/controllers/admin/budget_phases_controller.rb
index 8b71e5a0d..3dd08675b 100644
--- a/app/controllers/admin/budget_phases_controller.rb
+++ b/app/controllers/admin/budget_phases_controller.rb
@@ -1,8 +1,10 @@
class Admin::BudgetPhasesController < Admin::BaseController
+ include Translatable
before_action :load_phase, only: [:edit, :update]
- def edit; end
+ def edit
+ end
def update
if @phase.update(budget_phase_params)
@@ -20,8 +22,8 @@ class Admin::BudgetPhasesController < Admin::BaseController
end
def budget_phase_params
- valid_attributes = [:starts_at, :ends_at, :summary, :description, :enabled]
- params.require(:budget_phase).permit(*valid_attributes)
+ valid_attributes = [:starts_at, :ends_at, :enabled]
+ params.require(:budget_phase).permit(*valid_attributes, translation_params(Budget::Phase))
end
end
diff --git a/app/controllers/admin/budgets_controller.rb b/app/controllers/admin/budgets_controller.rb
index 04b8ea0b2..252e48134 100644
--- a/app/controllers/admin/budgets_controller.rb
+++ b/app/controllers/admin/budgets_controller.rb
@@ -1,4 +1,5 @@
class Admin::BudgetsController < Admin::BaseController
+ include Translatable
include FeatureFlags
feature_flag :budgets
@@ -11,23 +12,24 @@ class Admin::BudgetsController < Admin::BaseController
end
def show
- @budget = Budget.includes(groups: :headings).find(params[:id])
end
- def new; end
+ def new
+ end
- def edit; end
+ def edit
+ end
def calculate_winners
return unless @budget.balloting_process?
@budget.headings.each { |heading| Budget::Result.new(@budget, heading).delay.calculate_winners }
- redirect_to admin_budget_budget_investments_path(budget_id: @budget.id, filter: 'winners'),
+ redirect_to admin_budget_budget_investments_path(budget_id: @budget.id, filter: "winners"),
notice: I18n.t("admin.budgets.winners.calculated")
end
def update
if @budget.update(budget_params)
- redirect_to admin_budgets_path, notice: t('admin.budgets.update.notice')
+ redirect_to admin_budgets_path, notice: t("admin.budgets.update.notice")
else
render :edit
end
@@ -36,7 +38,7 @@ class Admin::BudgetsController < Admin::BaseController
def create
@budget = Budget.new(budget_params)
if @budget.save
- redirect_to admin_budget_path(@budget), notice: t('admin.budgets.create.notice')
+ redirect_to admin_budget_path(@budget), notice: t("admin.budgets.create.notice")
else
render :new
end
@@ -44,10 +46,10 @@ class Admin::BudgetsController < Admin::BaseController
def destroy
if @budget.investments.any?
- redirect_to admin_budgets_path, alert: t('admin.budgets.destroy.unable_notice')
+ redirect_to admin_budgets_path, alert: t("admin.budgets.destroy.unable_notice")
else
@budget.destroy
- redirect_to admin_budgets_path, notice: t('admin.budgets.destroy.success_notice')
+ redirect_to admin_budgets_path, notice: t("admin.budgets.destroy.success_notice")
end
end
@@ -55,8 +57,8 @@ class Admin::BudgetsController < Admin::BaseController
def budget_params
descriptions = Budget::Phase::PHASE_KINDS.map{|p| "description_#{p}"}.map(&:to_sym)
- valid_attributes = [:name, :phase, :currency_symbol] + descriptions
- params.require(:budget).permit(*valid_attributes)
+ valid_attributes = [:phase, :currency_symbol] + descriptions
+ params.require(:budget).permit(*valid_attributes, translation_params(Budget))
end
end
diff --git a/app/controllers/admin/emails_download_controller.rb b/app/controllers/admin/emails_download_controller.rb
index 2d6c2f2ef..434dc071f 100644
--- a/app/controllers/admin/emails_download_controller.rb
+++ b/app/controllers/admin/emails_download_controller.rb
@@ -13,6 +13,6 @@ class Admin::EmailsDownloadController < Admin::BaseController
private
def users_segment_emails_csv(users_segment)
- UserSegments.user_segment_emails(users_segment).join(',')
+ UserSegments.user_segment_emails(users_segment).join(",")
end
end
diff --git a/app/controllers/admin/geozones_controller.rb b/app/controllers/admin/geozones_controller.rb
index b73c13422..def75ed27 100644
--- a/app/controllers/admin/geozones_controller.rb
+++ b/app/controllers/admin/geozones_controller.rb
@@ -35,9 +35,9 @@ class Admin::GeozonesController < Admin::BaseController
def destroy
if @geozone.safe_to_destroy?
@geozone.destroy
- redirect_to admin_geozones_path, notice: t('admin.geozones.delete.success')
+ redirect_to admin_geozones_path, notice: t("admin.geozones.delete.success")
else
- redirect_to admin_geozones_path, flash: { error: t('admin.geozones.delete.error') }
+ redirect_to admin_geozones_path, flash: { error: t("admin.geozones.delete.error") }
end
end
diff --git a/app/controllers/admin/hidden_proposals_controller.rb b/app/controllers/admin/hidden_proposals_controller.rb
new file mode 100644
index 000000000..48c910c0c
--- /dev/null
+++ b/app/controllers/admin/hidden_proposals_controller.rb
@@ -0,0 +1,33 @@
+class Admin::HiddenProposalsController < Admin::BaseController
+ include FeatureFlags
+
+ has_filters %w[without_confirmed_hide all with_confirmed_hide], only: :index
+
+ feature_flag :proposals
+
+ before_action :load_proposal, only: [:confirm_hide, :restore]
+
+ def index
+ @proposals = Proposal.only_hidden.send(@current_filter).order(hidden_at: :desc)
+ .page(params[:page])
+ end
+
+ def confirm_hide
+ @proposal.confirm_hide
+ redirect_to request.query_parameters.merge(action: :index)
+ end
+
+ def restore
+ @proposal.restore
+ @proposal.ignore_flag
+ Activity.log(current_user, :restore, @proposal)
+ redirect_to request.query_parameters.merge(action: :index)
+ end
+
+ private
+
+ def load_proposal
+ @proposal = Proposal.with_hidden.find(params[:id])
+ end
+
+end
diff --git a/app/controllers/admin/homepage_controller.rb b/app/controllers/admin/homepage_controller.rb
index 93c5e070b..50a433df5 100644
--- a/app/controllers/admin/homepage_controller.rb
+++ b/app/controllers/admin/homepage_controller.rb
@@ -14,7 +14,7 @@ class Admin::HomepageController < Admin::BaseController
end
def load_recommendations
- @recommendations = Setting.where(key: 'feature.user.recommendations').first
+ @recommendations = Setting.where(key: "feature.user.recommendations").first
end
def load_cards
@@ -25,4 +25,4 @@ class Admin::HomepageController < Admin::BaseController
@feeds = Widget::Feed.order("created_at")
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/admin/legislation/draft_versions_controller.rb b/app/controllers/admin/legislation/draft_versions_controller.rb
index 703d8a543..21a4564ff 100644
--- a/app/controllers/admin/legislation/draft_versions_controller.rb
+++ b/app/controllers/admin/legislation/draft_versions_controller.rb
@@ -11,10 +11,10 @@ class Admin::Legislation::DraftVersionsController < Admin::Legislation::BaseCont
def create
if @draft_version.save
link = legislation_process_draft_version_path(@process, @draft_version).html_safe
- notice = t('admin.legislation.draft_versions.create.notice', link: link)
+ notice = t("admin.legislation.draft_versions.create.notice", link: link)
redirect_to admin_legislation_process_draft_versions_path, notice: notice
else
- flash.now[:error] = t('admin.legislation.draft_versions.create.error')
+ flash.now[:error] = t("admin.legislation.draft_versions.create.error")
render :new
end
end
@@ -22,18 +22,18 @@ class Admin::Legislation::DraftVersionsController < Admin::Legislation::BaseCont
def update
if @draft_version.update(draft_version_params)
link = legislation_process_draft_version_path(@process, @draft_version).html_safe
- notice = t('admin.legislation.draft_versions.update.notice', link: link)
+ notice = t("admin.legislation.draft_versions.update.notice", link: link)
edit_path = edit_admin_legislation_process_draft_version_path(@process, @draft_version)
redirect_to edit_path, notice: notice
else
- flash.now[:error] = t('admin.legislation.draft_versions.update.error')
+ flash.now[:error] = t("admin.legislation.draft_versions.update.error")
render :edit
end
end
def destroy
@draft_version.destroy
- notice = t('admin.legislation.draft_versions.destroy.notice')
+ notice = t("admin.legislation.draft_versions.destroy.notice")
redirect_to admin_legislation_process_draft_versions_path, notice: notice
end
@@ -41,13 +41,9 @@ class Admin::Legislation::DraftVersionsController < Admin::Legislation::BaseCont
def draft_version_params
params.require(:legislation_draft_version).permit(
- :title,
- :changelog,
:status,
:final_version,
- :body,
- :body_html,
- *translation_params(Legislation::DraftVersion)
+ translation_params(Legislation::DraftVersion)
)
end
diff --git a/app/controllers/admin/legislation/homepages_controller.rb b/app/controllers/admin/legislation/homepages_controller.rb
new file mode 100644
index 000000000..6b2084448
--- /dev/null
+++ b/app/controllers/admin/legislation/homepages_controller.rb
@@ -0,0 +1,36 @@
+class Admin::Legislation::HomepagesController < Admin::Legislation::BaseController
+ include Translatable
+
+ load_and_authorize_resource :process, class: "Legislation::Process"
+
+ def edit
+ end
+
+ def update
+ if @process.update(process_params)
+ link = legislation_process_path(@process).html_safe
+ redirect_to :back, notice: t("admin.legislation.processes.update.notice", link: link)
+ else
+ flash.now[:error] = t("admin.legislation.processes.update.error")
+ render :edit
+ end
+ end
+
+ private
+
+ def process_params
+ params.require(:legislation_process).permit(allowed_params)
+ end
+
+ def allowed_params
+ [
+ :homepage,
+ :homepage_enabled,
+ translation_params(::Legislation::Process)
+ ]
+ end
+
+ def resource
+ @process || ::Legislation::Process.find(params[:id])
+ end
+end
diff --git a/app/controllers/admin/legislation/milestones_controller.rb b/app/controllers/admin/legislation/milestones_controller.rb
new file mode 100644
index 000000000..09d55f6ca
--- /dev/null
+++ b/app/controllers/admin/legislation/milestones_controller.rb
@@ -0,0 +1,18 @@
+class Admin::Legislation::MilestonesController < Admin::MilestonesController
+ include FeatureFlags
+ feature_flag :legislation
+
+ def index
+ @process = milestoneable
+ end
+
+ private
+
+ def milestoneable
+ ::Legislation::Process.find(params[:process_id])
+ end
+
+ def milestoneable_path
+ admin_legislation_process_milestones_path(milestoneable)
+ end
+end
diff --git a/app/controllers/admin/legislation/processes_controller.rb b/app/controllers/admin/legislation/processes_controller.rb
index 2cb20d0ba..6c0d2ea6f 100644
--- a/app/controllers/admin/legislation/processes_controller.rb
+++ b/app/controllers/admin/legislation/processes_controller.rb
@@ -1,21 +1,23 @@
class Admin::Legislation::ProcessesController < Admin::Legislation::BaseController
include Translatable
+ include ImageAttributes
- has_filters %w{open next past all}, only: :index
+ has_filters %w[active all], only: :index
load_and_authorize_resource :process, class: "Legislation::Process"
def index
- @processes = ::Legislation::Process.send(@current_filter).order('id DESC').page(params[:page])
+ @processes = ::Legislation::Process.send(@current_filter).order(start_date: :desc)
+ .page(params[:page])
end
def create
if @process.save
link = legislation_process_path(@process).html_safe
- notice = t('admin.legislation.processes.create.notice', link: link)
+ notice = t("admin.legislation.processes.create.notice", link: link)
redirect_to edit_admin_legislation_process_path(@process), notice: notice
else
- flash.now[:error] = t('admin.legislation.processes.create.error')
+ flash.now[:error] = t("admin.legislation.processes.create.error")
render :new
end
end
@@ -25,31 +27,33 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseControll
set_tag_list
link = legislation_process_path(@process).html_safe
- redirect_to :back, notice: t('admin.legislation.processes.update.notice', link: link)
+ redirect_to :back, notice: t("admin.legislation.processes.update.notice", link: link)
else
- flash.now[:error] = t('admin.legislation.processes.update.error')
+ flash.now[:error] = t("admin.legislation.processes.update.error")
render :edit
end
end
def destroy
@process.destroy
- notice = t('admin.legislation.processes.destroy.notice')
+ notice = t("admin.legislation.processes.destroy.notice")
redirect_to admin_legislation_processes_path, notice: notice
end
private
def process_params
- params.require(:legislation_process).permit(
- :title,
- :summary,
- :description,
- :additional_info,
+ params.require(:legislation_process).permit(allowed_params)
+ end
+
+ def allowed_params
+ [
:start_date,
:end_date,
:debate_start_date,
:debate_end_date,
+ :draft_start_date,
+ :draft_end_date,
:draft_publication_date,
:allegations_start_date,
:allegations_end_date,
@@ -57,15 +61,19 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseControll
:proposals_phase_end_date,
:result_publication_date,
:debate_phase_enabled,
+ :draft_phase_enabled,
:allegations_phase_enabled,
:proposals_phase_enabled,
:draft_publication_enabled,
:result_publication_enabled,
:published,
:custom_list,
- *translation_params(Legislation::Process),
- documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
- )
+ :background_color,
+ :font_color,
+ translation_params(::Legislation::Process),
+ documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy],
+ image_attributes: image_attributes
+ ]
end
def set_tag_list
@@ -74,6 +82,6 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseControll
end
def resource
- @process || Legislation::Process.find(params[:id])
+ @process || ::Legislation::Process.find(params[:id])
end
end
diff --git a/app/controllers/admin/legislation/progress_bars_controller.rb b/app/controllers/admin/legislation/progress_bars_controller.rb
new file mode 100644
index 000000000..ba00d5e91
--- /dev/null
+++ b/app/controllers/admin/legislation/progress_bars_controller.rb
@@ -0,0 +1,14 @@
+class Admin::Legislation::ProgressBarsController < Admin::ProgressBarsController
+ include FeatureFlags
+ feature_flag :legislation
+
+ def index
+ @process = progressable
+ end
+
+ private
+
+ def progressable
+ ::Legislation::Process.find(params[:process_id])
+ end
+end
diff --git a/app/controllers/admin/legislation/questions_controller.rb b/app/controllers/admin/legislation/questions_controller.rb
index da73e905c..e5bcb57ae 100644
--- a/app/controllers/admin/legislation/questions_controller.rb
+++ b/app/controllers/admin/legislation/questions_controller.rb
@@ -9,33 +9,32 @@ class Admin::Legislation::QuestionsController < Admin::Legislation::BaseControll
end
def new
- @question.question_options.build
end
def create
@question.author = current_user
if @question.save
- notice = t('admin.legislation.questions.create.notice', link: question_path)
+ notice = t("admin.legislation.questions.create.notice", link: question_path)
redirect_to admin_legislation_process_questions_path, notice: notice
else
- flash.now[:error] = t('admin.legislation.questions.create.error')
+ flash.now[:error] = t("admin.legislation.questions.create.error")
render :new
end
end
def update
if @question.update(question_params)
- notice = t('admin.legislation.questions.update.notice', link: question_path)
+ notice = t("admin.legislation.questions.update.notice", link: question_path)
redirect_to edit_admin_legislation_process_question_path(@process, @question), notice: notice
else
- flash.now[:error] = t('admin.legislation.questions.update.error')
+ flash.now[:error] = t("admin.legislation.questions.update.error")
render :edit
end
end
def destroy
@question.destroy
- notice = t('admin.legislation.questions.destroy.notice')
+ notice = t("admin.legislation.questions.destroy.notice")
redirect_to admin_legislation_process_questions_path, notice: notice
end
@@ -47,10 +46,9 @@ class Admin::Legislation::QuestionsController < Admin::Legislation::BaseControll
def question_params
params.require(:legislation_question).permit(
- :title,
- *translation_params(::Legislation::Question),
- question_options_attributes: [:id, :value,
- *translation_params(::Legislation::QuestionOption)]
+ translation_params(::Legislation::Question),
+ question_options_attributes: [:id, :_destroy,
+ translation_params(::Legislation::QuestionOption)]
)
end
diff --git a/app/controllers/admin/milestone_statuses_controller.rb b/app/controllers/admin/milestone_statuses_controller.rb
new file mode 100644
index 000000000..b7cbb7b4d
--- /dev/null
+++ b/app/controllers/admin/milestone_statuses_controller.rb
@@ -0,0 +1,51 @@
+class Admin::MilestoneStatusesController < Admin::BaseController
+
+ before_action :load_status, only: [:edit, :update, :destroy]
+
+ def index
+ @statuses = Milestone::Status.all
+ end
+
+ def new
+ @status = Milestone::Status.new
+ end
+
+ def create
+ @status = Milestone::Status.new(status_params)
+
+ if @status.save
+ redirect_to admin_milestone_statuses_path,
+ notice: t("admin.statuses.create.notice")
+ else
+ render :new
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ if @status.update(status_params)
+ redirect_to admin_milestone_statuses_path,
+ notice: t("admin.statuses.update.notice")
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @status.destroy
+ redirect_to admin_milestone_statuses_path,
+ notice: t("admin.statuses.delete.notice")
+ end
+
+ private
+
+ def load_status
+ @status = Milestone::Status.find(params[:id])
+ end
+
+ def status_params
+ params.require(:milestone_status).permit([:name, :description])
+ end
+end
diff --git a/app/controllers/admin/milestones_controller.rb b/app/controllers/admin/milestones_controller.rb
new file mode 100644
index 000000000..e6fbe100b
--- /dev/null
+++ b/app/controllers/admin/milestones_controller.rb
@@ -0,0 +1,72 @@
+class Admin::MilestonesController < Admin::BaseController
+ include Translatable
+ include ImageAttributes
+
+ before_action :load_milestoneable, only: [:index, :new, :create, :edit, :update, :destroy]
+ before_action :load_milestone, only: [:edit, :update, :destroy]
+ before_action :load_statuses, only: [:index, :new, :create, :edit, :update]
+ helper_method :milestoneable_path
+
+ def index
+ end
+
+ def new
+ @milestone = @milestoneable.milestones.new
+ end
+
+ def create
+ @milestone = @milestoneable.milestones.new(milestone_params)
+ if @milestone.save
+ redirect_to milestoneable_path, notice: t("admin.milestones.create.notice")
+ else
+ render :new
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ if @milestone.update(milestone_params)
+ redirect_to milestoneable_path, notice: t("admin.milestones.update.notice")
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @milestone.destroy
+ redirect_to milestoneable_path, notice: t("admin.milestones.delete.notice")
+ end
+
+ private
+
+ def milestone_params
+ documents_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
+ attributes = [:publication_date, :status_id,
+ translation_params(Milestone),
+ image_attributes: image_attributes, documents_attributes: documents_attributes]
+
+ params.require(:milestone).permit(*attributes)
+ end
+
+ def load_milestoneable
+ @milestoneable = milestoneable
+ end
+
+ def milestoneable
+ raise "Implement in subclass"
+ end
+
+ def load_milestone
+ @milestone = @milestoneable.milestones.find(params[:id])
+ end
+
+ def load_statuses
+ @statuses = Milestone::Status.all
+ end
+
+ def milestoneable_path
+ polymorphic_path([:admin, *resource_hierarchy_for(@milestone.milestoneable)])
+ end
+end
diff --git a/app/controllers/admin/organizations_controller.rb b/app/controllers/admin/organizations_controller.rb
index b85460459..9c26147e2 100644
--- a/app/controllers/admin/organizations_controller.rb
+++ b/app/controllers/admin/organizations_controller.rb
@@ -6,14 +6,14 @@ class Admin::OrganizationsController < Admin::BaseController
def index
@organizations = @organizations.send(@current_filter)
@organizations = @organizations.includes(:user)
- .order('users.created_at', :name, 'users.email')
+ .order("users.created_at", :name, "users.email")
.page(params[:page])
end
def search
@organizations = Organization.includes(:user)
.search(params[:term])
- .order('users.created_at', :name, 'users.email')
+ .order("users.created_at", :name, "users.email")
.page(params[:page])
end
@@ -27,4 +27,4 @@ class Admin::OrganizationsController < Admin::BaseController
redirect_to request.query_parameters.merge(action: :index)
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/admin/poll/active_polls_controller.rb b/app/controllers/admin/poll/active_polls_controller.rb
new file mode 100644
index 000000000..97665ac2f
--- /dev/null
+++ b/app/controllers/admin/poll/active_polls_controller.rb
@@ -0,0 +1,36 @@
+class Admin::Poll::ActivePollsController < Admin::Poll::BaseController
+ include Translatable
+
+ before_action :load_active_poll
+
+ def create
+ if @active_poll.update(active_poll_params)
+ redirect_to admin_polls_url, notice: t("flash.actions.update.active_poll")
+ else
+ render :edit
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ if @active_poll.update(active_poll_params)
+ redirect_to admin_polls_url, notice: t("flash.actions.update.active_poll")
+ else
+ render :edit
+ end
+ end
+
+
+ private
+
+ def load_active_poll
+ @active_poll = ::ActivePoll.first_or_initialize
+ end
+
+ def active_poll_params
+ params.require(:active_poll).permit(translation_params(ActivePoll))
+ end
+
+end
diff --git a/app/controllers/admin/poll/booth_assignments_controller.rb b/app/controllers/admin/poll/booth_assignments_controller.rb
index ea1f2f28f..7ddf01b1e 100644
--- a/app/controllers/admin/poll/booth_assignments_controller.rb
+++ b/app/controllers/admin/poll/booth_assignments_controller.rb
@@ -3,7 +3,7 @@ class Admin::Poll::BoothAssignmentsController < Admin::Poll::BaseController
before_action :load_poll, except: [:create, :destroy]
def index
- @booth_assignments = @poll.booth_assignments.includes(:booth).order('poll_booths.name')
+ @booth_assignments = @poll.booth_assignments.includes(:booth).order("poll_booths.name")
.page(params[:page]).per(50)
end
diff --git a/app/controllers/admin/poll/booths_controller.rb b/app/controllers/admin/poll/booths_controller.rb
index 7a3a1370d..514389203 100644
--- a/app/controllers/admin/poll/booths_controller.rb
+++ b/app/controllers/admin/poll/booths_controller.rb
@@ -1,5 +1,5 @@
class Admin::Poll::BoothsController < Admin::Poll::BaseController
- load_and_authorize_resource class: 'Poll::Booth'
+ load_and_authorize_resource class: "Poll::Booth"
def index
@booths = @booths.order(name: :asc).page(params[:page])
diff --git a/app/controllers/admin/poll/officer_assignments_controller.rb b/app/controllers/admin/poll/officer_assignments_controller.rb
index d46d0418e..b23795d52 100644
--- a/app/controllers/admin/poll/officer_assignments_controller.rb
+++ b/app/controllers/admin/poll/officer_assignments_controller.rb
@@ -7,7 +7,7 @@ class Admin::Poll::OfficerAssignmentsController < Admin::Poll::BaseController
def index
@officers = ::Poll::Officer.
includes(:user).
- order('users.username').
+ order("users.username").
where(
id: @poll.officer_assignments.select(:officer_id).distinct.map(&:officer_id)
).page(params[:page]).per(50)
diff --git a/app/controllers/admin/poll/officers_controller.rb b/app/controllers/admin/poll/officers_controller.rb
index 1d5c19634..5a24251c4 100644
--- a/app/controllers/admin/poll/officers_controller.rb
+++ b/app/controllers/admin/poll/officers_controller.rb
@@ -30,10 +30,4 @@ class Admin::Poll::OfficersController < Admin::Poll::BaseController
redirect_to admin_officers_path
end
- def show
- end
-
- def edit
- end
-
end
diff --git a/app/controllers/admin/poll/polls_controller.rb b/app/controllers/admin/poll/polls_controller.rb
index e93a82d47..b012aad38 100644
--- a/app/controllers/admin/poll/polls_controller.rb
+++ b/app/controllers/admin/poll/polls_controller.rb
@@ -1,16 +1,18 @@
class Admin::Poll::PollsController < Admin::Poll::BaseController
include Translatable
+ include ImageAttributes
load_and_authorize_resource
before_action :load_search, only: [:search_booths, :search_officers]
before_action :load_geozones, only: [:new, :create, :edit, :update]
def index
+ @polls = Poll.order(starts_at: :desc)
end
def show
@poll = Poll.includes(:questions).
- order('poll_questions.title').
+ order("poll_questions.title").
find(params[:id])
end
@@ -50,7 +52,7 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController
end
def booth_assignments
- @polls = Poll.current_or_incoming
+ @polls = Poll.current
end
private
@@ -60,11 +62,10 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController
end
def poll_params
- image_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
- attributes = [:name, :starts_at, :ends_at, :geozone_restricted, :summary, :description,
- :results_enabled, :stats_enabled, geozone_ids: [],
+ attributes = [:name, :starts_at, :ends_at, :geozone_restricted, :results_enabled,
+ :stats_enabled, geozone_ids: [],
image_attributes: image_attributes]
- params.require(:poll).permit(*attributes, *translation_params(Poll))
+ params.require(:poll).permit(*attributes, translation_params(Poll))
end
def search_params
diff --git a/app/controllers/admin/poll/questions/answers_controller.rb b/app/controllers/admin/poll/questions/answers_controller.rb
index 1d549ba3f..7b56de3c1 100644
--- a/app/controllers/admin/poll/questions/answers_controller.rb
+++ b/app/controllers/admin/poll/questions/answers_controller.rb
@@ -11,9 +11,10 @@ class Admin::Poll::Questions::AnswersController < Admin::Poll::BaseController
def create
@answer = ::Poll::Question::Answer.new(answer_params)
+ @question = @answer.question
if @answer.save
- redirect_to admin_question_path(@answer.question),
+ redirect_to admin_question_path(@question),
notice: t("flash.actions.create.poll_question_answer")
else
render :new
@@ -31,14 +32,14 @@ class Admin::Poll::Questions::AnswersController < Admin::Poll::BaseController
redirect_to admin_question_path(@answer.question),
notice: t("flash.actions.save_changes.notice")
else
- redirect_to :back
+ render :edit
end
end
def documents
@documents = @answer.documents
- render 'admin/poll/questions/answers/documents'
+ render "admin/poll/questions/answers/documents"
end
def order_answers
@@ -52,7 +53,10 @@ class Admin::Poll::Questions::AnswersController < Admin::Poll::BaseController
documents_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
attributes = [:title, :description, :given_order, :question_id,
documents_attributes: documents_attributes]
- params.require(:poll_question_answer).permit(*attributes, *translation_params(Poll::Question::Answer))
+
+ params.require(:poll_question_answer).permit(
+ *attributes, translation_params(Poll::Question::Answer)
+ )
end
def load_answer
diff --git a/app/controllers/admin/poll/questions_controller.rb b/app/controllers/admin/poll/questions_controller.rb
index 913e6824a..ed39862b2 100644
--- a/app/controllers/admin/poll/questions_controller.rb
+++ b/app/controllers/admin/poll/questions_controller.rb
@@ -3,7 +3,7 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController
include Translatable
load_and_authorize_resource :poll
- load_and_authorize_resource :question, class: 'Poll::Question'
+ load_and_authorize_resource :question, class: "Poll::Question"
def index
@polls = Poll.all
@@ -56,8 +56,8 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController
private
def question_params
- attributes = [:poll_id, :title, :question, :proposal_id]
- params.require(:poll_question).permit(*attributes, *translation_params(Poll::Question))
+ attributes = [:poll_id, :question, :proposal_id]
+ params.require(:poll_question).permit(*attributes, translation_params(Poll::Question))
end
def search_params
diff --git a/app/controllers/admin/poll/recounts_controller.rb b/app/controllers/admin/poll/recounts_controller.rb
index 32c533eec..a09e2af19 100644
--- a/app/controllers/admin/poll/recounts_controller.rb
+++ b/app/controllers/admin/poll/recounts_controller.rb
@@ -6,6 +6,10 @@ class Admin::Poll::RecountsController < Admin::Poll::BaseController
includes(:booth, :recounts, :voters).
order("poll_booths.name").
page(params[:page]).per(50)
+ @all_booths_counts = {
+ final: ::Poll::Recount.select(:total_amount).where(booth_assignment_id: @poll.booth_assignment_ids).sum(:total_amount),
+ system: ::Poll::Voter.where(booth_assignment_id: @poll.booth_assignment_ids).count
+ }
end
private
diff --git a/app/controllers/admin/poll/shifts_controller.rb b/app/controllers/admin/poll/shifts_controller.rb
index d2ef8e74e..3396224dc 100644
--- a/app/controllers/admin/poll/shifts_controller.rb
+++ b/app/controllers/admin/poll/shifts_controller.rb
@@ -6,8 +6,8 @@ class Admin::Poll::ShiftsController < Admin::Poll::BaseController
def new
load_shifts
@shift = ::Poll::Shift.new
- @voting_polls = @booth.polls.current_or_incoming
- @recount_polls = @booth.polls.current_or_recounting_or_incoming
+ @voting_polls = @booth.polls.current
+ @recount_polls = @booth.polls.current_or_recounting
end
def create
@@ -26,9 +26,14 @@ class Admin::Poll::ShiftsController < Admin::Poll::BaseController
def destroy
@shift = Poll::Shift.find(params[:id])
- @shift.destroy
- notice = t("admin.poll_shifts.flash.destroy")
- redirect_to new_admin_booth_shift_path(@booth), notice: notice
+ if @shift.unable_to_destroy?
+ alert = t("admin.poll_shifts.flash.unable_to_destroy")
+ redirect_to new_admin_booth_shift_path(@booth), alert: alert
+ else
+ @shift.destroy
+ notice = t("admin.poll_shifts.flash.destroy")
+ redirect_to new_admin_booth_shift_path(@booth), notice: notice
+ end
end
def search_officers
diff --git a/app/controllers/admin/progress_bars_controller.rb b/app/controllers/admin/progress_bars_controller.rb
new file mode 100644
index 000000000..3ef397a6a
--- /dev/null
+++ b/app/controllers/admin/progress_bars_controller.rb
@@ -0,0 +1,69 @@
+class Admin::ProgressBarsController < Admin::BaseController
+ include Translatable
+
+ before_action :load_progressable
+ before_action :load_progress_bar, only: [:edit, :update, :destroy]
+ helper_method :progress_bars_index
+
+ def index
+ end
+
+ def new
+ @progress_bar = @progressable.progress_bars.new
+ end
+
+ def create
+ @progress_bar = @progressable.progress_bars.new(progress_bar_params)
+ if @progress_bar.save
+ redirect_to progress_bars_index, notice: t("admin.progress_bars.create.notice")
+ else
+ render :new
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ if @progress_bar.update(progress_bar_params)
+ redirect_to progress_bars_index, notice: t("admin.progress_bars.update.notice")
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @progress_bar.destroy
+ redirect_to progress_bars_index, notice: t("admin.progress_bars.delete.notice")
+ end
+
+ private
+
+ def progress_bar_params
+ params.require(:progress_bar).permit(allowed_params)
+ end
+
+ def allowed_params
+ [
+ :kind,
+ :percentage,
+ translation_params(ProgressBar)
+ ]
+ end
+
+ def load_progressable
+ @progressable = progressable
+ end
+
+ def progressable
+ raise "This method must be implemented in subclass #{self.class.name}"
+ end
+
+ def load_progress_bar
+ @progress_bar = progressable.progress_bars.find(params[:id])
+ end
+
+ def progress_bars_index
+ polymorphic_path([:admin, *resource_hierarchy_for(@progressable), ProgressBar.new])
+ end
+end
diff --git a/app/controllers/admin/proposal_milestones_controller.rb b/app/controllers/admin/proposal_milestones_controller.rb
new file mode 100644
index 000000000..3dec8463b
--- /dev/null
+++ b/app/controllers/admin/proposal_milestones_controller.rb
@@ -0,0 +1,8 @@
+class Admin::ProposalMilestonesController < Admin::MilestonesController
+
+ private
+
+ def milestoneable
+ Proposal.find(params[:proposal_id])
+ end
+end
diff --git a/app/controllers/admin/proposal_progress_bars_controller.rb b/app/controllers/admin/proposal_progress_bars_controller.rb
new file mode 100644
index 000000000..9259acc4b
--- /dev/null
+++ b/app/controllers/admin/proposal_progress_bars_controller.rb
@@ -0,0 +1,7 @@
+class Admin::ProposalProgressBarsController < Admin::ProgressBarsController
+
+ private
+ def progressable
+ Proposal.find(params[:proposal_id])
+ end
+end
diff --git a/app/controllers/admin/proposals_controller.rb b/app/controllers/admin/proposals_controller.rb
index dbc09b3da..e76efce21 100644
--- a/app/controllers/admin/proposals_controller.rb
+++ b/app/controllers/admin/proposals_controller.rb
@@ -1,33 +1,18 @@
class Admin::ProposalsController < Admin::BaseController
+ include HasOrders
+ include CommentableActions
include FeatureFlags
-
- has_filters %w{without_confirmed_hide all with_confirmed_hide}, only: :index
-
feature_flag :proposals
- before_action :load_proposal, only: [:confirm_hide, :restore]
+ has_orders %w[created_at]
- def index
- @proposals = Proposal.only_hidden.send(@current_filter).order(hidden_at: :desc)
- .page(params[:page])
- end
-
- def confirm_hide
- @proposal.confirm_hide
- redirect_to request.query_parameters.merge(action: :index)
- end
-
- def restore
- @proposal.restore
- @proposal.ignore_flag
- Activity.log(current_user, :restore, @proposal)
- redirect_to request.query_parameters.merge(action: :index)
+ def show
+ @proposal = Proposal.find(params[:id])
end
private
- def load_proposal
- @proposal = Proposal.with_hidden.find(params[:id])
+ def resource_model
+ Proposal
end
-
end
diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb
index 3e42480c9..05656be5b 100644
--- a/app/controllers/admin/settings_controller.rb
+++ b/app/controllers/admin/settings_controller.rb
@@ -6,11 +6,11 @@ class Admin::SettingsController < Admin::BaseController
:poster_feature_short_title_setting, :poster_feature_description_setting
def index
- all_settings = Setting.all.group_by { |s| s.type }
- @settings = all_settings['common']
- @feature_flags = all_settings['feature']
- @banner_styles = all_settings['banner-style']
- @banner_imgs = all_settings['banner-img']
+ all_settings = Setting.all.group_by { |setting| setting.type }
+ @configuration_settings = all_settings["configuration"]
+ @feature_settings = all_settings["feature"]
+ @participation_processes_settings = all_settings["process"]
+ @map_configuration_settings = all_settings["map"]
end
def update
@@ -20,15 +20,16 @@ class Admin::SettingsController < Admin::BaseController
end
def update_map
- Setting['map_latitude'] = params[:latitude].to_f
- Setting['map_longitude'] = params[:longitude].to_f
- Setting['map_zoom'] = params[:zoom].to_i
- redirect_to admin_settings_path, notice: t('admin.settings.index.map.flash.update')
+ Setting["map.latitude"] = params[:latitude].to_f
+ Setting["map.longitude"] = params[:longitude].to_f
+ Setting["map.zoom"] = params[:zoom].to_i
+ redirect_to admin_settings_path, notice: t("admin.settings.index.map.flash.update")
end
private
- def settings_params
- params.require(:setting).permit(:value)
- end
+ def settings_params
+ params.require(:setting).permit(:value)
+ end
+
end
diff --git a/app/controllers/admin/signature_sheets_controller.rb b/app/controllers/admin/signature_sheets_controller.rb
index 4a6777695..5c266a491 100644
--- a/app/controllers/admin/signature_sheets_controller.rb
+++ b/app/controllers/admin/signature_sheets_controller.rb
@@ -13,7 +13,7 @@ class Admin::SignatureSheetsController < Admin::BaseController
@signature_sheet.author = current_user
if @signature_sheet.save
@signature_sheet.delay.verify_signatures
- redirect_to [:admin, @signature_sheet], notice: I18n.t('flash.actions.create.signature_sheet')
+ redirect_to [:admin, @signature_sheet], notice: I18n.t("flash.actions.create.signature_sheet")
else
render :new
end
diff --git a/app/controllers/admin/site_customization/cards_controller.rb b/app/controllers/admin/site_customization/cards_controller.rb
new file mode 100644
index 000000000..c0d06018e
--- /dev/null
+++ b/app/controllers/admin/site_customization/cards_controller.rb
@@ -0,0 +1,9 @@
+class Admin::SiteCustomization::CardsController < Admin::SiteCustomization::BaseController
+ skip_authorization_check
+
+ def index
+ @page = ::SiteCustomization::Page.find(params[:page_id])
+ @cards = @page.cards
+ end
+
+end
diff --git a/app/controllers/admin/site_customization/content_blocks_controller.rb b/app/controllers/admin/site_customization/content_blocks_controller.rb
index 1697cb76f..eb6076dbe 100644
--- a/app/controllers/admin/site_customization/content_blocks_controller.rb
+++ b/app/controllers/admin/site_customization/content_blocks_controller.rb
@@ -1,36 +1,117 @@
class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomization::BaseController
- load_and_authorize_resource :content_block, class: "SiteCustomization::ContentBlock"
+ load_and_authorize_resource :content_block, class: "SiteCustomization::ContentBlock",
+ except: [
+ :delete_heading_content_block,
+ :edit_heading_content_block,
+ :update_heading_content_block
+ ]
def index
@content_blocks = SiteCustomization::ContentBlock.order(:name, :locale)
+ @headings_content_blocks = Budget::ContentBlock.all
+ all_settings = Setting.all.group_by { |setting| setting.type }
+ @html_settings = all_settings["html"]
end
def create
- if @content_block.save
- notice = t('admin.site_customization.content_blocks.create.notice')
+ if is_heading_content_block?(@content_block.name)
+ heading_content_block = new_heading_content_block
+ if heading_content_block.save
+ notice = t("admin.site_customization.content_blocks.create.notice")
+ redirect_to admin_site_customization_content_blocks_path, notice: notice
+ else
+ flash.now[:error] = t("admin.site_customization.content_blocks.create.error")
+ render :new
+ end
+ elsif @content_block.save
+ notice = t("admin.site_customization.content_blocks.create.notice")
redirect_to admin_site_customization_content_blocks_path, notice: notice
else
- flash.now[:error] = t('admin.site_customization.content_blocks.create.error')
+ flash.now[:error] = t("admin.site_customization.content_blocks.create.error")
render :new
end
end
+ def edit
+ if @content_block.is_a? SiteCustomization::ContentBlock
+ @selected_content_block = @content_block.name
+ else
+ @selected_content_block = "hcb_#{@content_block.heading_id}"
+ end
+ end
+
def update
- if @content_block.update(content_block_params)
- notice = t('admin.site_customization.content_blocks.update.notice')
+ if is_heading_content_block?(params[:site_customization_content_block][:name])
+ heading_content_block = new_heading_content_block
+ if heading_content_block.save
+ @content_block.destroy
+ notice = t("admin.site_customization.content_blocks.create.notice")
+ redirect_to admin_site_customization_content_blocks_path, notice: notice
+ else
+ flash.now[:error] = t("admin.site_customization.content_blocks.create.error")
+ render :new
+ end
+ elsif @content_block.update(content_block_params)
+ notice = t("admin.site_customization.content_blocks.update.notice")
redirect_to admin_site_customization_content_blocks_path, notice: notice
else
- flash.now[:error] = t('admin.site_customization.content_blocks.update.error')
+ flash.now[:error] = t("admin.site_customization.content_blocks.update.error")
render :edit
end
end
def destroy
@content_block.destroy
- notice = t('admin.site_customization.content_blocks.destroy.notice')
+ notice = t("admin.site_customization.content_blocks.destroy.notice")
redirect_to admin_site_customization_content_blocks_path, notice: notice
end
+ def delete_heading_content_block
+ heading_content_block = Budget::ContentBlock.find(params[:id])
+ heading_content_block.destroy if heading_content_block
+ notice = t("admin.site_customization.content_blocks.destroy.notice")
+ redirect_to admin_site_customization_content_blocks_path, notice: notice
+ end
+
+ def edit_heading_content_block
+ @content_block = Budget::ContentBlock.find(params[:id])
+ if @content_block.is_a? Budget::ContentBlock
+ @selected_content_block = "hcb_#{@content_block.heading_id}"
+ else
+ @selected_content_block = @content_block.heading.name
+ end
+ @is_heading_content_block = true
+ render :edit
+ end
+
+ def update_heading_content_block
+ heading_content_block = Budget::ContentBlock.find(params[:id])
+ if is_heading_content_block?(params[:name])
+ heading_content_block.locale = params[:locale]
+ heading_content_block.body = params[:body]
+ if heading_content_block.save
+ notice = t("admin.site_customization.content_blocks.update.notice")
+ redirect_to admin_site_customization_content_blocks_path, notice: notice
+ else
+ flash.now[:error] = t("admin.site_customization.content_blocks.update.error")
+ render :edit
+ end
+ else
+ @content_block = SiteCustomization::ContentBlock.new
+ @content_block.name = params[:name]
+ @content_block.locale = params[:locale]
+ @content_block.body = params[:body]
+ if @content_block.save
+ heading_content_block.destroy
+ notice = t("admin.site_customization.content_blocks.update.notice")
+ redirect_to admin_site_customization_content_blocks_path, notice: notice
+ else
+ flash.now[:error] = t("admin.site_customization.content_blocks.update.error")
+ render :edit
+ end
+ end
+ end
+
private
def content_block_params
@@ -40,4 +121,17 @@ class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomizati
:body
)
end
+
+ def is_heading_content_block?(name)
+ name.start_with?("hcb_")
+ end
+
+ def new_heading_content_block
+ heading_content_block = Budget::ContentBlock.new
+ heading_content_block.body = params[:site_customization_content_block][:body]
+ heading_content_block.locale = params[:site_customization_content_block][:locale]
+ block_heading_id = params[:site_customization_content_block][:name].sub("hcb_", "").to_i
+ heading_content_block.heading_id = block_heading_id
+ heading_content_block
+ end
end
diff --git a/app/controllers/admin/site_customization/images_controller.rb b/app/controllers/admin/site_customization/images_controller.rb
index 21951f527..ccca12477 100644
--- a/app/controllers/admin/site_customization/images_controller.rb
+++ b/app/controllers/admin/site_customization/images_controller.rb
@@ -12,10 +12,10 @@ class Admin::SiteCustomization::ImagesController < Admin::SiteCustomization::Bas
end
if @image.update(image_params)
- notice = t('admin.site_customization.images.update.notice')
+ notice = t("admin.site_customization.images.update.notice")
redirect_to admin_site_customization_images_path, notice: notice
else
- flash.now[:error] = t('admin.site_customization.images.update.error')
+ flash.now[:error] = t("admin.site_customization.images.update.error")
@images = SiteCustomization::Image.all_images
idx = @images.index {|e| e.name == @image.name }
@@ -28,10 +28,10 @@ class Admin::SiteCustomization::ImagesController < Admin::SiteCustomization::Bas
def destroy
@image.image = nil
if @image.save
- notice = t('admin.site_customization.images.destroy.notice')
+ notice = t("admin.site_customization.images.destroy.notice")
redirect_to admin_site_customization_images_path, notice: notice
else
- notice = t('admin.site_customization.images.destroy.error')
+ notice = t("admin.site_customization.images.destroy.error")
redirect_to admin_site_customization_images_path, notice: notice
end
end
diff --git a/app/controllers/admin/site_customization/information_texts_controller.rb b/app/controllers/admin/site_customization/information_texts_controller.rb
index 32483d5ed..277ec91a6 100644
--- a/app/controllers/admin/site_customization/information_texts_controller.rb
+++ b/app/controllers/admin/site_customization/information_texts_controller.rb
@@ -1,5 +1,5 @@
class Admin::SiteCustomization::InformationTextsController < Admin::SiteCustomization::BaseController
- include Translatable
+ before_action :delete_translations, only: [:update]
def index
fetch_existing_keys
@@ -9,7 +9,7 @@ class Admin::SiteCustomization::InformationTextsController < Admin::SiteCustomiz
def update
content_params.each do |content|
- values = content[:values].slice(*translation_params(I18nContent))
+ values = content[:values].slice(*translation_params)
unless values.empty?
values.each do |key, value|
@@ -28,7 +28,7 @@ class Admin::SiteCustomization::InformationTextsController < Admin::SiteCustomiz
end
redirect_to admin_site_customization_information_texts_path,
- notice: t('flash.actions.update.translation')
+ notice: t("flash.actions.update.translation")
end
private
@@ -42,8 +42,9 @@ class Admin::SiteCustomization::InformationTextsController < Admin::SiteCustomiz
end
def delete_translations
- languages_to_delete = params[:enabled_translations].select { |_, v| v == '0' }
+ languages_to_delete = params[:enabled_translations].select { |_, v| v == "0" }
.keys
+
languages_to_delete.each do |locale|
I18nContentTranslation.destroy_all(locale: locale)
end
@@ -53,9 +54,9 @@ class Admin::SiteCustomization::InformationTextsController < Admin::SiteCustomiz
@existing_keys = {}
@tab = params[:tab] || :debates
- I18nContent.begins_with_key(@tab)
- .all
- .map{ |content| @existing_keys[content.key] = content }
+ I18nContent.begins_with_key(@tab).map { |content|
+ @existing_keys[content.key] = content
+ }
end
def append_or_create_keys
@@ -65,18 +66,22 @@ class Admin::SiteCustomization::InformationTextsController < Admin::SiteCustomiz
locale = params[:locale] || I18n.locale
translations = I18n.backend.send(:translations)[locale.to_sym]
- translations.each do |k, v|
- @content[k.to_s] = flat_hash(v).keys
- .map { |s| @existing_keys["#{k.to_s}.#{s}"].nil? ?
- I18nContent.new(key: "#{k.to_s}.#{s}") :
- @existing_keys["#{k.to_s}.#{s}"] }
+ translations.each do |key, value|
+ @content[key.to_s] = I18nContent.flat_hash(value).keys.map { |string|
+ @existing_keys["#{key.to_s}.#{string}"] || I18nContent.new(key: "#{key.to_s}.#{string}")
+ }
end
end
- def flat_hash(h, f = nil, g = {})
- return g.update({ f => h }) unless h.is_a? Hash
- h.each { |k, r| flat_hash(r, [f,k].compact.join('.'), g) }
- return g
+ def translation_params
+ I18nContent.translated_attribute_names.product(enabled_translations).map do |attr_name, loc|
+ I18nContent.localized_attr_name_for(attr_name, loc)
+ end
end
+ def enabled_translations
+ params.fetch(:enabled_translations, {})
+ .select { |_, v| v == "1" }
+ .keys
+ end
end
diff --git a/app/controllers/admin/site_customization/pages_controller.rb b/app/controllers/admin/site_customization/pages_controller.rb
index e4c6a8ed7..ac2c1d0bc 100644
--- a/app/controllers/admin/site_customization/pages_controller.rb
+++ b/app/controllers/admin/site_customization/pages_controller.rb
@@ -3,49 +3,42 @@ class Admin::SiteCustomization::PagesController < Admin::SiteCustomization::Base
load_and_authorize_resource :page, class: "SiteCustomization::Page"
def index
- @pages = SiteCustomization::Page.order('slug').page(params[:page])
+ @pages = SiteCustomization::Page.order("slug").page(params[:page])
end
def create
if @page.save
- notice = t('admin.site_customization.pages.create.notice')
+ notice = t("admin.site_customization.pages.create.notice")
redirect_to admin_site_customization_pages_path, notice: notice
else
- flash.now[:error] = t('admin.site_customization.pages.create.error')
+ flash.now[:error] = t("admin.site_customization.pages.create.error")
render :new
end
end
def update
if @page.update(page_params)
- notice = t('admin.site_customization.pages.update.notice')
+ notice = t("admin.site_customization.pages.update.notice")
redirect_to admin_site_customization_pages_path, notice: notice
else
- flash.now[:error] = t('admin.site_customization.pages.update.error')
+ flash.now[:error] = t("admin.site_customization.pages.update.error")
render :edit
end
end
def destroy
@page.destroy
- notice = t('admin.site_customization.pages.destroy.notice')
+ notice = t("admin.site_customization.pages.destroy.notice")
redirect_to admin_site_customization_pages_path, notice: notice
end
private
def page_params
- attributes = [:slug,
- :title,
- :subtitle,
- :content,
- :more_info_flag,
- :print_content_flag,
- :status,
- :locale]
+ attributes = [:slug, :more_info_flag, :print_content_flag, :status]
params.require(:site_customization_page).permit(*attributes,
- *translation_params(SiteCustomization::Page)
+ translation_params(SiteCustomization::Page)
)
end
diff --git a/app/controllers/admin/stats_controller.rb b/app/controllers/admin/stats_controller.rb
index 774254777..352232d55 100644
--- a/app/controllers/admin/stats_controller.rb
+++ b/app/controllers/admin/stats_controller.rb
@@ -8,9 +8,9 @@ class Admin::StatsController < Admin::BaseController
@proposals = Proposal.with_hidden.count
@comments = Comment.not_valuations.with_hidden.count
- @debate_votes = Vote.where(votable_type: 'Debate').count
- @proposal_votes = Vote.where(votable_type: 'Proposal').count
- @comment_votes = Vote.where(votable_type: 'Comment').count
+ @debate_votes = Vote.where(votable_type: "Debate").count
+ @proposal_votes = Vote.where(votable_type: "Proposal").count
+ @comment_votes = Vote.where(votable_type: "Comment").count
@votes = Vote.count
@user_level_two = User.active.level_two_verified.count
@@ -19,14 +19,14 @@ class Admin::StatsController < Admin::BaseController
@unverified_users = User.active.unverified.count
@users = User.active.count
- @user_ids_who_voted_proposals = ActsAsVotable::Vote.where(votable_type: 'Proposal')
+ @user_ids_who_voted_proposals = ActsAsVotable::Vote.where(votable_type: "Proposal")
.distinct
.count(:voter_id)
@user_ids_who_didnt_vote_proposals = @verified_users - @user_ids_who_voted_proposals
@spending_proposals = SpendingProposal.count
- budgets_ids = Budget.where.not(phase: 'finished').pluck(:id)
+ budgets_ids = Budget.where.not(phase: "finished").pluck(:id)
@budgets = budgets_ids.size
@investments = Budget::Investment.where(budget_id: budgets_ids).count
end
diff --git a/app/controllers/admin/system_emails_controller.rb b/app/controllers/admin/system_emails_controller.rb
index d079c171b..689425569 100644
--- a/app/controllers/admin/system_emails_controller.rb
+++ b/app/controllers/admin/system_emails_controller.rb
@@ -4,15 +4,36 @@ class Admin::SystemEmailsController < Admin::BaseController
def index
@system_emails = {
- proposal_notification_digest: %w(view preview_pending)
+ proposal_notification_digest: %w[view preview_pending],
+ budget_investment_created: %w[view edit_info],
+ budget_investment_selected: %w[view edit_info],
+ budget_investment_unfeasible: %w[view edit_info],
+ budget_investment_unselected: %w[view edit_info],
+ comment: %w[view edit_info],
+ reply: %w[view edit_info],
+ 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]
}
end
def view
case @system_email
when "proposal_notification_digest"
- @notifications = Notification.where(notifiable_type: "ProposalNotification").limit(2)
- @subject = t('mailers.proposal_notification_digest.title', org_name: Setting['org_name'])
+ load_sample_proposal_notifications
+ when /\Abudget_investment/
+ load_sample_investment
+ when /\Adirect_message/
+ load_sample_direct_message
+ when "comment"
+ load_sample_comment
+ when "reply"
+ load_sample_reply
+ when "email_verification"
+ load_sample_user
+ when "user_invite"
+ @subject = t("mailers.user_invite.subject", org_name: Setting["org_name"])
end
end
@@ -39,12 +60,62 @@ class Admin::SystemEmailsController < Admin::BaseController
private
- def load_system_email
- @system_email = params[:system_email_id]
- end
+ def load_system_email
+ @system_email = params[:system_email_id]
+ end
- def unsent_proposal_notifications_ids
- Notification.where(notifiable_type: "ProposalNotification", emailed_at: nil)
- .group(:notifiable_id).count.keys
- end
+ def load_sample_proposal_notifications
+ @notifications = Notification.where(notifiable_type: "ProposalNotification").limit(2)
+ @subject = t("mailers.proposal_notification_digest.title", org_name: Setting["org_name"])
+ end
+
+ def load_sample_investment
+ if Budget::Investment.any?
+ @investment = Budget::Investment.last
+ @subject = t("mailers.#{@system_email}.subject", code: @investment.code)
+ else
+ redirect_to admin_system_emails_path, alert: t("admin.system_emails.alert.no_investments")
+ end
+ end
+
+ def load_sample_comment
+ @comment = Comment.where(commentable_type: %w[Debate Proposal Budget::Investment]).last
+ if @comment
+ @commentable = @comment.commentable
+ @subject = t("mailers.comment.subject", commentable: commentable_name)
+ else
+ redirect_to admin_system_emails_path, alert: t("admin.system_emails.alert.no_comments")
+ end
+ end
+
+ def load_sample_reply
+ reply = Comment.select { |comment| comment.reply? }.last
+ if reply
+ @email = ReplyEmail.new(reply)
+ else
+ redirect_to admin_system_emails_path, alert: t("admin.system_emails.alert.no_replies")
+ end
+ end
+
+ def load_sample_user
+ @user = User.last
+ @token = @user.email_verification_token || SecureRandom.hex
+ @subject = t("mailers.email_verification.subject")
+ end
+
+ def load_sample_direct_message
+ @direct_message = DirectMessage.new(sender: current_user, receiver: current_user,
+ title: t("admin.system_emails.message_title"),
+ body: t("admin.system_emails.message_body"))
+ @subject = t("mailers.#{@system_email}.subject")
+ end
+
+ def commentable_name
+ t("activerecord.models.#{@commentable.class.name.underscore}", count: 1)
+ end
+
+ def unsent_proposal_notifications_ids
+ Notification.where(notifiable_type: "ProposalNotification", emailed_at: nil)
+ .group(:notifiable_id).count.keys
+ end
end
diff --git a/app/controllers/admin/widget/cards_controller.rb b/app/controllers/admin/widget/cards_controller.rb
index f5dce76a1..eb1e6ba79 100644
--- a/app/controllers/admin/widget/cards_controller.rb
+++ b/app/controllers/admin/widget/cards_controller.rb
@@ -1,15 +1,19 @@
class Admin::Widget::CardsController < Admin::BaseController
include Translatable
+ include ImageAttributes
def new
- @card = ::Widget::Card.new(header: header_card?)
+ if header_card?
+ @card = ::Widget::Card.new(header: header_card?)
+ else
+ @card = ::Widget::Card.new(site_customization_page_id: params[:page_id])
+ end
end
def create
@card = ::Widget::Card.new(card_params)
if @card.save
- notice = "Success"
- redirect_to admin_homepage_url, notice: notice
+ redirect_to_customization_page_cards_or_homepage
else
render :new
end
@@ -22,8 +26,7 @@ class Admin::Widget::CardsController < Admin::BaseController
def update
@card = ::Widget::Card.find(params[:id])
if @card.update(card_params)
- notice = "Updated"
- redirect_to admin_homepage_url, notice: notice
+ redirect_to_customization_page_cards_or_homepage
else
render :edit
end
@@ -33,28 +36,39 @@ class Admin::Widget::CardsController < Admin::BaseController
@card = ::Widget::Card.find(params[:id])
@card.destroy
- notice = "Removed"
- redirect_to admin_homepage_url, notice: notice
+ redirect_to_customization_page_cards_or_homepage
end
private
- def card_params
- image_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
+ def card_params
+ params.require(:widget_card).permit(
+ :link_url, :button_text, :button_url, :alignment, :header, :site_customization_page_id,
+ :columns,
+ translation_params(Widget::Card),
+ image_attributes: image_attributes
+ )
+ end
- params.require(:widget_card).permit(
- :label, :title, :description, :link_text, :link_url,
- :button_text, :button_url, :alignment, :header,
- *translation_params(Widget::Card),
- image_attributes: image_attributes
- )
- end
+ def header_card?
+ params[:header_card].present?
+ end
- def header_card?
- params[:header_card].present?
- end
+ def redirect_to_customization_page_cards_or_homepage
+ notice = t("admin.site_customization.pages.cards.#{params[:action]}.notice")
- def resource
- Widget::Card.find(params[:id])
- end
+ if @card.site_customization_page_id
+ redirect_to admin_site_customization_page_cards_path(page), notice: notice
+ else
+ redirect_to admin_homepage_url, notice: notice
+ end
+ end
+
+ def page
+ ::SiteCustomization::Page.find(@card.site_customization_page_id)
+ end
+
+ def resource
+ Widget::Card.find(params[:id])
+ end
end
diff --git a/app/controllers/annotations_controller.rb b/app/controllers/annotations_controller.rb
deleted file mode 100644
index 8b004076c..000000000
--- a/app/controllers/annotations_controller.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-class AnnotationsController < ApplicationController
- skip_before_action :verify_authenticity_token
- load_and_authorize_resource
-
- def create
- @annotation = Annotation.new(annotation_params)
- @annotation.user = current_user
- if @annotation.save
- render json: @annotation.to_json(methods: :permissions)
- end
- end
-
- def update
- @annotation = Annotation.find(params[:id])
- if @annotation.update_attributes(annotation_params)
- render json: @annotation.to_json(methods: :permissions)
- end
- end
-
- def destroy
- @annotation = Annotation.find(params[:id])
- @annotation.destroy
- render json: { status: :ok }
- end
-
- def search
- @annotations = Annotation.where(legacy_legislation_id: params[:legacy_legislation_id])
- annotations_hash = { total: @annotations.size, rows: @annotations }
- render json: annotations_hash.to_json(methods: :permissions)
- end
-
- private
-
- def annotation_params
- params
- .require(:annotation)
- .permit(:quote, :text, ranges: [:start, :startOffset, :end, :endOffset])
- .merge(legacy_legislation_id: params[:legacy_legislation_id])
- end
-end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index e97b87cd3..5df842899 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -41,7 +41,7 @@ class ApplicationController < ActionController::Base
def verify_lock
if current_user.locked?
- redirect_to account_path, alert: t('verification.alert.lock')
+ redirect_to account_path, alert: t("verification.alert.lock")
end
end
@@ -94,13 +94,13 @@ class ApplicationController < ActionController::Base
def verify_resident!
unless current_user.residence_verified?
- redirect_to new_residence_path, alert: t('verification.residence.alert.unconfirmed_residency')
+ redirect_to new_residence_path, alert: t("verification.residence.alert.unconfirmed_residency")
end
end
def verify_verified!
if current_user.level_three_verified?
- redirect_to(account_path, notice: t('verification.redirect_notices.already_verified'))
+ redirect_to(account_path, notice: t("verification.redirect_notices.already_verified"))
end
end
@@ -112,7 +112,7 @@ class ApplicationController < ActionController::Base
end
def set_return_url
- if !devise_controller? && controller_name != 'welcome' && is_navigational_format?
+ if !devise_controller? && controller_name != "welcome" && is_navigational_format?
store_location_for(:user, request.path)
end
end
@@ -120,6 +120,8 @@ class ApplicationController < ActionController::Base
def set_default_budget_filter
if @budget.try(:balloting?) || @budget.try(:publishing_prices?)
params[:filter] ||= "selected"
+ elsif @budget.try(:finished?)
+ params[:filter] ||= "winners"
end
end
diff --git a/app/controllers/budgets/ballot/lines_controller.rb b/app/controllers/budgets/ballot/lines_controller.rb
index d5d5468a2..c2e617e08 100644
--- a/app/controllers/budgets/ballot/lines_controller.rb
+++ b/app/controllers/budgets/ballot/lines_controller.rb
@@ -2,7 +2,6 @@ module Budgets
module Ballot
class LinesController < ApplicationController
before_action :authenticate_user!
- #before_action :ensure_final_voting_allowed
before_action :load_budget
before_action :load_ballot
before_action :load_tag_cloud
@@ -17,6 +16,7 @@ module Budgets
def create
load_investment
load_heading
+ load_map
@ballot.add_investment(@investment)
end
@@ -24,6 +24,7 @@ module Budgets
def destroy
@investment = @line.investment
load_heading
+ load_map
@line.destroy
load_investments
@@ -31,10 +32,6 @@ module Budgets
private
- def ensure_final_voting_allowed
- return head(:forbidden) unless @budget.balloting?
- end
-
def line_params
params.permit(:investment_id, :budget_id)
end
@@ -74,6 +71,14 @@ module Budgets
@ballot_referer = session[:ballot_referer]
end
+ def load_map
+ @investments ||= []
+ @investments_map_coordinates = MapLocation.where(investment: @investments).map do |loc|
+ loc.json_data
+ end
+ @map_location = MapLocation.load_from_heading(@heading)
+ end
+
end
end
end
diff --git a/app/controllers/budgets/executions_controller.rb b/app/controllers/budgets/executions_controller.rb
new file mode 100644
index 000000000..54decebee
--- /dev/null
+++ b/app/controllers/budgets/executions_controller.rb
@@ -0,0 +1,35 @@
+module Budgets
+ class ExecutionsController < ApplicationController
+ before_action :load_budget
+
+ load_and_authorize_resource :budget
+
+ def show
+ authorize! :read_executions, @budget
+ @statuses = Milestone::Status.all
+ @investments_by_heading = investments_by_heading_ordered_alphabetically.to_h
+ end
+
+ private
+ def investments_by_heading
+ if params[:status].present?
+ @budget.investments.winners
+ .with_milestone_status_id(params[:status])
+ .uniq
+ .group_by(&:heading)
+ else
+ @budget.investments.winners
+ .joins(:milestones).includes(:milestones)
+ .distinct.group_by(&:heading)
+ end
+ end
+
+ def load_budget
+ @budget = Budget.find_by_slug_or_id params[:budget_id]
+ end
+
+ def investments_by_heading_ordered_alphabetically
+ investments_by_heading.sort { |a, b| a[0].name <=> b[0].name }
+ end
+ end
+end
diff --git a/app/controllers/budgets/groups_controller.rb b/app/controllers/budgets/groups_controller.rb
index d84eb2fdd..f298b5a93 100644
--- a/app/controllers/budgets/groups_controller.rb
+++ b/app/controllers/budgets/groups_controller.rb
@@ -4,7 +4,7 @@ module Budgets
load_and_authorize_resource :group, class: "Budget::Group"
before_action :set_default_budget_filter, only: :show
- has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: [:show]
+ has_filters %w[not_unfeasible feasible unfeasible unselected selected winners], only: [:show]
def show
end
diff --git a/app/controllers/budgets/investments_controller.rb b/app/controllers/budgets/investments_controller.rb
index ca2bf7dc4..cc762cff5 100644
--- a/app/controllers/budgets/investments_controller.rb
+++ b/app/controllers/budgets/investments_controller.rb
@@ -1,8 +1,13 @@
module Budgets
class InvestmentsController < ApplicationController
+
include FeatureFlags
include CommentableActions
include FlagActions
+ include RandomSeed
+ include ImageAttributes
+
+ PER_PAGE = 10
before_action :authenticate_user!, except: [:index, :show, :json_data]
@@ -17,6 +22,7 @@ module Budgets
before_action :load_categories, only: [:index, :new, :create]
before_action :set_default_budget_filter, only: :index
before_action :set_view, only: :index
+ before_action :load_content_blocks, only: :index
skip_authorization_check only: :json_data
@@ -24,7 +30,9 @@ module Budgets
has_orders %w{most_voted newest oldest}, only: :show
has_orders ->(c) { c.instance_variable_get(:@budget).investments_orders }, only: :index
- has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: [:index, :show, :suggest]
+
+ valid_filters = %w[not_unfeasible feasible unfeasible unselected selected winners]
+ has_filters valid_filters, only: [:index, :show, :suggest]
invisible_captcha only: [:create, :update], honeypot: :subtitle, scope: :budget_investment
@@ -32,13 +40,11 @@ module Budgets
respond_to :html, :js
def index
- if @budget.finished?
- @investments = investments.winners.page(params[:page]).per(10).for_render
- else
- @investments = investments.page(params[:page]).per(10).for_render
- end
+ @investments = investments.page(params[:page]).per(PER_PAGE).for_render
@investment_ids = @investments.pluck(:id)
+ @investments_map_coordinates = MapLocation.where(investment: investments).map(&:json_data)
+
load_investment_votes(@investments)
@tag_cloud = tag_cloud
end
@@ -61,7 +67,7 @@ module Budgets
if @investment.save
Mailer.budget_investment_created(@investment).deliver_later
redirect_to budget_investment_path(@budget, @investment),
- notice: t('flash.actions.create.budget_investment')
+ notice: t("flash.actions.create.budget_investment")
else
render :new
end
@@ -69,7 +75,7 @@ module Budgets
def destroy
@investment.destroy
- redirect_to user_path(current_user, filter: 'budget_investments'), notice: t('flash.actions.destroy.budget_investment')
+ redirect_to user_path(current_user, filter: "budget_investments"), notice: t("flash.actions.destroy.budget_investment")
end
def vote
@@ -114,21 +120,11 @@ module Budgets
@investment_votes = current_user ? current_user.budget_investment_votes(investments) : {}
end
- def set_random_seed
- if params[:order] == 'random' || params[:order].blank?
- seed = params[:random_seed] || session[:random_seed] || rand
- params[:random_seed] = seed
- session[:random_seed] = params[:random_seed]
- else
- params[:random_seed] = nil
- end
- end
-
def investment_params
params.require(:budget_investment)
.permit(:title, :description, :heading_id, :tag_list,
:organization_name, :location, :terms_of_service, :skip_map,
- image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy],
+ image_attributes: image_attributes,
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy],
map_location_attributes: [:latitude, :longitude, :zoom])
end
@@ -142,6 +138,7 @@ module Budgets
if params[:heading_id].present?
@heading = @budget.headings.find(params[:heading_id])
@assigned_heading = @ballot.try(:heading_for_group, @heading.try(:group))
+ load_map
end
end
@@ -149,6 +146,10 @@ module Budgets
@categories = ActsAsTaggableOn::Tag.category.order(:name)
end
+ def load_content_blocks
+ @heading_content_blocks = @heading.content_blocks.where(locale: I18n.locale) if @heading
+ end
+
def tag_cloud
TagCloud.new(Budget::Investment, params[:search])
end
@@ -158,15 +159,19 @@ module Budgets
end
def investments
- if @current_order == 'random'
- @investments.apply_filters_and_search(@budget, params, @current_filter)
- .send("sort_by_#{@current_order}", params[:random_seed])
+ if @current_order == "random"
+ @budget.investments.apply_filters_and_search(@budget, params, @current_filter)
+ .sort_by_random(session[:random_seed])
else
- @investments.apply_filters_and_search(@budget, params, @current_filter)
- .send("sort_by_#{@current_order}")
+ @budget.investments.apply_filters_and_search(@budget, params, @current_filter)
+ .send("sort_by_#{@current_order}")
end
end
+ def load_map
+ @map_location = MapLocation.load_from_heading(@heading)
+ end
+
end
end
diff --git a/app/controllers/budgets_controller.rb b/app/controllers/budgets_controller.rb
index 70efd04e9..c1f9e03ef 100644
--- a/app/controllers/budgets_controller.rb
+++ b/app/controllers/budgets_controller.rb
@@ -5,18 +5,18 @@ class BudgetsController < ApplicationController
load_and_authorize_resource
before_action :set_default_budget_filter, only: :show
- has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: :show
+ has_filters %w[not_unfeasible feasible unfeasible unselected selected winners], only: :show
respond_to :html, :js
def show
- raise ActionController::RoutingError, 'Not Found' unless budget_published?(@budget)
+ raise ActionController::RoutingError, "Not Found" unless budget_published?(@budget)
end
def index
@finished_budgets = @budgets.finished.order(created_at: :desc)
@budgets_coordinates = current_budget_map_locations
- @banners = Banner.in_section('budgets').with_active
+ @banners = Banner.in_section("budgets").with_active
end
end
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index fe614c295..47434ba16 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -36,13 +36,13 @@ class CommentsController < ApplicationController
def flag
Flag.flag(current_user, @comment)
set_comment_flags(@comment)
- respond_with @comment, template: 'comments/_refresh_flag_actions'
+ respond_with @comment, template: "comments/_refresh_flag_actions"
end
def unflag
Flag.unflag(current_user, @comment)
set_comment_flags(@comment)
- respond_with @comment, template: 'comments/_refresh_flag_actions'
+ respond_with @comment, template: "comments/_refresh_flag_actions"
end
private
@@ -103,7 +103,7 @@ class CommentsController < ApplicationController
return if current_user.administrator? || current_user.moderator?
if @commentable.respond_to?(:comments_closed?) && @commentable.comments_closed?
- redirect_to @commentable, alert: t('comments.comments_closed')
+ redirect_to @commentable, alert: t("comments.comments_closed")
end
end
diff --git a/app/controllers/communities_controller.rb b/app/controllers/communities_controller.rb
index 0d1ac6890..fc8298d41 100644
--- a/app/controllers/communities_controller.rb
+++ b/app/controllers/communities_controller.rb
@@ -7,8 +7,8 @@ class CommunitiesController < ApplicationController
skip_authorization_check
def show
- raise ActionController::RoutingError, 'Not Found' unless communitable_exists?
- redirect_to root_path if Setting['feature.community'].blank?
+ raise ActionController::RoutingError, "Not Found" unless communitable_exists?
+ redirect_to root_path if Setting["feature.community"].blank?
end
private
diff --git a/app/controllers/concerns/commentable_actions.rb b/app/controllers/concerns/commentable_actions.rb
index f3aadc2f7..aa1a40fc3 100644
--- a/app/controllers/concerns/commentable_actions.rb
+++ b/app/controllers/concerns/commentable_actions.rb
@@ -117,9 +117,9 @@ module CommentableActions
def section(resource_name)
case resource_name
when "Proposal"
- 'proposals'
+ "proposals"
when "Debate"
- 'debates'
+ "debates"
end
end
diff --git a/app/controllers/concerns/feature_flags.rb b/app/controllers/concerns/feature_flags.rb
index ca3cd929e..830b44f4b 100644
--- a/app/controllers/concerns/feature_flags.rb
+++ b/app/controllers/concerns/feature_flags.rb
@@ -10,7 +10,7 @@ module FeatureFlags
end
def check_feature_flag(name)
- raise FeatureDisabled, name unless Setting["feature.#{name}"]
+ raise FeatureDisabled, name unless Setting["feature.#{name}"] || Setting["process.#{name}"]
end
class FeatureDisabled < Exception
diff --git a/app/controllers/concerns/flag_actions.rb b/app/controllers/concerns/flag_actions.rb
index da637407a..4662d1ccb 100644
--- a/app/controllers/concerns/flag_actions.rb
+++ b/app/controllers/concerns/flag_actions.rb
@@ -4,7 +4,7 @@ module FlagActions
def flag
Flag.flag(current_user, flaggable)
- if controller_name == 'investments'
+ if controller_name == "investments"
respond_with flaggable, template: "budgets/#{controller_name}/_refresh_flag_actions"
else
respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
@@ -14,7 +14,7 @@ module FlagActions
def unflag
Flag.unflag(current_user, flaggable)
- if controller_name == 'investments'
+ if controller_name == "investments"
respond_with flaggable, template: "budgets/#{controller_name}/_refresh_flag_actions"
else
respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
@@ -24,7 +24,7 @@ module FlagActions
private
def flaggable
- if resource_model.to_s == 'Budget::Investment'
+ if resource_model.to_s == "Budget::Investment"
instance_variable_get("@investment")
else
instance_variable_get("@#{resource_model.to_s.downcase}")
diff --git a/app/controllers/concerns/image_attributes.rb b/app/controllers/concerns/image_attributes.rb
new file mode 100644
index 000000000..a46128c4c
--- /dev/null
+++ b/app/controllers/concerns/image_attributes.rb
@@ -0,0 +1,8 @@
+module ImageAttributes
+ extend ActiveSupport::Concern
+
+ def image_attributes
+ [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
+ end
+
+end
diff --git a/app/controllers/concerns/polymorphic.rb b/app/controllers/concerns/polymorphic.rb
index 0e25b4231..076a43076 100644
--- a/app/controllers/concerns/polymorphic.rb
+++ b/app/controllers/concerns/polymorphic.rb
@@ -3,7 +3,7 @@ module Polymorphic
private
def resource
- if resource_model.to_s == 'Budget::Investment'
+ if resource_model.to_s == "Budget::Investment"
@resource ||= instance_variable_get("@investment")
else
@resource ||= instance_variable_get("@#{resource_name}")
diff --git a/app/controllers/concerns/random_seed.rb b/app/controllers/concerns/random_seed.rb
new file mode 100644
index 000000000..a54d6832e
--- /dev/null
+++ b/app/controllers/concerns/random_seed.rb
@@ -0,0 +1,10 @@
+module RandomSeed
+ extend ActiveSupport::Concern
+
+ def set_random_seed
+ seed = (params[:random_seed] || session[:random_seed] || rand(10_000_000)).to_i
+
+ session[:random_seed] = seed
+ params[:random_seed] = seed
+ end
+end
diff --git a/app/controllers/concerns/search.rb b/app/controllers/concerns/search.rb
index b4e9fac68..ff010a76f 100644
--- a/app/controllers/concerns/search.rb
+++ b/app/controllers/concerns/search.rb
@@ -27,13 +27,13 @@ module Search
def search_start_date
case params[:advanced_search][:date_min]
- when '1'
+ when "1"
24.hours.ago
- when '2'
+ when "2"
1.week.ago
- when '3'
+ when "3"
1.month.ago
- when '4'
+ when "4"
1.year.ago
else
Date.parse(params[:advanced_search][:date_min]) rescue 100.years.ago
@@ -50,7 +50,7 @@ module Search
def set_search_order
if params[:search].present? && params[:order].blank?
- params[:order] = 'relevance'
+ params[:order] = "relevance"
end
end
diff --git a/app/controllers/concerns/translatable.rb b/app/controllers/concerns/translatable.rb
index 0acc874d8..94cdcaaab 100644
--- a/app/controllers/concerns/translatable.rb
+++ b/app/controllers/concerns/translatable.rb
@@ -1,34 +1,12 @@
module Translatable
extend ActiveSupport::Concern
- included do
- before_action :delete_translations, only: [:update]
- end
-
private
def translation_params(resource_model)
- return [] unless params[:enabled_translations]
-
- resource_model.translated_attribute_names.product(enabled_translations).map do |attr_name, loc|
- resource_model.localized_attr_name_for(attr_name, loc)
- end
- end
-
- def delete_translations
- locales = resource.translated_locales
- .select { |l| params.dig(:enabled_translations, l) == "0" }
-
- locales.each do |l|
- Globalize.with_locale(l) do
- resource.translation.destroy
- end
- end
- end
-
- def enabled_translations
- params.fetch(:enabled_translations, {})
- .select { |_, v| v == '1' }
- .keys
+ {
+ translations_attributes: [:id, :_destroy, :locale] +
+ resource_model.translated_attribute_names
+ }
end
end
diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb
index abcf79559..b10e28b88 100644
--- a/app/controllers/debates_controller.rb
+++ b/app/controllers/debates_controller.rb
@@ -46,9 +46,9 @@ class DebatesController < ApplicationController
def disable_recommendations
if current_user.update(recommended_debates: false)
- redirect_to debates_path, notice: t('debates.index.recommendations.actions.success')
+ redirect_to debates_path, notice: t("debates.index.recommendations.actions.success")
else
- redirect_to debates_path, error: t('debates.index.recommendations.actions.error')
+ redirect_to debates_path, error: t("debates.index.recommendations.actions.error")
end
end
@@ -67,7 +67,7 @@ class DebatesController < ApplicationController
end
def debates_recommendations
- if Setting['feature.user.recommendations_on_debates'] && current_user.recommended_debates
+ if Setting["feature.user.recommendations_on_debates"] && current_user.recommended_debates
@recommended_debates = Debate.recommendations(current_user).sort_by_random.limit(3)
end
end
diff --git a/app/controllers/documents_controller.rb b/app/controllers/documents_controller.rb
index 001d23446..1d6df8d14 100644
--- a/app/controllers/documents_controller.rb
+++ b/app/controllers/documents_controller.rb
@@ -11,7 +11,7 @@ class DocumentsController < ApplicationController
else
flash[:alert] = t "documents.actions.destroy.alert"
end
- redirect_to params[:from]
+ redirect_to request.referer
end
format.js do
if @document.destroy
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index 5f3fd0a9f..af28094d5 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -3,7 +3,8 @@ class GraphqlController < ApplicationController
skip_before_action :verify_authenticity_token
skip_authorization_check
- class QueryStringError < StandardError; end
+ class QueryStringError < StandardError
+ end
def query
begin
@@ -11,11 +12,11 @@ class GraphqlController < ApplicationController
response = consul_schema.execute query_string, variables: query_variables
render json: response, status: :ok
rescue GraphqlController::QueryStringError
- render json: { message: 'Query string not present' }, status: :bad_request
+ render json: { message: "Query string not present" }, status: :bad_request
rescue JSON::ParserError
- render json: { message: 'Error parsing JSON' }, status: :bad_request
+ render json: { message: "Error parsing JSON" }, status: :bad_request
rescue GraphQL::ParseError
- render json: { message: 'Query string is not valid JSON' }, status: :bad_request
+ render json: { message: "Query string is not valid JSON" }, status: :bad_request
rescue
unless Rails.env.production? then raise end
end
@@ -35,7 +36,7 @@ class GraphqlController < ApplicationController
end
def query_string
- if request.headers["CONTENT_TYPE"] == 'application/graphql'
+ if request.headers["CONTENT_TYPE"] == "application/graphql"
request.body.string # request.body.class => StringIO
else
params[:query]
@@ -43,7 +44,7 @@ class GraphqlController < ApplicationController
end
def query_variables
- if params[:variables].blank? || params[:variables] == 'null'
+ if params[:variables].blank? || params[:variables] == "null"
{}
else
JSON.parse(params[:variables])
diff --git a/app/controllers/installation_controller.rb b/app/controllers/installation_controller.rb
index 0651e9386..3f4461b5e 100644
--- a/app/controllers/installation_controller.rb
+++ b/app/controllers/installation_controller.rb
@@ -4,7 +4,7 @@ class InstallationController < ApplicationController
def details
respond_to do |format|
- format.any { render json: consul_installation_details.to_json, content_type: 'application/json' }
+ format.any { render json: consul_installation_details.to_json, content_type: "application/json" }
end
end
@@ -12,12 +12,12 @@ class InstallationController < ApplicationController
def consul_installation_details
{
- release: 'v0.16'
+ release: "v0.19"
}.merge(features: settings_feature_flags)
end
def settings_feature_flags
- Setting.where("key LIKE 'feature.%'").each_with_object({}) { |x, n| n[x.key.remove('feature.')] = x.value }
+ Setting.where("key LIKE 'feature.%'").each_with_object({}) { |x, n| n[x.key.remove("feature.")] = x.value }
end
end
diff --git a/app/controllers/legacy_legislations_controller.rb b/app/controllers/legacy_legislations_controller.rb
deleted file mode 100644
index 103c81cea..000000000
--- a/app/controllers/legacy_legislations_controller.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class LegacyLegislationsController < ApplicationController
- load_and_authorize_resource
-
- def show
- @legacy_legislation = LegacyLegislation.find(params[:id])
- end
-
-end
diff --git a/app/controllers/legislation/annotations_controller.rb b/app/controllers/legislation/annotations_controller.rb
index ebbe05b12..587a9578e 100644
--- a/app/controllers/legislation/annotations_controller.rb
+++ b/app/controllers/legislation/annotations_controller.rb
@@ -18,7 +18,7 @@ class Legislation::AnnotationsController < ApplicationController
@commentable = @annotation
if params[:sub_annotation_ids].present?
- @sub_annotations = Legislation::Annotation.where(id: params[:sub_annotation_ids].split(','))
+ @sub_annotations = Legislation::Annotation.where(id: params[:sub_annotation_ids].split(","))
annotations = [@commentable, @sub_annotations]
else
annotations = [@commentable]
diff --git a/app/controllers/legislation/answers_controller.rb b/app/controllers/legislation/answers_controller.rb
index ecaa0037a..9f9de89ae 100644
--- a/app/controllers/legislation/answers_controller.rb
+++ b/app/controllers/legislation/answers_controller.rb
@@ -18,7 +18,7 @@ class Legislation::AnswersController < Legislation::BaseController
format.html { redirect_to legislation_process_question_path(@process, @question) }
end
else
- alert = t('legislation.questions.participation.phase_not_open')
+ alert = t("legislation.questions.participation.phase_not_open")
respond_to do |format|
format.js { render json: {}, status: :not_found }
format.html { redirect_to legislation_process_question_path(@process, @question), alert: alert }
diff --git a/app/controllers/legislation/draft_versions_controller.rb b/app/controllers/legislation/draft_versions_controller.rb
index cdac2c9d5..00d2593a2 100644
--- a/app/controllers/legislation/draft_versions_controller.rb
+++ b/app/controllers/legislation/draft_versions_controller.rb
@@ -18,9 +18,9 @@ class Legislation::DraftVersionsController < Legislation::BaseController
def go_to_version
version = visible_draft_versions.find(params[:draft_version_id])
- if params[:redirect_action] == 'changes'
+ if params[:redirect_action] == "changes"
redirect_to legislation_process_draft_version_changes_path(@process, version)
- elsif params[:redirect_action] == 'annotations'
+ elsif params[:redirect_action] == "annotations"
redirect_to legislation_process_draft_version_annotations_path(@process, version)
else
redirect_to legislation_process_draft_version_path(@process, version)
diff --git a/app/controllers/legislation/processes_controller.rb b/app/controllers/legislation/processes_controller.rb
index f05d2fdda..1d9f32c5f 100644
--- a/app/controllers/legislation/processes_controller.rb
+++ b/app/controllers/legislation/processes_controller.rb
@@ -1,5 +1,7 @@
class Legislation::ProcessesController < Legislation::BaseController
- has_filters %w[open next past], only: :index
+ include RandomSeed
+
+ has_filters %w[open past], only: :index
has_filters %w[random winners], only: :proposals
load_and_authorize_resource
@@ -7,14 +9,18 @@ class Legislation::ProcessesController < Legislation::BaseController
before_action :set_random_seed, only: :proposals
def index
- @current_filter ||= 'open'
- @processes = ::Legislation::Process.send(@current_filter).published.page(params[:page])
+ @current_filter ||= "open"
+ @processes = ::Legislation::Process.send(@current_filter).published
+ .not_in_draft.order(start_date: :desc).page(params[:page])
end
def show
draft_version = @process.draft_versions.published.last
+ allegations_phase = @process.allegations_phase
- if @process.allegations_phase.enabled? && @process.allegations_phase.started? && draft_version.present?
+ if @process.homepage_enabled? && @process.homepage.present?
+ render :show
+ elsif allegations_phase.enabled? && allegations_phase.started? && draft_version.present?
redirect_to legislation_process_draft_version_path(@process, draft_version)
elsif @process.debate_phase.enabled?
redirect_to debate_legislation_process_path(@process)
@@ -87,6 +93,10 @@ class Legislation::ProcessesController < Legislation::BaseController
end
end
+ def milestones
+ @phase = :milestones
+ end
+
def proposals
set_process
@phase = :proposals_phase
@@ -95,7 +105,12 @@ class Legislation::ProcessesController < Legislation::BaseController
@proposals = @proposals.search(params[:search]) if params[:search].present?
@current_filter = "winners" if params[:filter].blank? && @proposals.winners.any?
- @proposals = @proposals.send(@current_filter).page(params[:page])
+
+ if @current_filter == "random"
+ @proposals = @proposals.sort_by_random(session[:random_seed]).page(params[:page])
+ else
+ @proposals = @proposals.send(@current_filter).page(params[:page])
+ end
if @process.proposals_phase.started? || (current_user && current_user.administrator?)
legislation_proposal_votes(@proposals)
@@ -115,15 +130,4 @@ class Legislation::ProcessesController < Legislation::BaseController
return if member_method?
@process = ::Legislation::Process.find(params[:process_id])
end
-
- def set_random_seed
- seed = begin
- Float(params[:random_seed] || session[:random_seed] || (rand(99) / 100.0))
- rescue
- 0
- end
- session[:random_seed], params[:random_seed] = seed
- seed = (-1..1).cover?(seed) ? seed : 1
- ::Legislation::Proposal.connection.execute "select setseed(#{seed})"
- end
end
diff --git a/app/controllers/legislation/proposals_controller.rb b/app/controllers/legislation/proposals_controller.rb
index eb5ce4e2f..4da2cb621 100644
--- a/app/controllers/legislation/proposals_controller.rb
+++ b/app/controllers/legislation/proposals_controller.rb
@@ -1,6 +1,7 @@
class Legislation::ProposalsController < Legislation::BaseController
include CommentableActions
include FlagActions
+ include ImageAttributes
before_action :parse_tag_filter, only: :index
before_action :load_categories, only: [:index, :new, :create, :edit, :map, :summary]
@@ -32,7 +33,7 @@ class Legislation::ProposalsController < Legislation::BaseController
@proposal = Legislation::Proposal.new(proposal_params.merge(author: current_user))
if @proposal.save
- redirect_to legislation_process_proposal_path(params[:process_id], @proposal), notice: I18n.t('flash.actions.create.proposal')
+ redirect_to legislation_process_proposal_path(params[:process_id], @proposal), notice: I18n.t("flash.actions.create.proposal")
else
render :new
end
@@ -54,7 +55,7 @@ class Legislation::ProposalsController < Legislation::BaseController
params.require(:legislation_proposal).permit(:legislation_process_id, :title,
:question, :summary, :description, :video_url, :tag_list,
:terms_of_service, :geozone_id,
- image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy],
+ image_attributes: image_attributes,
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id])
end
@@ -63,7 +64,7 @@ class Legislation::ProposalsController < Legislation::BaseController
end
def resource_name
- 'proposal'
+ "proposal"
end
def load_successful_proposals
diff --git a/app/controllers/management/base_controller.rb b/app/controllers/management/base_controller.rb
index ba8ece9f2..4314b2aa7 100644
--- a/app/controllers/management/base_controller.rb
+++ b/app/controllers/management/base_controller.rb
@@ -1,5 +1,5 @@
class Management::BaseController < ActionController::Base
- layout 'management'
+ layout "management"
before_action :verify_manager
before_action :set_locale
@@ -11,7 +11,7 @@ class Management::BaseController < ActionController::Base
private
def verify_manager
- raise ActionController::RoutingError.new('Not Found') if current_manager.blank?
+ raise ActionController::RoutingError.new("Not Found") if current_manager.blank?
end
def current_manager
diff --git a/app/controllers/management/budgets/investments_controller.rb b/app/controllers/management/budgets/investments_controller.rb
index d4ecac8d4..0b30820a2 100644
--- a/app/controllers/management/budgets/investments_controller.rb
+++ b/app/controllers/management/budgets/investments_controller.rb
@@ -1,10 +1,9 @@
class Management::Budgets::InvestmentsController < Management::BaseController
load_resource :budget
- load_resource :investment, through: :budget, class: 'Budget::Investment'
+ load_resource :investment, through: :budget, class: "Budget::Investment"
before_action :only_verified_users, except: :print
- before_action :load_heading, only: [:index, :show, :print]
def index
@investments = @investments.apply_filters_and_search(@budget, params).page(params[:page])
@@ -20,9 +19,10 @@ class Management::Budgets::InvestmentsController < Management::BaseController
@investment.author = managed_user
if @investment.save
- notice = t('flash.actions.create.notice', resource_name: Budget::Investment.model_name.human, count: 1)
+ notice = t("flash.actions.create.notice", resource_name: Budget::Investment.model_name.human, count: 1)
redirect_to management_budget_investment_path(@budget, @investment), notice: notice
else
+ load_categories
render :new
end
end
@@ -52,17 +52,14 @@ class Management::Budgets::InvestmentsController < Management::BaseController
end
def investment_params
- params.require(:budget_investment).permit(:title, :description, :external_url, :heading_id, :tag_list, :organization_name, :location)
+ params.require(:budget_investment).permit(:title, :description, :external_url, :heading_id,
+ :tag_list, :organization_name, :location, :skip_map)
end
def only_verified_users
check_verified_user t("management.budget_investments.alert.unverified_user")
end
- def load_heading
- @heading = @budget.headings.find(params[:heading_id]) if params[:heading_id].present?
- end
-
def load_categories
@categories = ActsAsTaggableOn::Tag.category.order(:name)
end
diff --git a/app/controllers/management/proposals_controller.rb b/app/controllers/management/proposals_controller.rb
index 0580ce607..24d5c22d6 100644
--- a/app/controllers/management/proposals_controller.rb
+++ b/app/controllers/management/proposals_controller.rb
@@ -35,7 +35,7 @@ class Management::ProposalsController < Management::BaseController
end
def vote
- @proposal.register_vote(managed_user, 'yes')
+ @proposal.register_vote(managed_user, "yes")
set_proposal_votes(@proposal)
end
diff --git a/app/controllers/management/spending_proposals_controller.rb b/app/controllers/management/spending_proposals_controller.rb
index f68c54f46..0a6ef4385 100644
--- a/app/controllers/management/spending_proposals_controller.rb
+++ b/app/controllers/management/spending_proposals_controller.rb
@@ -17,7 +17,7 @@ class Management::SpendingProposalsController < Management::BaseController
@spending_proposal.author = managed_user
if @spending_proposal.save
- notice = t('flash.actions.create.notice', resource_name: t("activerecord.models.spending_proposal", count: 1))
+ notice = t("flash.actions.create.notice", resource_name: t("activerecord.models.spending_proposal", count: 1))
redirect_to management_spending_proposal_path(@spending_proposal), notice: notice
else
render :new
@@ -29,12 +29,12 @@ class Management::SpendingProposalsController < Management::BaseController
end
def vote
- @spending_proposal.register_vote(managed_user, 'yes')
+ @spending_proposal.register_vote(managed_user, "yes")
set_spending_proposal_votes(@spending_proposal)
end
def print
- params[:geozone] ||= 'all'
+ params[:geozone] ||= "all"
@spending_proposals = apply_filters_and_search(SpendingProposal).order(cached_votes_up: :desc).for_render.limit(15)
set_spending_proposal_votes(@spending_proposals)
end
@@ -59,8 +59,8 @@ class Management::SpendingProposalsController < Management::BaseController
end
def set_geozone_name
- if params[:geozone] == 'all'
- @geozone_name = t('geozones.none')
+ if params[:geozone] == "all"
+ @geozone_name = t("geozones.none")
else
@geozone_name = Geozone.find(params[:geozone]).name
end
diff --git a/app/controllers/management/users_controller.rb b/app/controllers/management/users_controller.rb
index 1c8c6ed53..5f67aa506 100644
--- a/app/controllers/management/users_controller.rb
+++ b/app/controllers/management/users_controller.rb
@@ -13,7 +13,7 @@ class Management::UsersController < Management::BaseController
user_with_email
end
- @user.terms_of_service = '1'
+ @user.terms_of_service = "1"
@user.residence_verified_at = Time.current
@user.verified_at = Time.current
@@ -25,7 +25,7 @@ class Management::UsersController < Management::BaseController
end
def erase
- managed_user.erase(t("management.users.erased_by_manager", manager: current_manager['login'])) if current_manager.present?
+ managed_user.erase(t("management.users.erased_by_manager", manager: current_manager["login"])) if current_manager.present?
destroy_session
redirect_to management_document_verifications_path, notice: t("management.users.erased_notice")
end
@@ -48,7 +48,7 @@ class Management::UsersController < Management::BaseController
end
def user_without_email
- new_password = "aAbcdeEfghiJkmnpqrstuUvwxyz23456789$!".split('').sample(10).join('')
+ new_password = "aAbcdeEfghiJkmnpqrstuUvwxyz23456789$!".split("").sample(10).join("")
@user.password = new_password
@user.password_confirmation = new_password
diff --git a/app/controllers/moderation/base_controller.rb b/app/controllers/moderation/base_controller.rb
index de0c46a79..c175cb1bd 100644
--- a/app/controllers/moderation/base_controller.rb
+++ b/app/controllers/moderation/base_controller.rb
@@ -1,5 +1,5 @@
class Moderation::BaseController < ApplicationController
- layout 'admin'
+ layout "admin"
before_action :authenticate_user!
before_action :verify_moderator
diff --git a/app/controllers/moderation/budgets/investments_controller.rb b/app/controllers/moderation/budgets/investments_controller.rb
index 7f33058e8..a56534259 100644
--- a/app/controllers/moderation/budgets/investments_controller.rb
+++ b/app/controllers/moderation/budgets/investments_controller.rb
@@ -9,12 +9,12 @@ class Moderation::Budgets::InvestmentsController < Moderation::BaseController
before_action :load_resources, only: [:index, :moderate]
- load_and_authorize_resource class: 'Budget::Investment'
+ load_and_authorize_resource class: "Budget::Investment"
private
def resource_name
- 'budget_investment'
+ "budget_investment"
end
def resource_model
diff --git a/app/controllers/moderation/proposal_notifications_controller.rb b/app/controllers/moderation/proposal_notifications_controller.rb
index 64a2cae5a..d36e0614e 100644
--- a/app/controllers/moderation/proposal_notifications_controller.rb
+++ b/app/controllers/moderation/proposal_notifications_controller.rb
@@ -15,7 +15,7 @@ class Moderation::ProposalNotificationsController < Moderation::BaseController
private
def resource_name
- 'proposal_notification'
+ "proposal_notification"
end
def resource_model
diff --git a/app/controllers/moderation/users_controller.rb b/app/controllers/moderation/users_controller.rb
index cd1fff9a5..2fdf34437 100644
--- a/app/controllers/moderation/users_controller.rb
+++ b/app/controllers/moderation/users_controller.rb
@@ -10,7 +10,7 @@ class Moderation::UsersController < Moderation::BaseController
def hide_in_moderation_screen
block_user
- redirect_to request.query_parameters.merge(action: :index), notice: I18n.t('moderation.users.notice_hide')
+ redirect_to request.query_parameters.merge(action: :index), notice: I18n.t("moderation.users.notice_hide")
end
def hide
@@ -30,4 +30,4 @@ class Moderation::UsersController < Moderation::BaseController
Activity.log(current_user, :block, @user)
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index 2c4fd3e9f..e2293f2c3 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -36,6 +36,7 @@ class NotificationsController < ApplicationController
end
private
+
def linkable_resource_path(notification)
if notification.linkable_resource.is_a?(AdminNotification)
notification.linkable_resource.link || notifications_path
diff --git a/app/controllers/officing/base_controller.rb b/app/controllers/officing/base_controller.rb
index 07cf4cfa5..48054ce6a 100644
--- a/app/controllers/officing/base_controller.rb
+++ b/app/controllers/officing/base_controller.rb
@@ -1,5 +1,5 @@
class Officing::BaseController < ApplicationController
- layout 'admin'
+ layout "admin"
before_action :authenticate_user!
before_action :verify_officer
@@ -9,4 +9,4 @@ class Officing::BaseController < ApplicationController
def verify_officer
raise CanCan::AccessDenied unless current_user.try(:poll_officer?)
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/officing/results_controller.rb b/app/controllers/officing/results_controller.rb
index 39adcc7ed..54bb1076c 100644
--- a/app/controllers/officing/results_controller.rb
+++ b/app/controllers/officing/results_controller.rb
@@ -57,7 +57,7 @@ class Officing::ResultsController < Officing::BaseController
partial_result.officer_assignment_id = @officer_assignment.id
partial_result.amount = count.to_i
partial_result.author = current_user
- partial_result.origin = 'booth'
+ partial_result.origin = "booth"
@results << partial_result
end
end
@@ -70,7 +70,7 @@ class Officing::ResultsController < Officing::BaseController
date: Date.current)
recount.officer_assignment_id = @officer_assignment.id
recount.author = current_user
- recount.origin = 'booth'
+ recount.origin = "booth"
[:whites, :nulls, :total].each do |recount_type|
if results_params[recount_type].present?
recount["#{recount_type.to_s.singularize}_amount"] = results_params[recount_type].to_i
diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb
index 489ea9dcf..88ed65582 100644
--- a/app/controllers/pages_controller.rb
+++ b/app/controllers/pages_controller.rb
@@ -6,9 +6,10 @@ class PagesController < ApplicationController
def show
@custom_page = SiteCustomization::Page.published.find_by(slug: params[:id])
- @banners = Banner.in_section('help_page').with_active
+ @banners = Banner.in_section("help_page").with_active
if @custom_page.present?
+ @cards = @custom_page.cards
render action: :custom_page
else
render action: params[:id]
diff --git a/app/controllers/polls/questions_controller.rb b/app/controllers/polls/questions_controller.rb
index 73e7fa160..6773282ef 100644
--- a/app/controllers/polls/questions_controller.rb
+++ b/app/controllers/polls/questions_controller.rb
@@ -1,7 +1,7 @@
class Polls::QuestionsController < ApplicationController
load_and_authorize_resource :poll
- load_and_authorize_resource :question, class: 'Poll::Question'
+ load_and_authorize_resource :question, class: "Poll::Question"
has_orders %w{most_voted newest oldest}, only: :show
diff --git a/app/controllers/polls_controller.rb b/app/controllers/polls_controller.rb
index 26379f8cb..8bf987e9e 100644
--- a/app/controllers/polls_controller.rb
+++ b/app/controllers/polls_controller.rb
@@ -1,9 +1,11 @@
class PollsController < ApplicationController
include PollsHelper
+ before_action :load_active_poll, only: :index
+
load_and_authorize_resource
- has_filters %w{current expired incoming}
+ has_filters %w[current expired]
has_orders %w{most_voted newest oldest}, only: :show
::Poll::Answer # trigger autoload
@@ -34,4 +36,10 @@ class PollsController < ApplicationController
def results
end
+ private
+
+ def load_active_poll
+ @active_poll = ActivePoll.first
+ end
+
end
diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb
index f4a2ccf64..734976924 100644
--- a/app/controllers/proposals_controller.rb
+++ b/app/controllers/proposals_controller.rb
@@ -2,6 +2,7 @@ class ProposalsController < ApplicationController
include FeatureFlags
include CommentableActions
include FlagActions
+ include ImageAttributes
before_action :parse_tag_filter, only: :index
before_action :load_categories, only: [:index, :new, :create, :edit, :map, :summary]
@@ -35,7 +36,7 @@ class ProposalsController < ApplicationController
@proposal = Proposal.new(proposal_params.merge(author: current_user))
if @proposal.save
- redirect_to created_proposal_path(@proposal), notice: I18n.t('flash.actions.create.proposal')
+ redirect_to created_proposal_path(@proposal), notice: I18n.t("flash.actions.create.proposal")
else
render :new
end
@@ -47,18 +48,17 @@ class ProposalsController < ApplicationController
discard_draft
discard_archived
load_retired
- load_successful_proposals
- load_featured unless @proposal_successful_exists
+ load_featured
end
def vote
- @proposal.register_vote(current_user, 'yes')
+ @proposal.register_vote(current_user, "yes")
set_proposal_votes(@proposal)
end
def retire
if valid_retired_params? && @proposal.update(retired_params.merge(retired_at: Time.current))
- redirect_to proposal_path(@proposal), notice: t('proposals.notice.retired')
+ redirect_to proposal_path(@proposal), notice: t("proposals.notice.retired")
else
render action: :retire_form
end
@@ -67,14 +67,8 @@ class ProposalsController < ApplicationController
def retire_form
end
- def share
- if Setting['proposal_improvement_path'].present?
- @proposal_improvement_path = Setting['proposal_improvement_path']
- end
- end
-
def vote_featured
- @proposal.register_vote(current_user, 'yes')
+ @proposal.register_vote(current_user, "yes")
set_featured_proposal_votes(@proposal)
end
@@ -85,9 +79,9 @@ class ProposalsController < ApplicationController
def disable_recommendations
if current_user.update(recommended_proposals: false)
- redirect_to proposals_path, notice: t('proposals.index.recommendations.actions.success')
+ redirect_to proposals_path, notice: t("proposals.index.recommendations.actions.success")
else
- redirect_to proposals_path, error: t('proposals.index.recommendations.actions.error')
+ redirect_to proposals_path, error: t("proposals.index.recommendations.actions.error")
end
end
@@ -101,7 +95,7 @@ class ProposalsController < ApplicationController
def proposal_params
params.require(:proposal).permit(:title, :question, :summary, :description, :external_url, :video_url,
:responsible_name, :tag_list, :terms_of_service, :geozone_id, :skip_map,
- image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy],
+ image_attributes: image_attributes,
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy],
map_location_attributes: [:latitude, :longitude, :zoom])
end
@@ -111,8 +105,8 @@ class ProposalsController < ApplicationController
end
def valid_retired_params?
- @proposal.errors.add(:retired_reason, I18n.t('errors.messages.blank')) if params[:proposal][:retired_reason].blank?
- @proposal.errors.add(:retired_explanation, I18n.t('errors.messages.blank')) if params[:proposal][:retired_explanation].blank?
+ @proposal.errors.add(:retired_reason, I18n.t("errors.messages.blank")) if params[:proposal][:retired_reason].blank?
+ @proposal.errors.add(:retired_explanation, I18n.t("errors.messages.blank")) if params[:proposal][:retired_explanation].blank?
@proposal.errors.empty?
end
@@ -143,10 +137,13 @@ class ProposalsController < ApplicationController
def load_featured
return unless !@advanced_search_terms && @search_terms.blank? && @tag_filter.blank? && params[:retired].blank? && @current_order != "recommendations"
- @featured_proposals = Proposal.not_archived.sort_by_confidence_score.limit(3)
- if @featured_proposals.present?
- set_featured_proposal_votes(@featured_proposals)
- @resources = @resources.where('proposals.id NOT IN (?)', @featured_proposals.map(&:id))
+ if Setting["feature.featured_proposals"]
+ @featured_proposals = Proposal.not_archived.unsuccessful
+ .sort_by_confidence_score.limit(Setting["featured_proposals_number"])
+ if @featured_proposals.present?
+ set_featured_proposal_votes(@featured_proposals)
+ @resources = @resources.where("proposals.id NOT IN (?)", @featured_proposals.map(&:id))
+ end
end
end
@@ -154,10 +151,6 @@ class ProposalsController < ApplicationController
@view = (params[:view] == "minimal") ? "minimal" : "default"
end
- def load_successful_proposals
- @proposal_successful_exists = Proposal.successful.exists?
- end
-
def destroy_map_location_association
map_location = params[:proposal][:map_location_attributes]
if map_location && (map_location[:longitude] && map_location[:latitude]).blank? && !map_location[:id].blank?
@@ -166,7 +159,7 @@ class ProposalsController < ApplicationController
end
def proposals_recommendations
- if Setting['feature.user.recommendations_on_proposals'] && current_user.recommended_proposals
+ if Setting["feature.user.recommendations_on_proposals"] && current_user.recommended_proposals
@recommended_proposals = Proposal.recommendations(current_user).sort_by_random.limit(3)
end
end
diff --git a/app/controllers/related_contents_controller.rb b/app/controllers/related_contents_controller.rb
index db6be0018..0c31d5f69 100644
--- a/app/controllers/related_contents_controller.rb
+++ b/app/controllers/related_contents_controller.rb
@@ -9,13 +9,13 @@ class RelatedContentsController < ApplicationController
if relationable_object.url != related_object.url
RelatedContent.create(parent_relationable: @relationable, child_relationable: @related, author: current_user)
- flash[:success] = t('related_content.success')
+ flash[:success] = t("related_content.success")
else
- flash[:error] = t('related_content.error_itself')
+ flash[:error] = t("related_content.error_itself")
end
else
- flash[:error] = t('related_content.error', url: Setting['url'])
+ flash[:error] = t("related_content.error", url: Setting["url"])
end
redirect_to @relationable.url
end
@@ -31,14 +31,14 @@ class RelatedContentsController < ApplicationController
private
def score(action)
- @related = RelatedContent.find_by(id: params[:id])
+ @related = RelatedContent.find params[:id]
@related.send("score_#{action}", current_user)
- render template: 'relationable/_refresh_score_actions'
+ render template: "relationable/_refresh_score_actions"
end
def valid_url?
- params[:url].start_with?(Setting['url'])
+ params[:url].start_with?(Setting["url"])
end
def relationable_object
diff --git a/app/controllers/sandbox_controller.rb b/app/controllers/sandbox_controller.rb
index 6c6fa2d71..ec813c49f 100644
--- a/app/controllers/sandbox_controller.rb
+++ b/app/controllers/sandbox_controller.rb
@@ -6,14 +6,14 @@ class SandboxController < ApplicationController
helper_method(:namespace)
def index
- @templates = Dir.glob(Rails.root.join('app', 'views', 'sandbox', '*.html.erb').to_s).map do |filename|
+ @templates = Dir.glob(Rails.root.join("app", "views", "sandbox", "*.html.erb").to_s).map do |filename|
filename = File.basename(filename, File.extname(filename))
- filename unless filename.starts_with?('_') || filename == 'index.html'
+ filename unless filename.starts_with?("_") || filename == "index.html"
end.compact
end
def show
- if params[:template].index('.') # CVE-2014-0130
+ if params[:template].index(".") # CVE-2014-0130
render action: "index"
elsif lookup_context.exists?("sandbox/#{params[:template]}")
if params[:template] == "index"
diff --git a/app/controllers/spending_proposals_controller.rb b/app/controllers/spending_proposals_controller.rb
index 91ad8641c..e57cdd27c 100644
--- a/app/controllers/spending_proposals_controller.rb
+++ b/app/controllers/spending_proposals_controller.rb
@@ -31,7 +31,7 @@ class SpendingProposalsController < ApplicationController
if @spending_proposal.save
activity = "#{t('layouts.header.my_activity_link')}"
- notice = t('flash.actions.create.spending_proposal', activity: activity)
+ notice = t("flash.actions.create.spending_proposal", activity: activity)
redirect_to @spending_proposal, notice: notice, flash: { html_safe: true }
else
render :new
@@ -41,11 +41,11 @@ class SpendingProposalsController < ApplicationController
def destroy
spending_proposal = SpendingProposal.find(params[:id])
spending_proposal.destroy
- redirect_to user_path(current_user, filter: 'spending_proposals'), notice: t('flash.actions.destroy.spending_proposal')
+ redirect_to user_path(current_user, filter: "spending_proposals"), notice: t("flash.actions.destroy.spending_proposal")
end
def vote
- @spending_proposal.register_vote(current_user, 'yes')
+ @spending_proposal.register_vote(current_user, "yes")
set_spending_proposal_votes(@spending_proposal)
end
@@ -56,8 +56,8 @@ class SpendingProposalsController < ApplicationController
end
def set_geozone_name
- if params[:geozone] == 'all'
- @geozone_name = t('geozones.none')
+ if params[:geozone] == "all"
+ @geozone_name = t("geozones.none")
else
@geozone_name = Geozone.find(params[:geozone]).name
end
diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb
index 7bb872257..4d059cae6 100644
--- a/app/controllers/stats_controller.rb
+++ b/app/controllers/stats_controller.rb
@@ -6,19 +6,19 @@ class StatsController < ApplicationController
skip_authorization_check
def index
- @visits = daily_cache('visits') { Visit.count }
- @debates = daily_cache('debates') { Debate.with_hidden.count }
- @proposals = daily_cache('proposals') { Proposal.with_hidden.count }
- @comments = daily_cache('comments') { Comment.not_valuations.with_hidden.count }
+ @visits = daily_cache("visits") { Visit.count }
+ @debates = daily_cache("debates") { Debate.with_hidden.count }
+ @proposals = daily_cache("proposals") { Proposal.with_hidden.count }
+ @comments = daily_cache("comments") { Comment.not_valuations.with_hidden.count }
- @debate_votes = daily_cache('debate_votes') { Vote.where(votable_type: 'Debate').count }
- @proposal_votes = daily_cache('proposal_votes') { Vote.where(votable_type: 'Proposal').count }
- @comment_votes = daily_cache('comment_votes') { Vote.where(votable_type: 'Comment').count }
- @investment_votes = daily_cache('budget_investment_votes') { Vote.where(votable_type: 'Budget::Investment').count }
- @votes = daily_cache('votes') { Vote.count }
+ @debate_votes = daily_cache("debate_votes") { Vote.where(votable_type: "Debate").count }
+ @proposal_votes = daily_cache("proposal_votes") { Vote.where(votable_type: "Proposal").count }
+ @comment_votes = daily_cache("comment_votes") { Vote.where(votable_type: "Comment").count }
+ @investment_votes = daily_cache("budget_investment_votes") { Vote.where(votable_type: "Budget::Investment").count }
+ @votes = daily_cache("votes") { Vote.count }
- @verified_users = daily_cache('verified_users') { User.with_hidden.level_two_or_three_verified.count }
- @unverified_users = daily_cache('unverified_users') { User.with_hidden.unverified.count }
+ @verified_users = daily_cache("verified_users") { User.with_hidden.level_two_or_three_verified.count }
+ @unverified_users = daily_cache("unverified_users") { User.with_hidden.unverified.count }
end
private
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
index 0e63685bd..f3f0dd7ef 100644
--- a/app/controllers/topics_controller.rb
+++ b/app/controllers/topics_controller.rb
@@ -16,7 +16,7 @@ class TopicsController < ApplicationController
def create
@topic = Topic.new(topic_params.merge(author: current_user, community_id: params[:community_id]))
if @topic.save
- redirect_to community_path(@community), notice: I18n.t('flash.actions.create.topic')
+ redirect_to community_path(@community), notice: I18n.t("flash.actions.create.topic")
else
render :new
end
@@ -33,7 +33,7 @@ class TopicsController < ApplicationController
def update
if @topic.update(topic_params)
- redirect_to community_path(@community), notice: t('flash.actions.update.topic')
+ redirect_to community_path(@community), notice: t("flash.actions.update.topic")
else
render :edit
end
@@ -41,7 +41,7 @@ class TopicsController < ApplicationController
def destroy
@topic.destroy
- redirect_to community_path(@community), notice: I18n.t('flash.actions.destroy.topic')
+ redirect_to community_path(@community), notice: I18n.t("flash.actions.destroy.topic")
end
private
diff --git a/app/controllers/users/confirmations_controller.rb b/app/controllers/users/confirmations_controller.rb
index 9b7ebd41b..de65e592a 100644
--- a/app/controllers/users/confirmations_controller.rb
+++ b/app/controllers/users/confirmations_controller.rb
@@ -53,7 +53,7 @@ class Users::ConfirmationsController < Devise::ConfirmationsController
private
def set_official_position
- resource.add_official_position! (Setting['official_level_1_name']), 1
+ resource.add_official_position! (Setting["official_level_1_name"]), 1
end
end
diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb
index c83eecbcb..0e0f741a3 100644
--- a/app/controllers/users/omniauth_callbacks_controller.rb
+++ b/app/controllers/users/omniauth_callbacks_controller.rb
@@ -23,7 +23,7 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
private
def sign_in_with(feature, provider)
- raise ActionController::RoutingError.new('Not Found') unless Setting["feature.#{feature}"]
+ raise ActionController::RoutingError.new("Not Found") unless Setting["feature.#{feature}"]
auth = env["omniauth.auth"]
diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb
index ed8f3d0c4..a63945342 100644
--- a/app/controllers/users/registrations_controller.rb
+++ b/app/controllers/users/registrations_controller.rb
@@ -2,7 +2,7 @@ class Users::RegistrationsController < Devise::RegistrationsController
prepend_before_action :authenticate_scope!, only: [:edit, :update, :destroy, :finish_signup, :do_finish_signup]
before_filter :configure_permitted_parameters
- invisible_captcha only: [:create], honeypot: :family_name, scope: :user
+ invisible_captcha only: [:create], honeypot: :address, scope: :user
def new
super do |user|
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 0724b1f99..800a65e0a 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -13,9 +13,9 @@ class UsersController < ApplicationController
def set_activity_counts
@activity_counts = HashWithIndifferentAccess.new(
- proposals: Proposal.created_by(@user).count,
- debates: (Setting['feature.debates'] ? Debate.where(author_id: @user.id).count : 0),
- budget_investments: (Setting['feature.budgets'] ? Budget::Investment.where(author_id: @user.id).count : 0),
+ proposals: Proposal.where(author_id: @user.id).count,
+ debates: (Setting["process.debates"] ? Debate.where(author_id: @user.id).count : 0),
+ budget_investments: (Setting["process.budgets"] ? Budget::Investment.where(author_id: @user.id).count : 0),
comments: only_active_commentables.count,
follows: @user.follows.map(&:followable).compact.count)
end
@@ -93,8 +93,8 @@ class UsersController < ApplicationController
def only_active_commentables
disabled_commentables = []
- disabled_commentables << "Debate" unless Setting['feature.debates']
- disabled_commentables << "Budget::Investment" unless Setting['feature.budgets']
+ disabled_commentables << "Debate" unless Setting["process.debates"]
+ disabled_commentables << "Budget::Investment" unless Setting["process.budgets"]
if disabled_commentables.present?
all_user_comments.where("commentable_type NOT IN (?)", disabled_commentables)
else
diff --git a/app/controllers/valuation/base_controller.rb b/app/controllers/valuation/base_controller.rb
index fb42fb694..64001e6d7 100644
--- a/app/controllers/valuation/base_controller.rb
+++ b/app/controllers/valuation/base_controller.rb
@@ -1,5 +1,5 @@
class Valuation::BaseController < ApplicationController
- layout 'admin'
+ layout "admin"
before_action :authenticate_user!
before_action :verify_valuator
diff --git a/app/controllers/valuation/budget_investments_controller.rb b/app/controllers/valuation/budget_investments_controller.rb
index d8b832d47..2ee531f27 100644
--- a/app/controllers/valuation/budget_investments_controller.rb
+++ b/app/controllers/valuation/budget_investments_controller.rb
@@ -33,7 +33,7 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
end
Activity.log(current_user, :valuate, @investment)
- notice = t('valuation.budget_investments.notice.valuate')
+ notice = t("valuation.budget_investments.notice.valuate")
redirect_to valuation_budget_budget_investment_path(@budget, @investment), notice: notice
else
render action: :edit
@@ -61,7 +61,7 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
end
def resource_name
- resource_model.parameterize('_')
+ resource_model.parameterize("_")
end
def load_budget
@@ -75,13 +75,13 @@ 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.where(id: investments.pluck(:heading_id).uniq)
+ investment_headings = Budget::Heading.joins(:translations)
+ .where(id: investments.pluck(:heading_id).uniq)
.order(name: :asc)
all_headings_filter = [
{
- name: t('valuation.budget_investments.index.headings_filter_all'),
+ name: t("valuation.budget_investments.index.headings_filter_all"),
id: nil,
count: investments.size
}
@@ -109,7 +109,7 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
def restrict_access
unless current_user.administrator? || current_budget.valuating?
- raise CanCan::AccessDenied.new(I18n.t('valuation.budget_investments.not_in_valuating_phase'))
+ raise CanCan::AccessDenied.new(I18n.t("valuation.budget_investments.not_in_valuating_phase"))
end
end
@@ -117,16 +117,16 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
return if current_user.administrator? ||
Budget::ValuatorAssignment.exists?(investment_id: params[:id],
valuator_id: current_user.valuator.id)
- raise ActionController::RoutingError.new('Not Found')
+ raise ActionController::RoutingError.new("Not Found")
end
def valid_price_params?
if /\D/.match params[:budget_investment][:price]
- @investment.errors.add(:price, I18n.t('budgets.investments.wrong_price_format'))
+ @investment.errors.add(:price, I18n.t("budgets.investments.wrong_price_format"))
end
if /\D/.match params[:budget_investment][:price_first_year]
- @investment.errors.add(:price_first_year, I18n.t('budgets.investments.wrong_price_format'))
+ @investment.errors.add(:price_first_year, I18n.t("budgets.investments.wrong_price_format"))
end
@investment.errors.empty?
diff --git a/app/controllers/valuation/budgets_controller.rb b/app/controllers/valuation/budgets_controller.rb
index 9789ab929..338cccec4 100644
--- a/app/controllers/valuation/budgets_controller.rb
+++ b/app/controllers/valuation/budgets_controller.rb
@@ -7,11 +7,9 @@ class Valuation::BudgetsController < Valuation::BaseController
def index
@budget = current_budget
if @budget.present?
- @investments_with_valuation_open = {}
- @investments_with_valuation_open = @budget.investments
- .by_valuator(current_user.valuator.try(:id))
- .valuation_open
- .count
+ @investments = @budget.investments
+ .by_valuator(current_user.valuator)
+ .valuation_open
end
end
end
diff --git a/app/controllers/valuation/spending_proposals_controller.rb b/app/controllers/valuation/spending_proposals_controller.rb
index 53efcbc2e..04000f8f8 100644
--- a/app/controllers/valuation/spending_proposals_controller.rb
+++ b/app/controllers/valuation/spending_proposals_controller.rb
@@ -26,7 +26,7 @@ class Valuation::SpendingProposalsController < Valuation::BaseController
@spending_proposal.send_unfeasible_email
end
- redirect_to valuation_spending_proposal_path(@spending_proposal), notice: t('valuation.spending_proposals.notice.valuate')
+ redirect_to valuation_spending_proposal_path(@spending_proposal), notice: t("valuation.spending_proposals.notice.valuate")
else
render action: :edit
end
@@ -37,12 +37,12 @@ class Valuation::SpendingProposalsController < Valuation::BaseController
def geozone_filters
spending_proposals = SpendingProposal.by_valuator(current_user.valuator.try(:id)).valuation_open.all.to_a
- [ { name: t('valuation.spending_proposals.index.geozone_filter_all'),
+ [ { name: t("valuation.spending_proposals.index.geozone_filter_all"),
id: nil,
pending_count: spending_proposals.size
},
- { name: t('geozones.none'),
- id: 'all',
+ { name: t("geozones.none"),
+ id: "all",
pending_count: spending_proposals.count{|x| x.geozone_id.nil?}
}
] + Geozone.all.order(name: :asc).collect do |g|
@@ -54,7 +54,7 @@ class Valuation::SpendingProposalsController < Valuation::BaseController
end
def valuation_params
- params[:spending_proposal][:feasible] = nil if params[:spending_proposal][:feasible] == 'nil'
+ params[:spending_proposal][:feasible] = nil if params[:spending_proposal][:feasible] == "nil"
params.require(:spending_proposal).permit(:price, :price_first_year, :price_explanation, :feasible, :feasible_explanation,
:time_scope, :valuation_finished, :internal_comments)
@@ -67,16 +67,16 @@ class Valuation::SpendingProposalsController < Valuation::BaseController
def restrict_access_to_assigned_items
return if current_user.administrator? ||
ValuationAssignment.exists?(spending_proposal_id: params[:id], valuator_id: current_user.valuator.id)
- raise ActionController::RoutingError.new('Not Found')
+ raise ActionController::RoutingError.new("Not Found")
end
def valid_price_params?
if /\D/.match params[:spending_proposal][:price]
- @spending_proposal.errors.add(:price, I18n.t('spending_proposals.wrong_price_format'))
+ @spending_proposal.errors.add(:price, I18n.t("spending_proposals.wrong_price_format"))
end
if /\D/.match params[:spending_proposal][:price_first_year]
- @spending_proposal.errors.add(:price_first_year, I18n.t('spending_proposals.wrong_price_format'))
+ @spending_proposal.errors.add(:price_first_year, I18n.t("spending_proposals.wrong_price_format"))
end
@spending_proposal.errors.empty?
diff --git a/app/controllers/verification/email_controller.rb b/app/controllers/verification/email_controller.rb
index 1774197d9..9c6b10c3c 100644
--- a/app/controllers/verification/email_controller.rb
+++ b/app/controllers/verification/email_controller.rb
@@ -7,9 +7,9 @@ class Verification::EmailController < ApplicationController
def show
if Verification::Email.find(current_user, params[:email_verification_token])
current_user.update(verified_at: Time.current)
- redirect_to account_path, notice: t('verification.email.show.flash.success')
+ redirect_to account_path, notice: t("verification.email.show.flash.success")
else
- redirect_to verified_user_path, alert: t('verification.email.show.alert.failure')
+ redirect_to verified_user_path, alert: t("verification.email.show.alert.failure")
end
end
@@ -22,9 +22,9 @@ class Verification::EmailController < ApplicationController
@email.encrypted_token,
@verified_user.document_type,
@verified_user.document_number).deliver_later
- redirect_to account_path, notice: t('verification.email.create.flash.success', email: @verified_user.email)
+ redirect_to account_path, notice: t("verification.email.create.flash.success", email: @verified_user.email)
else
- redirect_to verified_user_path, alert: t('verification.email.create.alert.failure')
+ redirect_to verified_user_path, alert: t("verification.email.create.alert.failure")
end
end
diff --git a/app/controllers/verification/letter_controller.rb b/app/controllers/verification/letter_controller.rb
index db04002b4..9437f38e9 100644
--- a/app/controllers/verification/letter_controller.rb
+++ b/app/controllers/verification/letter_controller.rb
@@ -30,7 +30,7 @@ class Verification::LetterController < ApplicationController
@letter = Verification::Letter.new(letter_params.merge(user: current_user, verify: true))
if @letter.valid?
current_user.update(verified_at: Time.current)
- redirect_to account_path, notice: t('verification.letter.update.flash.success')
+ redirect_to account_path, notice: t("verification.letter.update.flash.success")
else
Lock.increase_tries(@letter.user) if @letter.user
render :edit
@@ -45,7 +45,7 @@ class Verification::LetterController < ApplicationController
def verify_phone!
unless current_user.sms_verified?
- redirect_to verified_user_path, alert: t('verification.letter.alert.unconfirmed_code')
+ redirect_to verified_user_path, alert: t("verification.letter.alert.unconfirmed_code")
end
end
diff --git a/app/controllers/verification/residence_controller.rb b/app/controllers/verification/residence_controller.rb
index f5a826058..48631a5c1 100644
--- a/app/controllers/verification/residence_controller.rb
+++ b/app/controllers/verification/residence_controller.rb
@@ -11,7 +11,7 @@ class Verification::ResidenceController < ApplicationController
def create
@residence = Verification::Residence.new(residence_params.merge(user: current_user))
if @residence.save
- redirect_to verified_user_path, notice: t('verification.residence.create.flash.success')
+ redirect_to verified_user_path, notice: t("verification.residence.create.flash.success")
else
render :new
end
@@ -22,4 +22,4 @@ class Verification::ResidenceController < ApplicationController
def residence_params
params.require(:residence).permit(:document_number, :document_type, :date_of_birth, :postal_code, :terms_of_service)
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/verification/sms_controller.rb b/app/controllers/verification/sms_controller.rb
index f06af5e6a..0f978561e 100644
--- a/app/controllers/verification/sms_controller.rb
+++ b/app/controllers/verification/sms_controller.rb
@@ -14,7 +14,7 @@ class Verification::SmsController < ApplicationController
def create
@sms = Verification::Sms.new(phone: @phone, user: current_user)
if @sms.save
- redirect_to edit_sms_path, notice: t('verification.sms.create.flash.success')
+ redirect_to edit_sms_path, notice: t("verification.sms.create.flash.success")
else
render :new
end
@@ -36,7 +36,7 @@ class Verification::SmsController < ApplicationController
redirect_to_next_path
else
- @error = t('verification.sms.update.error')
+ @error = t("verification.sms.update.error")
render :edit
end
end
@@ -63,9 +63,9 @@ class Verification::SmsController < ApplicationController
def redirect_to_next_path
current_user.reload
if current_user.level_three_verified?
- redirect_to account_path, notice: t('verification.sms.update.flash.level_three.success')
+ redirect_to account_path, notice: t("verification.sms.update.flash.level_three.success")
else
- redirect_to new_letter_path, notice: t('verification.sms.update.flash.level_two.success')
+ redirect_to new_letter_path, notice: t("verification.sms.update.flash.level_two.success")
end
end
diff --git a/app/controllers/verification_controller.rb b/app/controllers/verification_controller.rb
index adb3ee345..f4d630130 100644
--- a/app/controllers/verification_controller.rb
+++ b/app/controllers/verification_controller.rb
@@ -14,7 +14,7 @@ class VerificationController < ApplicationController
if user.organization?
{ path: account_path }
elsif user.level_three_verified?
- { path: account_path, notice: t('verification.redirect_notices.already_verified') }
+ { path: account_path, notice: t("verification.redirect_notices.already_verified") }
elsif user.verification_letter_sent?
{ path: edit_letter_path }
elsif user.level_two_verified?
@@ -22,7 +22,7 @@ class VerificationController < ApplicationController
elsif user.verification_sms_sent?
{ path: edit_sms_path }
elsif user.verification_email_sent?
- { path: verified_user_path, notice: t('verification.redirect_notices.email_already_sent') }
+ { path: verified_user_path, notice: t("verification.redirect_notices.email_already_sent") }
elsif user.residence_verified?
{ path: verified_user_path }
else
@@ -30,4 +30,4 @@ class VerificationController < ApplicationController
end
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb
index 8d19394d7..eb009746a 100644
--- a/app/controllers/welcome_controller.rb
+++ b/app/controllers/welcome_controller.rb
@@ -1,6 +1,7 @@
class WelcomeController < ApplicationController
skip_authorization_check
before_action :set_user_recommendations, only: :index, if: :current_user
+ before_action :authenticate_user!, only: :welcome
layout "devise", only: [:welcome, :verification]
@@ -8,10 +9,17 @@ class WelcomeController < ApplicationController
@header = Widget::Card.header.first
@feeds = Widget::Feed.active
@cards = Widget::Card.body
- @banners = Banner.in_section('homepage').with_active
+ @banners = Banner.in_section("homepage").with_active
end
def welcome
+ if current_user.level_three_verified?
+ redirect_to page_path("welcome_level_three_verified")
+ elsif current_user.level_two_or_three_verified?
+ redirect_to page_path("welcome_level_two_verified")
+ else
+ redirect_to page_path("welcome_not_verified")
+ end
end
def verification
diff --git a/app/helpers/admin_budget_investments_helper.rb b/app/helpers/admin_budget_investments_helper.rb
index 492225e35..5c2dc479e 100644
--- a/app/helpers/admin_budget_investments_helper.rb
+++ b/app/helpers/admin_budget_investments_helper.rb
@@ -1,7 +1,7 @@
module AdminBudgetInvestmentsHelper
def advanced_menu_visibility
- (params[:advanced_filters].empty? && params["min_total_supports"].blank?) ? 'hide' : ''
+ (params[:advanced_filters].empty? && params["min_total_supports"].blank?) ? "hide" : ""
end
def init_advanced_menu
diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb
index 21bdb6519..842f7725f 100644
--- a/app/helpers/admin_helper.rb
+++ b/app/helpers/admin_helper.rb
@@ -1,7 +1,7 @@
module AdminHelper
def side_menu
- if namespace == 'moderation/budgets'
+ if namespace == "moderation/budgets"
render "/moderation/menu"
else
render "/#{namespace}/menu"
@@ -9,15 +9,11 @@ module AdminHelper
end
def namespaced_root_path
- if namespace == 'moderation/budgets'
- "/moderation"
- else
- "/#{namespace}"
- end
+ "/#{namespace}"
end
def namespaced_header_title
- if namespace == 'moderation/budgets'
+ if namespace == "moderation/budgets"
t("moderation.header.title")
else
t("#{namespace}.header.title")
@@ -25,7 +21,16 @@ module AdminHelper
end
def menu_moderated_content?
- ["proposals", "debates", "comments", "hidden_users", "activity", "hidden_budget_investments"].include?(controller_name) && controller.class.parent != Admin::Legislation
+ moderated_sections.include?(controller_name) && controller.class.parent != Admin::Legislation
+ end
+
+ def moderated_sections
+ ["hidden_proposals", "debates", "comments", "hidden_users", "activity",
+ "hidden_budget_investments"]
+ end
+
+ def menu_budgets?
+ controller_name.starts_with?("budget")
end
def menu_budget?
@@ -33,7 +38,8 @@ module AdminHelper
end
def menu_polls?
- %w[polls questions answers recounts results].include?(controller_name)
+ %w[polls active_polls recounts results questions answers].include?(controller_name) ||
+ controller.class.parent == Admin::Poll::Questions::Answers
end
def menu_booths?
@@ -45,15 +51,21 @@ module AdminHelper
end
def menu_settings?
- ["settings", "tags", "geozones", "images", "content_blocks"].include?(controller_name)
+ ["settings", "tags", "geozones", "images", "content_blocks"].include?(controller_name) &&
+ controller.class.parent != Admin::Poll::Questions::Answers
end
def menu_customization?
- ["pages", "banners", "information_texts"].include?(controller_name) || menu_homepage?
+ ["pages", "banners", "information_texts"].include?(controller_name) ||
+ menu_homepage? || menu_pages?
end
def menu_homepage?
- ["homepage", "cards"].include?(controller_name)
+ ["homepage", "cards"].include?(controller_name) && params[:page_id].nil?
+ end
+
+ def menu_pages?
+ ["pages", "cards"].include?(controller_name) && params[:page_id].present?
end
def menu_dashboard?
@@ -63,13 +75,13 @@ module AdminHelper
def official_level_options
options = [["", 0]]
(1..5).each do |i|
- options << [[t("admin.officials.level_#{i}"), setting["official_level_#{i}_name"]].compact.join(': '), i]
+ options << [[t("admin.officials.level_#{i}"), setting["official_level_#{i}_name"]].compact.join(": "), i]
end
options
end
def admin_select_options
- Administrator.all.order('users.username asc').includes(:user).collect { |v| [ v.name, v.id ] }
+ Administrator.all.order("users.username asc").includes(:user).collect { |v| [ v.name, v.id ] }
end
def admin_submit_action(resource)
@@ -92,14 +104,10 @@ module AdminHelper
user_roles(user).join(", ")
end
- def display_budget_goup_form(group)
- group.errors.messages.size > 0 ? "" : "display:none"
- end
-
private
def namespace
- controller.class.parent.name.downcase.gsub("::", "/")
+ controller.class.name.downcase.split("::").first
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 06939294b..2b23d14a9 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -4,14 +4,10 @@ module ApplicationHelper
return false if user_signed_in?
# Using path because fullpath yields false negatives since it contains
# parameters too
- request.path == '/'
+ request.path == "/"
end
- def opendata_page?
- request.path == '/opendata'
- end
-
- # if current path is /debates current_path_with_query_params(foo: 'bar') returns /debates?foo=bar
+ # if current path is /debates current_path_with_query_params(foo: "bar") returns /debates?foo=bar
# notice: if query_params have a param which also exist in current path, it "overrides" (query_params is merged last)
def current_path_with_query_params(query_parameters)
url_for(request.query_parameters.merge(query_parameters))
@@ -67,4 +63,11 @@ module ApplicationHelper
base64 = Base64.encode64(asset.to_s).gsub(/\s+/, "")
"data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
end
+
+ def render_custom_partial(partial_name)
+ controller_action = @virtual_path.split("/").last
+ custom_partial_path = "custom/#{@virtual_path.remove(controller_action)}#{partial_name}"
+ render custom_partial_path if lookup_context.exists?(custom_partial_path, [], true)
+ end
+
end
diff --git a/app/helpers/banners_helper.rb b/app/helpers/banners_helper.rb
index 3e78764a9..20f7ab93d 100644
--- a/app/helpers/banners_helper.rb
+++ b/app/helpers/banners_helper.rb
@@ -4,4 +4,20 @@ module BannersHelper
@banners.present? && @banners.count > 0
end
+ def banner_default_bg_color
+ "#e7f2fc"
+ end
+
+ def banner_default_font_color
+ "#222222"
+ end
+
+ def banner_bg_color_or_default
+ @banner.background_color.present? ? @banner.background_color : banner_default_bg_color
+ end
+
+ def banner_font_color_or_default
+ @banner.font_color.present? ? @banner.font_color : banner_default_font_color
+ end
+
end
diff --git a/app/helpers/budget_executions_helper.rb b/app/helpers/budget_executions_helper.rb
new file mode 100644
index 000000000..90d0744b0
--- /dev/null
+++ b/app/helpers/budget_executions_helper.rb
@@ -0,0 +1,12 @@
+module BudgetExecutionsHelper
+
+ def filters_select_counts(status)
+ @budget.investments.winners.with_milestone_status_id(status).count
+ end
+
+ def first_milestone_with_image(investment)
+ investment.milestones.order_by_publication_date
+ .select{ |milestone| milestone.image.present? }.last
+ end
+
+end
diff --git a/app/helpers/budget_headings_helper.rb b/app/helpers/budget_headings_helper.rb
index 22eabfe11..80c21e9e8 100644
--- a/app/helpers/budget_headings_helper.rb
+++ b/app/helpers/budget_headings_helper.rb
@@ -1,7 +1,7 @@
module BudgetHeadingsHelper
def budget_heading_select_options(budget)
- budget.headings.order_by_group_name.map do |heading|
+ budget.headings.sort_by_name.map do |heading|
[heading.name_scoped_by_group, heading.id]
end
end
diff --git a/app/helpers/budget_investments_helper.rb b/app/helpers/budget_investments_helper.rb
index e3f17601a..bcfdf0f49 100644
--- a/app/helpers/budget_investments_helper.rb
+++ b/app/helpers/budget_investments_helper.rb
@@ -1,12 +1,34 @@
module BudgetInvestmentsHelper
- def budget_investments_sorting_options
- Budget::Investment::SORTING_OPTIONS.map do |so|
- [t("admin.budget_investments.index.sort_by.#{so}"), so]
+ def budget_investments_advanced_filters(params)
+ params.map { |af| t("admin.budget_investments.index.filters.#{af}") }.join(", ")
+ end
+
+ def link_to_investments_sorted_by(column)
+ direction = set_direction(params[:direction])
+ icon = set_sorting_icon(direction, column)
+
+ translation = t("admin.budget_investments.index.list.#{column}")
+
+ link_to(
+ "#{translation} ".html_safe,
+ admin_budget_budget_investments_path(sort_by: column, direction: direction)
+ )
+ end
+
+ def set_sorting_icon(direction, sort_by)
+ if sort_by.to_s == params[:sort_by]
+ if direction == "desc"
+ "desc"
+ else
+ "asc"
+ end
+ else
+ ""
end
end
- def budget_investments_advanced_filters(params)
- params.map { |af| t("admin.budget_investments.index.filters.#{af}") }.join(', ')
+ def set_direction(current_direction)
+ current_direction == "desc" ? "asc" : "desc"
end
def investments_minimal_view_path
diff --git a/app/helpers/budgets_helper.rb b/app/helpers/budgets_helper.rb
index d5ca1879c..df48a08fa 100644
--- a/app/helpers/budgets_helper.rb
+++ b/app/helpers/budgets_helper.rb
@@ -1,12 +1,12 @@
module BudgetsHelper
def show_links_to_budget_investments(budget)
- ['balloting', 'reviewing_ballots', 'finished'].include? budget.phase
+ ["balloting", "reviewing_ballots", "finished"].include? budget.phase
end
def heading_name_and_price_html(heading, budget)
content_tag :div do
- concat(heading.name + ' ')
+ concat(heading.name + " ")
concat(content_tag(:span, budget.formatted_heading_price(heading)))
end
end
@@ -27,7 +27,7 @@ module BudgetsHelper
def namespaced_budget_investment_path(investment, options = {})
case namespace
- when "management/budgets"
+ when "management"
management_budget_investment_path(investment.budget, investment, options)
else
budget_investment_path(investment.budget, investment, options)
@@ -36,7 +36,7 @@ module BudgetsHelper
def namespaced_budget_investment_vote_path(investment, options = {})
case namespace
- when "management/budgets"
+ when "management"
vote_management_budget_investment_path(investment.budget, investment, options)
else
vote_budget_investment_path(investment.budget, investment, options)
@@ -48,8 +48,8 @@ module BudgetsHelper
end
def css_for_ballot_heading(heading)
- return '' if current_ballot.blank?
- current_ballot.has_lines_in_heading?(heading) ? 'is-active' : ''
+ return "" if current_ballot.blank? || @current_filter == "unfeasible"
+ current_ballot.has_lines_in_heading?(heading) ? "is-active" : ""
end
def current_ballot
@@ -60,13 +60,17 @@ module BudgetsHelper
Budget::Investment.by_budget(budget).tags_on(:valuation).order(:name).select(:name).distinct
end
+ def unfeasible_or_unselected_filter
+ ["unselected", "unfeasible"].include?(@current_filter)
+ end
+
def budget_published?(budget)
!budget.drafting? || current_user&.administrator?
end
def current_budget_map_locations
return unless current_budget.present?
- if current_budget.valuating_or_later?
+ if current_budget.publishing_prices_or_later? && current_budget.investments.selected.any?
investments = current_budget.investments.selected
else
investments = current_budget.investments
@@ -86,4 +90,10 @@ module BudgetsHelper
t("admin.budgets.winners.recalculate")
end
end
+
+ def display_support_alert?(investment)
+ current_user &&
+ !current_user.voted_in_group?(investment.group) &&
+ investment.group.headings.count > 1
+ end
end
diff --git a/app/helpers/content_blocks_helper.rb b/app/helpers/content_blocks_helper.rb
new file mode 100644
index 000000000..23453219c
--- /dev/null
+++ b/app/helpers/content_blocks_helper.rb
@@ -0,0 +1,11 @@
+module ContentBlocksHelper
+ def valid_blocks
+ options = SiteCustomization::ContentBlock::VALID_BLOCKS.map do |key|
+ [t("admin.site_customization.content_blocks.content_block.names.#{key}"), key]
+ end
+ Budget::Heading.allow_custom_content.each do |heading|
+ options.push([heading.name, "hcb_#{heading.id}"])
+ end
+ options
+ end
+end
diff --git a/app/helpers/debates_helper.rb b/app/helpers/debates_helper.rb
index f81d69809..7771a2561 100644
--- a/app/helpers/debates_helper.rb
+++ b/app/helpers/debates_helper.rb
@@ -6,9 +6,9 @@ module DebatesHelper
def empty_recommended_debates_message_text(user)
if user.interests.any?
- t('debates.index.recommendations.without_results')
+ t("debates.index.recommendations.without_results")
else
- t('debates.index.recommendations.without_interests')
+ t("debates.index.recommendations.without_interests")
end
end
diff --git a/app/helpers/documentables_helper.rb b/app/helpers/documentables_helper.rb
index 5c3181c95..b277ae3eb 100644
--- a/app/helpers/documentables_helper.rb
+++ b/app/helpers/documentables_helper.rb
@@ -1,7 +1,7 @@
module DocumentablesHelper
def documentable_class(documentable)
- documentable.class.name.parameterize('_')
+ documentable.class.name.parameterize("_")
end
def max_documents_allowed(documentable)
diff --git a/app/helpers/documents_helper.rb b/app/helpers/documents_helper.rb
index 4766de0aa..b0facdacc 100644
--- a/app/helpers/documents_helper.rb
+++ b/app/helpers/documents_helper.rb
@@ -5,7 +5,7 @@ module DocumentsHelper
end
def document_errors_on_attachment(document)
- document.errors[:attachment].join(', ') if document.errors.key?(:attachment)
+ document.errors[:attachment].join(", ") if document.errors.key?(:attachment)
end
def bytes_to_mega(bytes)
@@ -18,7 +18,7 @@ module DocumentsHelper
def render_destroy_document_link(builder, document)
if !document.persisted? && document.cached_attachment.present?
- link_to t('documents.form.delete_button'),
+ link_to t("documents.form.delete_button"),
direct_upload_destroy_url("direct_upload[resource_type]": document.documentable_type,
"direct_upload[resource_id]": document.documentable_id,
"direct_upload[resource_relation]": "documents",
@@ -27,7 +27,7 @@ module DocumentsHelper
remote: true,
class: "delete remove-cached-attachment"
else
- link_to_remove_association document.new_record? ? t('documents.form.cancel_button') : t('documents.form.delete_button') , builder, class: "delete remove-document"
+ link_to_remove_association document.new_record? ? t("documents.form.cancel_button") : t("documents.form.delete_button") , builder, class: "delete remove-document"
end
end
@@ -40,7 +40,7 @@ module DocumentsHelper
html += builder.file_field :attachment,
label: false,
accept: accepted_content_types_extensions(document.documentable_type.constantize),
- class: 'js-document-attachment',
+ class: "js-document-attachment",
data: {
url: document_direct_upload_url(document),
nested_document: true
diff --git a/app/helpers/embed_videos_helper.rb b/app/helpers/embed_videos_helper.rb
index 823659cca..645376525 100644
--- a/app/helpers/embed_videos_helper.rb
+++ b/app/helpers/embed_videos_helper.rb
@@ -5,7 +5,7 @@ module EmbedVideosHelper
def embedded_video_code
link = @proposal.video_url
- title = t('proposals.show.embed_video_title', proposal: @proposal.title)
+ title = t("proposals.show.embed_video_title", proposal: @proposal.title)
if link =~ /vimeo.*/
server = "Vimeo"
elsif link =~ /youtu*.*/
@@ -27,7 +27,7 @@ module EmbedVideosHelper
if match && match[2]
''
else
- ''
+ ""
end
end
diff --git a/app/helpers/feeds_helper.rb b/app/helpers/feeds_helper.rb
index 3a5ee8f3d..a863de56c 100644
--- a/app/helpers/feeds_helper.rb
+++ b/app/helpers/feeds_helper.rb
@@ -12,8 +12,20 @@ module FeedsHelper
feed.kind == "processes"
end
+ def feed_debates_enabled?
+ Setting["homepage.widgets.feeds.debates"].present?
+ end
+
+ def feed_proposals_enabled?
+ Setting["homepage.widgets.feeds.proposals"].present?
+ end
+
def feed_processes_enabled?
- Setting['feature.homepage.widgets.feeds.processes'].present?
+ Setting["homepage.widgets.feeds.processes"].present?
+ end
+
+ def feed_debates_and_proposals_enabled?
+ feed_debates_enabled? && feed_proposals_enabled?
end
end
diff --git a/app/helpers/followables_helper.rb b/app/helpers/followables_helper.rb
index f7dd4a7a0..48dd761ce 100644
--- a/app/helpers/followables_helper.rb
+++ b/app/helpers/followables_helper.rb
@@ -6,8 +6,8 @@ module FollowablesHelper
def followable_icon(followable)
{
- proposals: 'Proposal',
- budget: 'Budget::Investment'
+ proposals: "Proposal",
+ budget: "Budget::Investment"
}.invert[followable]
end
diff --git a/app/helpers/follows_helper.rb b/app/helpers/follows_helper.rb
index b3426df12..1508e4c25 100644
--- a/app/helpers/follows_helper.rb
+++ b/app/helpers/follows_helper.rb
@@ -2,12 +2,12 @@ module FollowsHelper
def follow_text(followable)
entity = followable.class.name.underscore
- t('shared.follow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
+ t("shared.follow_entity", entity: t("activerecord.models.#{entity}.one").downcase)
end
def unfollow_text(followable)
entity = followable.class.name.underscore
- t('shared.unfollow_entity', entity: t("activerecord.models.#{entity}.one").downcase)
+ t("shared.unfollow_entity", entity: t("activerecord.models.#{entity}.one").downcase)
end
end
diff --git a/app/helpers/globalize_helper.rb b/app/helpers/globalize_helper.rb
index cff0b4ccd..575e81c8e 100644
--- a/app/helpers/globalize_helper.rb
+++ b/app/helpers/globalize_helper.rb
@@ -10,28 +10,37 @@ module GlobalizeHelper
end
end
- def display_translation?(locale)
- same_locale?(I18n.locale, locale) ? "" : "display: none;"
+ def display_translation?(resource, locale)
+ if !resource || resource.translations.blank? ||
+ resource.translations.map(&:locale).include?(I18n.locale)
+ locale == I18n.locale
+ else
+ locale == resource.translations.first.locale
+ end
+ end
+
+ def display_translation_style(resource, locale)
+ "display: none;" unless display_translation?(resource, locale)
end
def translation_enabled_tag(locale, enabled)
hidden_field_tag("enabled_translations[#{locale}]", (enabled ? 1 : 0))
end
- def css_to_display_translation?(resource, locale)
- enable_locale?(resource, locale) ? "" : "display: none;"
+ def enable_translation_style(resource, locale)
+ "display: none;" unless enable_locale?(resource, locale)
end
def enable_locale?(resource, locale)
- resource.translated_locales.include?(locale) || locale == I18n.locale
+ if resource.translations.any?
+ resource.locales_not_marked_for_destruction.include?(locale)
+ else
+ locale == I18n.locale
+ end
end
- def highlight_current?(locale)
- same_locale?(I18n.locale, locale) ? 'is-active' : ''
- end
-
- def show_delete?(locale)
- display_translation?(locale)
+ def highlight_class(resource, locale)
+ "is-active" if display_translation?(resource, locale)
end
def globalize(locale, &block)
diff --git a/app/helpers/imageables_helper.rb b/app/helpers/imageables_helper.rb
index 8cae1b989..04c48d6c3 100644
--- a/app/helpers/imageables_helper.rb
+++ b/app/helpers/imageables_helper.rb
@@ -5,7 +5,7 @@ module ImageablesHelper
end
def imageable_class(imageable)
- imageable.class.name.parameterize('_')
+ imageable.class.name.parameterize("_")
end
def imageable_max_file_size
diff --git a/app/helpers/images_helper.rb b/app/helpers/images_helper.rb
index 208ccf5ab..1998e63f5 100644
--- a/app/helpers/images_helper.rb
+++ b/app/helpers/images_helper.rb
@@ -19,7 +19,7 @@ module ImagesHelper
end
def image_errors_on_attachment(image)
- image.errors[:attachment].join(', ') if image.errors.key?(:attachment)
+ image.errors[:attachment].join(", ") if image.errors.key?(:attachment)
end
def image_bytes_to_megabytes(bytes)
@@ -32,7 +32,7 @@ module ImagesHelper
def render_destroy_image_link(builder, image)
if !image.persisted? && image.cached_attachment.present?
- link_to t('images.form.delete_button'),
+ link_to t("images.form.delete_button"),
direct_upload_destroy_url("direct_upload[resource_type]": image.imageable_type,
"direct_upload[resource_id]": image.imageable_id,
"direct_upload[resource_relation]": "image",
@@ -41,7 +41,7 @@ module ImagesHelper
remote: true,
class: "delete remove-cached-attachment"
else
- link_to_remove_association t('images.form.delete_button'), builder, class: "delete remove-image"
+ link_to_remove_association t("images.form.delete_button"), builder, class: "delete remove-image"
end
end
@@ -54,7 +54,7 @@ module ImagesHelper
html += builder.file_field :attachment,
label: false,
accept: imageable_accepted_content_types_extensions,
- class: 'js-image-attachment',
+ class: "js-image-attachment",
data: {
url: image_direct_upload_url(imageable),
nested_image: true
diff --git a/app/helpers/layouts_helper.rb b/app/helpers/layouts_helper.rb
index 782d9c639..b88547d8a 100644
--- a/app/helpers/layouts_helper.rb
+++ b/app/helpers/layouts_helper.rb
@@ -2,7 +2,7 @@ module LayoutsHelper
def layout_menu_link_to(text, path, is_active, options)
if is_active
- content_tag(:span, t('shared.you_are_in'), class: 'show-for-sr') + ' ' +
+ content_tag(:span, t("shared.you_are_in"), class: "show-for-sr") + " " +
link_to(text, path, options.merge(class: "is-active"))
else
link_to(text, path, options)
diff --git a/app/helpers/legislation_helper.rb b/app/helpers/legislation_helper.rb
index a737824ab..415de8e74 100644
--- a/app/helpers/legislation_helper.rb
+++ b/app/helpers/legislation_helper.rb
@@ -1,6 +1,6 @@
module LegislationHelper
def format_date(date)
- l(date, format: "%d %h %Y") if date
+ l(date, format: "%d %b %Y") if date
end
def format_date_for_calendar_form(date)
@@ -14,10 +14,10 @@ module LegislationHelper
def link_to_toggle_legislation_proposal_selection(proposal)
if proposal.selected?
button_text = t("admin.legislation.proposals.index.selected")
- html_class = 'button expanded'
+ html_class = "button expanded"
else
button_text = t("admin.legislation.proposals.index.select")
- html_class = 'button hollow expanded'
+ html_class = "button hollow expanded"
end
link_to button_text,
@@ -26,4 +26,42 @@ module LegislationHelper
method: :patch,
class: html_class
end
+
+ def legislation_process_tabs(process)
+ {
+ "info" => edit_admin_legislation_process_path(process),
+ "homepage" => edit_admin_legislation_process_homepage_path(process),
+ "questions" => admin_legislation_process_questions_path(process),
+ "proposals" => admin_legislation_process_proposals_path(process),
+ "draft_versions" => admin_legislation_process_draft_versions_path(process),
+ "milestones" => admin_legislation_process_milestones_path(process)
+ }
+ end
+
+ def banner_color?
+ @process.background_color.present? && @process.font_color.present?
+ end
+
+ def default_bg_color
+ "#e7f2fc"
+ end
+
+ def default_font_color
+ "#222222"
+ end
+
+ def bg_color_or_default
+ @process.background_color.present? ? @process.background_color : default_bg_color
+ end
+
+ def font_color_or_default
+ @process.font_color.present? ? @process.font_color : default_font_color
+ end
+
+ def css_for_process_header
+ if banner_color?
+ "background: #{@process.background_color};color: #{@process.font_color};"
+ end
+ end
+
end
diff --git a/app/helpers/map_locations_helper.rb b/app/helpers/map_locations_helper.rb
index a471d1b8d..d05f2c722 100644
--- a/app/helpers/map_locations_helper.rb
+++ b/app/helpers/map_locations_helper.rb
@@ -5,15 +5,15 @@ module MapLocationsHelper
end
def map_location_latitude(map_location)
- map_location.present? && map_location.latitude.present? ? map_location.latitude : Setting["map_latitude"]
+ map_location.present? && map_location.latitude.present? ? map_location.latitude : Setting["map.latitude"]
end
def map_location_longitude(map_location)
- map_location.present? && map_location.longitude.present? ? map_location.longitude : Setting["map_longitude"]
+ map_location.present? && map_location.longitude.present? ? map_location.longitude : Setting["map.longitude"]
end
def map_location_zoom(map_location)
- map_location.present? && map_location.zoom.present? ? map_location.zoom : Setting["map_zoom"]
+ map_location.present? && map_location.zoom.present? ? map_location.zoom : Setting["map.zoom"]
end
def map_location_input_id(prefix, attribute)
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
new file mode 100644
index 000000000..ed8a1e38b
--- /dev/null
+++ b/app/helpers/milestones_helper.rb
@@ -0,0 +1,18 @@
+module MilestonesHelper
+ def progress_tag_for(progress_bar)
+ text = number_to_percentage(progress_bar.percentage, precision: 0)
+
+ content_tag :div, class: "progress",
+ role: "progressbar",
+ "aria-valuenow": "#{progress_bar.percentage}",
+ "aria-valuetext": "#{progress_bar.percentage}%",
+ "aria-valuemax": ProgressBar::RANGE.max,
+ "aria-valuemin": "0",
+ tabindex: "0" do
+ content_tag(:span, "",
+ class: "progress-meter",
+ style: "width: #{progress_bar.percentage}%;") +
+ content_tag(:p, text, class: "progress-meter-text")
+ end
+ end
+end
diff --git a/app/helpers/officers_helper.rb b/app/helpers/officers_helper.rb
index 31c0a6ad4..e069cb9aa 100644
--- a/app/helpers/officers_helper.rb
+++ b/app/helpers/officers_helper.rb
@@ -1,7 +1,7 @@
module OfficersHelper
def officer_label(officer)
- truncate([officer.name, officer.email].compact.join(' - '), length: 100)
+ truncate([officer.name, officer.email].compact.join(" - "), length: 100)
end
def vote_collection_shift?
diff --git a/app/helpers/polls_helper.rb b/app/helpers/polls_helper.rb
index 0cb875dff..06d2f78f7 100644
--- a/app/helpers/polls_helper.rb
+++ b/app/helpers/polls_helper.rb
@@ -42,11 +42,30 @@ module PollsHelper
end
def poll_voter_token(poll, user)
- Poll::Voter.where(poll: poll, user: user, origin: "web").first&.token || ''
+ Poll::Voter.where(poll: poll, user: user, origin: "web").first&.token || ""
end
def voted_before_sign_in(question)
question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at > vote.updated_at }
end
+ def show_stats_or_results?
+ @poll.expired? && (@poll.results_enabled? || @poll.stats_enabled?)
+ end
+
+ def results_menu?
+ controller_name == "polls" && action_name == "results"
+ end
+
+ def stats_menu?
+ controller_name == "polls" && action_name == "stats"
+ end
+
+ def info_menu?
+ controller_name == "polls" && action_name == "show"
+ end
+
+ def show_polls_description?
+ @active_poll.present? && @current_filter == "current"
+ end
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index ebde2a954..b38048fb1 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -11,12 +11,12 @@ module SearchHelper
[t("shared.advanced_search.date_2"), 2],
[t("shared.advanced_search.date_3"), 3],
[t("shared.advanced_search.date_4"), 4],
- [t("shared.advanced_search.date_5"), 'custom']],
+ [t("shared.advanced_search.date_5"), "custom"]],
selected_date_range)
end
def selected_date_range
- custom_date_range? ? 'custom' : params[:advanced_search].try(:[], :date_min)
+ custom_date_range? ? "custom" : params[:advanced_search].try(:[], :date_min)
end
def custom_date_range?
diff --git a/app/helpers/settings.rb b/app/helpers/settings.rb
index d308535ab..209237f99 100644
--- a/app/helpers/settings.rb
+++ b/app/helpers/settings.rb
@@ -1,7 +1,7 @@
module SettingsHelper
def setting_for_widget(widget)
- Setting.where(key: 'feature.user.recommendations').first
+ Setting.where(key: "feature.user.recommendations").first
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index ad844e29f..b7db90beb 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -1,7 +1,7 @@
module SettingsHelper
def feature?(name)
- setting["feature.#{name}"].presence
+ setting["feature.#{name}"].presence || setting["process.#{name}"].presence
end
def setting
diff --git a/app/helpers/site_customization_helper.rb b/app/helpers/site_customization_helper.rb
index 1b4968b6c..14dfe1262 100644
--- a/app/helpers/site_customization_helper.rb
+++ b/app/helpers/site_customization_helper.rb
@@ -3,7 +3,20 @@ module SiteCustomizationHelper
I18nContentTranslation.existing_languages.include?(locale) || locale == I18n.locale
end
- def site_customization_display_translation?(locale)
+ def site_customization_display_translation_style(locale)
site_customization_enable_translation?(locale) ? "" : "display: none;"
end
+
+ def translation_for_locale(content, locale)
+ i18n_content = I18nContent.where(key: content.key).first
+
+ if i18n_content.present?
+ I18nContentTranslation.where(
+ i18n_content_id: i18n_content.id,
+ locale: locale
+ ).first.try(:value)
+ else
+ false
+ end
+ end
end
diff --git a/app/helpers/stats_helper.rb b/app/helpers/stats_helper.rb
index 19b54a5a2..b36977b3e 100644
--- a/app/helpers/stats_helper.rb
+++ b/app/helpers/stats_helper.rb
@@ -1,28 +1,28 @@
module StatsHelper
def events_chart_tag(events, opt = {})
- events = events.join(',') if events.is_a? Array
+ events = events.join(",") if events.is_a? Array
opt[:data] ||= {}
opt[:data][:graph] = admin_api_stats_path(events: events)
content_tag :div, "", opt
end
def visits_chart_tag(opt = {})
- events = events.join(',') if events.is_a? Array
+ events = events.join(",") if events.is_a? Array
opt[:data] ||= {}
opt[:data][:graph] = admin_api_stats_path(visits: true)
content_tag :div, "", opt
end
def spending_proposals_chart_tag(opt = {})
- events = events.join(',') if events.is_a? Array
+ events = events.join(",") if events.is_a? Array
opt[:data] ||= {}
opt[:data][:graph] = admin_api_stats_path(spending_proposals: true)
content_tag :div, "", opt
end
def budget_investments_chart_tag(opt = {})
- events = events.join(',') if events.is_a? Array
+ events = events.join(",") if events.is_a? Array
opt[:data] ||= {}
opt[:data][:graph] = admin_api_stats_path(budget_investments: true)
content_tag :div, "", opt
diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb
index b31f3167f..ce0445092 100644
--- a/app/helpers/tags_helper.rb
+++ b/app/helpers/tags_helper.rb
@@ -2,32 +2,32 @@ module TagsHelper
def taggables_path(taggable_type, tag_name)
case taggable_type
- when 'debate'
+ when "debate"
debates_path(search: tag_name)
- when 'proposal'
+ when "proposal"
proposals_path(search: tag_name)
- when 'budget/investment'
+ when "budget/investment"
budget_investments_path(@budget, search: tag_name)
- when 'legislation/proposal'
+ when "legislation/proposal"
legislation_process_proposals_path(@process, search: tag_name)
else
- '#'
+ "#"
end
end
def taggable_path(taggable)
taggable_type = taggable.class.name.underscore
case taggable_type
- when 'debate'
+ when "debate"
debate_path(taggable)
- when 'proposal'
+ when "proposal"
proposal_path(taggable)
- when 'budget/investment'
+ when "budget/investment"
budget_investment_path(taggable.budget_id, taggable)
- when 'legislation/proposal'
+ when "legislation/proposal"
legislation_process_proposal_path(@process, taggable)
else
- '#'
+ "#"
end
end
diff --git a/app/helpers/tracks_helper.rb b/app/helpers/tracks_helper.rb
index 0d6793e08..f63fe7852 100644
--- a/app/helpers/tracks_helper.rb
+++ b/app/helpers/tracks_helper.rb
@@ -4,11 +4,11 @@ module TracksHelper
track_data = ""
prefix = " data-track-event-"
data.each do |key, value|
- track_data = track_data + prefix + key.to_s + '=' + value + " "
+ track_data = track_data + prefix + key.to_s + "=" + value + " "
end
content_for :track_event do
track_data
end
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/translatable_form_helper.rb b/app/helpers/translatable_form_helper.rb
index 1e468c4ce..01b0dd2a7 100644
--- a/app/helpers/translatable_form_helper.rb
+++ b/app/helpers/translatable_form_helper.rb
@@ -1,67 +1,94 @@
module TranslatableFormHelper
- def translatable_form_for(record_or_record_path, options = {})
- object = record_or_record_path.is_a?(Array) ? record_or_record_path.last : record_or_record_path
-
- form_for(record_or_record_path, options.merge(builder: TranslatableFormBuilder)) do |f|
-
- object.globalize_locales.each do |locale|
- concat translation_enabled_tag(locale, enable_locale?(object, locale))
- end
-
+ def translatable_form_for(record, options = {})
+ form_for(record, options.merge(builder: TranslatableFormBuilder)) do |f|
yield(f)
end
end
- def merge_translatable_field_options(options, locale)
- options.merge(
- class: "#{options[:class]} js-globalize-attribute".strip,
- style: "#{options[:style]} #{display_translation?(locale)}".strip,
- data: options.fetch(:data, {}).merge(locale: locale),
- label_options: {
- class: "#{options.dig(:label_options, :class)} js-globalize-attribute".strip,
- style: "#{options.dig(:label_options, :style)} #{display_translation?(locale)}".strip,
- data: (options.dig(:label_options, :data) || {}) .merge(locale: locale)
- }
- )
- end
-
class TranslatableFormBuilder < FoundationRailsHelper::FormBuilder
-
- def translatable_text_field(method, options = {})
- translatable_field(:text_field, method, options)
- end
-
- def translatable_text_area(method, options = {})
- translatable_field(:text_area, method, options)
- end
-
- def translatable_cktext_area(method, options = {})
- translatable_field(:cktext_area, method, options)
+ def translatable_fields(&block)
+ @object.globalize_locales.map do |locale|
+ Globalize.with_locale(locale) { fields_for_locale(locale, &block) }
+ end.join.html_safe
end
private
- def translatable_field(field_type, method, options = {})
- @template.capture do
- @object.globalize_locales.each do |locale|
- Globalize.with_locale(locale) do
- localized_attr_name = @object.localized_attr_name_for(method, locale)
+ def fields_for_locale(locale, &block)
+ fields_for_translation(translation_for(locale)) do |translations_form|
+ @template.content_tag :div, translations_options(translations_form.object, locale) do
+ @template.concat translations_form.hidden_field(
+ :_destroy,
+ data: { locale: locale }
+ )
- label_without_locale = @object.class.human_attribute_name(method)
- final_options = @template.merge_translatable_field_options(options, locale)
- .reverse_merge(label: label_without_locale)
+ @template.concat translations_form.hidden_field(:locale, value: locale)
- if field_type == :cktext_area
- @template.concat content_tag :div, send(field_type, localized_attr_name, final_options),
- class: "js-globalize-attribute",
- style: @template.display_translation?(locale),
- data: { locale: locale }
- else
- @template.concat send(field_type, localized_attr_name, final_options)
- end
- end
+ yield translations_form
end
end
end
+
+ def fields_for_translation(translation, &block)
+ fields_for(:translations, translation, builder: TranslationsFieldsBuilder) do |f|
+ yield f
+ end
+ end
+
+ def translation_for(locale)
+ existing_translation_for(locale) || new_translation_for(locale)
+ end
+
+ def existing_translation_for(locale)
+ @object.translations.detect { |translation| translation.locale == locale }
+ end
+
+ def new_translation_for(locale)
+ @object.translations.new(locale: locale).tap do |translation|
+ unless locale == I18n.locale && no_other_translations?(translation)
+ translation.mark_for_destruction
+ end
+ end
+ end
+
+ def translations_options(resource, locale)
+ {
+ class: "translatable-fields js-globalize-attribute",
+ style: @template.display_translation_style(resource.globalized_model, locale),
+ data: { locale: locale }
+ }
+ end
+
+ def no_other_translations?(translation)
+ (@object.translations - [translation]).reject(&:_destroy).empty?
+ end
+ end
+
+ class TranslationsFieldsBuilder < FoundationRailsHelper::FormBuilder
+ %i[text_field text_area cktext_area].each do |field|
+ define_method field do |attribute, options = {}|
+ custom_label(attribute, options[:label], options[:label_options]) +
+ help_text(options[:hint]) +
+ super(attribute, options.merge(label: false, hint: false))
+ end
+ end
+
+ def locale
+ @object.locale
+ end
+
+ def label(attribute, text = nil, options = {})
+ label_options = options.dup
+ hint = label_options.delete(:hint)
+
+ super(attribute, text, label_options) + help_text(hint)
+ end
+
+ private
+ def help_text(text)
+ if text
+ content_tag :span, text, class: "help-text"
+ end
+ end
end
end
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index 4098b535e..13e537835 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -16,8 +16,8 @@ module UsersHelper
if commentable.nil?
deleted_commentable_text(comment)
elsif commentable.hidden?
- content_tag(:del, commentable.title) + ' ' +
- content_tag(:span, '(' + deleted_commentable_text(comment) + ')', class: 'small')
+ content_tag(:del, commentable.title) + " " +
+ content_tag(:span, "(" + deleted_commentable_text(comment) + ")", class: "small")
else
link_to(commentable.title, comment)
end
@@ -58,9 +58,9 @@ module UsersHelper
def interests_title_text(user)
if current_user == user
- t('account.show.public_interests_my_title_list')
+ t("account.show.public_interests_my_title_list")
else
- t('account.show.public_interests_user_title_list')
+ t("account.show.public_interests_user_title_list")
end
end
diff --git a/app/helpers/valuation_helper.rb b/app/helpers/valuation_helper.rb
index 1c11cb90b..56b1dd079 100644
--- a/app/helpers/valuation_helper.rb
+++ b/app/helpers/valuation_helper.rb
@@ -22,8 +22,8 @@ module ValuationHelper
valuators.first.name +
"".html_safe
else
- "".html_safe +
- t('valuation.budget_investments.index.valuators_assigned', count: valuators.size) +
+ "".html_safe +
+ t("valuation.budget_investments.index.valuators_assigned", count: valuators.size) +
"".html_safe
end
end
diff --git a/app/helpers/valuators_helper.rb b/app/helpers/valuators_helper.rb
index 752713ed3..17dd7fc24 100644
--- a/app/helpers/valuators_helper.rb
+++ b/app/helpers/valuators_helper.rb
@@ -1,7 +1,7 @@
module ValuatorsHelper
def valuator_label(valuator)
- truncate([valuator.name, valuator.email, valuator.description].compact.join(' - '), length: 100)
+ truncate([valuator.name, valuator.email, valuator.description].compact.join(" - "), length: 100)
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/verification_helper.rb b/app/helpers/verification_helper.rb
index 44f921264..54b340b8b 100644
--- a/app/helpers/verification_helper.rb
+++ b/app/helpers/verification_helper.rb
@@ -1,9 +1,13 @@
module VerificationHelper
def document_types
- [[t('verification.residence.new.document_type.spanish_id'), 1],
- [t('verification.residence.new.document_type.passport'), 2],
- [t('verification.residence.new.document_type.residence_card'), 3]]
+ [[t("verification.residence.new.document_type.spanish_id"), 1],
+ [t("verification.residence.new.document_type.passport"), 2],
+ [t("verification.residence.new.document_type.residence_card"), 3]]
+ end
+
+ def minimum_required_age
+ (Setting["min_age_to_participate"] || 16).to_i
end
def mask_phone(number)
diff --git a/app/helpers/votes_helper.rb b/app/helpers/votes_helper.rb
index dc1df0396..4255b7656 100644
--- a/app/helpers/votes_helper.rb
+++ b/app/helpers/votes_helper.rb
@@ -6,9 +6,9 @@ module VotesHelper
def votes_percentage(vote, debate)
return "0%" if debate.total_votes == 0
- if vote == 'likes'
+ if vote == "likes"
debate_percentage_of_likes(debate).to_s + "%"
- elsif vote == 'dislikes'
+ elsif vote == "dislikes"
(100 - debate_percentage_of_likes(debate)).to_s + "%"
end
end
diff --git a/app/helpers/welcome_helper.rb b/app/helpers/welcome_helper.rb
index 07d7b380a..fa729492e 100644
--- a/app/helpers/welcome_helper.rb
+++ b/app/helpers/welcome_helper.rb
@@ -15,7 +15,7 @@ module WelcomeHelper
when "Proposal"
proposal_path(recommended)
else
- '#'
+ "#"
end
end
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
index ea1d4fa40..eded65fb8 100644
--- a/app/mailers/application_mailer.rb
+++ b/app/mailers/application_mailer.rb
@@ -1,5 +1,5 @@
class ApplicationMailer < ActionMailer::Base
helper :settings
default from: "#{Setting['mailer_from_name']} <#{Setting['mailer_from_address']}>"
- layout 'mailer'
+ layout "mailer"
end
diff --git a/app/mailers/devise_mailer.rb b/app/mailers/devise_mailer.rb
index a914477fe..9f1bb6f4e 100644
--- a/app/mailers/devise_mailer.rb
+++ b/app/mailers/devise_mailer.rb
@@ -1,7 +1,7 @@
class DeviseMailer < Devise::Mailer
helper :application, :settings
include Devise::Controllers::UrlHelpers
- default template_path: 'devise/mailer'
+ default template_path: "devise/mailer"
protected
diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb
index 2cdb494c3..1e4993ec5 100644
--- a/app/mailers/mailer.rb
+++ b/app/mailers/mailer.rb
@@ -11,20 +11,17 @@ class Mailer < ApplicationMailer
@email_to = @commentable.author.email
with_user(@commentable.author) do
- subject = t('mailers.comment.subject', commentable: t("activerecord.models.#{@commentable.class.name.underscore}", count: 1).downcase)
+ subject = t("mailers.comment.subject", commentable: t("activerecord.models.#{@commentable.class.name.underscore}", count: 1).downcase)
mail(to: @email_to, subject: subject) if @commentable.present? && @commentable.author.present?
end
end
def reply(reply)
- @reply = reply
- @commentable = @reply.commentable
- parent = Comment.find(@reply.parent_id)
- @recipient = parent.author
- @email_to = @recipient.email
+ @email = ReplyEmail.new(reply)
+ @email_to = @email.to
- with_user(@recipient) do
- mail(to: @email_to, subject: t('mailers.reply.subject')) if @commentable.present? && @recipient.present?
+ with_user(@email.recipient) do
+ mail(to: @email_to, subject: @email.subject) if @email.can_be_sent?
end
end
@@ -36,7 +33,7 @@ class Mailer < ApplicationMailer
@document_number = document_number
with_user(user) do
- mail(to: @email_to, subject: t('mailers.email_verification.subject'))
+ mail(to: @email_to, subject: t("mailers.email_verification.subject"))
end
end
@@ -46,7 +43,7 @@ class Mailer < ApplicationMailer
@email_to = @author.email
with_user(@author) do
- mail(to: @email_to, subject: t('mailers.unfeasible_spending_proposal.subject', code: @spending_proposal.code))
+ mail(to: @email_to, subject: t("mailers.unfeasible_spending_proposal.subject", code: @spending_proposal.code))
end
end
@@ -56,7 +53,7 @@ class Mailer < ApplicationMailer
@email_to = @receiver.email
with_user(@receiver) do
- mail(to: @email_to, subject: t('mailers.direct_message_for_receiver.subject'))
+ mail(to: @email_to, subject: t("mailers.direct_message_for_receiver.subject"))
end
end
@@ -66,7 +63,7 @@ class Mailer < ApplicationMailer
@email_to = @sender.email
with_user(@sender) do
- mail(to: @email_to, subject: t('mailers.direct_message_for_sender.subject'))
+ mail(to: @email_to, subject: t("mailers.direct_message_for_sender.subject"))
end
end
@@ -75,7 +72,7 @@ class Mailer < ApplicationMailer
@email_to = user.email
with_user(user) do
- mail(to: @email_to, subject: t('mailers.proposal_notification_digest.title', org_name: Setting['org_name']))
+ mail(to: @email_to, subject: t("mailers.proposal_notification_digest.title", org_name: Setting["org_name"]))
end
end
@@ -83,7 +80,7 @@ class Mailer < ApplicationMailer
@email_to = email
I18n.with_locale(I18n.default_locale) do
- mail(to: @email_to, subject: t('mailers.user_invite.subject', org_name: Setting["org_name"]))
+ mail(to: @email_to, subject: t("mailers.user_invite.subject", org_name: Setting["org_name"]))
end
end
@@ -92,7 +89,7 @@ class Mailer < ApplicationMailer
@email_to = @investment.author.email
with_user(@investment.author) do
- mail(to: @email_to, subject: t('mailers.budget_investment_created.subject'))
+ mail(to: @email_to, subject: t("mailers.budget_investment_created.subject"))
end
end
@@ -102,7 +99,7 @@ class Mailer < ApplicationMailer
@email_to = @author.email
with_user(@author) do
- mail(to: @email_to, subject: t('mailers.budget_investment_unfeasible.subject', code: @investment.code))
+ mail(to: @email_to, subject: t("mailers.budget_investment_unfeasible.subject", code: @investment.code))
end
end
@@ -112,7 +109,7 @@ class Mailer < ApplicationMailer
@email_to = @author.email
with_user(@author) do
- mail(to: @email_to, subject: t('mailers.budget_investment_selected.subject', code: @investment.code))
+ mail(to: @email_to, subject: t("mailers.budget_investment_selected.subject", code: @investment.code))
end
end
@@ -122,7 +119,7 @@ class Mailer < ApplicationMailer
@email_to = @author.email
with_user(@author) do
- mail(to: @email_to, subject: t('mailers.budget_investment_unselected.subject', code: @investment.code))
+ mail(to: @email_to, subject: t("mailers.budget_investment_unselected.subject", code: @investment.code))
end
end
diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb
index 264ad7783..a72997dbf 100644
--- a/app/models/abilities/administrator.rb
+++ b/app/models/abilities/administrator.rb
@@ -57,7 +57,6 @@ module Abilities
can [:search, :create, :index, :destroy], ::Manager
can [:search, :index], ::User
- can :manage, Annotation
can :manage, Dashboard::Action
can [:read, :update, :valuate, :destroy, :summary], SpendingProposal
@@ -94,6 +93,7 @@ module Abilities
cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation, ::Legislation::Proposal]
can [:create], Document
+ can [:destroy], Document, documentable_type: "Poll::Question::Answer"
can [:create, :destroy], DirectUpload
can [:deliver], Newsletter, hidden_at: nil
diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb
index af819145d..be8ce7333 100644
--- a/app/models/abilities/common.rb
+++ b/app/models/abilities/common.rb
@@ -116,9 +116,6 @@ module Abilities
can [:create, :show], ProposalNotification, proposal: { author_id: user.id }
- can :create, Annotation
- can [:update, :destroy], Annotation, user_id: user.id
-
can [:create], Topic
can [:update, :destroy], Topic, author_id: user.id
diff --git a/app/models/abilities/everyone.rb b/app/models/abilities/everyone.rb
index 23cfdc971..a20a119fe 100644
--- a/app/models/abilities/everyone.rb
+++ b/app/models/abilities/everyone.rb
@@ -16,15 +16,14 @@ module Abilities
can :read, Poll::Question
can [:read, :welcome], Budget
can :read, SpendingProposal
- can :read, LegacyLegislation
can :read, User
- can [:search, :read], Annotation
can [:read], Budget
can [:read], Budget::Group
can [:read, :print, :json_data], Budget::Investment
- can :read_results, Budget, phase: "finished"
+ can [:read_results, :read_executions], Budget, phase: "finished"
can :new, DirectMessage
- can [:read, :debate, :draft_publication, :allegations, :result_publication, :proposals], Legislation::Process, published: true
+ can [:read, :debate, :draft_publication, :allegations, :result_publication,
+ :proposals, :milestones], Legislation::Process, published: true
can [:read, :changes, :go_to_version], Legislation::DraftVersion
can [:read], Legislation::Question
can [:read, :map, :share], Legislation::Proposal
diff --git a/app/models/abilities/valuator.rb b/app/models/abilities/valuator.rb
index ade0a42b7..0e1213070 100644
--- a/app/models/abilities/valuator.rb
+++ b/app/models/abilities/valuator.rb
@@ -8,7 +8,7 @@ module Abilities
can [:read, :update, :valuate], SpendingProposal
can [:read, :update, :comment_valuation], Budget::Investment, id: valuator.assigned_investment_ids
can [:valuate], Budget::Investment, { id: valuator.assigned_investment_ids, valuation_finished: false }
- cannot [:update, :valuate, :comment_valuation], Budget::Investment, budget: { phase: 'finished' }
+ cannot [:update, :valuate, :comment_valuation], Budget::Investment, budget: { phase: "finished" }
end
end
end
diff --git a/app/models/active_poll.rb b/app/models/active_poll.rb
new file mode 100644
index 000000000..50e185ea5
--- /dev/null
+++ b/app/models/active_poll.rb
@@ -0,0 +1,6 @@
+class ActivePoll < ActiveRecord::Base
+ include Measurable
+
+ translates :description, touch: true
+ include Globalizable
+end
diff --git a/app/models/activity.rb b/app/models/activity.rb
index afe25bed3..b5f3e0281 100644
--- a/app/models/activity.rb
+++ b/app/models/activity.rb
@@ -6,12 +6,12 @@ class Activity < ActiveRecord::Base
validates :action, inclusion: {in: VALID_ACTIONS}
- scope :on_proposals, -> { where(actionable_type: 'Proposal') }
- scope :on_debates, -> { where(actionable_type: 'Debate') }
- scope :on_users, -> { where(actionable_type: 'User') }
- scope :on_comments, -> { where(actionable_type: 'Comment') }
- scope :on_budget_investments, -> { where(actionable_type: 'Budget::Investment') }
- scope :on_system_emails, -> { where(actionable_type: 'ProposalNotification') }
+ scope :on_proposals, -> { where(actionable_type: "Proposal") }
+ scope :on_debates, -> { where(actionable_type: "Debate") }
+ scope :on_users, -> { where(actionable_type: "User") }
+ scope :on_comments, -> { where(actionable_type: "Comment") }
+ scope :on_budget_investments, -> { where(actionable_type: "Budget::Investment") }
+ scope :on_system_emails, -> { where(actionable_type: "ProposalNotification") }
scope :for_render, -> { includes(user: [:moderator, :administrator]).includes(:actionable) }
def self.log(user, action, actionable)
diff --git a/app/models/admin_notification.rb b/app/models/admin_notification.rb
index 4291206bc..6fc3e83e3 100644
--- a/app/models/admin_notification.rb
+++ b/app/models/admin_notification.rb
@@ -3,10 +3,10 @@ class AdminNotification < ActiveRecord::Base
translates :title, touch: true
translates :body, touch: true
- globalize_accessors
+ include Globalizable
- validates :title, presence: true
- validates :body, presence: true
+ validates_translation :title, presence: true
+ validates_translation :body, presence: true
validates :segment_recipient, presence: true
validate :validate_segment_recipient
diff --git a/app/models/annotation.rb b/app/models/annotation.rb
deleted file mode 100644
index 295badd92..000000000
--- a/app/models/annotation.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-class Annotation < ActiveRecord::Base
- serialize :ranges, Array
-
- belongs_to :legacy_legislation
- belongs_to :user
-
- def permissions
- { update: [user_id], delete: [user_id], admin: [] }
- end
-end
diff --git a/app/models/banner.rb b/app/models/banner.rb
index 37824d01f..cc05b3970 100644
--- a/app/models/banner.rb
+++ b/app/models/banner.rb
@@ -5,11 +5,11 @@ class Banner < ActiveRecord::Base
translates :title, touch: true
translates :description, touch: true
- globalize_accessors
+ include Globalizable
+
+ validates_translation :title, presence: true, length: { minimum: 2 }
+ validates_translation :description, presence: true
- validates :title, presence: true,
- length: { minimum: 2 }
- validates :description, presence: true
validates :target_url, presence: true
validates :post_started_at, presence: true
validates :post_ended_at, presence: true
diff --git a/app/models/budget.rb b/app/models/budget.rb
index 3f4bed9a1..ecfacc5c0 100644
--- a/app/models/budget.rb
+++ b/app/models/budget.rb
@@ -3,9 +3,14 @@ class Budget < ActiveRecord::Base
include Measurable
include Sluggable
+ translates :name, touch: true
+ include Globalizable
+
CURRENCY_SYMBOLS = %w(€ $ £ ¥).freeze
- validates :name, presence: true, uniqueness: true
+ before_validation :assign_model_to_translations
+
+ validates_translation :name, presence: true
validates :phase, inclusion: { in: Budget::Phase::PHASE_KINDS }
validates :currency_symbol, presence: true
validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/
@@ -105,8 +110,8 @@ class Budget < ActiveRecord::Base
Budget::Phase::PUBLISHED_PRICES_PHASES.include?(phase)
end
- def valuating_or_later?
- valuating? || publishing_prices? || balloting_or_later?
+ def publishing_prices_or_later?
+ publishing_prices? || balloting_or_later?
end
def balloting_process?
@@ -142,11 +147,11 @@ class Budget < ActiveRecord::Base
def investments_orders
case phase
- when 'accepting', 'reviewing'
+ when "accepting", "reviewing"
%w{random}
- when 'publishing_prices', 'balloting', 'reviewing_ballots'
+ when "publishing_prices", "balloting", "reviewing_ballots"
%w{random price}
- when 'finished'
+ when "finished"
%w{random}
else
%w{random confidence_score}
diff --git a/app/models/budget/content_block.rb b/app/models/budget/content_block.rb
new file mode 100644
index 000000000..bba830cec
--- /dev/null
+++ b/app/models/budget/content_block.rb
@@ -0,0 +1,9 @@
+class Budget
+ class ContentBlock < ActiveRecord::Base
+ validates :locale, presence: true, inclusion: { in: I18n.available_locales.map(&:to_s) }
+ validates :heading, presence: true
+ validates_uniqueness_of :heading, scope: :locale
+
+ belongs_to :heading
+ end
+end
diff --git a/app/models/budget/group.rb b/app/models/budget/group.rb
index bfbfd4741..37d6e658b 100644
--- a/app/models/budget/group.rb
+++ b/app/models/budget/group.rb
@@ -2,14 +2,21 @@ class Budget
class Group < ActiveRecord::Base
include Sluggable
+ translates :name, touch: true
+ include Globalizable
+
belongs_to :budget
has_many :headings, dependent: :destroy
+ before_validation :assign_model_to_translations
+
+ validates_translation :name, presence: true
validates :budget_id, presence: true
- validates :name, presence: true, uniqueness: { scope: :budget }
validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/
+ scope :sort_by_name, -> { includes(:translations).order(:name) }
+
def single_heading_group?
headings.count == 1
end
diff --git a/app/models/budget/group/translation.rb b/app/models/budget/group/translation.rb
new file mode 100644
index 000000000..36489eb10
--- /dev/null
+++ b/app/models/budget/group/translation.rb
@@ -0,0 +1,13 @@
+class Budget::Group::Translation < Globalize::ActiveRecord::Translation
+ delegate :budget, to: :globalized_model
+
+ validate :name_uniqueness_by_budget
+
+ def name_uniqueness_by_budget
+ if budget.groups.joins(:translations)
+ .where(name: name)
+ .where.not("budget_group_translations.budget_group_id": budget_group_id).any?
+ errors.add(:name, I18n.t("errors.messages.taken"))
+ end
+ end
+end
diff --git a/app/models/budget/heading.rb b/app/models/budget/heading.rb
index 4818eaeed..ac9ac6492 100644
--- a/app/models/budget/heading.rb
+++ b/app/models/budget/heading.rb
@@ -1,29 +1,44 @@
class Budget
class Heading < ActiveRecord::Base
+ OSM_DISTRICT_LEVEL_ZOOM = 12.freeze
+
include Sluggable
+ translates :name, touch: true
+ include Globalizable
+
belongs_to :group
has_many :investments
+ has_many :content_blocks
+ before_validation :assign_model_to_translations
+
+ validates_translation :name, presence: true
validates :group_id, presence: true
- validates :name, presence: true, uniqueness: { if: :name_exists_in_budget_headings }
validates :price, presence: true
validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/
validates :population, numericality: { greater_than: 0 }, allow_nil: true
+ validates :latitude, length: { maximum: 22 }, allow_blank: true, \
+ format: /\A(-|\+)?([1-8]?\d(?:\.\d{1,})?|90(?:\.0{1,6})?)\z/
+ validates :longitude, length: { maximum: 22 }, allow_blank: true, \
+ format: /\A(-|\+)?((?:1[0-7]|[1-9])?\d(?:\.\d{1,})?|180(?:\.0{1,})?)\z/
delegate :budget, :budget_id, to: :group, allow_nil: true
- scope :order_by_group_name, -> { includes(:group).order('budget_groups.name', 'budget_headings.name') }
+ scope :i18n, -> { includes(:translations) }
+ scope :allow_custom_content, -> { i18n.where(allow_custom_content: true).order(:name) }
+
+ def self.sort_by_name
+ all.sort do |heading, other_heading|
+ [other_heading.group.name, heading.name] <=> [heading.group.name, other_heading.name]
+ end
+ end
def name_scoped_by_group
group.single_heading_group? ? name : "#{group.name}: #{name}"
end
- def name_exists_in_budget_headings
- group.budget.headings.where(name: name).where.not(id: id).any?
- end
-
def can_be_deleted?
investments.empty?
end
diff --git a/app/models/budget/heading/translation.rb b/app/models/budget/heading/translation.rb
new file mode 100644
index 000000000..3cf930f66
--- /dev/null
+++ b/app/models/budget/heading/translation.rb
@@ -0,0 +1,14 @@
+class Budget::Heading::Translation < Globalize::ActiveRecord::Translation
+ delegate :budget, to: :globalized_model
+
+ validate :name_uniqueness_by_budget
+
+ def name_uniqueness_by_budget
+ if budget.headings
+ .joins(:translations)
+ .where(name: name)
+ .where.not("budget_heading_translations.budget_heading_id": budget_heading_id).any?
+ errors.add(:name, I18n.t("errors.messages.taken"))
+ end
+ end
+end
diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb
index e531612a8..0021755dc 100644
--- a/app/models/budget/investment.rb
+++ b/app/models/budget/investment.rb
@@ -1,6 +1,6 @@
class Budget
class Investment < ActiveRecord::Base
- SORTING_OPTIONS = %w(id title supports).freeze
+ SORTING_OPTIONS = {id: "id", title: "title", supports: "cached_votes_up"}.freeze
include Rails.application.routes.url_helpers
include Measurable
@@ -24,8 +24,10 @@ class Budget
include Notifiable
include Filterable
include Flaggable
+ include Milestoneable
+ include Randomizable
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
belongs_to :heading
belongs_to :group
belongs_to :budget
@@ -37,10 +39,8 @@ class Budget
has_many :valuator_group_assignments, dependent: :destroy
has_many :valuator_groups, through: :valuator_group_assignments
- has_many :comments, -> {where(valuation: false)}, as: :commentable, class_name: 'Comment'
- has_many :valuations, -> {where(valuation: true)}, as: :commentable, class_name: 'Comment'
-
- has_many :milestones
+ has_many :comments, -> {where(valuation: false)}, as: :commentable, class_name: "Comment"
+ has_many :valuations, -> {where(valuation: true)}, as: :commentable, class_name: "Comment"
validates :title, presence: true
validates :author, presence: true
@@ -56,7 +56,6 @@ class Budget
scope :sort_by_confidence_score, -> { reorder(confidence_score: :desc, id: :desc) }
scope :sort_by_ballots, -> { reorder(ballot_lines_count: :desc, id: :desc) }
scope :sort_by_price, -> { reorder(price: :desc, confidence_score: :desc, id: :desc) }
- scope :sort_by_random, ->(seed) { reorder("budget_investments.id % #{seed.to_f.nonzero? ? seed.to_f : 1}, budget_investments.id") }
scope :sort_by_id, -> { order("id DESC") }
scope :sort_by_title, -> { order("title ASC") }
@@ -64,7 +63,8 @@ class Budget
scope :valuation_open, -> { where(valuation_finished: false) }
scope :without_admin, -> { valuation_open.where(administrator_id: nil) }
- scope :without_valuator, -> { valuation_open.where(valuator_assignments_count: 0) }
+ scope :without_valuator_group, -> { where(valuator_group_assignments_count: 0) }
+ scope :without_valuator, -> { valuation_open.without_valuator_group.where(valuator_assignments_count: 0) }
scope :under_valuation, -> { valuation_open.valuating.where("administrator_id IS NOT ?", nil) }
scope :managed, -> { valuation_open.where(valuator_assignments_count: 0).where("administrator_id IS NOT ?", nil) }
scope :valuating, -> { valuation_open.where("valuator_assignments_count > 0 OR valuator_group_assignments_count > 0" ) }
@@ -75,7 +75,7 @@ class Budget
scope :unfeasible, -> { where(feasibility: "unfeasible") }
scope :not_unfeasible, -> { where.not(feasibility: "unfeasible") }
scope :undecided, -> { where(feasibility: "undecided") }
- scope :with_supports, -> { where('cached_votes_up > 0') }
+ scope :with_supports, -> { where("cached_votes_up > 0") }
scope :selected, -> { feasible.where(selected: true) }
scope :compatible, -> { where(incompatible: false) }
scope :incompatible, -> { where(incompatible: true) }
@@ -96,7 +96,7 @@ class Budget
scope :for_render, -> { includes(:heading) }
before_save :calculate_confidence_score
- after_save :recalculate_heading_winners if :incompatible_changed?
+ after_save :recalculate_heading_winners
before_validation :set_responsible_name
before_validation :set_denormalized_ids
@@ -133,16 +133,22 @@ class Budget
def self.advanced_filters(params, results)
ids = []
- ids += results.valuation_finished_feasible.pluck(:id) if params[:advanced_filters].include?('feasible')
- ids += results.where(selected: true).pluck(:id) if params[:advanced_filters].include?('selected')
- ids += results.undecided.pluck(:id) if params[:advanced_filters].include?('undecided')
- ids += results.unfeasible.pluck(:id) if params[:advanced_filters].include?('unfeasible')
+ ids += results.valuation_finished_feasible.pluck(:id) if params[:advanced_filters].include?("feasible")
+ ids += results.where(selected: true).pluck(:id) if params[:advanced_filters].include?("selected")
+ ids += results.undecided.pluck(:id) if params[:advanced_filters].include?("undecided")
+ ids += results.unfeasible.pluck(:id) if params[:advanced_filters].include?("unfeasible")
results.where("budget_investments.id IN (?)", ids)
end
- def self.order_filter(sorting_param)
- if sorting_param.present? && SORTING_OPTIONS.include?(sorting_param)
- send("sort_by_#{sorting_param}")
+ def self.order_filter(params)
+ sorting_key = params[:sort_by]&.downcase&.to_sym
+ allowed_sort_option = SORTING_OPTIONS[sorting_key]
+
+ if allowed_sort_option.present?
+ direction = params[:direction] == "desc" ? "desc" : "asc"
+ order("#{allowed_sort_option} #{direction}")
+ else
+ order(cached_votes_up: :desc).order(id: :desc)
end
end
@@ -167,11 +173,11 @@ class Budget
end
def searchable_values
- { title => 'A',
- author.username => 'B',
- heading.try(:name) => 'B',
- tag_list.join(' ') => 'B',
- description => 'C'
+ { title => "A",
+ author.username => "B",
+ heading.try(:name) => "B",
+ tag_list.join(" ") => "B",
+ description => "C"
}
end
@@ -180,7 +186,7 @@ class Budget
end
def self.by_heading(heading)
- where(heading_id: heading == 'all' ? nil : heading.presence)
+ where(heading_id: heading == "all" ? nil : heading.presence)
end
def undecided?
@@ -256,7 +262,7 @@ class Budget
end
def can_vote_in_another_heading?(user)
- headings_voted_by_user(user).count < group.max_votable_headings
+ user.headings_voted_within_group(group).count < group.max_votable_headings
end
def headings_voted_by_user(user)
@@ -264,7 +270,7 @@ class Budget
end
def voted_in?(heading, user)
- headings_voted_by_user(user).include?(heading.id)
+ user.headings_voted_within_group(group).where(id: heading.id).exists?
end
def ballotable_by?(user)
@@ -277,7 +283,7 @@ class Budget
end
def register_selection(user)
- vote_by(voter: user, vote: 'yes') if selectable_by?(user)
+ vote_by(voter: user, vote: "yes") if selectable_by?(user)
end
def calculate_confidence_score
@@ -336,11 +342,29 @@ class Budget
end
def assigned_valuators
- self.valuators.collect(&:description_or_name).compact.join(', ').presence
+ self.valuators.collect(&:description_or_name).compact.join(", ").presence
end
def assigned_valuation_groups
- self.valuator_groups.collect(&:name).compact.join(', ').presence
+ self.valuator_groups.collect(&:name).compact.join(", ").presence
+ end
+
+ def valuation_tag_list
+ tag_list_on(:valuation)
+ end
+
+ def valuation_tag_list=(tags)
+ set_tag_list_on(:valuation, tags)
+ end
+
+ def self.with_milestone_status_id(status_id)
+ joins(:milestones).includes(:milestones).select do |investment|
+ investment.milestone_status_id == status_id.to_i
+ end
+ end
+
+ def milestone_status_id
+ milestones.published.with_status.order_by_publication_date.last&.status_id
end
private
diff --git a/app/models/budget/investment/exporter.rb b/app/models/budget/investment/exporter.rb
index c7e4ce461..ec5b6abf4 100644
--- a/app/models/budget/investment/exporter.rb
+++ b/app/models/budget/investment/exporter.rb
@@ -1,5 +1,5 @@
class Budget::Investment::Exporter
- require 'csv'
+ require "csv"
def initialize(investments)
@investments = investments
@@ -37,13 +37,13 @@ class Budget::Investment::Exporter
investment.title,
investment.total_votes.to_s,
admin(investment),
- investment.assigned_valuators || '-',
- investment.assigned_valuation_groups || '-',
+ investment.assigned_valuators || "-",
+ investment.assigned_valuation_groups || "-",
investment.heading.name,
price(investment),
- investment.valuation_finished? ? I18n.t('shared.yes') : I18n.t('shared.no'),
- investment.selected? ? I18n.t('shared.yes') : I18n.t('shared.no'),
- investment.visible_to_valuators? ? I18n.t('shared.yes') : I18n.t('shared.no'),
+ investment.valuation_finished? ? I18n.t("shared.yes") : I18n.t("shared.no"),
+ investment.selected? ? I18n.t("shared.yes") : I18n.t("shared.no"),
+ investment.visible_to_valuators? ? I18n.t("shared.yes") : I18n.t("shared.no"),
investment.author.username
]
end
diff --git a/app/models/budget/investment/milestone.rb b/app/models/budget/investment/milestone.rb
deleted file mode 100644
index 1790f7323..000000000
--- a/app/models/budget/investment/milestone.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-class Budget
- class Investment
- class Milestone < ActiveRecord::Base
- include Imageable
- include Documentable
- documentable max_documents_allowed: 3,
- max_file_size: 3.megabytes,
- accepted_content_types: [ "application/pdf" ]
-
- translates :title, :description, touch: true
- globalize_accessors
-
- belongs_to :investment
- belongs_to :status, class_name: 'Budget::Investment::Status'
-
- validates :title, presence: true
- validates :investment, presence: true
- validates :publication_date, presence: true
- validate :description_or_status_present?
-
- scope :order_by_publication_date, -> { order(publication_date: :asc) }
-
- def self.title_max_length
- 80
- end
-
- def description_or_status_present?
- unless description.present? || status_id.present?
- errors.add(:description)
- end
- end
- end
- end
-end
diff --git a/app/models/budget/phase.rb b/app/models/budget/phase.rb
index 432c4b609..cd877e0cc 100644
--- a/app/models/budget/phase.rb
+++ b/app/models/budget/phase.rb
@@ -6,35 +6,37 @@ class Budget
SUMMARY_MAX_LENGTH = 1000
DESCRIPTION_MAX_LENGTH = 2000
- belongs_to :budget
- belongs_to :next_phase, class_name: 'Budget::Phase', foreign_key: :next_phase_id
- has_one :prev_phase, class_name: 'Budget::Phase', foreign_key: :next_phase_id
+ translates :summary, touch: true
+ translates :description, touch: true
+ include Globalizable
+ belongs_to :budget
+ belongs_to :next_phase, class_name: "Budget::Phase", foreign_key: :next_phase_id
+ has_one :prev_phase, class_name: "Budget::Phase", foreign_key: :next_phase_id
+
+ validates_translation :summary, length: { maximum: SUMMARY_MAX_LENGTH }
+ validates_translation :description, length: { maximum: DESCRIPTION_MAX_LENGTH }
validates :budget, presence: true
validates :kind, presence: true, uniqueness: { scope: :budget }, inclusion: { in: PHASE_KINDS }
- validates :summary, length: { maximum: SUMMARY_MAX_LENGTH }
- validates :description, length: { maximum: DESCRIPTION_MAX_LENGTH }
validate :invalid_dates_range?
validate :prev_phase_dates_valid?
validate :next_phase_dates_valid?
- before_validation :sanitize_description
-
after_save :adjust_date_ranges
after_save :touch_budget
scope :enabled, -> { where(enabled: true) }
- scope :published, -> { enabled.where.not(kind: 'drafting') }
- scope :drafting, -> { find_by_kind('drafting') }
- scope :informing, -> { find_by_kind('informing') }
- scope :accepting, -> { find_by_kind('accepting')}
- scope :reviewing, -> { find_by_kind('reviewing')}
- scope :selecting, -> { find_by_kind('selecting')}
- scope :valuating, -> { find_by_kind('valuating')}
- scope :publishing_prices, -> { find_by_kind('publishing_prices')}
- scope :balloting, -> { find_by_kind('balloting')}
- scope :reviewing_ballots, -> { find_by_kind('reviewing_ballots')}
- scope :finished, -> { find_by_kind('finished')}
+ scope :published, -> { enabled.where.not(kind: "drafting") }
+ scope :drafting, -> { find_by_kind("drafting") }
+ scope :informing, -> { find_by_kind("informing") }
+ scope :accepting, -> { find_by_kind("accepting")}
+ scope :reviewing, -> { find_by_kind("reviewing")}
+ scope :selecting, -> { find_by_kind("selecting")}
+ scope :valuating, -> { find_by_kind("valuating")}
+ scope :publishing_prices, -> { find_by_kind("publishing_prices")}
+ scope :balloting, -> { find_by_kind("balloting")}
+ scope :reviewing_ballots, -> { find_by_kind("reviewing_ballots")}
+ scope :finished, -> { find_by_kind("finished")}
def next_enabled_phase
next_phase&.enabled? ? next_phase : next_phase&.next_enabled_phase
@@ -46,7 +48,7 @@ class Budget
def invalid_dates_range?
if starts_at.present? && ends_at.present? && starts_at >= ends_at
- errors.add(:starts_at, I18n.t('budgets.phases.errors.dates_range_invalid'))
+ errors.add(:starts_at, I18n.t("budgets.phases.errors.dates_range_invalid"))
end
end
@@ -70,7 +72,7 @@ class Budget
prev_enabled_phase.assign_attributes(ends_at: starts_at)
if prev_enabled_phase.invalid_dates_range?
phase_name = I18n.t("budgets.phase.#{prev_enabled_phase.kind}")
- error = I18n.t('budgets.phases.errors.prev_phase_dates_invalid', phase_name: phase_name)
+ error = I18n.t("budgets.phases.errors.prev_phase_dates_invalid", phase_name: phase_name)
errors.add(:starts_at, error)
end
end
@@ -81,14 +83,11 @@ class Budget
next_enabled_phase.assign_attributes(starts_at: ends_at)
if next_enabled_phase.invalid_dates_range?
phase_name = I18n.t("budgets.phase.#{next_enabled_phase.kind}")
- error = I18n.t('budgets.phases.errors.next_phase_dates_invalid', phase_name: phase_name)
+ error = I18n.t("budgets.phases.errors.next_phase_dates_invalid", phase_name: phase_name)
errors.add(:ends_at, error)
end
end
end
- def sanitize_description
- self.description = WYSIWYGSanitizer.new.sanitize(description)
- end
end
end
diff --git a/app/models/budget/phase/translation.rb b/app/models/budget/phase/translation.rb
new file mode 100644
index 000000000..53390143a
--- /dev/null
+++ b/app/models/budget/phase/translation.rb
@@ -0,0 +1,9 @@
+class Budget::Phase::Translation < Globalize::ActiveRecord::Translation
+ before_validation :sanitize_description
+
+ private
+
+ def sanitize_description
+ self.description = WYSIWYGSanitizer.new.sanitize(description)
+ end
+end
diff --git a/app/models/budget/reclassification.rb b/app/models/budget/reclassification.rb
index b77dc374a..7eefc0d33 100644
--- a/app/models/budget/reclassification.rb
+++ b/app/models/budget/reclassification.rb
@@ -30,7 +30,7 @@ class Budget
end
def store_reclassified_votes(reason)
- ballot_lines_for_investment.each do |line|
+ ballot_lines_for_investment.order(:id).each do |line|
attrs = { user: line.ballot.user,
investment: self,
reason: reason }
diff --git a/app/models/budget/translation.rb b/app/models/budget/translation.rb
new file mode 100644
index 000000000..1f3d93ea1
--- /dev/null
+++ b/app/models/budget/translation.rb
@@ -0,0 +1,11 @@
+class Budget::Translation < Globalize::ActiveRecord::Translation
+ validate :name_uniqueness_by_budget
+
+ def name_uniqueness_by_budget
+ if Budget.joins(:translations)
+ .where(name: name)
+ .where.not("budget_translations.budget_id": budget_id).any?
+ errors.add(:name, I18n.t("errors.messages.taken"))
+ end
+ end
+end
diff --git a/app/models/ckeditor/picture.rb b/app/models/ckeditor/picture.rb
index 445c2bbd9..4a579b9d2 100644
--- a/app/models/ckeditor/picture.rb
+++ b/app/models/ckeditor/picture.rb
@@ -1,8 +1,8 @@
class Ckeditor::Picture < Ckeditor::Asset
has_attached_file :data,
- url: '/ckeditor_assets/pictures/:id/:style_:basename.:extension',
- path: ':rails_root/public/ckeditor_assets/pictures/:id/:style_:basename.:extension',
- styles: { content: '800>', thumb: '118x100#' }
+ url: "/ckeditor_assets/pictures/:id/:style_:basename.:extension",
+ path: ":rails_root/public/ckeditor_assets/pictures/:id/:style_:basename.:extension",
+ styles: { content: "800>", thumb: "118x100#" }
validates_attachment_presence :data
validates_attachment_size :data, less_than: 2.megabytes
diff --git a/app/models/comment.rb b/app/models/comment.rb
index d9329d3c0..f940a5b3c 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -117,7 +117,7 @@ class Comment < ActiveRecord::Base
end
def self.body_max_length
- Setting['comments_body_max_length'].to_i
+ Setting["comments_body_max_length"].to_i
end
def calculate_confidence_score
diff --git a/app/models/concerns/filterable.rb b/app/models/concerns/filterable.rb
index 91c6b0a96..889067dd1 100644
--- a/app/models/concerns/filterable.rb
+++ b/app/models/concerns/filterable.rb
@@ -20,9 +20,9 @@ module Filterable
def allowed_filter?(filter, value)
return if value.blank?
- ['official_level', 'date_range'].include?(filter)
+ ["official_level", "date_range"].include?(filter)
end
end
-end
\ No newline at end of file
+end
diff --git a/app/models/concerns/globalizable.rb b/app/models/concerns/globalizable.rb
new file mode 100644
index 000000000..e8772f19c
--- /dev/null
+++ b/app/models/concerns/globalizable.rb
@@ -0,0 +1,23 @@
+module Globalizable
+ extend ActiveSupport::Concern
+
+ included do
+ globalize_accessors
+ accepts_nested_attributes_for :translations, allow_destroy: true
+
+ def locales_not_marked_for_destruction
+ translations.reject(&:_destroy).map(&:locale)
+ end
+
+ def assign_model_to_translations
+ translations.each { |translation| translation.globalized_model = self }
+ end
+ end
+
+ class_methods do
+ def validates_translation(method, options = {})
+ validates(method, options.merge(if: lambda { |resource| resource.translations.blank? }))
+ translation_class.instance_eval { validates method, options }
+ end
+ end
+end
diff --git a/app/models/concerns/graphqlable.rb b/app/models/concerns/graphqlable.rb
index c8b47cece..53e5a8e0d 100644
--- a/app/models/concerns/graphqlable.rb
+++ b/app/models/concerns/graphqlable.rb
@@ -4,7 +4,7 @@ module Graphqlable
class_methods do
def graphql_field_name
- name.gsub('::', '_').underscore.to_sym
+ name.gsub("::", "_").underscore.to_sym
end
def graphql_field_description
@@ -12,7 +12,7 @@ module Graphqlable
end
def graphql_pluralized_field_name
- name.gsub('::', '_').underscore.pluralize.to_sym
+ name.gsub("::", "_").underscore.pluralize.to_sym
end
def graphql_pluralized_field_description
@@ -20,7 +20,7 @@ module Graphqlable
end
def graphql_type_name
- name.gsub('::', '_')
+ name.gsub("::", "_")
end
def graphql_type_description
diff --git a/app/models/concerns/mappable.rb b/app/models/concerns/mappable.rb
index 19af90432..fe2b847b9 100644
--- a/app/models/concerns/mappable.rb
+++ b/app/models/concerns/mappable.rb
@@ -13,7 +13,7 @@ module Mappable
return true if skip_map?
unless map_location.try(:available?)
- skip_map_error = I18n.t('activerecord.errors.models.map_location.attributes.map.invalid')
+ skip_map_error = I18n.t("activerecord.errors.models.map_location.attributes.map.invalid")
errors.add(:skip_map, skip_map_error)
end
end
diff --git a/app/models/concerns/measurable.rb b/app/models/concerns/measurable.rb
index 46625435d..9cf606e3f 100644
--- a/app/models/concerns/measurable.rb
+++ b/app/models/concerns/measurable.rb
@@ -4,11 +4,11 @@ module Measurable
class_methods do
def title_max_length
- @@title_max_length ||= (columns.find { |c| c.name == 'title' }.limit rescue nil) || 80
+ @@title_max_length ||= (columns.find { |c| c.name == "title" }.limit rescue nil) || 80
end
def responsible_name_max_length
- @@responsible_name_max_length ||= (columns.find { |c| c.name == 'responsible_name' }.limit rescue nil) || 60
+ @@responsible_name_max_length ||= (columns.find { |c| c.name == "responsible_name" }.limit rescue nil) || 60
end
def question_max_length
diff --git a/app/models/concerns/milestoneable.rb b/app/models/concerns/milestoneable.rb
new file mode 100644
index 000000000..66de28d6c
--- /dev/null
+++ b/app/models/concerns/milestoneable.rb
@@ -0,0 +1,19 @@
+module Milestoneable
+ extend ActiveSupport::Concern
+
+ included do
+ has_many :milestones, as: :milestoneable, dependent: :destroy
+
+ scope :with_milestones, -> { joins(:milestones).distinct }
+
+ has_many :progress_bars, as: :progressable
+
+ def primary_progress_bar
+ progress_bars.primary.first
+ end
+
+ def secondary_progress_bars
+ progress_bars.secondary
+ end
+ end
+end
diff --git a/app/models/concerns/randomizable.rb b/app/models/concerns/randomizable.rb
new file mode 100644
index 000000000..c346f1f02
--- /dev/null
+++ b/app/models/concerns/randomizable.rb
@@ -0,0 +1,16 @@
+module Randomizable
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def sort_by_random(seed = rand(10_000_000))
+ ids = pluck(:id).shuffle(random: Random.new(seed))
+
+ return all if ids.empty?
+
+ ids_with_order = ids.map.with_index { |id, order| "(#{id}, #{order})" }.join(", ")
+
+ joins("LEFT JOIN (VALUES #{ids_with_order}) AS ids(id, ordering) ON #{table_name}.id = ids.id")
+ .order("ids.ordering")
+ end
+ end
+end
diff --git a/app/models/concerns/searchable.rb b/app/models/concerns/searchable.rb
index b749377f3..e6c8777d5 100644
--- a/app/models/concerns/searchable.rb
+++ b/app/models/concerns/searchable.rb
@@ -8,11 +8,11 @@ module Searchable
pg_search_scope :pg_search, {
against: :ignored, # not used since using a tsvector_column
using: {
- tsearch: { tsvector_column: 'tsv', dictionary: "spanish", prefix: true }
+ tsearch: { tsvector_column: "tsv", dictionary: "spanish", prefix: true }
},
ignoring: :accents,
- ranked_by: '(:tsearch)',
- order_within_rank: (column_names.include?('cached_votes_up') ? "#{table_name}.cached_votes_up DESC" : nil)
+ ranked_by: "(:tsearch)",
+ order_within_rank: (column_names.include?("cached_votes_up") ? "#{table_name}.cached_votes_up DESC" : nil)
}
end
diff --git a/app/models/concerns/sluggable.rb b/app/models/concerns/sluggable.rb
index 495ffaf77..8fb308d22 100644
--- a/app/models/concerns/sluggable.rb
+++ b/app/models/concerns/sluggable.rb
@@ -3,6 +3,10 @@ module Sluggable
included do
before_validation :generate_slug, if: :generate_slug?
+
+ def self.find_by_slug_or_id(slug_or_id)
+ find_by_slug(slug_or_id) || find_by_id(slug_or_id)
+ end
end
def generate_slug
diff --git a/app/models/custom/verification/residence.rb b/app/models/custom/verification/residence.rb
index 1cbc6f7ab..4386b705c 100644
--- a/app/models/custom/verification/residence.rb
+++ b/app/models/custom/verification/residence.rb
@@ -1,5 +1,5 @@
-require_dependency Rails.root.join('app', 'models', 'verification', 'residence').to_s
+require_dependency Rails.root.join("app", "models", "verification", "residence").to_s
class Verification::Residence
@@ -7,7 +7,7 @@ class Verification::Residence
validate :residence_in_madrid
def postal_code_in_madrid
- errors.add(:postal_code, I18n.t('verification.residence.new.error_not_allowed_postal_code')) unless valid_postal_code?
+ errors.add(:postal_code, I18n.t("verification.residence.new.error_not_allowed_postal_code")) unless valid_postal_code?
end
def residence_in_madrid
diff --git a/app/models/debate.rb b/app/models/debate.rb
index 93ca5420f..e3b1aad68 100644
--- a/app/models/debate.rb
+++ b/app/models/debate.rb
@@ -1,4 +1,4 @@
-require 'numeric'
+require "numeric"
class Debate < ActiveRecord::Base
include Rails.application.routes.url_helpers
include Flaggable
@@ -12,12 +12,13 @@ class Debate < ActiveRecord::Base
include Graphqlable
include Relationable
include Notifiable
+ include Randomizable
acts_as_votable
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
belongs_to :geozone
has_many :comments, as: :commentable
@@ -37,7 +38,6 @@ class Debate < ActiveRecord::Base
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_random, -> { reorder("RANDOM()") }
scope :sort_by_relevance, -> { all }
scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
scope :sort_by_recommendations, -> { order(cached_votes_total: :desc) }
@@ -60,11 +60,11 @@ class Debate < ActiveRecord::Base
end
def searchable_values
- { title => 'A',
- author.username => 'B',
- tag_list.join(' ') => 'B',
- geozone.try(:name) => 'B',
- description => 'D'
+ { title => "A",
+ author.username => "B",
+ tag_list.join(" ") => "B",
+ geozone.try(:name) => "B",
+ description => "D"
}
end
@@ -88,12 +88,16 @@ class Debate < ActiveRecord::Base
cached_votes_total
end
+ def votes_score
+ cached_votes_score
+ end
+
def total_anonymous_votes
cached_anonymous_votes_total
end
def editable?
- total_votes <= Setting['max_votes_for_debate_edit'].to_i
+ total_votes <= Setting["max_votes_for_debate_edit"].to_i
end
def editable_by?(user)
@@ -111,8 +115,8 @@ class Debate < ActiveRecord::Base
return false unless user
total_votes <= 100 ||
!user.unverified? ||
- Setting['max_ratio_anon_votes_on_debates'].to_i == 100 ||
- anonymous_votes_ratio < Setting['max_ratio_anon_votes_on_debates'].to_i ||
+ Setting["max_ratio_anon_votes_on_debates"].to_i == 100 ||
+ anonymous_votes_ratio < Setting["max_ratio_anon_votes_on_debates"].to_i ||
user.voted_for?(self)
end
@@ -122,14 +126,11 @@ class Debate < ActiveRecord::Base
end
def after_commented
- save # updates the hot_score because there is a before_save
+ save # update cache when it has a new comment
end
def calculate_hot_score
- self.hot_score = ScoreCalculator.hot_score(created_at,
- cached_votes_total,
- cached_votes_up,
- comments_count)
+ self.hot_score = ScoreCalculator.hot_score(self)
end
def calculate_confidence_score
@@ -138,11 +139,11 @@ class Debate < ActiveRecord::Base
end
def after_hide
- tags.each{ |t| t.decrement_custom_counter_for('Debate') }
+ tags.each{ |t| t.decrement_custom_counter_for("Debate") }
end
def after_restore
- tags.each{ |t| t.increment_custom_counter_for('Debate') }
+ tags.each{ |t| t.increment_custom_counter_for("Debate") }
end
def featured?
@@ -151,7 +152,7 @@ class Debate < ActiveRecord::Base
def self.debates_orders(user)
orders = %w{hot_score confidence_score created_at relevance}
- orders << "recommendations" if Setting['feature.user.recommendations_on_debates'] && user&.recommended_debates
+ orders << "recommendations" if Setting["feature.user.recommendations_on_debates"] && user&.recommended_debates
return orders
end
end
diff --git a/app/models/direct_message.rb b/app/models/direct_message.rb
index 7c652c83e..b4907ae7a 100644
--- a/app/models/direct_message.rb
+++ b/app/models/direct_message.rb
@@ -1,6 +1,6 @@
class DirectMessage < ActiveRecord::Base
- belongs_to :sender, class_name: 'User', foreign_key: 'sender_id'
- belongs_to :receiver, class_name: 'User', foreign_key: 'receiver_id'
+ belongs_to :sender, class_name: "User", foreign_key: "sender_id"
+ belongs_to :receiver, class_name: "User", foreign_key: "receiver_id"
validates :title, presence: true
validates :body, presence: true
@@ -8,7 +8,7 @@ class DirectMessage < ActiveRecord::Base
validates :receiver, presence: true
validate :max_per_day
- scope :today, lambda { where('DATE(created_at) = DATE(?)', Time.current) }
+ scope :today, lambda { where("DATE(created_at) = DATE(?)", Time.current) }
def max_per_day
return if errors.any?
@@ -16,7 +16,7 @@ class DirectMessage < ActiveRecord::Base
return unless max
if sender.direct_messages_sent.today.count >= max.to_i
- errors.add(:title, I18n.t('activerecord.errors.models.direct_message.attributes.max_per_day.invalid'))
+ errors.add(:title, I18n.t("activerecord.errors.models.direct_message.attributes.max_per_day.invalid"))
end
end
diff --git a/app/models/failed_census_call.rb b/app/models/failed_census_call.rb
index b7d60e63a..c0add2070 100644
--- a/app/models/failed_census_call.rb
+++ b/app/models/failed_census_call.rb
@@ -1,4 +1,4 @@
class FailedCensusCall < ActiveRecord::Base
belongs_to :user, counter_cache: true
- belongs_to :poll_officer, class_name: 'Poll::Officer', counter_cache: true
+ belongs_to :poll_officer, class_name: "Poll::Officer", counter_cache: true
end
diff --git a/app/models/flag.rb b/app/models/flag.rb
index 824175b07..a05d8a737 100644
--- a/app/models/flag.rb
+++ b/app/models/flag.rb
@@ -8,7 +8,7 @@ class Flag < ActiveRecord::Base
flaggable_id: flaggable.id)
end)
- scope :for_comments, ->(comments) { where(flaggable_type: 'Comment', flaggable_id: comments) }
+ scope :for_comments, ->(comments) { where(flaggable_type: "Comment", flaggable_id: comments) }
def self.flag(user, flaggable)
return false if flagged?(user, flaggable)
diff --git a/app/models/geozone.rb b/app/models/geozone.rb
index a52ab5d15..7cdcbab27 100644
--- a/app/models/geozone.rb
+++ b/app/models/geozone.rb
@@ -15,7 +15,7 @@ class Geozone < ActiveRecord::Base
end
def self.city
- where(name: 'city').first
+ where(name: "city").first
end
def safe_to_destroy?
diff --git a/app/models/i18n_content.rb b/app/models/i18n_content.rb
index c291e696c..81c4ebee7 100644
--- a/app/models/i18n_content.rb
+++ b/app/models/i18n_content.rb
@@ -1,11 +1,49 @@
class I18nContent < ActiveRecord::Base
- scope :by_key, -> (key){ where(key: key) }
- scope :begins_with_key, -> (key){ where("key ILIKE ?", "#{key}?%") }
+ scope :by_key, ->(key) { where(key: key) }
+ scope :begins_with_key, ->(key) { where("key ILIKE ?", "#{key}%") }
validates :key, uniqueness: true
translates :value, touch: true
- globalize_accessors locales: [:en, :es, :fr, :nl]
+ globalize_accessors
+
+ # flat_hash returns a flattened hash, a hash with a single level of
+ # depth in which each key is composed from the keys of the original
+ # hash (whose value is not a hash) by typing in the key of the route
+ # from the first level of the original hash
+ #
+ # Examples:
+ #
+ # hash = {
+ # 'key1' => 'value1',
+ # 'key2' => { 'key3' => 'value2',
+ # 'key4' => { 'key5' => 'value3' } }
+ # }
+ #
+ # I18nContent.flat_hash(hash) = {
+ # 'key1' => 'value1',
+ # 'key2.key3' => 'value2',
+ # 'key2.key4.key5' => 'value3'
+ # }
+ #
+ # I18nContent.flat_hash(hash, 'string') = {
+ # 'string.key1' => 'value1',
+ # 'string.key2.key3' => 'value2',
+ # 'string.key2.key4.key5' => 'value3'
+ # }
+ #
+ # I18nContent.flat_hash(hash, 'string', { 'key6' => 'value4' }) = {
+ # 'key6' => 'value4',
+ # 'string.key1' => 'value1',
+ # 'string.key2.key3' => 'value2',
+ # 'string.key2.key4.key5' => 'value3'
+ # }
+
+ def self.flat_hash(input, path = nil, output = {})
+ return output.update({ path => input }) unless input.is_a? Hash
+ input.map { |key, value| flat_hash(value, [path, key].compact.join("."), output) }
+ return output
+ end
end
diff --git a/app/models/legacy_legislation.rb b/app/models/legacy_legislation.rb
deleted file mode 100644
index ddc267e3a..000000000
--- a/app/models/legacy_legislation.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class LegacyLegislation < ActiveRecord::Base
- has_many :annotations
-end
diff --git a/app/models/legislation.rb b/app/models/legislation.rb
index 5aa217fd0..b0b035cdd 100644
--- a/app/models/legislation.rb
+++ b/app/models/legislation.rb
@@ -1,5 +1,5 @@
module Legislation
def self.table_name_prefix
- 'legislation_'
+ "legislation_"
end
end
diff --git a/app/models/legislation/annotation.rb b/app/models/legislation/annotation.rb
index feab80902..5cb190cc2 100644
--- a/app/models/legislation/annotation.rb
+++ b/app/models/legislation/annotation.rb
@@ -5,8 +5,8 @@ class Legislation::Annotation < ActiveRecord::Base
serialize :ranges, Array
- belongs_to :draft_version, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_draft_version_id'
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :draft_version, class_name: "Legislation::DraftVersion", foreign_key: "legislation_draft_version_id"
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
has_many :comments, as: :commentable, dependent: :destroy
validates :text, presence: true
diff --git a/app/models/legislation/answer.rb b/app/models/legislation/answer.rb
index 7ee6119b5..298fe9f6d 100644
--- a/app/models/legislation/answer.rb
+++ b/app/models/legislation/answer.rb
@@ -2,9 +2,9 @@ class Legislation::Answer < ActiveRecord::Base
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
- belongs_to :question, class_name: 'Legislation::Question', foreign_key: 'legislation_question_id',
+ belongs_to :question, class_name: "Legislation::Question", foreign_key: "legislation_question_id",
inverse_of: :answers, counter_cache: true
- belongs_to :question_option, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_option_id',
+ belongs_to :question_option, class_name: "Legislation::QuestionOption", foreign_key: "legislation_question_option_id",
inverse_of: :answers, counter_cache: true
belongs_to :user, dependent: :destroy, inverse_of: :legislation_answers
diff --git a/app/models/legislation/draft_version.rb b/app/models/legislation/draft_version.rb
index 18e4489b7..99dafac76 100644
--- a/app/models/legislation/draft_version.rb
+++ b/app/models/legislation/draft_version.rb
@@ -9,16 +9,16 @@ class Legislation::DraftVersion < ActiveRecord::Base
translates :body, touch: true
translates :body_html, touch: true
translates :toc_html, touch: true
- globalize_accessors
+ include Globalizable
- belongs_to :process, class_name: 'Legislation::Process', foreign_key: 'legislation_process_id'
- has_many :annotations, class_name: 'Legislation::Annotation', foreign_key: 'legislation_draft_version_id', dependent: :destroy
+ belongs_to :process, class_name: "Legislation::Process", foreign_key: "legislation_process_id"
+ has_many :annotations, class_name: "Legislation::Annotation", foreign_key: "legislation_draft_version_id", dependent: :destroy
- validates :title, presence: true
- validates :body, presence: true
+ validates_translation :title, presence: true
+ validates_translation :body, presence: true
validates :status, presence: true, inclusion: { in: VALID_STATUSES }
- scope :published, -> { where(status: 'published').order('id DESC') }
+ scope :published, -> { where(status: "published").order("id DESC") }
before_save :render_html
@@ -40,7 +40,7 @@ class Legislation::DraftVersion < ActiveRecord::Base
end
def display_title
- status == 'draft' ? "#{title} *" : title
+ status == "draft" ? "#{title} *" : title
end
def total_comments
diff --git a/app/models/legislation/process.rb b/app/models/legislation/process.rb
index bc3df6be4..46d879b63 100644
--- a/app/models/legislation/process.rb
+++ b/app/models/legislation/process.rb
@@ -1,6 +1,8 @@
class Legislation::Process < ActiveRecord::Base
include ActsAsParanoidAliases
include Taggable
+ include Milestoneable
+ include Imageable
include Documentable
documentable max_documents_allowed: 3,
max_file_size: 3.megabytes,
@@ -9,47 +11,73 @@ class Legislation::Process < ActiveRecord::Base
acts_as_paranoid column: :hidden_at
acts_as_taggable_on :customs
- translates :title, touch: true
- translates :summary, touch: true
- translates :description, touch: true
- translates :additional_info, touch: true
- globalize_accessors
+ translates :title, touch: true
+ translates :summary, touch: true
+ translates :description, touch: true
+ translates :additional_info, touch: true
+ translates :milestones_summary, touch: true
+ translates :homepage, touch: true
+ include Globalizable
- PHASES_AND_PUBLICATIONS = %i(debate_phase allegations_phase proposals_phase draft_publication result_publication).freeze
+ PHASES_AND_PUBLICATIONS = %i[homepage_phase draft_phase debate_phase allegations_phase
+ proposals_phase draft_publication result_publication].freeze
- has_many :draft_versions, -> { order(:id) }, class_name: 'Legislation::DraftVersion',
- foreign_key: 'legislation_process_id', dependent: :destroy
- has_one :final_draft_version, -> { where final_version: true, status: 'published' }, class_name: 'Legislation::DraftVersion',
- foreign_key: 'legislation_process_id'
- has_many :questions, -> { order(:id) }, class_name: 'Legislation::Question', foreign_key: 'legislation_process_id', dependent: :destroy
- has_many :proposals, -> { order(:id) }, class_name: 'Legislation::Proposal', foreign_key: 'legislation_process_id', dependent: :destroy
+ CSS_HEX_COLOR = /\A#?(?:[A-F0-9]{3}){1,2}\z/i
- validates :title, presence: true
+ has_many :draft_versions, -> { order(:id) }, class_name: "Legislation::DraftVersion",
+ foreign_key: "legislation_process_id",
+ dependent: :destroy
+ has_one :final_draft_version, -> { where final_version: true, status: "published" },
+ class_name: "Legislation::DraftVersion",
+ foreign_key: "legislation_process_id"
+ has_many :questions, -> { order(:id) }, class_name: "Legislation::Question",
+ foreign_key: "legislation_process_id", dependent: :destroy
+ has_many :proposals, -> { order(:id) }, class_name: "Legislation::Proposal",
+ foreign_key: "legislation_process_id", dependent: :destroy
+
+ validates_translation :title, presence: true
validates :start_date, presence: true
validates :end_date, presence: true
validates :debate_start_date, presence: true, if: :debate_end_date?
validates :debate_end_date, presence: true, if: :debate_start_date?
+ validates :draft_start_date, presence: true, if: :draft_end_date?
+ validates :draft_end_date, presence: true, if: :draft_start_date?
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?
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 }
- scope :open, -> { where("start_date <= ? and end_date >= ?", Date.current, Date.current).order('id DESC') }
- scope :next, -> { where("start_date > ?", Date.current).order('id DESC') }
- scope :past, -> { where("end_date < ?", Date.current).order('id DESC') }
+ scope :open, -> { where("start_date <= ? and end_date >= ?", Date.current, Date.current) }
+ scope :active, -> { where("end_date >= ?", Date.current) }
+ scope :past, -> { where("end_date < ?", Date.current) }
scope :published, -> { where(published: true) }
+ scope :not_in_draft, -> { where("draft_phase_enabled = false or (draft_start_date IS NOT NULL and
+ draft_end_date IS NOT NULL and (draft_start_date > ? or
+ draft_end_date < ?))", Date.current, Date.current) }
+
+ def homepage_phase
+ Legislation::Process::Phase.new(start_date, end_date, homepage_enabled)
+ end
+
+ def draft_phase
+ Legislation::Process::Phase.new(draft_start_date, draft_end_date, draft_phase_enabled)
+ end
def debate_phase
Legislation::Process::Phase.new(debate_start_date, debate_end_date, debate_phase_enabled)
end
def allegations_phase
- Legislation::Process::Phase.new(allegations_start_date, allegations_end_date, allegations_phase_enabled)
+ Legislation::Process::Phase.new(allegations_start_date,
+ allegations_end_date, allegations_phase_enabled)
end
def proposals_phase
- Legislation::Process::Phase.new(proposals_phase_start_date, proposals_phase_end_date, proposals_phase_enabled)
+ Legislation::Process::Phase.new(proposals_phase_start_date,
+ proposals_phase_end_date, proposals_phase_enabled)
end
def draft_publication
@@ -60,6 +88,10 @@ class Legislation::Process < ActiveRecord::Base
Legislation::Process::Publication.new(result_publication_date, result_publication_enabled)
end
+ def enabled_phases?
+ PHASES_AND_PUBLICATIONS.any? { |process| send(process).enabled? }
+ end
+
def enabled_phases_and_publications_count
PHASES_AND_PUBLICATIONS.count { |process| send(process).enabled? }
end
@@ -83,9 +115,17 @@ class Legislation::Process < ActiveRecord::Base
private
def valid_date_ranges
- errors.add(:end_date, :invalid_date_range) if end_date && start_date && end_date < start_date
- errors.add(:debate_end_date, :invalid_date_range) if debate_end_date && debate_start_date && debate_end_date < debate_start_date
- if allegations_end_date && allegations_start_date && allegations_end_date < allegations_start_date
+ if end_date && start_date && end_date < start_date
+ errors.add(:end_date, :invalid_date_range)
+ end
+ if debate_end_date && debate_start_date && debate_end_date < debate_start_date
+ errors.add(:debate_end_date, :invalid_date_range)
+ end
+ if draft_end_date && draft_start_date && draft_end_date < draft_start_date
+ errors.add(:draft_end_date, :invalid_date_range)
+ end
+ if allegations_end_date && allegations_start_date &&
+ allegations_end_date < allegations_start_date
errors.add(:allegations_end_date, :invalid_date_range)
end
end
diff --git a/app/models/legislation/proposal.rb b/app/models/legislation/proposal.rb
index 43a5cf1e8..cbf25bccf 100644
--- a/app/models/legislation/proposal.rb
+++ b/app/models/legislation/proposal.rb
@@ -12,6 +12,7 @@ class Legislation::Proposal < ActiveRecord::Base
include Documentable
include Notifiable
include Imageable
+ include Randomizable
documentable max_documents_allowed: 3,
max_file_size: 3.megabytes,
@@ -21,8 +22,8 @@ class Legislation::Proposal < ActiveRecord::Base
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'
+ belongs_to :process, class_name: "Legislation::Process", foreign_key: "legislation_process_id"
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
belongs_to :geozone
has_many :comments, as: :commentable
@@ -47,12 +48,10 @@ class Legislation::Proposal < ActiveRecord::Base
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_up: :desc) }
- scope :sort_by_random, -> { reorder("RANDOM()") }
+ scope :sort_by_supports, -> { reorder(cached_votes_score: :desc) }
scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
scope :last_week, -> { where("proposals.created_at >= ?", 7.days.ago)}
scope :selected, -> { where(selected: true) }
- scope :random, -> { sort_by_random }
scope :winners, -> { selected.sort_by_confidence_score }
def to_param
@@ -60,13 +59,13 @@ class Legislation::Proposal < ActiveRecord::Base
end
def searchable_values
- { title => 'A',
- question => 'B',
- author.username => 'B',
- tag_list.join(' ') => 'B',
- geozone.try(:name) => 'B',
- summary => 'C',
- description => 'D'}
+ { title => "A",
+ question => "B",
+ author.username => "B",
+ tag_list.join(" ") => "B",
+ geozone.try(:name) => "B",
+ summary => "C",
+ description => "D"}
end
def self.search(terms)
@@ -96,6 +95,10 @@ class Legislation::Proposal < ActiveRecord::Base
cached_votes_total
end
+ def votes_score
+ cached_votes_score
+ end
+
def voters
User.active.where(id: votes_for.voters)
end
@@ -121,14 +124,11 @@ class Legislation::Proposal < ActiveRecord::Base
end
def after_commented
- save # updates the hot_score because there is a before_save
+ save # update cache when it has a new comment
end
def calculate_hot_score
- self.hot_score = ScoreCalculator.hot_score(created_at,
- total_votes,
- total_votes,
- comments_count)
+ self.hot_score = ScoreCalculator.hot_score(self)
end
def calculate_confidence_score
@@ -136,11 +136,11 @@ class Legislation::Proposal < ActiveRecord::Base
end
def after_hide
- tags.each{ |t| t.decrement_custom_counter_for('LegislationProposal') }
+ tags.each{ |t| t.decrement_custom_counter_for("LegislationProposal") }
end
def after_restore
- tags.each{ |t| t.increment_custom_counter_for('LegislationProposal') }
+ tags.each{ |t| t.increment_custom_counter_for("LegislationProposal") }
end
protected
diff --git a/app/models/legislation/question.rb b/app/models/legislation/question.rb
index 0c9a5703f..acee09088 100644
--- a/app/models/legislation/question.rb
+++ b/app/models/legislation/question.rb
@@ -4,22 +4,22 @@ class Legislation::Question < ActiveRecord::Base
include Notifiable
translates :title, touch: true
- globalize_accessors
+ include Globalizable
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
- belongs_to :process, class_name: 'Legislation::Process', foreign_key: 'legislation_process_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
+ belongs_to :process, class_name: "Legislation::Process", foreign_key: "legislation_process_id"
- has_many :question_options, -> { order(:id) }, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_id',
+ has_many :question_options, -> { order(:id) }, class_name: "Legislation::QuestionOption", foreign_key: "legislation_question_id",
dependent: :destroy, inverse_of: :question
- has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
+ has_many :answers, class_name: "Legislation::Answer", foreign_key: "legislation_question_id", dependent: :destroy, inverse_of: :question
has_many :comments, as: :commentable, dependent: :destroy
accepts_nested_attributes_for :question_options, reject_if: proc { |attributes| attributes.all? { |k, v| v.blank? } }, allow_destroy: true
validates :process, presence: true
- validates :title, presence: true
+ validates_translation :title, presence: true
- scope :sorted, -> { order('id ASC') }
+ scope :sorted, -> { order("id ASC") }
def next_question_id
@next_question_id ||= process.questions.where("id > ?", id).sorted.limit(1).pluck(:id).first
diff --git a/app/models/legislation/question_option.rb b/app/models/legislation/question_option.rb
index 1ee46ee90..f69c60894 100644
--- a/app/models/legislation/question_option.rb
+++ b/app/models/legislation/question_option.rb
@@ -3,11 +3,11 @@ class Legislation::QuestionOption < ActiveRecord::Base
include ActsAsParanoidAliases
translates :value, touch: true
- globalize_accessors
+ include Globalizable
- belongs_to :question, class_name: 'Legislation::Question', foreign_key: 'legislation_question_id', inverse_of: :question_options
- has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
+ belongs_to :question, class_name: "Legislation::Question", foreign_key: "legislation_question_id", inverse_of: :question_options
+ has_many :answers, class_name: "Legislation::Answer", foreign_key: "legislation_question_id", dependent: :destroy, inverse_of: :question
validates :question, presence: true
- validates :value, presence: true, uniqueness: { scope: :legislation_question_id }
+ validates_translation :value, presence: true
end
diff --git a/app/models/map_location.rb b/app/models/map_location.rb
index f66d71e34..892ba8f20 100644
--- a/app/models/map_location.rb
+++ b/app/models/map_location.rb
@@ -18,4 +18,12 @@ class MapLocation < ActiveRecord::Base
}
end
+ def self.load_from_heading(heading)
+ map = new
+ map.zoom = Budget::Heading::OSM_DISTRICT_LEVEL_ZOOM
+ map.latitude = heading.latitude.to_f if heading.latitude.present?
+ map.longitude = heading.longitude.to_f if heading.longitude.present?
+ map
+ end
+
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
new file mode 100644
index 000000000..d4ef41137
--- /dev/null
+++ b/app/models/milestone.rb
@@ -0,0 +1,28 @@
+class Milestone < ActiveRecord::Base
+ 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
+
+ belongs_to :milestoneable, polymorphic: true
+ belongs_to :status
+
+ validates :milestoneable, presence: true
+ validates :publication_date, presence: true
+
+ before_validation :assign_model_to_translations
+ validates_translation :description, presence: true, unless: -> { status_id.present? }
+
+ scope :order_by_publication_date, -> { order(publication_date: :asc, created_at: :asc) }
+ scope :published, -> { where("publication_date <= ?", Date.current) }
+ scope :with_status, -> { where("status_id IS NOT NULL") }
+
+ def self.title_max_length
+ 80
+ end
+
+end
diff --git a/app/models/budget/investment/status.rb b/app/models/milestone/status.rb
similarity index 65%
rename from app/models/budget/investment/status.rb
rename to app/models/milestone/status.rb
index df2b991ba..51b03427d 100644
--- a/app/models/budget/investment/status.rb
+++ b/app/models/milestone/status.rb
@@ -1,4 +1,4 @@
-class Budget::Investment::Status < ActiveRecord::Base
+class Milestone::Status < ActiveRecord::Base
acts_as_paranoid column: :hidden_at
has_many :milestones
diff --git a/app/models/milestone/translation.rb b/app/models/milestone/translation.rb
new file mode 100644
index 000000000..e1b589d96
--- /dev/null
+++ b/app/models/milestone/translation.rb
@@ -0,0 +1,3 @@
+class Milestone::Translation < Globalize::ActiveRecord::Translation
+ delegate :status_id, to: :globalized_model
+end
diff --git a/app/models/newsletter.rb b/app/models/newsletter.rb
index b99e3e2ca..35ed57b91 100644
--- a/app/models/newsletter.rb
+++ b/app/models/newsletter.rb
@@ -1,4 +1,5 @@
class Newsletter < ActiveRecord::Base
+ has_many :activities, as: :actionable
validates :subject, presence: true
validates :segment_recipient, presence: true
diff --git a/app/models/officing/residence.rb b/app/models/officing/residence.rb
index ba930b16c..1d20660d2 100644
--- a/app/models/officing/residence.rb
+++ b/app/models/officing/residence.rb
@@ -35,7 +35,7 @@ class Officing::Residence
verified_at: Time.current,
erased_at: Time.current,
password: random_password,
- terms_of_service: '1',
+ terms_of_service: "1",
email: nil
}
self.user = User.create!(user_params)
@@ -75,7 +75,7 @@ class Officing::Residence
return unless @census_api_response.valid?
unless allowed_age?
- errors.add(:year_of_birth, I18n.t('verification.residence.new.error_not_allowed_age'))
+ errors.add(:year_of_birth, I18n.t("verification.residence.new.error_not_allowed_age"))
end
end
@@ -119,7 +119,7 @@ class Officing::Residence
end
def random_password
- (0...20).map { ('a'..'z').to_a[rand(26)] }.join
+ (0...20).map { ("a".."z").to_a[rand(26)] }.join
end
end
diff --git a/app/models/organization.rb b/app/models/organization.rb
index e5b568818..0c7aa92e9 100644
--- a/app/models/organization.rb
+++ b/app/models/organization.rb
@@ -43,11 +43,11 @@ class Organization < ActiveRecord::Base
end
def self.name_max_length
- @@name_max_length ||= columns.find { |c| c.name == 'name' }.limit || 60
+ @@name_max_length ||= columns.find { |c| c.name == "name" }.limit || 60
end
def self.responsible_name_max_length
- @@responsible_name_max_length ||= columns.find { |c| c.name == 'responsible_name' }.limit || 60
+ @@responsible_name_max_length ||= columns.find { |c| c.name == "responsible_name" }.limit || 60
end
private
diff --git a/app/models/poll.rb b/app/models/poll.rb
index c879b3a25..debe1828d 100644
--- a/app/models/poll.rb
+++ b/app/models/poll.rb
@@ -7,7 +7,7 @@ class Poll < ActiveRecord::Base
translates :name, touch: true
translates :summary, touch: true
translates :description, touch: true
- globalize_accessors
+ include Globalizable
RECOUNT_DURATION = 1.week
@@ -22,11 +22,10 @@ class Poll < ActiveRecord::Base
has_many :comments, as: :commentable
has_and_belongs_to_many :geozones
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
belongs_to :related, polymorphic: true
- validates :name, presence: true
-
+ validates_translation :name, presence: true
validate :date_range
validate :only_one_active, unless: :public?
@@ -34,11 +33,10 @@ class Poll < ActiveRecord::Base
scope :for, ->(element) { where(related: element) }
scope :public_polls, -> { where(related: nil) }
- scope :current, -> { where('starts_at <= ? and ? <= ends_at', Date.current.beginning_of_day, Date.current.beginning_of_day) }
- scope :incoming, -> { where('? < starts_at', Date.current.beginning_of_day) }
- scope :expired, -> { where('ends_at < ?', Date.current.beginning_of_day) }
+ scope :current, -> { where("starts_at <= ? and ? <= ends_at", Date.current.beginning_of_day, Date.current.beginning_of_day) }
+ scope :expired, -> { where("ends_at < ?", Date.current.beginning_of_day) }
scope :recounting, -> { Poll.where(ends_at: (Date.current.beginning_of_day - RECOUNT_DURATION)..Date.current.beginning_of_day) }
- scope :published, -> { where('published = ?', true) }
+ scope :published, -> { where("published = ?", true) }
scope :by_geozone_id, ->(geozone_id) { where(geozones: {id: geozone_id}.joins(:geozones)) }
scope :public_for_api, -> { all }
scope :sort_for_list, -> { order(:geozone_restricted, :starts_at, :name) }
@@ -57,20 +55,12 @@ class Poll < ActiveRecord::Base
starts_at <= timestamp && timestamp <= ends_at
end
- def incoming?(timestamp = Date.current.beginning_of_day)
- timestamp < starts_at
- end
-
def expired?(timestamp = Date.current.beginning_of_day)
ends_at < timestamp
end
- def self.current_or_incoming
- current + incoming
- end
-
- def self.current_or_recounting_or_incoming
- current + recounting + incoming
+ def self.current_or_recounting
+ current + recounting
end
def answerable_by?(user)
@@ -83,15 +73,35 @@ class Poll < ActiveRecord::Base
def self.answerable_by(user)
return none if user.nil? || user.unverified?
current.joins('LEFT JOIN "geozones_polls" ON "geozones_polls"."poll_id" = "polls"."id"')
- .where('geozone_restricted = ? OR geozones_polls.geozone_id = ?', false, user.geozone_id)
+ .where("geozone_restricted = ? OR geozones_polls.geozone_id = ?", false, user.geozone_id)
+ end
+
+ def self.votable_by(user)
+ answerable_by(user).
+ not_voted_by(user)
end
def votable_by?(user)
- !document_has_voted?(user.document_number, user.document_type)
+ answerable_by?(user) &&
+ not_voted_by?(user)
end
- def document_has_voted?(document_number, document_type)
- voters.where(document_number: document_number, document_type: document_type).exists?
+ def self.not_voted_by(user)
+ where("polls.id not in (?)", poll_ids_voted_by(user))
+ end
+
+ def self.poll_ids_voted_by(user)
+ return -1 if Poll::Voter.where(user: user).empty?
+
+ Poll::Voter.where(user: user).pluck(:poll_id)
+ end
+
+ def not_voted_by?(user)
+ Poll::Voter.where(poll: self, user: user).empty?
+ end
+
+ def voted_by?(user)
+ Poll::Voter.where(poll: self, user: user).exists?
end
def voted_in_booth?(user)
@@ -104,7 +114,7 @@ class Poll < ActiveRecord::Base
def date_range
unless starts_at.present? && ends_at.present? && starts_at <= ends_at
- errors.add(:starts_at, I18n.t('errors.messages.invalid_date_range'))
+ errors.add(:starts_at, I18n.t("errors.messages.invalid_date_range"))
end
end
diff --git a/app/models/poll/answer.rb b/app/models/poll/answer.rb
index 851ce2fbc..8e92988ad 100644
--- a/app/models/poll/answer.rb
+++ b/app/models/poll/answer.rb
@@ -1,7 +1,7 @@
class Poll::Answer < ActiveRecord::Base
belongs_to :question, -> { with_hidden }
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
delegate :poll, :poll_id, to: :question
diff --git a/app/models/poll/booth.rb b/app/models/poll/booth.rb
index b9cba45b1..e794a0190 100644
--- a/app/models/poll/booth.rb
+++ b/app/models/poll/booth.rb
@@ -12,7 +12,7 @@ class Poll
end
def self.available
- where(polls: { id: Poll.current_or_recounting_or_incoming }).includes(:polls)
+ where(polls: { id: Poll.current_or_recounting }).includes(:polls)
end
def assignment_on_poll(poll)
diff --git a/app/models/poll/booth_assignment.rb b/app/models/poll/booth_assignment.rb
index 81759ee0f..811b98923 100644
--- a/app/models/poll/booth_assignment.rb
+++ b/app/models/poll/booth_assignment.rb
@@ -15,6 +15,10 @@ class Poll
shifts.empty? ? false : true
end
+ def unable_to_destroy?
+ (partial_results.count + recounts.count).positive?
+ end
+
private
def shifts
diff --git a/app/models/poll/partial_result.rb b/app/models/poll/partial_result.rb
index 72a3372b3..b24ae9750 100644
--- a/app/models/poll/partial_result.rb
+++ b/app/models/poll/partial_result.rb
@@ -3,7 +3,7 @@ class Poll::PartialResult < ActiveRecord::Base
VALID_ORIGINS = %w{web booth}
belongs_to :question, -> { with_hidden }
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
belongs_to :booth_assignment
belongs_to :officer_assignment
diff --git a/app/models/poll/question.rb b/app/models/poll/question.rb
index 35bc56222..03c89f0c5 100644
--- a/app/models/poll/question.rb
+++ b/app/models/poll/question.rb
@@ -6,28 +6,26 @@ class Poll::Question < ActiveRecord::Base
include ActsAsParanoidAliases
translates :title, touch: true
- globalize_accessors
+ include Globalizable
belongs_to :poll
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
has_many :comments, as: :commentable
- has_many :answers, class_name: 'Poll::Answer'
- has_many :question_answers, -> { order 'given_order asc' }, class_name: 'Poll::Question::Answer'
+ has_many :answers, class_name: "Poll::Answer"
+ has_many :question_answers, -> { order "given_order asc" }, class_name: "Poll::Question::Answer"
has_many :partial_results
belongs_to :proposal
- validates :title, presence: true
+ validates_translation :title, presence: true, length: { minimum: 4 }
validates :author, presence: true
validates :poll_id, presence: true, if: Proc.new { |question| question.poll.nil? }
- validates :title, length: { minimum: 4 }
-
accepts_nested_attributes_for :question_answers, reject_if: :all_blank, allow_destroy: true
scope :by_poll_id, ->(poll_id) { where(poll_id: poll_id) }
- scope :sort_for_list, -> { order('poll_questions.proposal_id IS NULL', :created_at)}
+ scope :sort_for_list, -> { order("poll_questions.proposal_id IS NULL", :created_at)}
scope :for_render, -> { includes(:author, :proposal) }
def self.search(params)
@@ -38,10 +36,10 @@ class Poll::Question < ActiveRecord::Base
end
def searchable_values
- { title => 'A',
- proposal.try(:title) => 'A',
- author.username => 'C',
- author_visible_name => 'C' }
+ { title => "A",
+ proposal.try(:title) => "A",
+ author.username => "C",
+ author_visible_name => "C" }
end
def copy_attributes_from_proposal(proposal)
@@ -49,7 +47,7 @@ class Poll::Question < ActiveRecord::Base
self.author = proposal.author
self.author_visible_name = proposal.author.name
self.proposal_id = proposal.id
- self.title = proposal.title
+ send(:"#{localized_attr_name_for(:title, Globalize.locale)}=", proposal.title)
end
end
diff --git a/app/models/poll/question/answer.rb b/app/models/poll/question/answer.rb
index 48abdd9b8..4f901459a 100644
--- a/app/models/poll/question/answer.rb
+++ b/app/models/poll/question/answer.rb
@@ -4,17 +4,17 @@ class Poll::Question::Answer < ActiveRecord::Base
translates :title, touch: true
translates :description, touch: true
- globalize_accessors
+ 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'
- has_many :videos, class_name: 'Poll::Question::Answer::Video'
+ belongs_to :question, class_name: "Poll::Question", foreign_key: "question_id"
+ has_many :videos, class_name: "Poll::Question::Answer::Video"
- validates :title, presence: true
+ validates_translation :title, presence: true
validates :given_order, presence: true, uniqueness: { scope: :question_id }
def description
@@ -28,7 +28,7 @@ class Poll::Question::Answer < ActiveRecord::Base
end
def self.last_position(question_id)
- where(question_id: question_id).maximum('given_order') || 0
+ where(question_id: question_id).maximum("given_order") || 0
end
def total_votes
@@ -40,7 +40,7 @@ class Poll::Question::Answer < ActiveRecord::Base
end
def total_votes_percentage
- question.answers_total_votes.zero? ? 0 : (total_votes * 100) / question.answers_total_votes
+ question.answers_total_votes.zero? ? 0 : (total_votes * 100.0) / question.answers_total_votes
end
def set_most_voted
diff --git a/app/models/poll/question/answer/video.rb b/app/models/poll/question/answer/video.rb
index 3d214af96..4804f5188 100644
--- a/app/models/poll/question/answer/video.rb
+++ b/app/models/poll/question/answer/video.rb
@@ -1,5 +1,5 @@
class Poll::Question::Answer::Video < ActiveRecord::Base
- belongs_to :answer, class_name: 'Poll::Question::Answer', foreign_key: 'answer_id'
+ belongs_to :answer, class_name: "Poll::Question::Answer", foreign_key: "answer_id"
VIMEO_REGEX = /vimeo.*(staffpicks\/|channels\/|videos\/|video\/|\/)([^#\&\?]*).*/
YOUTUBE_REGEX = /youtu.*(be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/
diff --git a/app/models/poll/recount.rb b/app/models/poll/recount.rb
index 74a6fe937..878b1ee55 100644
--- a/app/models/poll/recount.rb
+++ b/app/models/poll/recount.rb
@@ -2,16 +2,16 @@ class Poll::Recount < ActiveRecord::Base
VALID_ORIGINS = %w{web booth letter}.freeze
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
belongs_to :booth_assignment
belongs_to :officer_assignment
validates :author, presence: true
validates :origin, inclusion: {in: VALID_ORIGINS}
- scope :web, -> { where(origin: 'web') }
- scope :booth, -> { where(origin: 'booth') }
- scope :letter, -> { where(origin: 'letter') }
+ scope :web, -> { where(origin: "web") }
+ scope :booth, -> { where(origin: "booth") }
+ scope :letter, -> { where(origin: "letter") }
scope :by_author, ->(author_id) { where(author_id: author_id) }
diff --git a/app/models/poll/shift.rb b/app/models/poll/shift.rb
index e3cfd2280..dd5c1db32 100644
--- a/app/models/poll/shift.rb
+++ b/app/models/poll/shift.rb
@@ -10,8 +10,8 @@ class Poll
enum task: { vote_collection: 0, recount_scrutiny: 1 }
- scope :vote_collection, -> { where(task: 'vote_collection') }
- scope :recount_scrutiny, -> { where(task: 'recount_scrutiny') }
+ scope :vote_collection, -> { where(task: "vote_collection") }
+ scope :recount_scrutiny, -> { where(task: "recount_scrutiny") }
scope :current, -> { where(date: Date.current) }
before_create :persist_data
@@ -24,7 +24,7 @@ class Poll
end
def create_officer_assignments
- booth.booth_assignments.each do |booth_assignment|
+ booth.booth_assignments.order(:id).each do |booth_assignment|
attrs = {
officer_id: officer_id,
date: date,
@@ -35,6 +35,10 @@ class Poll
end
end
+ def unable_to_destroy?
+ booth.booth_assignments.map(&:unable_to_destroy?).any?
+ end
+
def destroy_officer_assignments
Poll::OfficerAssignment.where(booth_assignment: booth.booth_assignments,
officer: officer,
diff --git a/app/models/poll/stats.rb b/app/models/poll/stats.rb
index f07795a73..7f12e2a56 100644
--- a/app/models/poll/stats.rb
+++ b/app/models/poll/stats.rb
@@ -18,121 +18,121 @@ class Poll
private
def total_participants
- stats_cache('total_participants') { total_participants_web + total_participants_booth }
+ stats_cache("total_participants") { total_participants_web + total_participants_booth }
end
def total_participants_web
- stats_cache('total_participants_web') { total_web_valid + total_web_white + total_web_null }
+ stats_cache("total_participants_web") { total_web_valid + total_web_white + total_web_null }
end
def total_participants_web_percentage
- stats_cache('total_participants_web_percentage') do
+ stats_cache("total_participants_web_percentage") do
total_participants.zero? ? 0 : total_participants_web * 100 / total_participants
end
end
def total_participants_booth
- stats_cache('total_participants_booth') { voters.where(origin: 'booth').count }
+ stats_cache("total_participants_booth") { voters.where(origin: "booth").count }
end
def total_participants_booth_percentage
- stats_cache('total_participants_booth_percentage') do
+ stats_cache("total_participants_booth_percentage") do
total_participants.zero? ? 0 : total_participants_booth * 100 / total_participants.to_f
end
end
def total_web_valid
- stats_cache('total_web_valid') { voters.where(origin: 'web').count }
+ stats_cache("total_web_valid") { voters.where(origin: "web").count }
end
def valid_percentage_web
- stats_cache('valid_percentage_web') do
+ stats_cache("valid_percentage_web") do
total_valid_votes.zero? ? 0 : total_web_valid * 100 / total_valid_votes.to_f
end
end
def total_web_white
- stats_cache('total_web_white') { 0 }
+ stats_cache("total_web_white") { 0 }
end
def white_percentage_web
- stats_cache('white_percentage_web') { 0 }
+ stats_cache("white_percentage_web") { 0 }
end
def total_web_null
- stats_cache('total_web_null') { 0 }
+ stats_cache("total_web_null") { 0 }
end
def null_percentage_web
- stats_cache('null_percentage_web') { 0 }
+ stats_cache("null_percentage_web") { 0 }
end
def total_booth_valid
- stats_cache('total_booth_valid') { recounts.sum(:total_amount) }
+ stats_cache("total_booth_valid") { recounts.sum(:total_amount) }
end
def valid_percentage_booth
- stats_cache('valid_percentage_booth') do
+ stats_cache("valid_percentage_booth") do
total_valid_votes.zero? ? 0 : total_booth_valid * 100 / total_valid_votes.to_f
end
end
def total_booth_white
- stats_cache('total_booth_white') { recounts.sum(:white_amount) }
+ stats_cache("total_booth_white") { recounts.sum(:white_amount) }
end
def white_percentage_booth
- stats_cache('white_percentage_booth') do
+ stats_cache("white_percentage_booth") do
total_white_votes.zero? ? 0 : total_booth_white * 100 / total_white_votes.to_f
end
end
def total_booth_null
- stats_cache('total_booth_null') { recounts.sum(:null_amount) }
+ stats_cache("total_booth_null") { recounts.sum(:null_amount) }
end
def null_percentage_booth
- stats_cache('null_percentage_booth') do
+ stats_cache("null_percentage_booth") do
total_null_votes.zero? ? 0 : total_booth_null * 100 / total_null_votes.to_f
end
end
def total_valid_votes
- stats_cache('total_valid_votes') { total_web_valid + total_booth_valid }
+ stats_cache("total_valid_votes") { total_web_valid + total_booth_valid }
end
def total_valid_percentage
- stats_cache('total_valid_percentage') do
+ stats_cache("total_valid_percentage") do
total_participants.zero? ? 0 : total_valid_votes * 100 / total_participants.to_f
end
end
def total_white_votes
- stats_cache('total_white_votes') { total_web_white + total_booth_white }
+ stats_cache("total_white_votes") { total_web_white + total_booth_white }
end
def total_white_percentage
- stats_cache('total_white_percentage') do
+ stats_cache("total_white_percentage") do
total_participants.zero? ? 0 : total_white_votes * 100 / total_participants.to_f
end
end
def total_null_votes
- stats_cache('total_null_votes') { total_web_null + total_booth_null }
+ stats_cache("total_null_votes") { total_web_null + total_booth_null }
end
def total_null_percentage
- stats_cache('total_null_percentage') do
+ stats_cache("total_null_percentage") do
total_participants.zero? ? 0 : total_null_votes * 100 / total_participants.to_f
end
end
def voters
- stats_cache('voters') { @poll.voters }
+ stats_cache("voters") { @poll.voters }
end
def recounts
- stats_cache('recounts') { @poll.recounts }
+ stats_cache("recounts") { @poll.recounts }
end
def stats_cache(key, &block)
diff --git a/app/models/poll/voter.rb b/app/models/poll/voter.rb
index 778a5d88a..0826092d2 100644
--- a/app/models/poll/voter.rb
+++ b/app/models/poll/voter.rb
@@ -18,8 +18,8 @@ class Poll
before_validation :set_demographic_info, :set_document_info
- scope :web, -> { where(origin: 'web') }
- scope :booth, -> { where(origin: 'booth') }
+ scope :web, -> { where(origin: "web") }
+ scope :booth, -> { where(origin: "booth") }
def set_demographic_info
return if user.blank?
diff --git a/app/models/progress_bar.rb b/app/models/progress_bar.rb
new file mode 100644
index 000000000..2f494196e
--- /dev/null
+++ b/app/models/progress_bar.rb
@@ -0,0 +1,23 @@
+class ProgressBar < ActiveRecord::Base
+ self.inheritance_column = nil
+ RANGE = 0..100
+
+ enum kind: %i[primary secondary]
+
+ belongs_to :progressable, polymorphic: true
+
+ translates :title, touch: true
+ include Globalizable
+
+ validates :progressable, presence: true
+ validates :kind, presence: true,
+ uniqueness: {
+ scope: [:progressable_type, :progressable_id],
+ conditions: -> { primary }
+ }
+ validates :percentage, presence: true, inclusion: RANGE, numericality: { only_integer: true }
+
+ before_validation :assign_model_to_translations
+ validates_translation :title, presence: true, unless: :primary?
+
+end
diff --git a/app/models/progress_bar/translation.rb b/app/models/progress_bar/translation.rb
new file mode 100644
index 000000000..d61f1d47b
--- /dev/null
+++ b/app/models/progress_bar/translation.rb
@@ -0,0 +1,3 @@
+class ProgressBar::Translation < Globalize::ActiveRecord::Translation
+ delegate :primary?, to: :globalized_model
+end
diff --git a/app/models/proposal.rb b/app/models/proposal.rb
index 95473ed15..e494fed09 100644
--- a/app/models/proposal.rb
+++ b/app/models/proposal.rb
@@ -20,6 +20,8 @@ class Proposal < ActiveRecord::Base
accepted_content_types: [ "application/pdf" ]
include EmbedVideosHelper
include Relationable
+ include Milestoneable
+ include Randomizable
acts_as_votable
acts_as_paranoid column: :hidden_at
@@ -27,7 +29,7 @@ class Proposal < ActiveRecord::Base
RETIRE_OPTIONS = %w(duplicated started unfeasible done other)
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
belongs_to :geozone
has_many :comments, as: :commentable, dependent: :destroy
has_many :proposal_notifications, dependent: :destroy
@@ -62,7 +64,6 @@ class Proposal < ActiveRecord::Base
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_random, -> { reorder("RANDOM()") }
scope :sort_by_relevance, -> { all }
scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
scope :sort_by_archival_date, -> { archived.sort_by_confidence_score }
@@ -115,13 +116,13 @@ class Proposal < ActiveRecord::Base
end
def searchable_values
- { title => 'A',
- question => 'B',
- author.username => 'B',
- tag_list.join(' ') => 'B',
- geozone.try(:name) => 'B',
- summary => 'C',
- description => 'D'
+ { title => "A",
+ question => "B",
+ author.username => "B",
+ tag_list.join(" ") => "B",
+ geozone.try(:name) => "B",
+ summary => "C",
+ description => "D"
}
end
@@ -187,14 +188,11 @@ class Proposal < ActiveRecord::Base
end
def after_commented
- save # updates the hot_score because there is a before_save
+ save # update cache when it has a new comment
end
def calculate_hot_score
- self.hot_score = ScoreCalculator.hot_score(created_at,
- total_votes,
- total_votes,
- comments_count)
+ self.hot_score = ScoreCalculator.hot_score(self)
end
def calculate_confidence_score
@@ -202,15 +200,15 @@ class Proposal < ActiveRecord::Base
end
def after_hide
- tags.each{ |t| t.decrement_custom_counter_for('Proposal') }
+ tags.each{ |t| t.decrement_custom_counter_for("Proposal") }
end
def after_restore
- tags.each{ |t| t.increment_custom_counter_for('Proposal') }
+ tags.each{ |t| t.increment_custom_counter_for("Proposal") }
end
def self.votes_needed_for_success
- Setting['votes_for_proposal_success'].to_i
+ Setting["votes_for_proposal_success"].to_i
end
def successful?
@@ -231,7 +229,7 @@ class Proposal < ActiveRecord::Base
def self.proposals_orders(user)
orders = %w{hot_score confidence_score created_at relevance archival_date}
- orders << "recommendations" if Setting['feature.user.recommendations_on_proposals'] && user&.recommended_proposals
+ orders << "recommendations" if Setting["feature.user.recommendations_on_proposals"] && user&.recommended_proposals
return orders
end
diff --git a/app/models/proposal_notification.rb b/app/models/proposal_notification.rb
index 686fdc075..bdb9f7698 100644
--- a/app/models/proposal_notification.rb
+++ b/app/models/proposal_notification.rb
@@ -2,7 +2,7 @@ class ProposalNotification < ActiveRecord::Base
include Graphqlable
include Notifiable
- belongs_to :author, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, class_name: "User", foreign_key: "author_id"
belongs_to :proposal
validates :title, presence: true
@@ -29,7 +29,7 @@ class ProposalNotification < ActiveRecord::Base
interval = Setting[:proposal_notification_minimum_interval_in_days]
minimum_interval = (Time.current - interval.to_i.days).to_datetime
if proposal.notifications.last.created_at > minimum_interval
- errors.add(:title, I18n.t('activerecord.errors.models.proposal_notification.attributes.minimum_interval.invalid', interval: interval))
+ errors.add(:title, I18n.t("activerecord.errors.models.proposal_notification.attributes.minimum_interval.invalid", interval: interval))
end
end
@@ -38,7 +38,7 @@ class ProposalNotification < ActiveRecord::Base
end
def moderate_system_email(moderator)
- Notification.where(notifiable_type: 'ProposalNotification', notifiable: self).destroy_all
+ Notification.where(notifiable_type: "ProposalNotification", notifiable: self).destroy_all
Activity.log(moderator, :hide, self)
end
diff --git a/app/models/related_content.rb b/app/models/related_content.rb
index 8a4cd949c..f9facb47a 100644
--- a/app/models/related_content.rb
+++ b/app/models/related_content.rb
@@ -1,14 +1,14 @@
class RelatedContent < ActiveRecord::Base
- RELATED_CONTENT_SCORE_THRESHOLD = Setting['related_content_score_threshold'].to_f
+ RELATED_CONTENT_SCORE_THRESHOLD = Setting["related_content_score_threshold"].to_f
RELATIONABLE_MODELS = %w{proposals debates budgets investments}.freeze
acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases
- belongs_to :author, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, class_name: "User", foreign_key: "author_id"
belongs_to :parent_relationable, polymorphic: true, touch: true
belongs_to :child_relationable, polymorphic: true, touch: true
- has_one :opposite_related_content, class_name: 'RelatedContent', foreign_key: :related_content_id
+ has_one :opposite_related_content, class_name: "RelatedContent", foreign_key: :related_content_id
has_many :related_content_scores
validates :parent_relationable_id, presence: true
diff --git a/app/models/setting.rb b/app/models/setting.rb
index b40aded40..58d41e934 100644
--- a/app/models/setting.rb
+++ b/app/models/setting.rb
@@ -2,35 +2,18 @@ class Setting < ActiveRecord::Base
validates :key, presence: true, uniqueness: true
default_scope { order(id: :asc) }
- scope :banner_style, -> { where("key ilike ?", "banner-style.%")}
- scope :banner_img, -> { where("key ilike ?", "banner-img.%")}
def type
- return 'feature' if feature_flag?
- return 'banner-style' if banner_style?
- return 'banner-img' if banner_img?
- return 'proposals' if proposals?
- 'common'
- end
-
- def feature_flag?
- key.start_with?('feature.')
+ prefix = key.split(".").first
+ if %w[feature process proposals map html homepage].include? prefix
+ prefix
+ else
+ "configuration"
+ end
end
def enabled?
- feature_flag? && value.present?
- end
-
- def banner_style?
- key.start_with?('banner-style.')
- end
-
- def banner_img?
- key.start_with?('banner-img.')
- end
-
- def proposals?
- key.start_with?('proposals.')
+ value.present?
end
class << self
@@ -44,5 +27,18 @@ class Setting < ActiveRecord::Base
setting.save!
value
end
+
+ def rename_key(from:, to:)
+ if where(key: to).empty?
+ value = where(key: from).pluck(:value).first.presence
+ create!(key: to, value: value)
+ end
+ remove(from)
+ end
+
+ def remove(key)
+ setting = where(key: key).first
+ setting.destroy if setting.present?
+ end
end
end
diff --git a/app/models/signature.rb b/app/models/signature.rb
index b354a7a15..3f5729058 100644
--- a/app/models/signature.rb
+++ b/app/models/signature.rb
@@ -26,7 +26,7 @@ class Signature < ActiveRecord::Base
def assign_vote_to_user
set_user
if signable.is_a? Budget::Investment
- signable.vote_by(voter: user, vote: 'yes') if [nil, :no_selecting_allowed].include?(signable.reason_for_not_being_selectable_by(user))
+ signable.vote_by(voter: user, vote: "yes") if [nil, :no_selecting_allowed].include?(signable.reason_for_not_being_selectable_by(user))
else
signable.register_vote(user, "yes")
end
@@ -49,7 +49,7 @@ class Signature < ActiveRecord::Base
verified_at: Time.current,
erased_at: Time.current,
password: random_password,
- terms_of_service: '1',
+ terms_of_service: "1",
email: nil,
date_of_birth: @census_api_response.date_of_birth,
gender: @census_api_response.gender,
@@ -64,7 +64,7 @@ class Signature < ActiveRecord::Base
end
def random_password
- (0...20).map { ('a'..'z').to_a[rand(26)] }.join
+ (0...20).map { ("a".."z").to_a[rand(26)] }.join
end
def in_census?
diff --git a/app/models/signature_sheet.rb b/app/models/signature_sheet.rb
index 3e46c1cd1..a8a10a150 100644
--- a/app/models/signature_sheet.rb
+++ b/app/models/signature_sheet.rb
@@ -1,6 +1,6 @@
class SignatureSheet < ActiveRecord::Base
belongs_to :signable, polymorphic: true
- belongs_to :author, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, class_name: "User", foreign_key: "author_id"
VALID_SIGNABLES = %w(Proposal Budget::Investment SpendingProposal)
@@ -29,7 +29,7 @@ class SignatureSheet < ActiveRecord::Base
end
def parsed_document_numbers
- document_numbers.split(/\r\n|\n|[,]/).collect {|d| d.gsub(/\s+/, '') }
+ document_numbers.split(/\r\n|\n|[,]/).collect {|d| d.gsub(/\s+/, "") }
end
def signable_found
diff --git a/app/models/site_customization.rb b/app/models/site_customization.rb
index e5d2f2137..5b9584f93 100644
--- a/app/models/site_customization.rb
+++ b/app/models/site_customization.rb
@@ -1,5 +1,5 @@
module SiteCustomization
def self.table_name_prefix
- 'site_customization_'
+ "site_customization_"
end
end
diff --git a/app/models/site_customization/content_block.rb b/app/models/site_customization/content_block.rb
index 81d624ac3..6903303e7 100644
--- a/app/models/site_customization/content_block.rb
+++ b/app/models/site_customization/content_block.rb
@@ -1,5 +1,5 @@
class SiteCustomization::ContentBlock < ActiveRecord::Base
- VALID_BLOCKS = %w(top_links footer subnavigation_left subnavigation_right)
+ VALID_BLOCKS = %w[top_links footer subnavigation_left subnavigation_right]
validates :locale, presence: true, inclusion: { in: I18n.available_locales.map(&:to_s) }
validates :name, presence: true, uniqueness: { scope: :locale }, inclusion: { in: VALID_BLOCKS }
diff --git a/app/models/site_customization/image.rb b/app/models/site_customization/image.rb
index b10f3799f..e933c40a0 100644
--- a/app/models/site_customization/image.rb
+++ b/app/models/site_customization/image.rb
@@ -1,16 +1,17 @@
class SiteCustomization::Image < ActiveRecord::Base
VALID_IMAGES = {
- "icon_home" => [330, 240],
"logo_header" => [260, 80],
"social_media_icon" => [470, 246],
"social_media_icon_twitter" => [246, 246],
- "apple-touch-icon-200" => [200, 200]
+ "apple-touch-icon-200" => [200, 200],
+ "budget_execution_no_image" => [800, 600],
+ "map" => [420, 500]
}
has_attached_file :image
validates :name, presence: true, uniqueness: true, inclusion: { in: VALID_IMAGES.keys }
- validates_attachment_content_type :image, content_type: ["image/png"]
+ validates_attachment_content_type :image, content_type: ["image/png", "image/jpeg"]
validate :check_image
def self.all_images
diff --git a/app/models/site_customization/page.rb b/app/models/site_customization/page.rb
index 34e470759..6dd8f8d2f 100644
--- a/app/models/site_customization/page.rb
+++ b/app/models/site_customization/page.rb
@@ -1,20 +1,24 @@
class SiteCustomization::Page < ActiveRecord::Base
- VALID_STATUSES = %w(draft published)
-
- validates :slug, presence: true,
- uniqueness: { case_sensitive: false },
- format: { with: /\A[0-9a-zA-Z\-_]*\Z/, message: :slug_format }
- validates :title, presence: true
- validates :status, presence: true, inclusion: { in: VALID_STATUSES }
+ VALID_STATUSES = %w[draft published]
+ has_many :cards, class_name: "Widget::Card", foreign_key: "site_customization_page_id"
translates :title, touch: true
translates :subtitle, touch: true
translates :content, touch: true
- globalize_accessors
+ include Globalizable
- scope :published, -> { where(status: 'published').order('id DESC') }
- scope :with_more_info_flag, -> { where(status: 'published', more_info_flag: true).order('id ASC') }
- scope :with_same_locale, -> { joins(:translations).where("site_customization_page_translations.locale": I18n.locale) }
+ validates_translation :title, presence: true
+ validates :slug, presence: true,
+ uniqueness: { case_sensitive: false },
+ format: { with: /\A[0-9a-zA-Z\-_]*\Z/, message: :slug_format }
+ validates :status, presence: true, inclusion: { in: VALID_STATUSES }
+
+ scope :published, -> { where(status: "published").sort_desc }
+ scope :sort_asc, -> { order("id ASC") }
+ scope :sort_desc, -> { order("id DESC") }
+ scope :with_more_info_flag, -> { where(status: "published", more_info_flag: true).sort_asc }
+ scope :with_same_locale, -> { joins(:translations).locale }
+ scope :locale, -> { where("site_customization_page_translations.locale": I18n.locale) }
def url
"/#{slug}"
diff --git a/app/models/spending_proposal.rb b/app/models/spending_proposal.rb
index f6f367f62..3bd753476 100644
--- a/app/models/spending_proposal.rb
+++ b/app/models/spending_proposal.rb
@@ -6,7 +6,7 @@ class SpendingProposal < ActiveRecord::Base
acts_as_votable
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
belongs_to :geozone
belongs_to :administrator
has_many :valuation_assignments, dependent: :destroy
@@ -29,7 +29,7 @@ class SpendingProposal < ActiveRecord::Base
scope :feasible, -> { where(feasible: true) }
scope :unfeasible, -> { where(feasible: false) }
scope :not_unfeasible, -> { where("feasible IS ? OR feasible = ?", nil, true) }
- scope :with_supports, -> { where('cached_votes_up > 0') }
+ scope :with_supports, -> { where("cached_votes_up > 0") }
scope :by_admin, ->(admin) { where(administrator_id: admin.presence) }
scope :by_tag, ->(tag_name) { tagged_with(tag_name) }
@@ -58,10 +58,10 @@ class SpendingProposal < ActiveRecord::Base
end
def searchable_values
- { title => 'A',
- author.username => 'B',
- geozone.try(:name) => 'B',
- description => 'C'
+ { title => "A",
+ author.username => "B",
+ geozone.try(:name) => "B",
+ description => "C"
}
end
@@ -70,7 +70,7 @@ class SpendingProposal < ActiveRecord::Base
end
def self.by_geozone(geozone)
- if geozone == 'all'
+ if geozone == "all"
where(geozone_id: nil)
else
where(geozone_id: geozone.presence)
diff --git a/app/models/tag.rb b/app/models/tag.rb
new file mode 100644
index 000000000..ef3d4af06
--- /dev/null
+++ b/app/models/tag.rb
@@ -0,0 +1,2 @@
+class Tag < ActsAsTaggableOn::Tag
+end
diff --git a/app/models/tag_cloud.rb b/app/models/tag_cloud.rb
index b0882af82..47b9a94fc 100644
--- a/app/models/tag_cloud.rb
+++ b/app/models/tag_cloud.rb
@@ -28,11 +28,11 @@ class TagCloud
end
def default_blacklist
- ['']
+ [""]
end
def table_name
resource_model.to_s.downcase.pluralize.gsub("::", "/")
end
-end
\ No newline at end of file
+end
diff --git a/app/models/topic.rb b/app/models/topic.rb
index 11c921dd4..e9e463aa5 100644
--- a/app/models/topic.rb
+++ b/app/models/topic.rb
@@ -4,7 +4,7 @@ class Topic < ActiveRecord::Base
include Notifiable
belongs_to :community
- belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
+ belongs_to :author, -> { with_hidden }, class_name: "User", foreign_key: "author_id"
has_many :comments, as: :commentable
diff --git a/app/models/user.rb b/app/models/user.rb
index 3a274f056..e02c93d99 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -23,14 +23,14 @@ class User < ActiveRecord::Base
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 :budget_investments, -> { with_hidden }, foreign_key: :author_id, class_name: 'Budget::Investment'
+ has_many :budget_investments, -> { with_hidden }, foreign_key: :author_id, class_name: "Budget::Investment"
has_many :comments, -> { with_hidden }
has_many :spending_proposals, foreign_key: :author_id
has_many :failed_census_calls
has_many :notifications
- has_many :direct_messages_sent, class_name: 'DirectMessage', foreign_key: :sender_id
- has_many :direct_messages_received, class_name: 'DirectMessage', foreign_key: :receiver_id
- has_many :legislation_answers, class_name: 'Legislation::Answer', dependent: :destroy, inverse_of: :user
+ has_many :direct_messages_sent, class_name: "DirectMessage", foreign_key: :sender_id
+ has_many :direct_messages_received, class_name: "DirectMessage", foreign_key: :receiver_id
+ has_many :legislation_answers, class_name: "Legislation::Answer", dependent: :destroy, inverse_of: :user
has_many :follows
belongs_to :geozone
@@ -84,7 +84,7 @@ class User < ActiveRecord::Base
email: oauth_email,
oauth_email: oauth_email,
password: Devise.friendly_token[0, 20],
- terms_of_service: '1',
+ terms_of_service: "1",
confirmed_at: oauth_email_confirmed ? DateTime.current : nil
)
end
@@ -127,6 +127,14 @@ class User < ActiveRecord::Base
votes.for_budget_investments(Budget::Investment.where(group: group)).exists?
end
+ def headings_voted_within_group(group)
+ Budget::Heading.order("name").where(id: voted_investments.by_group(group).pluck(:heading_id))
+ end
+
+ def voted_investments
+ Budget::Investment.where(id: votes.for_budget_investments.pluck(:votable_id))
+ end
+
def administrator?
administrator.present?
end
@@ -169,7 +177,7 @@ class User < ActiveRecord::Base
end
def has_official_email?
- domain = Setting['email_domain_for_officials']
+ domain = Setting["email_domain_for_officials"]
email.present? && ((email.end_with? "@#{domain}") || (email.end_with? ".#{domain}"))
end
@@ -243,11 +251,11 @@ class User < ActiveRecord::Base
end
def self.username_max_length
- @@username_max_length ||= columns.find { |c| c.name == 'username' }.limit || 60
+ @@username_max_length ||= columns.find { |c| c.name == "username" }.limit || 60
end
def self.minimum_required_age
- (Setting['min_age_to_participate'] || 16).to_i
+ (Setting["min_age_to_participate"] || 16).to_i
end
def show_welcome_screen?
diff --git a/app/models/valuator.rb b/app/models/valuator.rb
index 30b171823..2aedfc8f6 100644
--- a/app/models/valuator.rb
+++ b/app/models/valuator.rb
@@ -6,8 +6,8 @@ class Valuator < ActiveRecord::Base
has_many :valuation_assignments, dependent: :destroy
has_many :spending_proposals, through: :valuation_assignments
- has_many :valuator_assignments, dependent: :destroy, class_name: 'Budget::ValuatorAssignment'
- has_many :investments, through: :valuator_assignments, class_name: 'Budget::Investment'
+ has_many :valuator_assignments, dependent: :destroy, class_name: "Budget::ValuatorAssignment"
+ has_many :investments, through: :valuator_assignments, class_name: "Budget::Investment"
validates :user_id, presence: true, uniqueness: true
diff --git a/app/models/valuator_group.rb b/app/models/valuator_group.rb
index 61a4e4458..26738b542 100644
--- a/app/models/valuator_group.rb
+++ b/app/models/valuator_group.rb
@@ -1,7 +1,7 @@
class ValuatorGroup < ActiveRecord::Base
has_many :valuators
- has_many :valuator_group_assignments, dependent: :destroy, class_name: 'Budget::ValuatorGroupAssignment'
- has_many :investments, through: :valuator_group_assignments, class_name: 'Budget::Investment'
+ has_many :valuator_group_assignments, dependent: :destroy, class_name: "Budget::ValuatorGroupAssignment"
+ has_many :investments, through: :valuator_group_assignments, class_name: "Budget::Investment"
validates :name, presence: true, uniqueness: true
end
diff --git a/app/models/verification/letter.rb b/app/models/verification/letter.rb
index c746e73e4..e70da2b5f 100644
--- a/app/models/verification/letter.rb
+++ b/app/models/verification/letter.rb
@@ -22,14 +22,14 @@ class Verification::Letter
def validate_existing_user
unless user
- errors.add(:email, I18n.t('devise.failure.invalid', authentication_keys: 'email'))
+ errors.add(:email, I18n.t("devise.failure.invalid", authentication_keys: "email"))
end
end
def validate_correct_code
return if errors.include?(:verification_code)
if user.try(:letter_verification_code).to_i != verification_code.to_i
- errors.add(:verification_code, I18n.t('verification.letter.errors.incorrect_code'))
+ errors.add(:verification_code, I18n.t("verification.letter.errors.incorrect_code"))
end
end
diff --git a/app/models/verification/management/email.rb b/app/models/verification/management/email.rb
index de13d1ab4..8cad381d2 100644
--- a/app/models/verification/management/email.rb
+++ b/app/models/verification/management/email.rb
@@ -40,9 +40,9 @@ class Verification::Management::Email
def validate_user
return if errors.count > 0
if !user?
- errors.add(:email, I18n.t('errors.messages.user_not_found'))
+ errors.add(:email, I18n.t("errors.messages.user_not_found"))
elsif user.level_three_verified?
- errors.add(:email, I18n.t('management.email_verifications.already_verified'))
+ errors.add(:email, I18n.t("management.email_verifications.already_verified"))
end
end
@@ -50,7 +50,7 @@ class Verification::Management::Email
return if errors.count > 0
if document_number_mismatch?
errors.add(:email,
- I18n.t('management.email_verifications.document_mismatch',
+ I18n.t("management.email_verifications.document_mismatch",
document_type: ApplicationController.helpers.humanize_document_type(user.document_type),
document_number: user.document_number))
end
diff --git a/app/models/verification/management/managed_user.rb b/app/models/verification/management/managed_user.rb
index e61cc2937..7332b5f7e 100644
--- a/app/models/verification/management/managed_user.rb
+++ b/app/models/verification/management/managed_user.rb
@@ -2,9 +2,9 @@ class Verification::Management::ManagedUser
include ActiveModel::Model
def self.find(document_type, document_number)
- User.where('document_number is not null').
+ User.where("document_number is not null").
find_or_initialize_by(document_type: document_type,
document_number: document_number)
end
-end
\ No newline at end of file
+end
diff --git a/app/models/verification/residence.rb b/app/models/verification/residence.rb
index 0b8f420ce..a8c20adfd 100644
--- a/app/models/verification/residence.rb
+++ b/app/models/verification/residence.rb
@@ -18,8 +18,8 @@ class Verification::Residence
validate :document_number_uniqueness
def initialize(attrs = {})
- self.date_of_birth = parse_date('date_of_birth', attrs)
- attrs = remove_date('date_of_birth', attrs)
+ self.date_of_birth = parse_date("date_of_birth", attrs)
+ attrs = remove_date("date_of_birth", attrs)
super
clean_document_number
end
@@ -39,11 +39,11 @@ class Verification::Residence
def allowed_age
return if errors[:date_of_birth].any? || Age.in_years(date_of_birth) >= User.minimum_required_age
- errors.add(:date_of_birth, I18n.t('verification.residence.new.error_not_allowed_age'))
+ errors.add(:date_of_birth, I18n.t("verification.residence.new.error_not_allowed_age"))
end
def document_number_uniqueness
- errors.add(:document_number, I18n.t('errors.messages.taken')) if User.active.where(document_number: document_number).any?
+ errors.add(:document_number, I18n.t("errors.messages.taken")) if User.active.where(document_number: document_number).any?
end
def store_failed_attempt
diff --git a/app/models/widget/card.rb b/app/models/widget/card.rb
index 73bc3eb00..5ec0d4944 100644
--- a/app/models/widget/card.rb
+++ b/app/models/widget/card.rb
@@ -1,5 +1,6 @@
class Widget::Card < ActiveRecord::Base
include Imageable
+ belongs_to :page, class_name: "SiteCustomization::Page", foreign_key: "site_customization_page_id"
# table_name must be set before calls to 'translates'
self.table_name = "widget_cards"
@@ -8,13 +9,19 @@ class Widget::Card < ActiveRecord::Base
translates :title, touch: true
translates :description, touch: true
translates :link_text, touch: true
- globalize_accessors
+ include Globalizable
def self.header
where(header: true)
end
def self.body
- where(header: false).order(:created_at)
+ where(header: false, site_customization_page_id: nil).order(:created_at)
end
+
+ #add widget cards to custom pages
+ def self.page(page_id)
+ where(site_customization_page_id: page_id)
+ end
+
end
diff --git a/app/models/widget/feed.rb b/app/models/widget/feed.rb
index 4fc23a1dd..997f9e8b6 100644
--- a/app/models/widget/feed.rb
+++ b/app/models/widget/feed.rb
@@ -8,7 +8,7 @@ class Widget::Feed < ActiveRecord::Base
end
def setting
- Setting.where(key: "feature.homepage.widgets.feeds.#{kind}").first
+ Setting.where(key: "homepage.widgets.feeds.#{kind}").first
end
def self.active
@@ -31,7 +31,7 @@ class Widget::Feed < ActiveRecord::Base
end
def processes
- Legislation::Process.open.published.limit(limit)
+ Legislation::Process.open.published.order("created_at DESC").limit(limit)
end
end
\ No newline at end of file
diff --git a/app/views/account/show.html.erb b/app/views/account/show.html.erb
index a0a782f2b..871e2de0d 100644
--- a/app/views/account/show.html.erb
+++ b/app/views/account/show.html.erb
@@ -33,7 +33,7 @@
<%= f.label :public_activity do %>
- <%= f.check_box :public_activity, title: t('account.show.public_activity_label'), label: false %>
+ <%= f.check_box :public_activity, title: t("account.show.public_activity_label"), label: false %>
<%= t("account.show.public_activity_label") %>
@@ -42,7 +42,7 @@
<%= f.label :public_interests do %>
- <%= f.check_box :public_interests, title: t('account.show.public_interests_label'), label: false %>
+ <%= f.check_box :public_interests, title: t("account.show.public_interests_label"), label: false %>
<%= t("account.show.public_interests_label") %>
@@ -55,7 +55,7 @@
<%= f.label :email_on_comment do %>
- <%= f.check_box :email_on_comment, title: t('account.show.email_on_comment_label'), label: false %>
+ <%= f.check_box :email_on_comment, title: t("account.show.email_on_comment_label"), label: false %>
<%= t("account.show.email_on_comment_label") %>
@@ -64,7 +64,7 @@
<%= f.label :email_on_comment_reply do %>
- <%= f.check_box :email_on_comment_reply, title: t('account.show.email_on_comment_reply_label'), label: false %>
+ <%= f.check_box :email_on_comment_reply, title: t("account.show.email_on_comment_reply_label"), label: false %>
<%= t("account.show.email_on_comment_reply_label") %>
@@ -73,7 +73,7 @@
<%= f.label :email_newsletter_subscribed do %>
- <%= f.check_box :newsletter, title: t('account.show.subscription_to_website_newsletter_label'), label: false %>
+ <%= f.check_box :newsletter, title: t("account.show.subscription_to_website_newsletter_label"), label: false %>
<%= t("account.show.subscription_to_website_newsletter_label") %>
@@ -82,7 +82,7 @@
<%= f.label :email_digest do %>
- <%= f.check_box :email_digest, title: t('account.show.email_digest_label'), label: false %>
+ <%= f.check_box :email_digest, title: t("account.show.email_digest_label"), label: false %>
<%= t("account.show.email_digest_label") %>
@@ -91,7 +91,7 @@
<%= f.label :email_on_direct_message do %>
- <%= f.check_box :email_on_direct_message, title: t('account.show.email_on_direct_message_label'), label: false %>
+ <%= f.check_box :email_on_direct_message, title: t("account.show.email_on_direct_message_label"), label: false %>
<%= t("account.show.email_on_direct_message_label") %>
@@ -103,7 +103,7 @@
<%= f.label :official_position_badge do %>
<%= f.check_box :official_position_badge,
- title: t('account.show.official_position_badge_label'),
+ title: t("account.show.official_position_badge_label"),
label: false %>
<%= t("account.show.official_position_badge_label") %>
diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb
index 6e201e2ca..9fe52bcd4 100644
--- a/app/views/admin/_menu.html.erb
+++ b/app/views/admin/_menu.html.erb
@@ -1,21 +1,38 @@
@@ -21,7 +21,7 @@ <% end %> <% @comment_tree.root_comments.each do |comment| %> - <%= render 'comments/comment', comment: comment %> + <%= render "comments/comment", comment: comment %> <% end %> <%= paginate @comment_tree.root_comments %>