Merge branch 'master' into dashboard-master
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -33,3 +33,4 @@
|
||||
|
||||
public/sitemap.xml
|
||||
public/system/
|
||||
/public/ckeditor_assets/
|
||||
|
||||
@@ -25,6 +25,12 @@ Layout/IndentationConsistency:
|
||||
Layout/EndOfLine:
|
||||
EnforcedStyle: lf
|
||||
|
||||
Layout/TrailingBlankLines:
|
||||
Enabled: true
|
||||
|
||||
Layout/TrailingWhitespace:
|
||||
Enabled: true
|
||||
|
||||
Bundler/DuplicatedGem:
|
||||
Enabled: true
|
||||
|
||||
@@ -420,3 +426,6 @@ Security/MarshalLoad:
|
||||
|
||||
Security/YAMLLoad:
|
||||
Enabled: true
|
||||
|
||||
Style/PercentLiteralDelimiters:
|
||||
Enabled: true
|
||||
|
||||
@@ -34,21 +34,12 @@ If you want to contribute code to solve an issue:
|
||||
* Fork the project.
|
||||
* Create a topic branch based on master.
|
||||
* Commit there your code to solve the issue.
|
||||
* Make sure all test are passing (and add specs to test any new feature if needed).
|
||||
* Make sure all test are passing (and add specs to test any new feature you've added).
|
||||
* Follow these [best practices](https://github.com/styleguide/ruby)
|
||||
* Open a *pull request* to the main repository describing what issue you are addressing.
|
||||
|
||||
**Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)
|
||||
|
||||
## Cleaning up
|
||||
|
||||
In the rush of time sometimes things get messy, you can help us cleaning things up:
|
||||
|
||||
* implement [pending specs](https://travis-ci.org/consul/consul)
|
||||
* increase [code coverage](https://coveralls.io/github/consul/consul?branch=master)
|
||||
* improve [code quality](https://codeclimate.com/github/consul/consul)
|
||||
* make [code consistent](https://github.com/bbatsov/rubocop)
|
||||
|
||||
## Other ways of contributing without coding
|
||||
|
||||
* If you think there's a feature missing, or find a bug, create an issue (make sure it has not already been reported).
|
||||
|
||||
17
Dockerfile
17
Dockerfile
@@ -1,7 +1,11 @@
|
||||
# Use Ruby 2.3.6 as base image
|
||||
FROM ruby:2.3.6
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
# Install essential Linux packages
|
||||
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev postgresql-client nodejs imagemagick sudo
|
||||
RUN apt-get update -qq
|
||||
RUN apt-get install -y build-essential libpq-dev postgresql-client nodejs imagemagick sudo libxss1 libappindicator1 libindicator7 unzip memcached
|
||||
|
||||
# Files created inside the container repect the ownership
|
||||
RUN adduser --shell /bin/bash --disabled-password --gecos "" consul \
|
||||
@@ -34,9 +38,18 @@ COPY Gemfile_custom Gemfile_custom
|
||||
# Prevent bundler warnings; ensure that the bundler version executed is >= that which created Gemfile.lock
|
||||
RUN gem install bundler
|
||||
|
||||
# Finish establishing our Ruby enviornment
|
||||
# Finish establishing our Ruby environment
|
||||
RUN bundle install --full-index
|
||||
|
||||
# Install Chromium and ChromeDriver for E2E integration tests
|
||||
RUN apt-get update -qq && apt-get install -y chromium
|
||||
RUN wget -N http://chromedriver.storage.googleapis.com/2.38/chromedriver_linux64.zip
|
||||
RUN unzip chromedriver_linux64.zip
|
||||
RUN chmod +x chromedriver
|
||||
RUN mv -f chromedriver /usr/local/share/chromedriver
|
||||
RUN ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver
|
||||
RUN ln -s /usr/local/share/chromedriver /usr/bin/chromedriver
|
||||
|
||||
# Copy the Rails application into place
|
||||
COPY . .
|
||||
|
||||
|
||||
31
Gemfile
31
Gemfile
@@ -5,17 +5,17 @@ gem 'rails', '4.2.10'
|
||||
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.1'
|
||||
gem 'autoprefixer-rails', '~> 8.2.0'
|
||||
gem 'ancestry', '~> 3.0.2'
|
||||
gem 'autoprefixer-rails', '~> 9.1.4'
|
||||
gem 'best_in_place', '~> 3.0.1'
|
||||
gem 'browser', '~> 2.5.2'
|
||||
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.1'
|
||||
gem 'coffee-rails', '~> 4.2.2'
|
||||
gem 'daemons', '~> 1.2.4'
|
||||
gem 'dalli', '~> 2.7.6'
|
||||
gem 'delayed_job_active_record', '~> 4.1.0'
|
||||
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'
|
||||
@@ -28,7 +28,7 @@ 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.1'
|
||||
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'
|
||||
@@ -37,7 +37,7 @@ 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.0'
|
||||
gem 'paranoia', '~> 2.4.1'
|
||||
gem 'pg', '~> 0.21.0'
|
||||
gem 'pg_search', '~> 2.0.1'
|
||||
gem 'redcarpet', '~> 3.4.0'
|
||||
@@ -45,14 +45,14 @@ 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.11.1'
|
||||
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.0'
|
||||
gem 'unicorn', '~> 5.4.1'
|
||||
gem 'whenever', '~> 0.10.0', require: false
|
||||
gem 'globalize', '~> 5.0.0'
|
||||
gem 'globalize-accessors', '~> 0.2.1'
|
||||
@@ -68,7 +68,8 @@ group :development, :test do
|
||||
gem 'bullet', '~> 5.7.0'
|
||||
gem 'byebug', '~> 10.0.0'
|
||||
gem 'factory_bot_rails', '~> 4.8.2'
|
||||
gem 'i18n-tasks', '~> 0.9.20'
|
||||
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'
|
||||
@@ -79,7 +80,7 @@ end
|
||||
|
||||
group :test do
|
||||
gem 'capybara', '~> 2.17.0'
|
||||
gem 'coveralls', '~> 0.8.21', require: false
|
||||
gem 'coveralls', '~> 0.8.22', require: false
|
||||
gem 'database_cleaner', '~> 1.6.1'
|
||||
gem 'email_spec', '~> 2.1.0'
|
||||
gem 'rspec-rails', '~> 3.6'
|
||||
@@ -89,13 +90,13 @@ end
|
||||
group :development do
|
||||
gem 'capistrano', '~> 3.10.1', require: false
|
||||
gem 'capistrano-bundler', '~> 1.2', require: false
|
||||
gem 'capistrano-rails', '~> 1.3.1', require: false
|
||||
gem 'capistrano-rails', '~> 1.4.0', require: false
|
||||
gem 'capistrano3-delayed-job', '~> 1.7.3'
|
||||
gem 'mdl', '~> 0.4.0', require: false
|
||||
gem 'mdl', '~> 0.5.0', require: false
|
||||
gem 'rubocop', '~> 0.54.0', require: false
|
||||
gem 'rubocop-rspec', '~> 1.24.0', require: false
|
||||
gem 'rubocop-rspec', '~> 1.26.0', require: false
|
||||
gem 'rvm1-capistrano3', '~> 1.4.0', require: false
|
||||
gem 'scss_lint', '~> 0.54.0', require: false
|
||||
gem 'scss_lint', '~> 0.55.0', require: false
|
||||
gem 'web-console', '~> 3.3.0'
|
||||
end
|
||||
|
||||
|
||||
126
Gemfile.lock
126
Gemfile.lock
@@ -57,11 +57,11 @@ GEM
|
||||
akami (1.3.1)
|
||||
gyoku (>= 0.4.0)
|
||||
nokogiri
|
||||
ancestry (3.0.1)
|
||||
ancestry (3.0.2)
|
||||
activerecord (>= 3.2.0)
|
||||
arel (6.0.4)
|
||||
ast (2.4.0)
|
||||
autoprefixer-rails (8.2.0)
|
||||
autoprefixer-rails (9.1.4)
|
||||
execjs
|
||||
babel-source (5.8.35)
|
||||
babel-transpiler (0.7.0)
|
||||
@@ -71,7 +71,7 @@ GEM
|
||||
best_in_place (3.0.3)
|
||||
actionpack (>= 3.2)
|
||||
railties (>= 3.2)
|
||||
browser (2.5.2)
|
||||
browser (2.5.3)
|
||||
builder (3.2.3)
|
||||
bullet (5.7.1)
|
||||
activesupport (>= 3.0.0)
|
||||
@@ -86,7 +86,7 @@ GEM
|
||||
capistrano-bundler (1.3.0)
|
||||
capistrano (~> 3.1)
|
||||
sshkit (~> 1.2)
|
||||
capistrano-rails (1.3.1)
|
||||
capistrano-rails (1.4.0)
|
||||
capistrano (~> 3.1)
|
||||
capistrano-bundler (~> 1.1)
|
||||
capistrano3-delayed-job (1.7.5)
|
||||
@@ -117,21 +117,21 @@ GEM
|
||||
execjs
|
||||
coffee-script-source (1.12.2)
|
||||
concurrent-ruby (1.0.5)
|
||||
coveralls (0.8.21)
|
||||
coveralls (0.8.22)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov (~> 0.14.1)
|
||||
simplecov (~> 0.16.1)
|
||||
term-ansicolor (~> 1.3)
|
||||
thor (~> 0.19.4)
|
||||
tins (~> 1.6)
|
||||
crass (1.0.3)
|
||||
crass (1.0.4)
|
||||
daemons (1.2.6)
|
||||
dalli (2.7.6)
|
||||
database_cleaner (1.6.2)
|
||||
debug_inspector (0.0.3)
|
||||
delayed_job (4.1.3)
|
||||
activesupport (>= 3.0, < 5.2)
|
||||
delayed_job_active_record (4.1.2)
|
||||
activerecord (>= 3.0, < 5.2)
|
||||
delayed_job (4.1.5)
|
||||
activesupport (>= 3.0, < 5.3)
|
||||
delayed_job_active_record (4.1.3)
|
||||
activerecord (>= 3.0, < 5.3)
|
||||
delayed_job (>= 3.0, < 5)
|
||||
devise (3.5.10)
|
||||
bcrypt (~> 3.0)
|
||||
@@ -146,16 +146,13 @@ GEM
|
||||
devise (>= 3.0.0, < 4.0)
|
||||
railties (>= 3.2.6, < 5.0)
|
||||
diff-lcs (1.3)
|
||||
docile (1.1.5)
|
||||
easy_translate (0.5.1)
|
||||
thread
|
||||
thread_safe
|
||||
docile (1.3.1)
|
||||
email_spec (2.1.1)
|
||||
htmlentities (~> 4.3.3)
|
||||
launchy (~> 2.1)
|
||||
mail (~> 2.6)
|
||||
errbase (0.0.3)
|
||||
erubi (1.7.0)
|
||||
erubi (1.7.1)
|
||||
erubis (2.7.0)
|
||||
execjs (2.7.0)
|
||||
factory_bot (4.8.2)
|
||||
@@ -167,7 +164,7 @@ GEM
|
||||
i18n (>= 0.7)
|
||||
faraday (0.12.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.23)
|
||||
ffi (1.9.25)
|
||||
foundation-rails (6.4.3.0)
|
||||
railties (>= 3.1.0)
|
||||
sass (>= 3.3.0, < 3.5)
|
||||
@@ -194,22 +191,21 @@ GEM
|
||||
gyoku (1.3.1)
|
||||
builder (>= 2.1.2)
|
||||
hashie (3.5.7)
|
||||
highline (1.7.10)
|
||||
highline (2.0.0)
|
||||
htmlentities (4.3.4)
|
||||
httpi (2.4.2)
|
||||
httpi (2.4.4)
|
||||
rack
|
||||
socksify
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-tasks (0.9.20)
|
||||
i18n-tasks (0.9.25)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
easy_translate (>= 0.5.1)
|
||||
erubi
|
||||
highline (>= 1.7.3)
|
||||
highline (>= 2.0.0)
|
||||
i18n
|
||||
parser (>= 2.2.3.0)
|
||||
rainbow (~> 2.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
terminal-table (>= 1.5.1)
|
||||
initialjs-rails (0.2.0.5)
|
||||
railties (>= 3.1, < 6.0)
|
||||
@@ -219,7 +215,7 @@ GEM
|
||||
actionpack (>= 3.1)
|
||||
railties (>= 3.1)
|
||||
sass (>= 3.2)
|
||||
jquery-rails (4.3.1)
|
||||
jquery-rails (4.3.3)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
@@ -239,10 +235,10 @@ GEM
|
||||
activerecord
|
||||
kaminari-core (= 1.1.1)
|
||||
kaminari-core (1.1.1)
|
||||
kgio (2.11.1)
|
||||
kgio (2.11.2)
|
||||
knapsack_pro (0.53.0)
|
||||
rake
|
||||
kramdown (1.14.0)
|
||||
kramdown (1.17.0)
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
letter_opener (1.6.0)
|
||||
@@ -256,7 +252,7 @@ GEM
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.0)
|
||||
mini_mime (>= 0.1.1)
|
||||
mdl (0.4.0)
|
||||
mdl (0.5.0)
|
||||
kramdown (~> 1.12, >= 1.12.0)
|
||||
mixlib-cli (~> 1.7, >= 1.7.0)
|
||||
mixlib-config (~> 2.2, >= 2.2.1)
|
||||
@@ -268,15 +264,16 @@ GEM
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.11.3)
|
||||
mixlib-cli (1.7.0)
|
||||
mixlib-config (2.2.4)
|
||||
mixlib-config (2.2.13)
|
||||
tomlrb
|
||||
multi_json (1.12.2)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
net-scp (1.2.1)
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (4.2.0)
|
||||
net-ssh (5.0.2)
|
||||
newrelic_rpm (4.1.0.333)
|
||||
nokogiri (1.8.2)
|
||||
nokogiri (1.8.4)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
nori (2.6.0)
|
||||
oauth (0.5.3)
|
||||
@@ -313,16 +310,16 @@ GEM
|
||||
mime-types
|
||||
mimemagic (~> 0.3.0)
|
||||
parallel (1.12.1)
|
||||
paranoia (2.4.0)
|
||||
activerecord (>= 4.0, < 5.2)
|
||||
parser (2.5.0.5)
|
||||
paranoia (2.4.1)
|
||||
activerecord (>= 4.0, < 5.3)
|
||||
parser (2.5.1.2)
|
||||
ast (~> 2.4.0)
|
||||
pg (0.21.0)
|
||||
pg_search (2.0.1)
|
||||
activerecord (>= 4.2)
|
||||
activesupport (>= 4.2)
|
||||
arel (>= 6)
|
||||
powerpack (0.1.1)
|
||||
powerpack (0.1.2)
|
||||
public_suffix (3.0.1)
|
||||
quiet_assets (1.1.0)
|
||||
railties (>= 3.1, < 5.0)
|
||||
@@ -359,8 +356,7 @@ GEM
|
||||
activesupport (= 4.2.10)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.2.2)
|
||||
rake
|
||||
rainbow (3.0.0)
|
||||
raindrops (0.19.0)
|
||||
rake (12.3.1)
|
||||
redcarpet (3.4.0)
|
||||
@@ -396,10 +392,10 @@ GEM
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
rubocop-rspec (1.24.0)
|
||||
rubocop-rspec (1.26.0)
|
||||
rubocop (>= 0.53.0)
|
||||
ruby-progressbar (1.9.0)
|
||||
rubyzip (1.2.1)
|
||||
ruby-progressbar (1.10.0)
|
||||
rubyzip (1.2.2)
|
||||
rvm1-capistrano3 (1.4.0)
|
||||
capistrano (~> 3.0)
|
||||
sshkit (>= 1.2)
|
||||
@@ -412,25 +408,25 @@ GEM
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
savon (2.11.2)
|
||||
savon (2.12.0)
|
||||
akami (~> 1.2)
|
||||
builder (>= 2.1.2)
|
||||
gyoku (~> 1.2)
|
||||
httpi (~> 2.3)
|
||||
nokogiri (>= 1.4.0)
|
||||
nokogiri (>= 1.8.1)
|
||||
nori (~> 2.4)
|
||||
wasabi (~> 3.4)
|
||||
scss_lint (0.54.0)
|
||||
scss_lint (0.55.0)
|
||||
rake (>= 0.9, < 13)
|
||||
sass (~> 3.4.20)
|
||||
selenium-webdriver (3.10.0)
|
||||
childprocess (~> 0.5)
|
||||
rubyzip (~> 1.2)
|
||||
simplecov (0.14.1)
|
||||
docile (~> 1.1.0)
|
||||
simplecov (0.16.1)
|
||||
docile (~> 1.1)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.1)
|
||||
simplecov-html (0.10.2)
|
||||
sitemap_generator (6.0.1)
|
||||
builder (~> 3.0)
|
||||
social-share-button (1.1.0)
|
||||
@@ -451,7 +447,7 @@ GEM
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
sshkit (1.15.1)
|
||||
sshkit (1.17.0)
|
||||
net-scp (>= 1.1.2)
|
||||
net-ssh (>= 2.8.0)
|
||||
term-ansicolor (1.6.0)
|
||||
@@ -459,10 +455,10 @@ GEM
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thor (0.19.4)
|
||||
thread (0.2.2)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.8)
|
||||
tins (1.15.0)
|
||||
tins (1.16.3)
|
||||
tomlrb (1.2.7)
|
||||
turbolinks (2.5.3)
|
||||
coffee-rails
|
||||
turnout (2.4.0)
|
||||
@@ -474,8 +470,8 @@ GEM
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.1.3)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicode-display_width (1.3.0)
|
||||
unicorn (5.4.0)
|
||||
unicode-display_width (1.4.0)
|
||||
unicorn (5.4.1)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
uniform_notifier (1.11.0)
|
||||
@@ -504,26 +500,26 @@ DEPENDENCIES
|
||||
acts-as-taggable-on (~> 5.0.0)
|
||||
acts_as_votable (~> 0.11.1)
|
||||
ahoy_matey (~> 1.6.0)
|
||||
ancestry (~> 3.0.1)
|
||||
autoprefixer-rails (~> 8.2.0)
|
||||
ancestry (~> 3.0.2)
|
||||
autoprefixer-rails (~> 9.1.4)
|
||||
best_in_place (~> 3.0.1)
|
||||
browser (~> 2.5.2)
|
||||
browser (~> 2.5.3)
|
||||
bullet (~> 5.7.0)
|
||||
byebug (~> 10.0.0)
|
||||
cancancan (~> 2.1.2)
|
||||
capistrano (~> 3.10.1)
|
||||
capistrano-bundler (~> 1.2)
|
||||
capistrano-rails (~> 1.3.1)
|
||||
capistrano-rails (~> 1.4.0)
|
||||
capistrano3-delayed-job (~> 1.7.3)
|
||||
capybara (~> 2.17.0)
|
||||
ckeditor (~> 4.2.3)
|
||||
cocoon (~> 1.2.9)
|
||||
coffee-rails (~> 4.2.1)
|
||||
coveralls (~> 0.8.21)
|
||||
coffee-rails (~> 4.2.2)
|
||||
coveralls (~> 0.8.22)
|
||||
daemons (~> 1.2.4)
|
||||
dalli (~> 2.7.6)
|
||||
database_cleaner (~> 1.6.1)
|
||||
delayed_job_active_record (~> 4.1.0)
|
||||
delayed_job_active_record (~> 4.1.3)
|
||||
devise (~> 3.5.7)
|
||||
devise-async (~> 0.10.2)
|
||||
devise_security_extension (~> 0.10.0)
|
||||
@@ -537,24 +533,24 @@ DEPENDENCIES
|
||||
graphiql-rails (~> 1.4.1)
|
||||
graphql (~> 1.7.8)
|
||||
groupdate (~> 3.2.0)
|
||||
i18n-tasks (~> 0.9.20)
|
||||
i18n-tasks (~> 0.9.25)
|
||||
initialjs-rails (~> 0.2.0.5)
|
||||
invisible_captcha (~> 0.10.0)
|
||||
jquery-fileupload-rails
|
||||
jquery-rails (~> 4.3.1)
|
||||
jquery-rails (~> 4.3.3)
|
||||
jquery-ui-rails (~> 6.0.1)
|
||||
kaminari (~> 1.1.1)
|
||||
knapsack_pro (~> 0.53.0)
|
||||
launchy (~> 2.4.3)
|
||||
letter_opener_web (~> 1.3.2)
|
||||
mdl (~> 0.4.0)
|
||||
mdl (~> 0.5.0)
|
||||
newrelic_rpm (~> 4.1.0.333)
|
||||
omniauth (~> 1.8.1)
|
||||
omniauth-facebook (~> 4.0.0)
|
||||
omniauth-google-oauth2 (~> 0.4.0)
|
||||
omniauth-twitter (~> 1.4.0)
|
||||
paperclip (~> 5.2.1)
|
||||
paranoia (~> 2.4.0)
|
||||
paranoia (~> 2.4.1)
|
||||
pg (~> 0.21.0)
|
||||
pg_search (~> 2.0.1)
|
||||
quiet_assets (~> 1.1.0)
|
||||
@@ -567,11 +563,11 @@ DEPENDENCIES
|
||||
rollbar (~> 2.15.5)
|
||||
rspec-rails (~> 3.6)
|
||||
rubocop (~> 0.54.0)
|
||||
rubocop-rspec (~> 1.24.0)
|
||||
rubocop-rspec (~> 1.26.0)
|
||||
rvm1-capistrano3 (~> 1.4.0)
|
||||
sass-rails (~> 5.0, >= 5.0.4)
|
||||
savon (~> 2.11.1)
|
||||
scss_lint (~> 0.54.0)
|
||||
savon (~> 2.12.0)
|
||||
scss_lint (~> 0.55.0)
|
||||
selenium-webdriver (~> 3.10)
|
||||
sitemap_generator (~> 6.0.1)
|
||||
social-share-button (~> 1.1)
|
||||
@@ -581,7 +577,7 @@ DEPENDENCIES
|
||||
turbolinks (~> 2.5.3)
|
||||
turnout (~> 2.4.0)
|
||||
uglifier (~> 4.1.2)
|
||||
unicorn (~> 5.4.0)
|
||||
unicorn (~> 5.4.1)
|
||||
web-console (~> 3.3.0)
|
||||
whenever (~> 0.10.0)
|
||||
wicked_pdf (~> 1.1.0)
|
||||
|
||||
0
app/assets/fonts/custom/.keep
Normal file
0
app/assets/fonts/custom/.keep
Normal file
@@ -34,6 +34,7 @@
|
||||
//= require moderator_comment
|
||||
//= require moderator_debates
|
||||
//= require moderator_proposals
|
||||
//= require moderator_budget_investments
|
||||
//= require moderator_proposal_notifications
|
||||
//= require prevent_double_submission
|
||||
//= require gettext
|
||||
|
||||
@@ -5,35 +5,19 @@ For licensing, see LICENSE.html or http://ckeditor.com/license
|
||||
|
||||
CKEDITOR.editorConfig = function( config )
|
||||
{
|
||||
// Define changes to default configuration here. For example:
|
||||
// config.language = 'fr';
|
||||
// config.uiColor = '#AADC6E';
|
||||
|
||||
config.forcePasteAsPlainText = true;
|
||||
|
||||
/* Filebrowser routes */
|
||||
// The location of an external file browser, that should be launched when "Browse Server" button is pressed.
|
||||
config.filebrowserBrowseUrl = "/ckeditor/attachment_files";
|
||||
|
||||
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Flash dialog.
|
||||
config.filebrowserFlashBrowseUrl = "/ckeditor/attachment_files";
|
||||
|
||||
// The location of a script that handles file uploads in the Flash dialog.
|
||||
config.filebrowserFlashUploadUrl = "/ckeditor/attachment_files";
|
||||
|
||||
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Link tab of Image dialog.
|
||||
config.filebrowserImageBrowseLinkUrl = "/ckeditor/pictures";
|
||||
|
||||
// The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Image dialog.
|
||||
config.filebrowserImageBrowseUrl = "/ckeditor/pictures";
|
||||
|
||||
// The location of a script that handles file uploads in the Image dialog.
|
||||
config.filebrowserImageUploadUrl = "/ckeditor/pictures";
|
||||
|
||||
// The location of a script that handles file uploads.
|
||||
config.filebrowserUploadUrl = "/ckeditor/attachment_files";
|
||||
|
||||
config.allowedContent = true;
|
||||
config.format_tags = "p;h2;h3";
|
||||
|
||||
// Rails CSRF token
|
||||
config.filebrowserParams = function(){
|
||||
@@ -111,7 +95,14 @@ CKEDITOR.editorConfig = function( config )
|
||||
|
||||
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' ] }
|
||||
];
|
||||
|
||||
config.toolbar_admin = config.toolbar_mini.concat([
|
||||
{ name: 'insert', items: [ 'Image' ] }
|
||||
]);
|
||||
|
||||
config.toolbar = "mini";
|
||||
};
|
||||
|
||||
0
app/assets/javascripts/custom/.keep
Normal file
0
app/assets/javascripts/custom/.keep
Normal file
@@ -1,6 +1,7 @@
|
||||
App.Globalize =
|
||||
|
||||
display_locale: (locale) ->
|
||||
App.Globalize.enable_locale(locale)
|
||||
$(".js-globalize-locale-link").each ->
|
||||
if $(this).data("locale") == locale
|
||||
$(this).show()
|
||||
@@ -22,12 +23,25 @@ App.Globalize =
|
||||
element.addClass('is-active');
|
||||
|
||||
remove_language: (locale) ->
|
||||
$(".js-globalize-attribute[data-locale=" + locale + "]").val('').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"))
|
||||
$("#delete_translations_" + locale).val(1)
|
||||
App.Globalize.disable_locale(locale)
|
||||
|
||||
enable_locale: (locale) ->
|
||||
$("#enabled_translations_" + locale).val(1)
|
||||
|
||||
disable_locale: (locale) ->
|
||||
$("#enabled_translations_" + locale).val(0)
|
||||
|
||||
refresh_visible_translations: ->
|
||||
locale = $('.js-globalize-locale-link.is-active').data("locale")
|
||||
App.Globalize.display_translations(locale)
|
||||
|
||||
initialize: ->
|
||||
$('.js-globalize-locale').on 'change', ->
|
||||
|
||||
@@ -12,3 +12,5 @@ App.LegislationAdmin =
|
||||
else
|
||||
$(this).val("")
|
||||
|
||||
$("#nested-question-options").on "cocoon:after-insert", ->
|
||||
App.Globalize.refresh_visible_translations()
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
App.MarkdownEditor =
|
||||
|
||||
refresh_preview: (element, md) ->
|
||||
textarea_content = element.find('textarea').val()
|
||||
textarea_content = App.MarkdownEditor.find_textarea(element).val()
|
||||
result = md.render(textarea_content)
|
||||
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')
|
||||
|
||||
initialize: ->
|
||||
$('.markdown-editor').each ->
|
||||
md = window.markdownit({
|
||||
@@ -13,18 +18,18 @@ App.MarkdownEditor =
|
||||
typographer: true,
|
||||
})
|
||||
|
||||
App.MarkdownEditor.refresh_preview($(this), md)
|
||||
editor = $(this)
|
||||
|
||||
$(this).on 'change input paste keyup', ->
|
||||
editor.on 'input', ->
|
||||
App.MarkdownEditor.refresh_preview($(this), md)
|
||||
$('.legislation-draft-versions-edit .warning').show()
|
||||
return
|
||||
|
||||
$(this).find('textarea').on 'scroll', ->
|
||||
editor.find('textarea').on 'scroll', ->
|
||||
$('#markdown-preview').scrollTop($(this).scrollTop())
|
||||
|
||||
$(this).find('.fullscreen-toggle').on 'click', ->
|
||||
$('.markdown-editor').toggleClass('fullscreen')
|
||||
editor.find('.fullscreen-toggle').on 'click', ->
|
||||
editor.toggleClass('fullscreen')
|
||||
$('.fullscreen-container').toggleClass('medium-8', 'medium-12')
|
||||
span = $(this).find('span')
|
||||
current_html = span.html()
|
||||
@@ -33,7 +38,8 @@ App.MarkdownEditor =
|
||||
else
|
||||
span.html(span.data('open-text'))
|
||||
|
||||
if $('.markdown-editor').hasClass('fullscreen')
|
||||
$('.markdown-editor textarea').height($(window).height() - 100)
|
||||
if editor.hasClass('fullscreen')
|
||||
App.MarkdownEditor.find_textarea(editor).height($(window).height() - 100)
|
||||
App.MarkdownEditor.refresh_preview(editor, md)
|
||||
else
|
||||
$('.markdown-editor textarea').height("10em")
|
||||
App.MarkdownEditor.find_textarea(editor).height("10em")
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
App.ModeratorBudgetInvestments =
|
||||
|
||||
add_class_faded: (id) ->
|
||||
$("##{id}").addClass("faded")
|
||||
$("#comments").addClass("faded")
|
||||
|
||||
hide_moderator_actions: (id) ->
|
||||
$("##{id} .js-moderator-investment-actions:first").hide()
|
||||
@@ -46,6 +46,10 @@ $sidebar-active: #f4fcd0;
|
||||
|
||||
.top-links {
|
||||
background: #000;
|
||||
|
||||
a {
|
||||
line-height: rem-calc($line-height * 1.5);
|
||||
}
|
||||
}
|
||||
|
||||
.admin-top-bar {
|
||||
@@ -190,6 +194,11 @@ $sidebar-active: #f4fcd0;
|
||||
|
||||
&.with-button {
|
||||
line-height: $line-height * 2;
|
||||
|
||||
.button {
|
||||
background: #fff;
|
||||
color: $brand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +213,19 @@ $sidebar-active: #f4fcd0;
|
||||
|
||||
table {
|
||||
|
||||
thead {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
th {
|
||||
background: $brand;
|
||||
color: #fff;
|
||||
|
||||
label {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.break {
|
||||
word-break: break-word;
|
||||
}
|
||||
@@ -220,7 +242,6 @@ $sidebar-active: #f4fcd0;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
margin-left: $line-height / 2;
|
||||
margin-right: $line-height / 2;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
@@ -335,6 +356,14 @@ $sidebar-active: #f4fcd0;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.enabled {
|
||||
color: $color-success;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: $text-medium;
|
||||
}
|
||||
|
||||
// 02. Sidebar
|
||||
// -----------
|
||||
|
||||
|
||||
@@ -878,11 +878,6 @@ footer {
|
||||
h1 {
|
||||
margin-top: $line-height;
|
||||
|
||||
img {
|
||||
height: rem-calc(80);
|
||||
width: rem-calc(80);
|
||||
}
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
display: block;
|
||||
|
||||
@@ -10,14 +10,24 @@
|
||||
// ----------------------
|
||||
|
||||
.jumbo {
|
||||
background: $highlight;
|
||||
margin-bottom: $line-height;
|
||||
margin-top: rem-calc(-24);
|
||||
padding-bottom: $line-height;
|
||||
padding-top: $line-height;
|
||||
|
||||
@include breakpoint(medium) {
|
||||
padding: rem-calc(24) 0;
|
||||
}
|
||||
|
||||
&.light {
|
||||
background: #ecf0f1;
|
||||
}
|
||||
|
||||
h1,
|
||||
p {
|
||||
color: $text;
|
||||
}
|
||||
}
|
||||
|
||||
.lead {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
// 07. Proposals successful
|
||||
// 08. Polls
|
||||
// 09. Polls results and stats
|
||||
// 10. Guides
|
||||
//
|
||||
|
||||
// 01. Votes and supports
|
||||
@@ -685,7 +684,8 @@
|
||||
}
|
||||
|
||||
.budget-investments-list .budget-investment,
|
||||
.proposals-list .proposal {
|
||||
.proposals-list .proposal,
|
||||
.legislation-proposals .proposal {
|
||||
|
||||
@include breakpoint(medium) {
|
||||
|
||||
@@ -886,6 +886,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
.legislation-proposals {
|
||||
|
||||
.votes {
|
||||
min-height: $line-height * 8;
|
||||
}
|
||||
}
|
||||
|
||||
.proposal-show .votes,
|
||||
.debate-show .votes {
|
||||
border: 0;
|
||||
@@ -2087,94 +2094,3 @@
|
||||
line-height: rem-calc(60);
|
||||
}
|
||||
}
|
||||
|
||||
// 10. Guides
|
||||
// ----------------------
|
||||
|
||||
.guides {
|
||||
|
||||
h2 {
|
||||
margin: $line-height 0 $line-height * 2;
|
||||
}
|
||||
|
||||
.guide-budget,
|
||||
.guide-proposal {
|
||||
border-radius: rem-calc(3);
|
||||
margin: $line-height 0;
|
||||
padding: $line-height;
|
||||
position: relative;
|
||||
|
||||
.button {
|
||||
color: $text;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&::before {
|
||||
border-radius: 100%;
|
||||
color: #fff;
|
||||
font-family: "icons" !important;
|
||||
height: rem-calc(80);
|
||||
left: 50%;
|
||||
line-height: rem-calc(80);
|
||||
margin-left: rem-calc(-40);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: -40px;
|
||||
width: rem-calc(80);
|
||||
z-index: 99;
|
||||
}
|
||||
}
|
||||
|
||||
.guide-budget {
|
||||
border: 1px solid $budget;
|
||||
|
||||
&::before {
|
||||
background: $budget;
|
||||
content: '\53';
|
||||
font-size: rem-calc(40);
|
||||
}
|
||||
|
||||
.button {
|
||||
background: #f8f5f9;
|
||||
border: 1px solid $budget;
|
||||
}
|
||||
}
|
||||
|
||||
.guide-proposal {
|
||||
border: 1px solid $proposals;
|
||||
|
||||
&::before {
|
||||
background: $proposals;
|
||||
content: '\68';
|
||||
font-size: rem-calc(40);
|
||||
}
|
||||
|
||||
.button {
|
||||
background: #fffaf4;
|
||||
border: 1px solid $proposals;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
|
||||
@include breakpoint(medium) {
|
||||
min-height: $line-height * 14;
|
||||
}
|
||||
|
||||
li {
|
||||
margin-bottom: $line-height;
|
||||
padding-left: $line-height;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
color: #37af65;
|
||||
content: '\56';
|
||||
font-family: "icons" !important;
|
||||
font-size: $small-font-size;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Admin::ActivityController < Admin::BaseController
|
||||
has_filters %w{all on_users on_proposals on_debates on_comments}
|
||||
has_filters %w{all on_users on_proposals on_debates on_comments on_system_emails}
|
||||
|
||||
def show
|
||||
@activity = Activity.for_render.send(@current_filter)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class Admin::AdminNotificationsController < Admin::BaseController
|
||||
include Translatable
|
||||
|
||||
def index
|
||||
@admin_notifications = AdminNotification.all
|
||||
@@ -62,6 +63,13 @@ class Admin::AdminNotificationsController < Admin::BaseController
|
||||
private
|
||||
|
||||
def admin_notification_params
|
||||
params.require(:admin_notification).permit(:title, :body, :link, :segment_recipient)
|
||||
attributes = [:title, :body, :link, :segment_recipient,
|
||||
*translation_params(AdminNotification)]
|
||||
|
||||
params.require(:admin_notification).permit(attributes)
|
||||
end
|
||||
|
||||
def resource
|
||||
AdminNotification.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class Admin::BannersController < Admin::BaseController
|
||||
include Translatable
|
||||
|
||||
has_filters %w{all with_active with_inactive}, only: :index
|
||||
|
||||
@@ -40,6 +41,7 @@ class Admin::BannersController < Admin::BaseController
|
||||
attributes = [:title, :description, :target_url,
|
||||
:post_started_at, :post_ended_at,
|
||||
:background_color, :font_color,
|
||||
*translation_params(Banner),
|
||||
web_section_ids: []]
|
||||
params.require(:banner).permit(*attributes)
|
||||
end
|
||||
@@ -59,4 +61,9 @@ class Admin::BannersController < Admin::BaseController
|
||||
def banner_sections
|
||||
@banner_sections = WebSection.all
|
||||
end
|
||||
|
||||
def resource
|
||||
@banner = Banner.find(params[:id]) unless @banner
|
||||
@banner
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,9 +47,10 @@ class Admin::BudgetInvestmentMilestonesController < Admin::BaseController
|
||||
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, translation_params(params[:budget_investment_milestone]))
|
||||
params.require(:budget_investment_milestone).permit(*attributes)
|
||||
end
|
||||
|
||||
def load_budget_investment
|
||||
@@ -64,10 +65,6 @@ class Admin::BudgetInvestmentMilestonesController < Admin::BaseController
|
||||
Budget::Investment::Milestone.find(params[:id])
|
||||
end
|
||||
|
||||
def resource_model
|
||||
Budget::Investment::Milestone
|
||||
end
|
||||
|
||||
def resource
|
||||
get_milestone
|
||||
end
|
||||
|
||||
@@ -75,25 +75,17 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
|
||||
resource_model.parameterize('_')
|
||||
end
|
||||
|
||||
def sort_by(params)
|
||||
if params.present? && Budget::Investment::SORTING_OPTIONS.include?(params)
|
||||
"#{params == 'supports' ? 'cached_votes_up' : params} ASC"
|
||||
else
|
||||
"cached_votes_up DESC, created_at DESC"
|
||||
end
|
||||
end
|
||||
|
||||
def load_investments
|
||||
@investments = Budget::Investment.scoped_filter(params, @current_filter)
|
||||
.order(sort_by(params[:sort_by]))
|
||||
@investments = @investments.order_filter(params[:sort_by]) if params[:sort_by].present?
|
||||
@investments = @investments.page(params[:page]) unless request.format.csv?
|
||||
end
|
||||
|
||||
def budget_investment_params
|
||||
params.require(:budget_investment)
|
||||
.permit(:title, :description, :external_url, :heading_id, :administrator_id, :tag_list,
|
||||
:valuation_tag_list, :incompatible, :visible_to_valuators, :selected, valuator_ids: [],
|
||||
valuator_group_ids: [])
|
||||
:valuation_tag_list, :incompatible, :visible_to_valuators, :selected,
|
||||
valuator_ids: [], valuator_group_ids: [])
|
||||
end
|
||||
|
||||
def load_budget
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
class Admin::HiddenBudgetInvestmentsController < Admin::BaseController
|
||||
include FeatureFlags
|
||||
|
||||
has_filters %w{all with_confirmed_hide without_confirmed_hide}, only: :index
|
||||
|
||||
feature_flag :budgets
|
||||
|
||||
before_action :load_investment, only: [:confirm_hide, :restore]
|
||||
|
||||
def index
|
||||
@investments = Budget::Investment.only_hidden.send(@current_filter)
|
||||
.order(hidden_at: :desc)
|
||||
.page(params[:page])
|
||||
end
|
||||
|
||||
def confirm_hide
|
||||
@investment.confirm_hide
|
||||
redirect_to request.query_parameters.merge(action: :index)
|
||||
end
|
||||
|
||||
def restore
|
||||
@investment.restore
|
||||
@investment.ignore_flag
|
||||
Activity.log(current_user, :restore, @investment)
|
||||
redirect_to request.query_parameters.merge(action: :index)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_investment
|
||||
@investment = Budget::Investment.with_hidden.find(params[:id])
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,6 +1,8 @@
|
||||
class Admin::Legislation::DraftVersionsController < Admin::Legislation::BaseController
|
||||
load_and_authorize_resource :process, class: "Legislation::Process"
|
||||
load_and_authorize_resource :draft_version, class: "Legislation::DraftVersion", through: :process
|
||||
include Translatable
|
||||
|
||||
load_and_authorize_resource :draft_version, class: "Legislation::DraftVersion", through: :process, prepend: true
|
||||
load_and_authorize_resource :process, class: "Legislation::Process", prepend: true
|
||||
|
||||
def index
|
||||
@draft_versions = @process.draft_versions
|
||||
@@ -44,7 +46,12 @@ class Admin::Legislation::DraftVersionsController < Admin::Legislation::BaseCont
|
||||
:status,
|
||||
:final_version,
|
||||
:body,
|
||||
:body_html
|
||||
:body_html,
|
||||
*translation_params(Legislation::DraftVersion)
|
||||
)
|
||||
end
|
||||
|
||||
def resource
|
||||
@draft_version
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class Admin::Legislation::ProcessesController < Admin::Legislation::BaseController
|
||||
include Translatable
|
||||
|
||||
has_filters %w{open next past all}, only: :index
|
||||
|
||||
load_and_authorize_resource :process, class: "Legislation::Process"
|
||||
@@ -61,6 +63,7 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseControll
|
||||
:result_publication_enabled,
|
||||
:published,
|
||||
:custom_list,
|
||||
*translation_params(Legislation::Process),
|
||||
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
|
||||
)
|
||||
end
|
||||
@@ -69,4 +72,8 @@ class Admin::Legislation::ProcessesController < Admin::Legislation::BaseControll
|
||||
@process.set_tag_list_on(:customs, process_params[:custom_list])
|
||||
@process.save
|
||||
end
|
||||
|
||||
def resource
|
||||
@process || Legislation::Process.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
class Admin::Legislation::ProposalsController < Admin::Legislation::BaseController
|
||||
|
||||
has_orders %w[id title supports], only: :index
|
||||
|
||||
load_and_authorize_resource :process, class: "Legislation::Process"
|
||||
load_and_authorize_resource :proposal, class: "Legislation::Proposal", through: :process
|
||||
|
||||
def index
|
||||
@proposals = @proposals.send("sort_by_#{@current_order}").page(params[:page])
|
||||
end
|
||||
|
||||
def toggle_selection
|
||||
@proposal.toggle :selected
|
||||
@proposal.save!
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class Admin::Legislation::QuestionsController < Admin::Legislation::BaseController
|
||||
include Translatable
|
||||
|
||||
load_and_authorize_resource :process, class: "Legislation::Process"
|
||||
load_and_authorize_resource :question, class: "Legislation::Question", through: :process
|
||||
|
||||
@@ -46,7 +48,13 @@ class Admin::Legislation::QuestionsController < Admin::Legislation::BaseControll
|
||||
def question_params
|
||||
params.require(:legislation_question).permit(
|
||||
:title,
|
||||
question_options_attributes: [:id, :value, :_destroy]
|
||||
*translation_params(::Legislation::Question),
|
||||
question_options_attributes: [:id, :value,
|
||||
*translation_params(::Legislation::QuestionOption)]
|
||||
)
|
||||
end
|
||||
|
||||
def resource
|
||||
@question || ::Legislation::Question.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,10 +48,7 @@ class Admin::NewslettersController < Admin::BaseController
|
||||
@newsletter = Newsletter.find(params[:id])
|
||||
|
||||
if @newsletter.valid?
|
||||
@newsletter.list_of_recipient_emails.each do |recipient_email|
|
||||
Mailer.newsletter(@newsletter, recipient_email).deliver_later
|
||||
end
|
||||
|
||||
@newsletter.delay.deliver
|
||||
@newsletter.update(sent_at: Time.current)
|
||||
flash[:notice] = t("admin.newsletters.send_success")
|
||||
else
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class Admin::Poll::PollsController < Admin::Poll::BaseController
|
||||
include Translatable
|
||||
load_and_authorize_resource
|
||||
|
||||
before_action :load_search, only: [:search_booths, :search_officers]
|
||||
@@ -63,7 +64,7 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController
|
||||
attributes = [:name, :starts_at, :ends_at, :geozone_restricted, :summary, :description,
|
||||
:results_enabled, :stats_enabled, geozone_ids: [],
|
||||
image_attributes: image_attributes]
|
||||
params.require(:poll).permit(*attributes)
|
||||
params.require(:poll).permit(*attributes, *translation_params(Poll))
|
||||
end
|
||||
|
||||
def search_params
|
||||
@@ -74,4 +75,7 @@ class Admin::Poll::PollsController < Admin::Poll::BaseController
|
||||
@search = search_params[:search]
|
||||
end
|
||||
|
||||
def resource
|
||||
@poll ||= Poll.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
class Admin::Poll::Questions::AnswersController < Admin::Poll::BaseController
|
||||
include Translatable
|
||||
|
||||
before_action :load_answer, only: [:show, :edit, :update, :documents]
|
||||
|
||||
load_and_authorize_resource :question, class: "::Poll::Question"
|
||||
@@ -49,11 +51,15 @@ class Admin::Poll::Questions::AnswersController < Admin::Poll::BaseController
|
||||
def answer_params
|
||||
documents_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
|
||||
attributes = [:title, :description, :question_id, documents_attributes: documents_attributes]
|
||||
params.require(:poll_question_answer).permit(*attributes)
|
||||
params.require(:poll_question_answer).permit(*attributes, *translation_params(Poll::Question::Answer))
|
||||
end
|
||||
|
||||
def load_answer
|
||||
@answer = ::Poll::Question::Answer.find(params[:id] || params[:answer_id])
|
||||
end
|
||||
|
||||
def resource
|
||||
load_answer unless @answer
|
||||
@answer
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class Admin::Poll::QuestionsController < Admin::Poll::BaseController
|
||||
include CommentableActions
|
||||
include Translatable
|
||||
|
||||
load_and_authorize_resource :poll
|
||||
load_and_authorize_resource :question, class: 'Poll::Question'
|
||||
@@ -55,11 +56,15 @@ class Admin::Poll::QuestionsController < Admin::Poll::BaseController
|
||||
private
|
||||
|
||||
def question_params
|
||||
params.require(:poll_question).permit(:poll_id, :title, :question, :proposal_id)
|
||||
attributes = [:poll_id, :title, :question, :proposal_id]
|
||||
params.require(:poll_question).permit(*attributes, *translation_params(Poll::Question))
|
||||
end
|
||||
|
||||
def search_params
|
||||
params.permit(:poll_id, :search)
|
||||
end
|
||||
|
||||
def resource
|
||||
@poll_question ||= Poll::Question.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,9 @@ class Admin::ProposalNotificationsController < Admin::BaseController
|
||||
before_action :load_proposal, only: [:confirm_hide, :restore]
|
||||
|
||||
def index
|
||||
@proposal_notifications = ProposalNotification.only_hidden.send(@current_filter).order(hidden_at: :desc)
|
||||
@proposal_notifications = ProposalNotification.only_hidden
|
||||
.send(@current_filter)
|
||||
.order(hidden_at: :desc)
|
||||
.page(params[:page])
|
||||
end
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class Admin::SignatureSheetsController < Admin::BaseController
|
||||
|
||||
def index
|
||||
@signature_sheets = SignatureSheet.all
|
||||
@signature_sheets = SignatureSheet.all.order(created_at: :desc)
|
||||
end
|
||||
|
||||
def new
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
class Admin::SiteCustomization::InformationTextsController < Admin::SiteCustomization::BaseController
|
||||
include Translatable
|
||||
|
||||
def index
|
||||
fetch_existing_keys
|
||||
append_or_create_keys
|
||||
@content = @content[@tab.to_s]
|
||||
end
|
||||
|
||||
def update
|
||||
content_params.each do |content|
|
||||
values = content[:values].slice(*translation_params(I18nContent))
|
||||
|
||||
unless values.empty?
|
||||
values.each do |key, value|
|
||||
locale = key.split("_").last
|
||||
|
||||
if value == t(content[:id], locale: locale) || value.match(/translation missing/)
|
||||
next
|
||||
else
|
||||
text = I18nContent.find_or_create_by(key: content[:id])
|
||||
Globalize.locale = locale
|
||||
text.update(value: value)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
redirect_to admin_site_customization_information_texts_path,
|
||||
notice: t('flash.actions.update.translation')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resource
|
||||
I18nContent.find(content_params[:id])
|
||||
end
|
||||
|
||||
def content_params
|
||||
params.require(:contents).values
|
||||
end
|
||||
|
||||
def delete_translations
|
||||
languages_to_delete = params[:enabled_translations].select { |_, v| v == '0' }
|
||||
.keys
|
||||
languages_to_delete.each do |locale|
|
||||
I18nContentTranslation.destroy_all(locale: locale)
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_existing_keys
|
||||
@existing_keys = {}
|
||||
@tab = params[:tab] || :debates
|
||||
|
||||
I18nContent.begins_with_key(@tab)
|
||||
.all
|
||||
.map{ |content| @existing_keys[content.key] = content }
|
||||
end
|
||||
|
||||
def append_or_create_keys
|
||||
@content = {}
|
||||
I18n.backend.send(:init_translations) unless I18n.backend.initialized?
|
||||
|
||||
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}"] }
|
||||
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
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,4 +1,5 @@
|
||||
class Admin::SiteCustomization::PagesController < Admin::SiteCustomization::BaseController
|
||||
include Translatable
|
||||
load_and_authorize_resource :page, class: "SiteCustomization::Page"
|
||||
|
||||
def index
|
||||
@@ -34,15 +35,21 @@ class Admin::SiteCustomization::PagesController < Admin::SiteCustomization::Base
|
||||
private
|
||||
|
||||
def page_params
|
||||
params.require(:site_customization_page).permit(
|
||||
:slug,
|
||||
attributes = [:slug,
|
||||
:title,
|
||||
:subtitle,
|
||||
:content,
|
||||
:more_info_flag,
|
||||
:print_content_flag,
|
||||
:status,
|
||||
:locale
|
||||
:locale]
|
||||
|
||||
params.require(:site_customization_page).permit(*attributes,
|
||||
*translation_params(SiteCustomization::Page)
|
||||
)
|
||||
end
|
||||
|
||||
def resource
|
||||
SiteCustomization::Page.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,8 +18,13 @@ class Admin::StatsController < Admin::BaseController
|
||||
@verified_users = User.active.level_two_or_three_verified.count
|
||||
@unverified_users = User.active.unverified.count
|
||||
@users = User.active.count
|
||||
@user_ids_who_voted_proposals = ActsAsVotable::Vote.where(votable_type: 'Proposal').distinct.count(:voter_id)
|
||||
|
||||
@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 = budgets_ids.size
|
||||
|
||||
50
app/controllers/admin/system_emails_controller.rb
Normal file
50
app/controllers/admin/system_emails_controller.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
class Admin::SystemEmailsController < Admin::BaseController
|
||||
|
||||
before_action :load_system_email, only: [:view, :preview_pending, :moderate_pending]
|
||||
|
||||
def index
|
||||
@system_emails = {
|
||||
proposal_notification_digest: %w(view preview_pending)
|
||||
}
|
||||
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'])
|
||||
end
|
||||
end
|
||||
|
||||
def preview_pending
|
||||
case @system_email
|
||||
when "proposal_notification_digest"
|
||||
@previews = ProposalNotification.where(id: unsent_proposal_notifications_ids)
|
||||
.page(params[:page])
|
||||
end
|
||||
end
|
||||
|
||||
def moderate_pending
|
||||
ProposalNotification.find(params[:id]).moderate_system_email(current_user)
|
||||
|
||||
redirect_to admin_system_email_preview_pending_path("proposal_notification_digest")
|
||||
end
|
||||
|
||||
def send_pending
|
||||
Notification.delay.send_pending
|
||||
|
||||
flash[:notice] = t("admin.system_emails.preview_pending.send_pending_notification")
|
||||
redirect_to admin_system_emails_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
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
|
||||
end
|
||||
@@ -5,7 +5,9 @@ class Admin::VerificationsController < Admin::BaseController
|
||||
end
|
||||
|
||||
def search
|
||||
@users = User.incomplete_verification.search(params[:name_or_email]).page(params[:page]).for_render
|
||||
@users = User.incomplete_verification.search(params[:name_or_email])
|
||||
.page(params[:page])
|
||||
.for_render
|
||||
render :index
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class Admin::Widget::CardsController < Admin::BaseController
|
||||
include Translatable
|
||||
|
||||
def new
|
||||
@card = ::Widget::Card.new(header: header_card?)
|
||||
@@ -39,13 +40,21 @@ class Admin::Widget::CardsController < Admin::BaseController
|
||||
private
|
||||
|
||||
def card_params
|
||||
params.require(:widget_card).permit(:label, :title, :description, :link_text, :link_url,
|
||||
image_attributes = [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy]
|
||||
|
||||
params.require(:widget_card).permit(
|
||||
:label, :title, :description, :link_text, :link_url,
|
||||
:button_text, :button_url, :alignment, :header,
|
||||
image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy])
|
||||
*translation_params(Widget::Card),
|
||||
image_attributes: image_attributes
|
||||
)
|
||||
end
|
||||
|
||||
def header_card?
|
||||
params[:header_card].present?
|
||||
end
|
||||
|
||||
def resource
|
||||
Widget::Card.find(params[:id])
|
||||
end
|
||||
end
|
||||
@@ -3,18 +3,32 @@ module FlagActions
|
||||
|
||||
def flag
|
||||
Flag.flag(current_user, flaggable)
|
||||
|
||||
if controller_name == 'investments'
|
||||
respond_with flaggable, template: "budgets/#{controller_name}/_refresh_flag_actions"
|
||||
else
|
||||
respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
|
||||
end
|
||||
end
|
||||
|
||||
def unflag
|
||||
Flag.unflag(current_user, flaggable)
|
||||
|
||||
if controller_name == 'investments'
|
||||
respond_with flaggable, template: "budgets/#{controller_name}/_refresh_flag_actions"
|
||||
else
|
||||
respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def flaggable
|
||||
if resource_model.to_s == 'Budget::Investment'
|
||||
instance_variable_get("@investment")
|
||||
else
|
||||
instance_variable_get("@#{resource_model.to_s.downcase}")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -3,8 +3,12 @@ module Polymorphic
|
||||
private
|
||||
|
||||
def resource
|
||||
if resource_model.to_s == 'Budget::Investment'
|
||||
@resource ||= instance_variable_get("@investment")
|
||||
else
|
||||
@resource ||= instance_variable_get("@#{resource_name}")
|
||||
end
|
||||
end
|
||||
|
||||
def resource_name
|
||||
@resource_name ||= resource_model.to_s.downcase
|
||||
|
||||
@@ -7,13 +7,18 @@ module Translatable
|
||||
|
||||
private
|
||||
|
||||
def translation_params(params)
|
||||
resource_model.globalize_attribute_names.select { |k, v| params.include?(k.to_sym) && params[k].present? }
|
||||
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_model.globalize_locales.
|
||||
select { |k, v| params[:delete_translations].include?(k.to_sym) && params[:delete_translations][k] == "1" }
|
||||
locales = resource.translated_locales
|
||||
.select { |l| params.dig(:enabled_translations, l) == "0" }
|
||||
|
||||
locales.each do |l|
|
||||
Globalize.with_locale(l) do
|
||||
resource.translation.destroy
|
||||
@@ -21,4 +26,9 @@ module Translatable
|
||||
end
|
||||
end
|
||||
|
||||
def enabled_translations
|
||||
params.fetch(:enabled_translations, {})
|
||||
.select { |_, v| v == '1' }
|
||||
.keys
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
class GuidesController < ApplicationController
|
||||
|
||||
skip_authorization_check
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,7 +1,11 @@
|
||||
class Legislation::ProcessesController < Legislation::BaseController
|
||||
has_filters %w{open next past}, only: :index
|
||||
has_filters %w[open next past], only: :index
|
||||
has_filters %w[random winners], only: :proposals
|
||||
|
||||
load_and_authorize_resource
|
||||
|
||||
before_action :set_random_seed, only: :proposals
|
||||
|
||||
def index
|
||||
@current_filter ||= 'open'
|
||||
@processes = ::Legislation::Process.send(@current_filter).published.page(params[:page])
|
||||
@@ -25,7 +29,7 @@ class Legislation::ProcessesController < Legislation::BaseController
|
||||
set_process
|
||||
@phase = :debate_phase
|
||||
|
||||
if @process.debate_phase.started?
|
||||
if @process.debate_phase.started? || (current_user && current_user.administrator?)
|
||||
render :debate
|
||||
else
|
||||
render :phase_not_open
|
||||
@@ -87,8 +91,14 @@ class Legislation::ProcessesController < Legislation::BaseController
|
||||
set_process
|
||||
@phase = :proposals_phase
|
||||
|
||||
if @process.proposals_phase.started?
|
||||
legislation_proposal_votes(@process.proposals)
|
||||
@proposals = ::Legislation::Proposal.where(process: @process)
|
||||
@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 @process.proposals_phase.started? || (current_user && current_user.administrator?)
|
||||
legislation_proposal_votes(@proposals)
|
||||
render :proposals
|
||||
else
|
||||
render :phase_not_open
|
||||
@@ -105,4 +115,15 @@ 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
|
||||
|
||||
@@ -2,13 +2,13 @@ class Legislation::ProposalsController < Legislation::BaseController
|
||||
include CommentableActions
|
||||
include FlagActions
|
||||
|
||||
load_and_authorize_resource :process, class: "Legislation::Process"
|
||||
load_and_authorize_resource :proposal, class: "Legislation::Proposal", through: :process
|
||||
|
||||
before_action :parse_tag_filter, only: :index
|
||||
before_action :load_categories, only: [:index, :new, :create, :edit, :map, :summary]
|
||||
before_action :load_geozones, only: [:edit, :map, :summary]
|
||||
|
||||
before_action :authenticate_user!, except: [:index, :show, :map, :summary]
|
||||
load_and_authorize_resource :process, class: "Legislation::Process"
|
||||
load_and_authorize_resource :proposal, class: "Legislation::Proposal", through: :process
|
||||
|
||||
invisible_captcha only: [:create, :update], honeypot: :subtitle
|
||||
|
||||
@@ -54,6 +54,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],
|
||||
documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id])
|
||||
end
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ class Management::BaseController < ActionController::Base
|
||||
|
||||
helper_method :managed_user
|
||||
helper_method :current_user
|
||||
helper_method :manager_logged_in
|
||||
|
||||
private
|
||||
|
||||
@@ -22,7 +23,10 @@ class Management::BaseController < ActionController::Base
|
||||
end
|
||||
|
||||
def managed_user
|
||||
@managed_user ||= Verification::Management::ManagedUser.find(session[:document_type], session[:document_number])
|
||||
@managed_user ||= Verification::Management::ManagedUser.find(
|
||||
session[:document_type],
|
||||
session[:document_number]
|
||||
)
|
||||
end
|
||||
|
||||
def check_verified_user(alert_msg)
|
||||
@@ -49,4 +53,11 @@ class Management::BaseController < ActionController::Base
|
||||
def clear_password
|
||||
session[:new_password] = nil
|
||||
end
|
||||
|
||||
def manager_logged_in
|
||||
if current_manager
|
||||
@manager_logged_in = User.find_by_manager_login(session[:manager]["login"])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
24
app/controllers/moderation/budgets/investments_controller.rb
Normal file
24
app/controllers/moderation/budgets/investments_controller.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
class Moderation::Budgets::InvestmentsController < Moderation::BaseController
|
||||
include FeatureFlags
|
||||
include ModerateActions
|
||||
|
||||
has_filters %w{pending_flag_review all with_ignored_flag}, only: :index
|
||||
has_orders %w{flags created_at}, only: :index
|
||||
|
||||
feature_flag :budgets
|
||||
|
||||
before_action :load_resources, only: [:index, :moderate]
|
||||
|
||||
load_and_authorize_resource class: 'Budget::Investment'
|
||||
|
||||
private
|
||||
|
||||
def resource_name
|
||||
'budget_investment'
|
||||
end
|
||||
|
||||
def resource_model
|
||||
Budget::Investment
|
||||
end
|
||||
|
||||
end
|
||||
@@ -36,19 +36,11 @@ class NotificationsController < ApplicationController
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def linkable_resource_path(notification)
|
||||
case notification.linkable_resource.class.name
|
||||
when "Budget::Investment"
|
||||
budget_investment_path @notification.linkable_resource.budget, @notification.linkable_resource
|
||||
when "Topic"
|
||||
community_topic_path @notification.linkable_resource.community, @notification.linkable_resource
|
||||
if notification.linkable_resource.is_a?(AdminNotification)
|
||||
notification.linkable_resource.link || notifications_path
|
||||
else
|
||||
if @notification.linkable_resource.is_a?(AdminNotification)
|
||||
@notification.linkable_resource.link || notifications_path
|
||||
else
|
||||
url_for @notification.linkable_resource
|
||||
end
|
||||
polymorphic_hierarchy_path(notification.linkable_resource)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
class PagesController < ApplicationController
|
||||
include FeatureFlags
|
||||
skip_authorization_check
|
||||
|
||||
feature_flag :help_page, if: lambda { params[:id] == "help/index" }
|
||||
|
||||
def show
|
||||
@custom_page = SiteCustomization::Page.published.find_by(slug: params[:id])
|
||||
@banners = Banner.in_section('help_page').with_active
|
||||
|
||||
@@ -14,6 +14,7 @@ class StatsController < ApplicationController
|
||||
@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 }
|
||||
|
||||
@@ -11,7 +11,7 @@ class Users::SessionsController < Devise::SessionsController
|
||||
end
|
||||
|
||||
def after_sign_out_path_for(resource)
|
||||
request.referer.present? ? request.referer : super
|
||||
request.referer.present? && !request.referer.match("management") ? request.referer : super
|
||||
end
|
||||
|
||||
def verifying_via_email?
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module AdminBudgetInvestmentsHelper
|
||||
|
||||
def advanced_menu_visibility
|
||||
(params[:advanced_filters].empty? && params["max_per_heading"].blank?) ? 'hide' : ''
|
||||
(params[:advanced_filters].empty? && params["min_total_supports"].blank?) ? 'hide' : ''
|
||||
end
|
||||
|
||||
def init_advanced_menu
|
||||
|
||||
@@ -1,19 +1,31 @@
|
||||
module AdminHelper
|
||||
|
||||
def side_menu
|
||||
if namespace == 'moderation/budgets'
|
||||
render "/moderation/menu"
|
||||
else
|
||||
render "/#{namespace}/menu"
|
||||
end
|
||||
end
|
||||
|
||||
def namespaced_root_path
|
||||
if namespace == 'moderation/budgets'
|
||||
"/moderation"
|
||||
else
|
||||
"/#{namespace}"
|
||||
end
|
||||
end
|
||||
|
||||
def namespaced_header_title
|
||||
if namespace == 'moderation/budgets'
|
||||
t("moderation.header.title")
|
||||
else
|
||||
t("#{namespace}.header.title")
|
||||
end
|
||||
end
|
||||
|
||||
def menu_moderated_content?
|
||||
["proposals", "debates", "comments", "hidden_users", "activity"].include?(controller_name) && controller.class.parent != Admin::Legislation
|
||||
["proposals", "debates", "comments", "hidden_users", "activity", "hidden_budget_investments"].include?(controller_name) && controller.class.parent != Admin::Legislation
|
||||
end
|
||||
|
||||
def menu_budget?
|
||||
@@ -21,11 +33,11 @@ module AdminHelper
|
||||
end
|
||||
|
||||
def menu_polls?
|
||||
%w[polls questions answers].include?(controller_name)
|
||||
%w[polls questions answers recounts results].include?(controller_name)
|
||||
end
|
||||
|
||||
def menu_booths?
|
||||
%w[officers booths officer_assignments booth_assignments recounts results shifts].include?(controller_name)
|
||||
%w[officers booths shifts booth_assignments officer_assignments].include?(controller_name)
|
||||
end
|
||||
|
||||
def menu_profiles?
|
||||
@@ -37,7 +49,7 @@ module AdminHelper
|
||||
end
|
||||
|
||||
def menu_customization?
|
||||
["pages", "banners"].include?(controller_name) || menu_homepage?
|
||||
["pages", "banners", "information_texts"].include?(controller_name) || menu_homepage?
|
||||
end
|
||||
|
||||
def menu_homepage?
|
||||
|
||||
@@ -41,22 +41,7 @@ module CommentsHelper
|
||||
end
|
||||
|
||||
def commentable_path(comment)
|
||||
commentable = comment.commentable
|
||||
|
||||
case comment.commentable_type
|
||||
when "Budget::Investment"
|
||||
budget_investment_path(commentable.budget_id, commentable)
|
||||
when "Legislation::Question"
|
||||
legislation_process_question_path(commentable.process, commentable)
|
||||
when "Legislation::Annotation"
|
||||
legislation_process_draft_version_annotation_path(commentable.draft_version.process, commentable.draft_version, commentable)
|
||||
when "Topic"
|
||||
community_topic_path(commentable.community, commentable)
|
||||
when "Legislation::Proposal"
|
||||
legislation_process_proposal_path(commentable.legislation_process_id, commentable)
|
||||
else
|
||||
commentable
|
||||
end
|
||||
polymorphic_hierarchy_path(comment.commentable)
|
||||
end
|
||||
|
||||
def user_level_class(comment)
|
||||
|
||||
@@ -6,16 +6,24 @@ module GlobalizeHelper
|
||||
|
||||
def locale_options
|
||||
I18n.available_locales.map do |locale|
|
||||
[name_for_locale(locale), neutral_locale(locale)]
|
||||
[name_for_locale(locale), locale]
|
||||
end
|
||||
end
|
||||
|
||||
def display_translation?(locale)
|
||||
same_locale?(neutral_locale(I18n.locale), neutral_locale(locale)) ? "" : "display: none"
|
||||
same_locale?(I18n.locale, locale) ? "" : "display: none;"
|
||||
end
|
||||
|
||||
def translation_enabled_tag(locale, enabled)
|
||||
hidden_field_tag("enabled_translations[#{locale}]", (enabled ? 1 : 0))
|
||||
end
|
||||
|
||||
def css_to_display_translation?(resource, locale)
|
||||
resource.translated_locales.include?(neutral_locale(locale)) || locale == I18n.locale ? "" : "display: none"
|
||||
enable_locale?(resource, locale) ? "" : "display: none;"
|
||||
end
|
||||
|
||||
def enable_locale?(resource, locale)
|
||||
resource.translated_locales.include?(locale) || locale == I18n.locale
|
||||
end
|
||||
|
||||
def highlight_current?(locale)
|
||||
@@ -26,10 +34,6 @@ module GlobalizeHelper
|
||||
display_translation?(locale)
|
||||
end
|
||||
|
||||
def neutral_locale(locale)
|
||||
locale.to_s.downcase.underscore.to_sym
|
||||
end
|
||||
|
||||
def globalize(locale, &block)
|
||||
Globalize.with_locale(locale) do
|
||||
yield
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
module GuidesHelper
|
||||
|
||||
def new_proposal_guide
|
||||
if feature?('guides') && Budget.current&.accepting?
|
||||
new_guide_path
|
||||
else
|
||||
new_proposal_path
|
||||
end
|
||||
end
|
||||
|
||||
def new_budget_investment_guide
|
||||
if feature?('guides')
|
||||
new_guide_path
|
||||
else
|
||||
new_budget_investment_path(current_budget)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -6,4 +6,24 @@ module LegislationHelper
|
||||
def format_date_for_calendar_form(date)
|
||||
l(date, format: "%d/%m/%Y") if date
|
||||
end
|
||||
|
||||
def new_legislation_proposal_link_text(process)
|
||||
t("proposals.index.start_proposal")
|
||||
end
|
||||
|
||||
def link_to_toggle_legislation_proposal_selection(proposal)
|
||||
if proposal.selected?
|
||||
button_text = t("admin.legislation.proposals.index.selected")
|
||||
html_class = 'button expanded'
|
||||
else
|
||||
button_text = t("admin.legislation.proposals.index.select")
|
||||
html_class = 'button hollow expanded'
|
||||
end
|
||||
|
||||
link_to button_text,
|
||||
toggle_selection_admin_legislation_process_proposal_path(proposal.process, proposal),
|
||||
remote: true,
|
||||
method: :patch,
|
||||
class: html_class
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
module LocalesHelper
|
||||
|
||||
def name_for_locale(locale)
|
||||
default = I18n.t("locale", locale: locale)
|
||||
I18n.backend.translate(locale, "i18n.language.name", default: default)
|
||||
rescue
|
||||
nil
|
||||
I18n.t("i18n.language.name", locale: locale, fallback: false, default: locale.to_s)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -46,7 +46,7 @@ module PollsHelper
|
||||
end
|
||||
|
||||
def voted_before_sign_in(question)
|
||||
question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at >= vote.updated_at }
|
||||
question.answers.where(author: current_user).any? { |vote| current_user.current_sign_in_at > vote.updated_at }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
9
app/helpers/site_customization_helper.rb
Normal file
9
app/helpers/site_customization_helper.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
module SiteCustomizationHelper
|
||||
def site_customization_enable_translation?(locale)
|
||||
I18nContentTranslation.existing_languages.include?(locale) || locale == I18n.locale
|
||||
end
|
||||
|
||||
def site_customization_display_translation?(locale)
|
||||
site_customization_enable_translation?(locale) ? "" : "display: none;"
|
||||
end
|
||||
end
|
||||
67
app/helpers/translatable_form_helper.rb
Normal file
67
app/helpers/translatable_form_helper.rb
Normal file
@@ -0,0 +1,67 @@
|
||||
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
|
||||
|
||||
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)
|
||||
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)
|
||||
|
||||
label_without_locale = @object.class.human_attribute_name(method)
|
||||
final_options = @template.merge_translatable_field_options(options, locale)
|
||||
.reverse_merge(label: label_without_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
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -52,8 +52,8 @@ module UsersHelper
|
||||
current_user && current_user.manager?
|
||||
end
|
||||
|
||||
def show_admin_menu?
|
||||
current_administrator? || current_moderator? || current_valuator? || current_manager?
|
||||
def show_admin_menu?(user = nil)
|
||||
current_administrator? || current_moderator? || current_valuator? || current_manager? || (user && user.administrator?)
|
||||
end
|
||||
|
||||
def interests_title_text(user)
|
||||
|
||||
@@ -14,9 +14,16 @@ module Abilities
|
||||
can :restore, Proposal
|
||||
cannot :restore, Proposal, hidden_at: nil
|
||||
|
||||
can :create, Legislation::Proposal
|
||||
can :show, Legislation::Proposal
|
||||
can :proposals, ::Legislation::Process
|
||||
|
||||
can :restore, Legislation::Proposal
|
||||
cannot :restore, Legislation::Proposal, hidden_at: nil
|
||||
|
||||
can :restore, Budget::Investment
|
||||
cannot :restore, Budget::Investment, hidden_at: nil
|
||||
|
||||
can :restore, User
|
||||
cannot :restore, User, hidden_at: nil
|
||||
|
||||
@@ -32,6 +39,9 @@ module Abilities
|
||||
can :confirm_hide, Legislation::Proposal
|
||||
cannot :confirm_hide, Legislation::Proposal, hidden_at: nil
|
||||
|
||||
can :confirm_hide, Budget::Investment
|
||||
cannot :confirm_hide, Budget::Investment, hidden_at: nil
|
||||
|
||||
can :confirm_hide, User
|
||||
cannot :confirm_hide, User, hidden_at: nil
|
||||
|
||||
@@ -51,8 +61,7 @@ module Abilities
|
||||
can :manage, Dashboard::Action
|
||||
|
||||
can [:read, :update, :valuate, :destroy, :summary], SpendingProposal
|
||||
|
||||
can [:index, :read, :new, :create, :update, :destroy, :calculate_winners, :read_results], Budget
|
||||
can [:index, :read, :new, :create, :update, :destroy, :calculate_winners], Budget
|
||||
can [:read, :create, :update, :destroy], Budget::Group
|
||||
can [:read, :create, :update, :destroy], Budget::Heading
|
||||
can [:hide, :update, :toggle_selection], Budget::Investment
|
||||
@@ -75,6 +84,9 @@ module Abilities
|
||||
can :manage, SiteCustomization::Image
|
||||
can :manage, SiteCustomization::ContentBlock
|
||||
|
||||
can :access, :ckeditor
|
||||
can :manage, Ckeditor::Picture
|
||||
|
||||
can [:manage], ::Legislation::Process
|
||||
can [:manage], ::Legislation::DraftVersion
|
||||
can [:manage], ::Legislation::Question
|
||||
|
||||
@@ -66,6 +66,9 @@ module Abilities
|
||||
can [:flag, :unflag], Legislation::Proposal
|
||||
cannot [:flag, :unflag], Legislation::Proposal, author_id: user.id
|
||||
|
||||
can [:flag, :unflag], Budget::Investment
|
||||
cannot [:flag, :unflag], Budget::Investment, author_id: user.id
|
||||
|
||||
can [:create, :destroy], Follow
|
||||
|
||||
can [:destroy], Document do |document|
|
||||
|
||||
@@ -63,6 +63,15 @@ module Abilities
|
||||
cannot :moderate, ProposalNotification, author_id: user.id
|
||||
|
||||
can :index, ProposalNotification
|
||||
|
||||
can :hide, Budget::Investment, hidden_at: nil
|
||||
cannot :hide, Budget::Investment, author_id: user.id
|
||||
|
||||
can :ignore_flag, Budget::Investment, ignored_flag_at: nil, hidden_at: nil
|
||||
cannot :ignore_flag, Budget::Investment, author_id: user.id
|
||||
|
||||
can :moderate, Budget::Investment
|
||||
cannot :moderate, Budget::Investment, author_id: user.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ class Activity < ActiveRecord::Base
|
||||
belongs_to :actionable, -> { with_hidden }, polymorphic: true
|
||||
belongs_to :user, -> { with_hidden }
|
||||
|
||||
VALID_ACTIONS = %w(hide block restore valuate)
|
||||
VALID_ACTIONS = %w(hide block restore valuate email)
|
||||
|
||||
validates :action, inclusion: {in: VALID_ACTIONS}
|
||||
|
||||
@@ -11,6 +11,7 @@ class Activity < ActiveRecord::Base
|
||||
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)
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
class AdminNotification < ActiveRecord::Base
|
||||
include Notifiable
|
||||
|
||||
translates :title, touch: true
|
||||
translates :body, touch: true
|
||||
globalize_accessors
|
||||
|
||||
validates :title, presence: true
|
||||
validates :body, presence: true
|
||||
validates :segment_recipient, presence: true
|
||||
|
||||
@@ -3,6 +3,10 @@ class Banner < ActiveRecord::Base
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
translates :title, touch: true
|
||||
translates :description, touch: true
|
||||
globalize_accessors
|
||||
|
||||
validates :title, presence: true,
|
||||
length: { minimum: 2 }
|
||||
validates :description, presence: true
|
||||
|
||||
@@ -23,6 +23,7 @@ class Budget
|
||||
include Relationable
|
||||
include Notifiable
|
||||
include Filterable
|
||||
include Flaggable
|
||||
|
||||
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
|
||||
belongs_to :heading
|
||||
@@ -57,6 +58,10 @@ class Budget
|
||||
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") }
|
||||
scope :sort_by_supports, -> { order("cached_votes_up DESC") }
|
||||
|
||||
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) }
|
||||
@@ -77,6 +82,8 @@ class Budget
|
||||
scope :winners, -> { selected.compatible.where(winner: true) }
|
||||
scope :unselected, -> { not_unfeasible.where(selected: false) }
|
||||
scope :last_week, -> { where("created_at >= ?", 7.days.ago)}
|
||||
scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
|
||||
scope :sort_by_created_at, -> { reorder(created_at: :desc) }
|
||||
|
||||
scope :by_budget, ->(budget) { where(budget: budget) }
|
||||
scope :by_group, ->(group_id) { where(group_id: group_id) }
|
||||
@@ -109,7 +116,8 @@ class Budget
|
||||
budget = Budget.find_by(slug: params[:budget_id]) || Budget.find_by(id: params[:budget_id])
|
||||
results = Investment.by_budget(budget)
|
||||
|
||||
results = limit_results(budget, params, results) if params[:max_per_heading].present?
|
||||
results = results.where("cached_votes_up + physical_votes >= ?",
|
||||
params[:min_total_supports]) if params[:min_total_supports].present?
|
||||
results = results.where(group_id: params[:group_id]) if params[:group_id].present?
|
||||
results = results.by_tag(params[:tag_name]) if params[:tag_name].present?
|
||||
results = results.by_heading(params[:heading_id]) if params[:heading_id].present?
|
||||
@@ -132,6 +140,12 @@ class Budget
|
||||
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}")
|
||||
end
|
||||
end
|
||||
|
||||
def self.limit_results(budget, params, results)
|
||||
max_per_heading = params[:max_per_heading].to_i
|
||||
return results if max_per_heading <= 0
|
||||
|
||||
@@ -8,7 +8,7 @@ class Budget
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
|
||||
translates :title, :description, touch: true
|
||||
globalize_accessors locales: [:en, :es, :fr, :nl, :val, :pt_br]
|
||||
globalize_accessors
|
||||
|
||||
belongs_to :investment
|
||||
belongs_to :status, class_name: 'Budget::Investment::Status'
|
||||
|
||||
4
app/models/ckeditor/asset.rb
Normal file
4
app/models/ckeditor/asset.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
class Ckeditor::Asset < ActiveRecord::Base
|
||||
include Ckeditor::Orm::ActiveRecord::AssetBase
|
||||
include Ckeditor::Backend::Paperclip
|
||||
end
|
||||
14
app/models/ckeditor/picture.rb
Normal file
14
app/models/ckeditor/picture.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
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#' }
|
||||
|
||||
validates_attachment_presence :data
|
||||
validates_attachment_size :data, less_than: 2.megabytes
|
||||
validates_attachment_content_type :data, content_type: /\Aimage/
|
||||
|
||||
def url_content
|
||||
url(:content)
|
||||
end
|
||||
end
|
||||
11
app/models/i18n_content.rb
Normal file
11
app/models/i18n_content.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class I18nContent < ActiveRecord::Base
|
||||
|
||||
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]
|
||||
|
||||
end
|
||||
5
app/models/i18n_content_translation.rb
Normal file
5
app/models/i18n_content_translation.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class I18nContentTranslation < ActiveRecord::Base
|
||||
def self.existing_languages
|
||||
self.select(:locale).uniq.map{ |l| l.locale.to_sym }.to_a
|
||||
end
|
||||
end
|
||||
@@ -2,7 +2,7 @@ class Image < ActiveRecord::Base
|
||||
include ImagesHelper
|
||||
include ImageablesHelper
|
||||
|
||||
TITLE_LEGHT_RANGE = 4..80
|
||||
TITLE_LENGTH_RANGE = 4..80
|
||||
MIN_SIZE = 475
|
||||
MAX_IMAGE_SIZE = 1.megabyte
|
||||
ACCEPTED_CONTENT_TYPE = %w(image/jpeg image/jpg).freeze
|
||||
@@ -23,7 +23,7 @@ class Image < ActiveRecord::Base
|
||||
validate :attachment_presence
|
||||
validate :validate_attachment_content_type, if: -> { attachment.present? }
|
||||
validate :validate_attachment_size, if: -> { attachment.present? }
|
||||
validates :title, presence: true, length: { in: TITLE_LEGHT_RANGE }
|
||||
validates :title, presence: true, length: { in: TITLE_LENGTH_RANGE }
|
||||
validates :user_id, presence: true
|
||||
validates :imageable_id, presence: true, if: -> { persisted? }
|
||||
validates :imageable_type, presence: true, if: -> { persisted? }
|
||||
|
||||
@@ -4,6 +4,13 @@ class Legislation::DraftVersion < ActiveRecord::Base
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
translates :title, touch: true
|
||||
translates :changelog, touch: true
|
||||
translates :body, touch: true
|
||||
translates :body_html, touch: true
|
||||
translates :toc_html, touch: true
|
||||
globalize_accessors
|
||||
|
||||
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
|
||||
|
||||
@@ -19,10 +26,19 @@ class Legislation::DraftVersion < ActiveRecord::Base
|
||||
renderer = Redcarpet::Render::HTML.new(with_toc_data: true)
|
||||
toc_renderer = Redcarpet::Render::HTML_TOC.new(with_toc_data: true)
|
||||
|
||||
if body_changed?
|
||||
self.body_html = Redcarpet::Markdown.new(renderer).render(body)
|
||||
self.toc_html = Redcarpet::Markdown.new(toc_renderer).render(body)
|
||||
end
|
||||
|
||||
translations.each do |translation|
|
||||
if translation.body_changed?
|
||||
translation.body_html = Redcarpet::Markdown.new(renderer).render(translation.body)
|
||||
translation.toc_html = Redcarpet::Markdown.new(toc_renderer).render(translation.body)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def display_title
|
||||
status == 'draft' ? "#{title} *" : title
|
||||
end
|
||||
|
||||
@@ -9,6 +9,12 @@ 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
|
||||
|
||||
PHASES_AND_PUBLICATIONS = %i(debate_phase allegations_phase proposals_phase draft_publication result_publication).freeze
|
||||
|
||||
has_many :draft_versions, -> { order(:id) }, class_name: 'Legislation::DraftVersion',
|
||||
|
||||
@@ -11,6 +11,7 @@ class Legislation::Proposal < ActiveRecord::Base
|
||||
include Communitable
|
||||
include Documentable
|
||||
include Notifiable
|
||||
include Imageable
|
||||
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
@@ -44,9 +45,15 @@ class Legislation::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_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_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
|
||||
"#{id}-#{title}".parameterize
|
||||
|
||||
@@ -3,6 +3,9 @@ class Legislation::Question < ActiveRecord::Base
|
||||
include ActsAsParanoidAliases
|
||||
include Notifiable
|
||||
|
||||
translates :title, touch: true
|
||||
globalize_accessors
|
||||
|
||||
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
|
||||
belongs_to :process, class_name: 'Legislation::Process', foreign_key: 'legislation_process_id'
|
||||
|
||||
@@ -11,7 +14,7 @@ class Legislation::Question < ActiveRecord::Base
|
||||
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[:value].blank? }, allow_destroy: true
|
||||
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
|
||||
|
||||
@@ -2,6 +2,9 @@ class Legislation::QuestionOption < ActiveRecord::Base
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
translates :value, touch: true
|
||||
globalize_accessors
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ class Newsletter < ActiveRecord::Base
|
||||
|
||||
validates_format_of :from, :with => /@/
|
||||
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
def list_of_recipient_emails
|
||||
UserSegments.user_segment_emails(segment_recipient) if valid_segment_recipient?
|
||||
end
|
||||
@@ -20,9 +23,47 @@ class Newsletter < ActiveRecord::Base
|
||||
sent_at.nil?
|
||||
end
|
||||
|
||||
def deliver
|
||||
run_at = first_batch_run_at
|
||||
list_of_recipient_emails_in_batches.each do |recipient_emails|
|
||||
recipient_emails.each do |recipient_email|
|
||||
if valid_email?(recipient_email)
|
||||
Mailer.delay(run_at: run_at).newsletter(self, recipient_email)
|
||||
log_delivery(recipient_email)
|
||||
end
|
||||
end
|
||||
run_at += batch_interval
|
||||
end
|
||||
end
|
||||
|
||||
def batch_size
|
||||
10000
|
||||
end
|
||||
|
||||
def batch_interval
|
||||
20.minutes
|
||||
end
|
||||
|
||||
def first_batch_run_at
|
||||
Time.current
|
||||
end
|
||||
|
||||
def list_of_recipient_emails_in_batches
|
||||
list_of_recipient_emails.in_groups_of(batch_size, false)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_segment_recipient
|
||||
errors.add(:segment_recipient, :invalid) unless valid_segment_recipient?
|
||||
end
|
||||
|
||||
def valid_email?(email)
|
||||
email.match(/\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i)
|
||||
end
|
||||
|
||||
def log_delivery(recipient_email)
|
||||
user = User.where(email: recipient_email).first
|
||||
Activity.log(user, :email, self)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -68,4 +68,29 @@ class Notification < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def self.send_pending
|
||||
run_at = first_batch_run_at
|
||||
User.email_digest.find_in_batches(batch_size: batch_size) do |users|
|
||||
users.each do |user|
|
||||
email_digest = EmailDigest.new(user)
|
||||
email_digest.deliver(run_at)
|
||||
end
|
||||
run_at += batch_interval
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.batch_size
|
||||
10000
|
||||
end
|
||||
|
||||
def self.batch_interval
|
||||
20.minutes
|
||||
end
|
||||
|
||||
def self.first_batch_run_at
|
||||
Time.current
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -4,6 +4,11 @@ class Poll < ActiveRecord::Base
|
||||
include ActsAsParanoidAliases
|
||||
include Notifiable
|
||||
|
||||
translates :name, touch: true
|
||||
translates :summary, touch: true
|
||||
translates :description, touch: true
|
||||
globalize_accessors
|
||||
|
||||
RECOUNT_DURATION = 1.week
|
||||
|
||||
has_many :booth_assignments, class_name: "Poll::BoothAssignment"
|
||||
|
||||
@@ -9,7 +9,9 @@ class Poll::Answer < ActiveRecord::Base
|
||||
validates :author, presence: true
|
||||
validates :answer, presence: true
|
||||
|
||||
validates :answer, inclusion: { in: ->(a) { a.question.question_answers.pluck(:title) }},
|
||||
validates :answer, inclusion: { in: ->(a) { a.question.question_answers
|
||||
.joins(:translations)
|
||||
.pluck("poll_question_answer_translations.title") }},
|
||||
unless: ->(a) { a.question.blank? }
|
||||
|
||||
scope :by_author, ->(author_id) { where(author_id: author_id) }
|
||||
|
||||
@@ -10,7 +10,9 @@ class Poll::PartialResult < ActiveRecord::Base
|
||||
validates :question, presence: true
|
||||
validates :author, presence: true
|
||||
validates :answer, presence: true
|
||||
validates :answer, inclusion: { in: ->(a) { a.question.question_answers.pluck(:title) }},
|
||||
validates :answer, inclusion: { in: ->(a) { a.question.question_answers
|
||||
.joins(:translations)
|
||||
.pluck("poll_question_answer_translations.title") }},
|
||||
unless: ->(a) { a.question.blank? }
|
||||
validates :origin, inclusion: { in: VALID_ORIGINS }
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ class Poll::Question < ActiveRecord::Base
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
translates :title, touch: true
|
||||
globalize_accessors
|
||||
|
||||
belongs_to :poll
|
||||
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
class Poll::Question::Answer < ActiveRecord::Base
|
||||
include Galleryable
|
||||
include Documentable
|
||||
|
||||
translates :title, touch: true
|
||||
translates :description, touch: true
|
||||
globalize_accessors
|
||||
|
||||
documentable max_documents_allowed: 3,
|
||||
max_file_size: 3.megabytes,
|
||||
accepted_content_types: [ "application/pdf" ]
|
||||
@@ -15,7 +20,7 @@ class Poll::Question::Answer < ActiveRecord::Base
|
||||
before_validation :set_order, on: :create
|
||||
|
||||
def description
|
||||
super.try :html_safe
|
||||
self[:description].try :html_safe
|
||||
end
|
||||
|
||||
def self.order_answers(ordered_array)
|
||||
|
||||
@@ -223,7 +223,7 @@ class Proposal < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def users_to_notify
|
||||
(voters + followers).uniq
|
||||
(voters + followers).uniq - [author]
|
||||
end
|
||||
|
||||
def self.proposals_orders(user)
|
||||
|
||||
@@ -37,6 +37,11 @@ class ProposalNotification < ActiveRecord::Base
|
||||
proposal
|
||||
end
|
||||
|
||||
def moderate_system_email(moderator)
|
||||
Notification.where(notifiable_type: 'ProposalNotification', notifiable: self).destroy_all
|
||||
Activity.log(moderator, :hide, self)
|
||||
end
|
||||
|
||||
def ignore_flag
|
||||
update(ignored_at: Time.current)
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class SiteCustomization::ContentBlock < ActiveRecord::Base
|
||||
VALID_BLOCKS = %w(top_links footer)
|
||||
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 }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class SiteCustomization::Image < ActiveRecord::Base
|
||||
VALID_IMAGES = {
|
||||
"icon_home" => [330, 240],
|
||||
"logo_header" => [80, 80],
|
||||
"logo_header" => [260, 80],
|
||||
"social_media_icon" => [470, 246],
|
||||
"social_media_icon_twitter" => [246, 246],
|
||||
"apple-touch-icon-200" => [200, 200]
|
||||
|
||||
@@ -6,11 +6,15 @@ class SiteCustomization::Page < ActiveRecord::Base
|
||||
format: { with: /\A[0-9a-zA-Z\-_]*\Z/, message: :slug_format }
|
||||
validates :title, presence: true
|
||||
validates :status, presence: true, inclusion: { in: VALID_STATUSES }
|
||||
validates :locale, presence: true
|
||||
|
||||
translates :title, touch: true
|
||||
translates :subtitle, touch: true
|
||||
translates :content, touch: true
|
||||
globalize_accessors
|
||||
|
||||
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, -> { where(locale: I18n.locale).order('id ASC') }
|
||||
scope :with_same_locale, -> { joins(:translations).where("site_customization_page_translations.locale": I18n.locale) }
|
||||
|
||||
def url
|
||||
"/#{slug}"
|
||||
|
||||
@@ -182,6 +182,7 @@ class User < ActiveRecord::Base
|
||||
debates_ids = Debate.where(author_id: id).pluck(:id)
|
||||
comments_ids = Comment.where(user_id: id).pluck(:id)
|
||||
proposal_ids = Proposal.where(author_id: id).pluck(:id)
|
||||
investment_ids = Budget::Investment.where(author_id: id).pluck(:id)
|
||||
proposal_notification_ids = ProposalNotification.where(author_id: id).pluck(:id)
|
||||
|
||||
hide
|
||||
@@ -189,6 +190,7 @@ class User < ActiveRecord::Base
|
||||
Debate.hide_all debates_ids
|
||||
Comment.hide_all comments_ids
|
||||
Proposal.hide_all proposal_ids
|
||||
Budget::Investment.hide_all investment_ids
|
||||
ProposalNotification.hide_all proposal_notification_ids
|
||||
end
|
||||
|
||||
@@ -327,6 +329,10 @@ class User < ActiveRecord::Base
|
||||
where(conditions.to_hash).where(["username = ?", login]).first
|
||||
end
|
||||
|
||||
def self.find_by_manager_login(manager_login)
|
||||
find_by(id: manager_login.split("_").last)
|
||||
end
|
||||
|
||||
def interests
|
||||
followables = follows.map(&:followable)
|
||||
followables.compact.map { |followable| followable.tags.map(&:name) }.flatten.compact.uniq
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
class Widget::Card < ActiveRecord::Base
|
||||
include Imageable
|
||||
|
||||
# table_name must be set before calls to 'translates'
|
||||
self.table_name = "widget_cards"
|
||||
|
||||
translates :label, touch: true
|
||||
translates :title, touch: true
|
||||
translates :description, touch: true
|
||||
translates :link_text, touch: true
|
||||
globalize_accessors
|
||||
|
||||
def self.header
|
||||
where(header: true)
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<strong><%= t("admin.menu.title_polls") %></strong>
|
||||
</a>
|
||||
<ul id="polls_menu" <%= "class=is-active" if menu_polls? || controller.class.parent == Admin::Poll::Questions::Answers %>>
|
||||
<li <%= "class=is-active" if controller_name == "polls" && action_name != "booth_assignments" %>>
|
||||
<li <%= "class=is-active" if %w(polls recounts results).include?(controller_name) %>>
|
||||
<%= link_to t("admin.menu.polls"), admin_polls_path %>
|
||||
</li>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<strong><%= t("admin.menu.title_booths") %></strong>
|
||||
</a>
|
||||
<ul id="booths_menu" <%= "class=is-active" if menu_booths? || controller_name == "polls" && action_name == "booth_assignments" %>>
|
||||
<li <%= "class=is-active" if controller_name == "officers" %>>
|
||||
<li <%= "class=is-active" if %w(officers officer_assignments).include?(controller_name) %>>
|
||||
<%= link_to t("admin.menu.poll_officers"), admin_officers_path %>
|
||||
</li>
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
</li>
|
||||
|
||||
<li <%= "class=is-active" if (controller_name == "polls" && action_name == "booth_assignments") ||
|
||||
(controller_name == "booth_assignments" && action_name == "manage") %>>
|
||||
controller_name == "booth_assignments" %>>
|
||||
<%= link_to t("admin.menu.poll_booth_assignments"), booth_assignments_admin_polls_path %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=is-active" if %w(shifts booths).include?(controller_name) &&
|
||||
action_name == "available" %>>
|
||||
%w(available new).include?(action_name) %>>
|
||||
<%= link_to t("admin.menu.poll_shifts"), available_admin_booths_path %>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -79,21 +79,24 @@
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% newsletters_notifications_sections = %w(newsletters emails_download admin_notifications) %>
|
||||
<% newsletters_menu_active = newsletters_notifications_sections.include?(controller_name) %>
|
||||
<li class="section-title" <%= "class=active" if newsletters_menu_active %>>
|
||||
<% messages_sections = %w(newsletters emails_download admin_notifications system_emails) %>
|
||||
<% messages_menu_active = messages_sections.include?(controller_name) %>
|
||||
<li class="section-title" <%= "class=is-active" if messages_menu_active %>>
|
||||
<a href="#">
|
||||
<span class="icon-zip"></span>
|
||||
<strong><%= t("admin.menu.newsletters_and_notifications") %></strong>
|
||||
<strong><%= t("admin.menu.messaging_users") %></strong>
|
||||
</a>
|
||||
<ul id="newsletters_and_notifications_menu" <%= "class=is-active" if newsletters_menu_active %>>
|
||||
<li <%= "class=active" if controller_name == "newsletters" %>>
|
||||
<ul id="messaging_users_menu" <%= "class=is-active" if messages_menu_active %>>
|
||||
<li <%= "class=is-active" if controller_name == "newsletters" %>>
|
||||
<%= link_to t("admin.menu.newsletters"), admin_newsletters_path %>
|
||||
</li>
|
||||
<li <%= "class=active" if controller_name == "admin_notifications" %>>
|
||||
<li <%= "class=is-active" if controller_name == "admin_notifications" %>>
|
||||
<%= link_to t("admin.menu.admin_notifications"), admin_admin_notifications_path %>
|
||||
</li>
|
||||
<li <%= "class=active" if controller_name == "emails_download" %>>
|
||||
<li <%= "class=is-active" if controller_name == "system_emails" %>>
|
||||
<%= link_to t("admin.menu.system_emails"), admin_system_emails_path %>
|
||||
</li>
|
||||
<li <%= "class=is-active" if controller_name == "emails_download" %>>
|
||||
<%= link_to t("admin.menu.emails_download"), admin_emails_download_index_path %>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -107,7 +110,7 @@
|
||||
<ul <%= "class=is-active" if menu_customization? &&
|
||||
controller.class.parent != Admin::Poll::Questions::Answers %>>
|
||||
|
||||
<li <%= "class=active" if menu_homepage? %>>
|
||||
<li <%= "class=is-active" if menu_homepage? %>>
|
||||
<%= link_to t("admin.menu.site_customization.homepage"), admin_homepage_path %>
|
||||
</li>
|
||||
|
||||
@@ -118,6 +121,10 @@
|
||||
<li <%= "class=is-active" if controller_name == "banners" %>>
|
||||
<%= link_to t("admin.menu.banner"), admin_banners_path %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=is-active" if controller_name == "information_texts" %>>
|
||||
<%= link_to t("admin.menu.site_customization.information_texts"), admin_site_customization_information_texts_path %>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -148,6 +155,12 @@
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if feature?(:budgets) %>
|
||||
<li <%= "class=is-active" if controller_name == "hidden_budget_investments" %>>
|
||||
<%= link_to t("admin.menu.hidden_budget_investments"), admin_hidden_budget_investments_path %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<li <%= "class=is-active" if controller_name == "comments" %>>
|
||||
<%= link_to t("admin.menu.hidden_comments"), admin_comments_path %>
|
||||
</li>
|
||||
|
||||
@@ -33,12 +33,16 @@
|
||||
<%= activity.actionable.username %> (<%= activity.actionable.email %>)
|
||||
<% when "Comment" %>
|
||||
<%= activity.actionable.body %>
|
||||
<% when "Newsletter" %>
|
||||
<strong><%= activity.actionable.subject %></strong>
|
||||
<% when "ProposalNotification" %>
|
||||
<strong><%= activity.actionable.title %></strong>
|
||||
<br>
|
||||
<%= activity.actionable.body %>
|
||||
<% else %>
|
||||
<strong><%= activity.actionable.title %></strong>
|
||||
<br>
|
||||
<div class="proposal-description">
|
||||
<%= activity.actionable.description %>
|
||||
</div>
|
||||
<% end %>
|
||||
<td class="align-top">
|
||||
<%= activity.user.name %> (<%= activity.user.email %>)
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
<%= form_for [:admin, @admin_notification] do |f| %>
|
||||
<%= render "admin/shared/globalize_locales", resource: @admin_notification %>
|
||||
|
||||
<%= translatable_form_for [:admin, @admin_notification] do |f| %>
|
||||
<%= render 'shared/errors', resource: @admin_notification %>
|
||||
|
||||
<%= f.select :segment_recipient, options_for_select(user_segments_options,
|
||||
@admin_notification[:segment_recipient]) %>
|
||||
<%= f.text_field :title %>
|
||||
|
||||
<%= f.translatable_text_field :title %>
|
||||
|
||||
<%= f.text_field :link %>
|
||||
<%= f.text_area :body %>
|
||||
|
||||
<%= f.translatable_text_area :body %>
|
||||
|
||||
<div class="margin-top">
|
||||
<%= f.submit class: "button success" %>
|
||||
<%= f.submit t("admin.admin_notifications.#{admin_submit_action(@admin_notification)}.submit_button"),
|
||||
class: "button success" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<th><%= t("admin.admin_notifications.index.title") %></th>
|
||||
<th><%= t("admin.admin_notifications.index.segment_recipient") %></th>
|
||||
<th><%= t("admin.admin_notifications.index.sent") %></th>
|
||||
<th class="small-5 text-right"><%= t("admin.admin_notifications.index.actions") %></th>
|
||||
<th class="small-5"><%= t("admin.admin_notifications.index.actions") %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -28,21 +28,29 @@
|
||||
<%= l admin_notification.sent_at.to_date %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<td>
|
||||
<% if admin_notification.draft? %>
|
||||
<div class="small-4 column">
|
||||
<%= link_to t("admin.admin_notifications.index.edit"),
|
||||
edit_admin_admin_notification_path(admin_notification),
|
||||
method: :get, class: "button hollow" %>
|
||||
method: :get, class: "button expanded hollow" %>
|
||||
</div>
|
||||
<div class="small-4 column">
|
||||
<%= link_to t("admin.admin_notifications.index.delete"),
|
||||
admin_admin_notification_path(admin_notification),
|
||||
method: :delete, class: "button hollow alert" %>
|
||||
method: :delete, class: "button expanded hollow alert" %>
|
||||
</div>
|
||||
<div class="small-4 column">
|
||||
<%= link_to t("admin.admin_notifications.index.preview"),
|
||||
admin_admin_notification_path(admin_notification),
|
||||
class: "button" %>
|
||||
class: "button expanded" %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="small-4 column">
|
||||
<%= link_to t("admin.admin_notifications.index.view"),
|
||||
admin_admin_notification_path(admin_notification),
|
||||
class: "button" %>
|
||||
class: "button expanded" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
<h2><%= t("admin.admin_notifications.show.section_title") %></h2>
|
||||
|
||||
<div class="small-12 column">
|
||||
<div class="callout highlight">
|
||||
<div class="row">
|
||||
<div class="small-12 column callout highlight">
|
||||
<div class="small-12 medium-6 column">
|
||||
<strong><%= t("admin.admin_notifications.show.sent_at") %></strong><br>
|
||||
<% if @admin_notification.draft? %>
|
||||
@@ -13,23 +11,22 @@
|
||||
<%= l(@admin_notification.sent_at.to_date) %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 column">
|
||||
<strong><%= t("admin.admin_notifications.show.title") %></strong><br>
|
||||
<%= @admin_notification.title %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="small-12 medium-6 column">
|
||||
<strong><%= t("admin.admin_notifications.show.body") %></strong><br>
|
||||
<%= @admin_notification.body %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 column">
|
||||
<strong><%= t("admin.admin_notifications.show.link") %></strong><br>
|
||||
<%= @admin_notification.link %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
||||
<div class="small-12 column">
|
||||
<strong><%= t("admin.admin_notifications.show.segment_recipient") %></strong><br>
|
||||
<%= segment_name(@admin_notification.segment_recipient) %>
|
||||
@@ -42,7 +39,6 @@
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="help-text" id="phase-description-help-text">
|
||||
<% if @admin_notification.draft? %>
|
||||
@@ -65,13 +61,15 @@
|
||||
</ul>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<% if @admin_notification.draft? && @admin_notification.valid_segment_recipient? %>
|
||||
<div class="small-12 medium-6 large-3 column end">
|
||||
<%= link_to t("admin.admin_notifications.show.send"),
|
||||
deliver_admin_admin_notification_path(@admin_notification),
|
||||
"data-alert": t("admin.admin_notifications.show.send_alert",
|
||||
n: @admin_notification.list_of_recipients_count),
|
||||
method: :post,
|
||||
id: "js-send-admin_notification-alert",
|
||||
class: "button success" %>
|
||||
class: "button success expanded" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user