merge to master
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -39,3 +39,4 @@ sgemset
|
||||
|
||||
# Ignore .vagrant folder with images
|
||||
.vagrant
|
||||
.metadata
|
||||
1
.ruby-version
Normal file
1
.ruby-version
Normal file
@ -0,0 +1 @@
|
||||
2.2.0
|
||||
@ -1,7 +1,7 @@
|
||||
language: ruby
|
||||
rvm:
|
||||
- 2.1
|
||||
- 2.2
|
||||
env: DATABASE_URL=postgres://postgres@localhost/timeoverflow_test
|
||||
before_script:
|
||||
- psql -c 'create database timeoverflow_test;' -U postgres
|
||||
- RAILS_ENV=test bundle exec rake db:migrate
|
||||
- RAILS_ENV=test bundle exec rake db:migrate
|
||||
|
||||
45
CONTRIBUTING.md
Normal file
45
CONTRIBUTING.md
Normal file
@ -0,0 +1,45 @@
|
||||
Entorno de desarrollo aconsejado (para mac)
|
||||
===========================================
|
||||
|
||||
iTerm2 - un terminal mucho más completo (<http://iterm2.com>). Especialmente recomendado activar
|
||||
la opción "Working directory -> Reuse previous session's directory" para el perfil por defecto,
|
||||
para jugar fácilmente con múltiples pestañas en la misma directory.
|
||||
|
||||
SublimeText2 - un editor muy muy avanzado (<http://www.sublimetext.com>). Instalar también
|
||||
PackageControl para luego instalar extensiones de forma muy fácil (seguir instrucciones en
|
||||
<https://packagecontrol.io/installation#st2>). Otro editor que promete es Atom (<https://atom.io>)
|
||||
aunque no es tan maduro, tiene unos grandes desarrolladores detrás. Ambos permiten - y es muy
|
||||
importante - evitar que se cuelen TABs en el código.
|
||||
|
||||
Homebrew - para instalar todo tipo de paquetes adicionales (<http://brew.sh>).
|
||||
|
||||
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
|
||||
YADR - una biblioteca de shortcuts y mejoras para zsh y la línea de comando de ruby
|
||||
(<https://github.com/skwp/dotfiles>). No hacen falta las opciones para `vim`, sobretodo si uno
|
||||
no está acostumbrado a vim, la opción "vimification of command line tools" puede ser mortal!
|
||||
|
||||
sh -c "`curl -fsSL https://raw.githubusercontent.com/skwp/dotfiles/master/install.sh`" -s ask
|
||||
|
||||
Instalar varios paquetes por medio de homebrew
|
||||
|
||||
brew install git rbenv ruby-build postgresql
|
||||
|
||||
Instalar ruby
|
||||
|
||||
rbenv install 2.2.0
|
||||
rbenv global 2.2.0
|
||||
|
||||
Añadir la siguiente línea al fichero `.profile` para tener rbenv activado) y reiniciar
|
||||
el terminal.
|
||||
|
||||
eval "$(rbenv init -)"
|
||||
|
||||
|
||||
Actualizar rubygems e instalar bundler
|
||||
|
||||
gem update --system
|
||||
gem install bundler
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
timeoverflow:
|
||||
ruby_version: 2.1.4
|
||||
ruby_version: 2.2.0
|
||||
environment: production # RAILS_ENV
|
||||
monitoring_email: saverio.trioni@gmail.com
|
||||
domains:
|
||||
@ -12,7 +12,7 @@ timeoverflow:
|
||||
# delayed_job: 1
|
||||
# sidekiq: 1
|
||||
# clockwork: on
|
||||
# whenever: on
|
||||
whenever: on
|
||||
# elasticsearch: on
|
||||
databases:
|
||||
- postgresql
|
||||
|
||||
36
Gemfile
36
Gemfile
@ -1,71 +1,52 @@
|
||||
source 'https://rubygems.org'
|
||||
ruby '2.2.0'
|
||||
|
||||
gem 'rails', '~> 4.1'
|
||||
gem 'rails', '~> 4.2'
|
||||
gem 'rails-i18n'
|
||||
gem 'rails_12factor'
|
||||
gem "rdiscount"
|
||||
|
||||
gem 'high_voltage', '~> 2.1.0'
|
||||
|
||||
gem 'activeadmin', github: 'gregbell/active_admin'
|
||||
|
||||
gem 'activeadmin', github: 'activeadmin'
|
||||
gem 'has_scope'
|
||||
gem 'inherited_resources'
|
||||
gem 'responders', '~> 2.0'
|
||||
gem 'pundit'
|
||||
|
||||
gem 'pg', '0.17.1'
|
||||
gem 'hstore_translate'
|
||||
|
||||
gem 'dalli'
|
||||
|
||||
gem "sass-rails", "4.0.5"
|
||||
gem 'coffee-rails'
|
||||
gem 'ngannotate-rails'
|
||||
gem 'uglifier', '>= 1.0.3'
|
||||
|
||||
gem 'jquery-rails'
|
||||
|
||||
gem "devise_browserid_authenticatable"
|
||||
gem "http_accept_language"
|
||||
|
||||
gem 'thin'
|
||||
gem 'foreman'
|
||||
gem 'dotenv-rails'
|
||||
|
||||
gem 'kaminari'
|
||||
gem 'textacular', "~> 3.0", require: 'textacular/rails'
|
||||
|
||||
gem 'textacular', "3.2.1", require: 'textacular/rails'
|
||||
# To use debugger
|
||||
# gem 'debugger'
|
||||
|
||||
gem "haml-rails"
|
||||
gem 'turbolinks'
|
||||
|
||||
gem "simple_form", ">= 3.0.0"
|
||||
|
||||
gem "awesome_print"
|
||||
gem "jbuilder"
|
||||
gem "paranoia"
|
||||
|
||||
gem "rest-client"
|
||||
|
||||
gem 'memcachier'
|
||||
gem 'rollbar'
|
||||
|
||||
gem "rails-erd", group: :development
|
||||
|
||||
gem 'travis-lint'
|
||||
|
||||
gem 'faker'
|
||||
gem 'fabrication'
|
||||
|
||||
gem "shelly-dependencies"
|
||||
gem 'whenever', :require => false
|
||||
|
||||
group :development do
|
||||
gem "binding_of_caller"
|
||||
gem "better_errors"
|
||||
gem "rubocop"
|
||||
gem "haml-lint"
|
||||
gem 'web-console', '~> 2.0'
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
@ -77,4 +58,7 @@ group :test do
|
||||
# Needed for TravisCI
|
||||
gem 'rake'
|
||||
gem "database_cleaner"
|
||||
gem 'shoulda', ">= 3.5"
|
||||
gem 'fabrication'
|
||||
gem 'faker'
|
||||
end
|
||||
|
||||
339
Gemfile.lock
339
Gemfile.lock
@ -1,67 +1,74 @@
|
||||
GIT
|
||||
remote: git://github.com/gregbell/active_admin.git
|
||||
revision: b5ce6af4e5538010ff02387be04c2d60b6b62127
|
||||
remote: git://github.com/activeadmin/activeadmin.git
|
||||
revision: 60914c887942cb34d737428fb9813f69bb8ae3ee
|
||||
specs:
|
||||
activeadmin (1.0.0.pre)
|
||||
arbre (~> 1.0)
|
||||
arbre (~> 1.0, >= 1.0.2)
|
||||
bourbon
|
||||
coffee-rails
|
||||
formtastic (~> 2.3.0.rc3)
|
||||
inherited_resources (~> 1.3)
|
||||
formtastic (~> 3.1)
|
||||
formtastic_i18n
|
||||
inherited_resources (~> 1.6)
|
||||
jquery-rails
|
||||
jquery-ui-rails
|
||||
jquery-ui-rails (~> 5.0)
|
||||
kaminari (~> 0.15)
|
||||
rails (>= 3.2, < 4.2)
|
||||
ransack (~> 1.0)
|
||||
rails (>= 3.2, < 5.0)
|
||||
ransack (~> 1.3)
|
||||
sass-rails
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (4.1.1)
|
||||
actionpack (= 4.1.1)
|
||||
actionview (= 4.1.1)
|
||||
mail (~> 2.5.4)
|
||||
actionpack (4.1.1)
|
||||
actionview (= 4.1.1)
|
||||
activesupport (= 4.1.1)
|
||||
rack (~> 1.5.2)
|
||||
actionmailer (4.2.0)
|
||||
actionpack (= 4.2.0)
|
||||
actionview (= 4.2.0)
|
||||
activejob (= 4.2.0)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.0)
|
||||
actionview (= 4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
rack (~> 1.6.0)
|
||||
rack-test (~> 0.6.2)
|
||||
actionview (4.1.1)
|
||||
activesupport (= 4.1.1)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
||||
actionview (4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
activemodel (4.1.1)
|
||||
activesupport (= 4.1.1)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
||||
activejob (4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
globalid (>= 0.3.0)
|
||||
activemodel (4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.1.1)
|
||||
activemodel (= 4.1.1)
|
||||
activesupport (= 4.1.1)
|
||||
arel (~> 5.0.0)
|
||||
activerecord-postgres-hstore (0.7.6)
|
||||
activerecord (>= 3.1)
|
||||
pg-hstore (>= 1.1.5)
|
||||
rake
|
||||
activesupport (4.1.1)
|
||||
i18n (~> 0.6, >= 0.6.9)
|
||||
activerecord (4.2.0)
|
||||
activemodel (= 4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.0)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
arbre (1.0.2)
|
||||
arbre (1.0.3)
|
||||
activesupport (>= 3.0.0)
|
||||
arel (5.0.1.20140414130214)
|
||||
arel (6.0.0)
|
||||
ast (2.0.0)
|
||||
astrolabe (1.3.0)
|
||||
parser (>= 2.2.0.pre.3, < 3.0)
|
||||
awesome_print (1.2.0)
|
||||
bcrypt (3.1.7)
|
||||
better_errors (1.0.1)
|
||||
awesome_print (1.6.1)
|
||||
bcrypt (3.1.9)
|
||||
better_errors (2.1.1)
|
||||
coderay (>= 1.0.0)
|
||||
erubis (>= 2.6.6)
|
||||
rack (>= 0.9.0)
|
||||
binding_of_caller (0.7.2)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bourbon (3.2.3)
|
||||
bourbon (3.2.4)
|
||||
sass (~> 3.2)
|
||||
thor
|
||||
builder (3.2.2)
|
||||
@ -71,218 +78,255 @@ GEM
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
choice (0.1.6)
|
||||
choice (0.1.7)
|
||||
chronic (0.10.2)
|
||||
coderay (1.1.0)
|
||||
coffee-rails (4.0.1)
|
||||
coffee-rails (4.1.0)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
coffee-script (2.2.0)
|
||||
coffee-script (2.3.0)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.7.0)
|
||||
coffee-script-source (1.8.0)
|
||||
daemons (1.1.9)
|
||||
dalli (2.6.4)
|
||||
database_cleaner (1.2.0)
|
||||
dalli (2.7.2)
|
||||
database_cleaner (1.4.0)
|
||||
debug_inspector (0.0.2)
|
||||
devise (3.2.4)
|
||||
devise (3.4.1)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 3.2.6, < 5)
|
||||
responders
|
||||
thread_safe (~> 0.1)
|
||||
warden (~> 1.2.3)
|
||||
devise_browserid_authenticatable (1.3.2)
|
||||
devise (>= 2.1)
|
||||
diff-lcs (1.2.5)
|
||||
dotenv (0.9.0)
|
||||
dotenv-rails (0.9.0)
|
||||
dotenv (= 0.9.0)
|
||||
dotenv (1.0.2)
|
||||
dotenv-rails (1.0.2)
|
||||
dotenv (= 1.0.2)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.0.3)
|
||||
execjs (2.0.2)
|
||||
fabrication (2.9.1)
|
||||
faker (1.2.0)
|
||||
eventmachine (1.0.7)
|
||||
execjs (2.2.2)
|
||||
fabrication (2.11.3)
|
||||
faker (1.4.3)
|
||||
i18n (~> 0.5)
|
||||
foreman (0.63.0)
|
||||
dotenv (>= 0.7)
|
||||
thor (>= 0.13.6)
|
||||
formtastic (2.3.1)
|
||||
actionpack (>= 3.0)
|
||||
haml (4.0.5)
|
||||
foreman (0.77.0)
|
||||
dotenv (~> 1.0.2)
|
||||
thor (~> 0.19.1)
|
||||
formtastic (3.1.3)
|
||||
actionpack (>= 3.2.13)
|
||||
formtastic_i18n (0.1.1)
|
||||
globalid (0.3.0)
|
||||
activesupport (>= 4.1.0)
|
||||
haml (4.1.0.beta.1)
|
||||
tilt
|
||||
haml-lint (0.8.0)
|
||||
haml-lint (0.10.0)
|
||||
haml (~> 4.0)
|
||||
rubocop (>= 0.25.0)
|
||||
sysexits (~> 1.1)
|
||||
haml-rails (0.5.3)
|
||||
haml-rails (0.6.0)
|
||||
actionpack (>= 4.0.1)
|
||||
activesupport (>= 4.0.1)
|
||||
haml (>= 3.1, < 5.0)
|
||||
html2haml (>= 1.0.1)
|
||||
railties (>= 4.0.1)
|
||||
has_scope (0.6.0.rc)
|
||||
has_scope (0.6.0)
|
||||
actionpack (>= 3.2, < 5)
|
||||
activesupport (>= 3.2, < 5)
|
||||
hashr (0.0.22)
|
||||
high_voltage (2.1.0)
|
||||
hike (1.2.3)
|
||||
hstore_translate (0.0.12)
|
||||
hpricot (0.8.6)
|
||||
hstore_translate (1.0.0)
|
||||
activerecord (>= 3.1.0)
|
||||
activerecord-postgres-hstore (~> 0.7.0)
|
||||
pg
|
||||
html2haml (1.0.1)
|
||||
erubis (~> 2.7.0)
|
||||
haml (>= 4.0.0.rc.1)
|
||||
hpricot (~> 0.8.6)
|
||||
ruby_parser (~> 3.1.1)
|
||||
http_accept_language (2.0.2)
|
||||
i18n (0.6.11)
|
||||
inherited_resources (1.4.1)
|
||||
i18n (0.7.0)
|
||||
inherited_resources (1.6.0)
|
||||
actionpack (>= 3.2, < 5)
|
||||
has_scope (~> 0.6.0.rc)
|
||||
responders (~> 1.0.0.rc)
|
||||
jbuilder (1.5.1)
|
||||
activesupport (>= 3.0.0)
|
||||
multi_json (>= 1.2.0)
|
||||
jquery-rails (3.1.0)
|
||||
railties (>= 3.0, < 5.0)
|
||||
railties (>= 3.2, < 5)
|
||||
responders
|
||||
jbuilder (2.2.6)
|
||||
activesupport (>= 3.0.0, < 5)
|
||||
multi_json (~> 1.2)
|
||||
jquery-rails (4.0.3)
|
||||
rails-dom-testing (~> 1.0)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
jquery-ui-rails (4.2.1)
|
||||
jquery-ui-rails (5.0.3)
|
||||
railties (>= 3.2.16)
|
||||
json (1.8.1)
|
||||
kaminari (0.15.1)
|
||||
json (1.8.2)
|
||||
kaminari (0.16.1)
|
||||
actionpack (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
mail (2.5.4)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
loofah (2.0.1)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.6.3)
|
||||
mime-types (>= 1.16, < 3)
|
||||
memcachier (0.0.2)
|
||||
mime-types (1.25.1)
|
||||
mini_portile (0.6.1)
|
||||
minitest (5.4.3)
|
||||
mime-types (2.4.3)
|
||||
mini_portile (0.6.2)
|
||||
minitest (5.5.1)
|
||||
multi_json (1.10.1)
|
||||
ngannotate-rails (0.9.2)
|
||||
netrc (0.10.2)
|
||||
ngannotate-rails (0.14.1)
|
||||
execjs
|
||||
rails (>= 3.1)
|
||||
nokogiri (1.6.4.1)
|
||||
nokogiri (1.6.6.2)
|
||||
mini_portile (~> 0.6.0)
|
||||
orm_adapter (0.5.0)
|
||||
paranoia (2.0.0)
|
||||
paranoia (2.0.4)
|
||||
activerecord (~> 4.0)
|
||||
parser (2.2.0.pre.8)
|
||||
parser (2.2.0.2)
|
||||
ast (>= 1.1, < 3.0)
|
||||
slop (~> 3.4, >= 3.4.5)
|
||||
pg (0.17.1)
|
||||
pg-hstore (1.2.0)
|
||||
polyamorous (1.0.0)
|
||||
polyamorous (1.1.0)
|
||||
activerecord (>= 3.0)
|
||||
polyglot (0.3.4)
|
||||
powerpack (0.0.9)
|
||||
pundit (0.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
rack (1.5.2)
|
||||
rack-test (0.6.2)
|
||||
rack (1.6.0)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.1.1)
|
||||
actionmailer (= 4.1.1)
|
||||
actionpack (= 4.1.1)
|
||||
actionview (= 4.1.1)
|
||||
activemodel (= 4.1.1)
|
||||
activerecord (= 4.1.1)
|
||||
activesupport (= 4.1.1)
|
||||
rails (4.2.0)
|
||||
actionmailer (= 4.2.0)
|
||||
actionpack (= 4.2.0)
|
||||
actionview (= 4.2.0)
|
||||
activejob (= 4.2.0)
|
||||
activemodel (= 4.2.0)
|
||||
activerecord (= 4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.1.1)
|
||||
sprockets-rails (~> 2.0)
|
||||
railties (= 4.2.0)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.5)
|
||||
activesupport (>= 4.2.0.beta, < 5.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-erd (1.1.0)
|
||||
activerecord (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
choice (~> 0.1.6)
|
||||
ruby-graphviz (~> 1.0.4)
|
||||
rails-i18n (4.0.2)
|
||||
rails-html-sanitizer (1.0.1)
|
||||
loofah (~> 2.0)
|
||||
rails-i18n (4.0.3)
|
||||
i18n (~> 0.6)
|
||||
rails (>= 4.0)
|
||||
rails_12factor (0.0.2)
|
||||
railties (~> 4.0)
|
||||
rails_12factor (0.0.3)
|
||||
rails_serve_static_assets
|
||||
rails_stdout_logging
|
||||
rails_serve_static_assets (0.0.1)
|
||||
rails_serve_static_assets (0.0.3)
|
||||
rails_stdout_logging (0.0.3)
|
||||
railties (4.1.1)
|
||||
actionpack (= 4.1.1)
|
||||
activesupport (= 4.1.1)
|
||||
railties (4.2.0)
|
||||
actionpack (= 4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.0.0)
|
||||
rake (10.4.0)
|
||||
ransack (1.2.3)
|
||||
rake (10.4.2)
|
||||
ransack (1.6.3)
|
||||
actionpack (>= 3.0)
|
||||
activerecord (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
i18n
|
||||
polyamorous (~> 1.0.0)
|
||||
rdiscount (2.1.7)
|
||||
responders (1.0.0)
|
||||
railties (>= 3.2, < 5)
|
||||
rest-client (1.6.7)
|
||||
mime-types (>= 1.16)
|
||||
rollbar (0.12.18)
|
||||
polyamorous (~> 1.1)
|
||||
rdiscount (2.1.7.1)
|
||||
responders (2.0.2)
|
||||
railties (>= 4.2.0.alpha, < 5)
|
||||
rest-client (1.7.2)
|
||||
mime-types (>= 1.16, < 3.0)
|
||||
netrc (~> 0.7)
|
||||
rollbar (1.3.2)
|
||||
multi_json (~> 1.3)
|
||||
rspec-core (2.14.8)
|
||||
rspec-expectations (2.14.5)
|
||||
rspec-collection_matchers (1.1.2)
|
||||
rspec-expectations (>= 2.99.0.beta1)
|
||||
rspec-core (2.99.2)
|
||||
rspec-expectations (2.99.2)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rspec-mocks (2.14.6)
|
||||
rspec-rails (2.14.2)
|
||||
rspec-mocks (2.99.2)
|
||||
rspec-rails (2.99.0)
|
||||
actionpack (>= 3.0)
|
||||
activemodel (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 2.14.0)
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
rubocop (0.27.1)
|
||||
rspec-collection_matchers
|
||||
rspec-core (~> 2.99.0)
|
||||
rspec-expectations (~> 2.99.0)
|
||||
rspec-mocks (~> 2.99.0)
|
||||
rubocop (0.28.0)
|
||||
astrolabe (~> 1.3)
|
||||
parser (>= 2.2.0.pre.7, < 3.0)
|
||||
powerpack (~> 0.0.6)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
ruby-graphviz (1.0.9)
|
||||
ruby-progressbar (1.7.0)
|
||||
ruby-progressbar (1.7.1)
|
||||
ruby_parser (3.1.3)
|
||||
sexp_processor (~> 4.1)
|
||||
sass (3.2.19)
|
||||
sass-rails (4.0.5)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass (~> 3.2.2)
|
||||
sprockets (~> 2.8, < 3.0)
|
||||
sprockets-rails (~> 2.0)
|
||||
shelly-dependencies (0.2.3)
|
||||
sexp_processor (4.4.4)
|
||||
shelly-dependencies (0.2.4)
|
||||
rake
|
||||
thin
|
||||
simple_form (3.0.2)
|
||||
shoulda (3.5.0)
|
||||
shoulda-context (~> 1.0, >= 1.0.1)
|
||||
shoulda-matchers (>= 1.4.1, < 3.0)
|
||||
shoulda-context (1.2.1)
|
||||
shoulda-matchers (2.8.0)
|
||||
activesupport (>= 3.0.0)
|
||||
simple_form (3.1.0)
|
||||
actionpack (~> 4.0)
|
||||
activemodel (~> 4.0)
|
||||
slop (3.6.0)
|
||||
sprockets (2.12.3)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sprockets-rails (2.2.1)
|
||||
sprockets-rails (2.2.2)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sysexits (1.2.0)
|
||||
textacular (3.2.0)
|
||||
activerecord (>= 3.0, < 4.2)
|
||||
thin (1.6.2)
|
||||
daemons (>= 1.0.9)
|
||||
eventmachine (>= 1.0.0)
|
||||
rack (>= 1.0.0)
|
||||
textacular (3.2.1)
|
||||
activerecord (>= 3.0, < 5.0)
|
||||
thin (1.6.3)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.4)
|
||||
tilt (1.4.1)
|
||||
travis-lint (1.7.0)
|
||||
hashr (~> 0.0.22)
|
||||
treetop (1.4.15)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
turbolinks (1.3.0)
|
||||
travis-lint (2.0.0)
|
||||
json
|
||||
turbolinks (2.5.3)
|
||||
coffee-rails
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (2.2.1)
|
||||
uglifier (2.7.0)
|
||||
execjs (>= 0.3.0)
|
||||
multi_json (~> 1.0, >= 1.0.2)
|
||||
json (>= 1.8.0)
|
||||
warden (1.2.3)
|
||||
rack (>= 1.0)
|
||||
web-console (2.0.0)
|
||||
activemodel (~> 4.0)
|
||||
binding_of_caller (>= 0.7.2)
|
||||
railties (~> 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
whenever (0.9.4)
|
||||
chronic (>= 0.6.3)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
@ -309,7 +353,6 @@ DEPENDENCIES
|
||||
high_voltage (~> 2.1.0)
|
||||
hstore_translate
|
||||
http_accept_language
|
||||
inherited_resources
|
||||
jbuilder
|
||||
jquery-rails
|
||||
kaminari
|
||||
@ -318,21 +361,25 @@ DEPENDENCIES
|
||||
paranoia
|
||||
pg (= 0.17.1)
|
||||
pundit
|
||||
rails (~> 4.1)
|
||||
rails (~> 4.2)
|
||||
rails-erd
|
||||
rails-i18n
|
||||
rails_12factor
|
||||
rake
|
||||
rdiscount
|
||||
responders (~> 2.0)
|
||||
rest-client
|
||||
rollbar
|
||||
rspec-rails (~> 2.14)
|
||||
rubocop
|
||||
sass-rails (= 4.0.5)
|
||||
shelly-dependencies
|
||||
shoulda (>= 3.5)
|
||||
simple_form (>= 3.0.0)
|
||||
textacular (~> 3.0)
|
||||
textacular (= 3.2.1)
|
||||
thin
|
||||
travis-lint
|
||||
turbolinks
|
||||
uglifier (>= 1.0.3)
|
||||
web-console (~> 2.0)
|
||||
whenever
|
||||
|
||||
12
README.md
12
README.md
@ -15,7 +15,7 @@ con tres niveles de privilegios: superadmin, admin (solo gestiona un Banco) y mi
|
||||
|
||||
TimeOverflow está dividido en 2 grandes bloques:
|
||||
* **Sistema de gestión**
|
||||
* **Red social y banca on-line**
|
||||
* **Red social y banca on-line para los usuarios**
|
||||
|
||||
*NOTA: Un Banco de Tiempo físico puede funcionar solo con el bloque de gestión, podría ocurrir, por ejemplo, que la inmensa*
|
||||
*mayoria de sus miembros no usen Internet y podrían querer funcionar solo con listados, cheques y una oficina de gestión*
|
||||
@ -73,17 +73,9 @@ OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
Wireframes
|
||||
=======
|
||||
|
||||
https://moqups.com/sseerrggii/JIu1Z1eD/
|
||||
|
||||
|
||||
|
||||
|
||||
Notas para desarrollo
|
||||
=====================
|
||||
Únete al equipo de colaboradores!! Gestionamos las tareas en Redbooth.com https://redbooth.com/public/timeoverflow
|
||||
Únete al equipo de colaboradores!! Gestionamos las tareas en Redbooth.com
|
||||
|
||||
Si quieres probar la plataforma en local, necesitas PostgreSQL y ruby en sus últimas versiones.
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
ActiveAdmin.register Category do
|
||||
|
||||
index do
|
||||
selectable_column
|
||||
id_column
|
||||
@ -24,7 +23,7 @@ ActiveAdmin.register Category do
|
||||
I18n.available_locales.map do |loc|
|
||||
next unless cat.send("name_#{loc}")
|
||||
content_tag(:strong, "#{loc}: ") +
|
||||
content_tag(:span, cat.send("name_#{loc}"))
|
||||
content_tag(:span, cat.send("name_#{loc}"))
|
||||
end.compact.sum
|
||||
end
|
||||
end
|
||||
@ -33,5 +32,4 @@ ActiveAdmin.register Category do
|
||||
end
|
||||
|
||||
permit_params :name
|
||||
|
||||
end
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
ActiveAdmin.register_page "Dashboard" do
|
||||
menu priority: 1, label: proc { I18n.t("active_admin.dashboard") }
|
||||
|
||||
menu :priority => 1, :label => proc{ I18n.t("active_admin.dashboard") }
|
||||
|
||||
content :title => proc{ I18n.t("active_admin.dashboard") } do
|
||||
|
||||
content title: proc { I18n.t("active_admin.dashboard") } do
|
||||
columns do
|
||||
column do
|
||||
panel "Recent Organizations" do
|
||||
@ -31,6 +29,5 @@ ActiveAdmin.register_page "Dashboard" do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
ActiveAdmin.register Document do
|
||||
permit_params *Document.attribute_names
|
||||
|
||||
index do |t|
|
||||
index do
|
||||
selectable_column
|
||||
id_column
|
||||
column :documentable
|
||||
|
||||
@ -2,7 +2,9 @@ ActiveAdmin.register Organization do
|
||||
index do
|
||||
id_column
|
||||
column :name
|
||||
column :created_at do |organization| l organization.created_at.to_date, format: :short end
|
||||
column :created_at do |organization|
|
||||
l organization.created_at.to_date, format: :short
|
||||
end
|
||||
column :city
|
||||
column :neighborhood
|
||||
column :email
|
||||
@ -26,9 +28,8 @@ ActiveAdmin.register Organization do
|
||||
end
|
||||
|
||||
filter :name
|
||||
filter :city, as: :select, collection: -> { Organization.pluck('city').uniq }
|
||||
filter :city, as: :select, collection: -> { Organization.pluck(:city).uniq }
|
||||
filter :neighborhood
|
||||
|
||||
permit_params *Organization.attribute_names
|
||||
|
||||
end
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
ActiveAdmin.register Post do
|
||||
|
||||
index do
|
||||
selectable_column
|
||||
id_column
|
||||
column :class
|
||||
column :title
|
||||
column :created_at do |post| l post.created_at.to_date, format: :short end
|
||||
column :created_at do |post|
|
||||
l post.created_at.to_date, format: :short
|
||||
end
|
||||
column :user
|
||||
column :category
|
||||
column :tag_list
|
||||
@ -33,5 +34,4 @@ ActiveAdmin.register Post do
|
||||
filter :organization
|
||||
filter :category
|
||||
filter :created_at
|
||||
|
||||
end
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
# coding: utf-8
|
||||
|
||||
ActiveAdmin.register User do
|
||||
action_item :only => :index do
|
||||
link_to I18n.t("active_admin.users.upload_from_csv"), :action => 'upload_csv'
|
||||
action_item only: :index do
|
||||
link_to I18n.t("active_admin.users.upload_from_csv"), action: "upload_csv"
|
||||
end
|
||||
|
||||
collection_action :upload_csv do
|
||||
render "admin/csv/upload_csv"
|
||||
end
|
||||
|
||||
collection_action :import_csv, :method => :post do
|
||||
errors = CsvDb.convert_save(params[:dump][:organization_id], params[:dump][:file])
|
||||
collection_action :import_csv, method: :post do
|
||||
errors = CsvDb.convert_save(params[:dump][:organization_id],
|
||||
params[:dump][:file])
|
||||
flash[:error] = errors.join("<br/>").html_safe if errors.present?
|
||||
redirect_to :action => :index
|
||||
redirect_to action: :index
|
||||
end
|
||||
|
||||
index do
|
||||
@ -37,7 +38,7 @@ ActiveAdmin.register User do
|
||||
f.inputs "Admin Details" do
|
||||
f.input :username
|
||||
f.input :email
|
||||
f.input :gender, :as => :select, :collection => User::GENDERS
|
||||
f.input :gender, as: :select, collection: User::GENDERS
|
||||
f.input :identity_document
|
||||
end
|
||||
f.inputs "Members" do
|
||||
@ -72,5 +73,6 @@ ActiveAdmin.register User do
|
||||
end
|
||||
end
|
||||
|
||||
permit_params *User.attribute_names, members_attributes: Member.attribute_names
|
||||
permit_params *User.attribute_names,
|
||||
members_attributes: Member.attribute_names
|
||||
end
|
||||
|
||||
@ -11,8 +11,6 @@
|
||||
*= require_self
|
||||
*/
|
||||
|
||||
@import "flags";
|
||||
|
||||
.post {
|
||||
border-top: solid black 1px;
|
||||
list-style: none;
|
||||
@ -129,3 +127,12 @@ ul.statistics li{
|
||||
.ui-datepicker{
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
// fields that contain an error
|
||||
.field_with_errors{
|
||||
color: red;
|
||||
}
|
||||
|
||||
label[required]::after{
|
||||
content: " *";
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ class ApplicationController < ActionController::Base
|
||||
if user.members.any? &:manager
|
||||
users_path
|
||||
else
|
||||
offers_path
|
||||
users_path
|
||||
end
|
||||
else
|
||||
page_path("home")
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
class DocumentsController < InheritedResources::Base
|
||||
class DocumentsController < ApplicationController
|
||||
respond_to :html, :js
|
||||
|
||||
def show
|
||||
@document = Document.new(title: 'Missing document', content: 'Available very soon') if Document.find_by_id(params[:id]).blank?
|
||||
show! do |format|
|
||||
@document = find_document_or_missing
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
if params[:modal]
|
||||
render "show+modal", layout: false
|
||||
@ -11,4 +11,12 @@ class DocumentsController < InheritedResources::Base
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_document_or_missing
|
||||
Document.find params[:id]
|
||||
rescue ActiveRecord::NotFound
|
||||
Document.new(title: "Missing document", content: "Available very soon")
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
class InquiriesController < PostsController
|
||||
|
||||
def model
|
||||
Inquiry
|
||||
end
|
||||
end
|
||||
|
||||
@ -2,14 +2,15 @@ class MembersController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
||||
def destroy
|
||||
user_id = Member.find(params[:id]).user_id
|
||||
current_organization.members.find(params[:id]).destroy
|
||||
current_organization.posts.where(user_id: user_id).destroy_all
|
||||
find_member
|
||||
current_organization.posts.where(user_id: @member.user_id).destroy_all
|
||||
@member.destroy
|
||||
redirect_to users_path
|
||||
end
|
||||
|
||||
def toggle_manager
|
||||
current_organization.members.find(params[:id]).toggle(:manager).save!
|
||||
find_member
|
||||
@member.toggle(:manager).save!
|
||||
respond_to do |format|
|
||||
format.json { head :ok }
|
||||
format.html { redirect_to :back }
|
||||
@ -17,11 +18,17 @@ class MembersController < ApplicationController
|
||||
end
|
||||
|
||||
def toggle_active
|
||||
current_organization.members.find(params[:id]).toggle(:active).save!
|
||||
find_member
|
||||
@member.toggle(:active).save!
|
||||
respond_to do |format|
|
||||
format.json { head :ok }
|
||||
format.html { redirect_to :back }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_member
|
||||
@member ||= current_organization.members.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
# Managems of offer-type posts
|
||||
#
|
||||
class OffersController < PostsController
|
||||
def model
|
||||
Offer
|
||||
end
|
||||
|
||||
def dashboard
|
||||
initial_scope =
|
||||
if current_organization
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
class OrganizationsController < ApplicationController
|
||||
|
||||
respond_to :json, :html
|
||||
|
||||
before_filter :load_resource
|
||||
@ -12,7 +11,6 @@ class OrganizationsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def new
|
||||
@organization = Organization.new
|
||||
end
|
||||
@ -49,19 +47,33 @@ class OrganizationsController < ApplicationController
|
||||
|
||||
def give_time
|
||||
@destination = @organization.account.id
|
||||
@source = current_user.members.find_by(organization: @organization).account.id
|
||||
@offer = current_organization.offers.find(params[:offer]) if params[:offer].present?
|
||||
@source = find_transfer_source
|
||||
@offer = find_transfer_offer
|
||||
@transfer = Transfer.new(source: @source, destination: @destination)
|
||||
if admin?
|
||||
@sources = [current_organization.account] + current_organization.member_accounts.where("members.active is true")
|
||||
end
|
||||
@sources = find_transfer_sources_for_admin
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def organization_params
|
||||
params[:organization].permit(*%w"name theme email phone web public_opening_times description address neighborhood city domain")
|
||||
params[:organization].permit(*%w[name theme email phone web
|
||||
public_opening_times description address
|
||||
neighborhood city domain])
|
||||
end
|
||||
|
||||
def find_transfer_offer
|
||||
current_organization.offers.
|
||||
find(params[:offer]) if params[:offer].present?
|
||||
end
|
||||
|
||||
def find_transfer_source
|
||||
current_user.members.
|
||||
find_by(organization: @organization).account.id
|
||||
end
|
||||
|
||||
def find_transfer_sources_for_admin
|
||||
return unless admin?
|
||||
[current_organization.account] +
|
||||
current_organization.member_accounts.where("members.active is true")
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
class PostsController < InheritedResources::Base
|
||||
class PostsController < ApplicationController
|
||||
respond_to :html, :js
|
||||
|
||||
has_scope :by_category, as: :cat
|
||||
@ -6,21 +6,63 @@ class PostsController < InheritedResources::Base
|
||||
has_scope :tagged_with, as: :tag
|
||||
has_scope :by_organization, as: :org
|
||||
|
||||
before_action only: %i[update destroy] do
|
||||
authorize resource
|
||||
def index
|
||||
posts = apply_scopes(model).page(params[:page]).per(25)
|
||||
instance_variable_set("@#{resources}", posts)
|
||||
end
|
||||
|
||||
protected
|
||||
def new
|
||||
post = model.new
|
||||
post.user = current_user
|
||||
instance_variable_set("@#{resource}", post)
|
||||
end
|
||||
|
||||
def collection
|
||||
get_collection_ivar || begin
|
||||
c = end_of_association_chain
|
||||
set_collection_ivar(c.page(params[:page]).per(25))
|
||||
def create
|
||||
post = model.new(post_params)
|
||||
post.organization = current_organization
|
||||
if post.save
|
||||
redirect_to send("#{resource}_path", post)
|
||||
else
|
||||
instance_variable_set("@#{resource}", post)
|
||||
render action: :new
|
||||
end
|
||||
end
|
||||
|
||||
def begin_of_association_chain
|
||||
current_organization
|
||||
def edit
|
||||
post = current_organization.posts.find params[:id]
|
||||
instance_variable_set("@#{resource}", post)
|
||||
end
|
||||
|
||||
def show
|
||||
post = current_organization.posts.find params[:id]
|
||||
instance_variable_set("@#{resource}", post)
|
||||
end
|
||||
|
||||
def update
|
||||
post = current_organization.posts.find params[:id]
|
||||
authorize post
|
||||
instance_variable_set("@#{resource}", post)
|
||||
if post.update_attributes(post_params)
|
||||
redirect_to post
|
||||
else
|
||||
render action: :edit, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
post = current_organization.posts.find params[:id]
|
||||
authorize post
|
||||
redirect_to send("#{resources}_path") if post.destroy
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resource
|
||||
controller_name.singularize
|
||||
end
|
||||
|
||||
def resources
|
||||
controller_name
|
||||
end
|
||||
|
||||
def set_user_id(p)
|
||||
@ -32,13 +74,12 @@ class PostsController < InheritedResources::Base
|
||||
end
|
||||
end
|
||||
|
||||
def build_resource_params
|
||||
def post_params
|
||||
permitted_fields = %i[description end_on global joinable permanent start_on
|
||||
title category_id tag_list user_id publisher_id]
|
||||
|
||||
[
|
||||
params.fetch(resource_instance_name, {}).
|
||||
permit(*permitted_fields).tap { |p| set_user_id(p) }
|
||||
]
|
||||
params.fetch(resource, {}).permit(*permitted_fields).tap do |p|
|
||||
set_user_id(p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -4,12 +4,17 @@ class ReportsController < ApplicationController
|
||||
layout "report"
|
||||
|
||||
def user_list
|
||||
@members = current_organization.members.active.includes(:user).order("members.member_uid")
|
||||
@members = current_organization.members.active.
|
||||
includes(:user).
|
||||
order("members.member_uid")
|
||||
end
|
||||
|
||||
def post_list
|
||||
@post_type = (params[:type] || "offer").capitalize.constantize
|
||||
@posts = current_organization.posts.with_member.where(type: @post_type).group_by(&:category).to_a.sort_by {|c, p| c.try(:name) || ""}
|
||||
@posts = current_organization.posts.with_member.
|
||||
where(type: @post_type).
|
||||
group_by(&:category).
|
||||
to_a.
|
||||
sort_by { |category, _| category.try(:name).to_s }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -1,8 +1,19 @@
|
||||
class StatisticsController < ApplicationController
|
||||
before_filter :authenticate_user!
|
||||
|
||||
AGE_GROUP_LABELS = {
|
||||
0..17 => " -17",
|
||||
18..24 => "18-24",
|
||||
25..34 => "25-34",
|
||||
35..44 => "35-44",
|
||||
45..54 => "45-54",
|
||||
55..64 => "55-64",
|
||||
65..100 => "65+",
|
||||
}
|
||||
|
||||
def statistics_global_activity
|
||||
@members = current_organization.members
|
||||
@active_members = @members.active
|
||||
@total_hours = num_movements = 0
|
||||
@members.each do |m|
|
||||
num_movements += m.account.movements.count
|
||||
@ -57,46 +68,22 @@ class StatisticsController < ApplicationController
|
||||
end
|
||||
|
||||
def statistics_inactive_users
|
||||
@members = current_organization.members
|
||||
@members = current_organization.members.active
|
||||
end
|
||||
|
||||
def statistics_demographics
|
||||
@members = current_organization.members
|
||||
|
||||
@age_groups = @members.group_by do |member|
|
||||
case (age(member.user.date_of_birth.presence) rescue nil)
|
||||
when 0..17 then " -17"
|
||||
when 18..24 then "18-24"
|
||||
when 25..34 then "25-34"
|
||||
when 35..44 then "35-44"
|
||||
when 45..54 then "45-54"
|
||||
when 55..64 then "55-64"
|
||||
when 65..100 then "65+"
|
||||
else t("statistics.statistics_demographics.unknown")
|
||||
end
|
||||
end
|
||||
|
||||
@age_counts = Hash[@age_groups.map { |name, group| [name, group.size] }]
|
||||
|
||||
@gender_groups = @members.group_by do |member|
|
||||
case member.user_gender
|
||||
when "male" then t("statistics.statistics_demographics.male")
|
||||
when "female" then t("statistics.statistics_demographics.female")
|
||||
else t("statistics.statistics_demographics.unknown")
|
||||
end
|
||||
end
|
||||
@gender_counts = Hash[@gender_groups.map do |name, group|
|
||||
[name, group.size]
|
||||
end]
|
||||
@age_counts = age_counts
|
||||
@gender_counts = gender_counts
|
||||
end
|
||||
|
||||
def statistics_last_login
|
||||
@members = current_organization.members.joins(:user).
|
||||
@members = current_organization.members.active.joins(:user).
|
||||
order("users.current_sign_in_at ASC NULLS FIRST")
|
||||
end
|
||||
|
||||
def statistics_without_offers
|
||||
@members = current_organization.members
|
||||
@members = current_organization.members.active
|
||||
end
|
||||
|
||||
def statistics_type_swaps
|
||||
@ -107,64 +94,78 @@ class StatisticsController < ApplicationController
|
||||
count_of_transfers").
|
||||
where("movements.amount > 0").
|
||||
group("posts.tags, posts.category_id, posts.updated_at")
|
||||
total = 0.0
|
||||
offers_array = offers.map do |offer|
|
||||
if offer.category_id.blank?
|
||||
if offer.tags.blank?
|
||||
total += offer.count_of_transfers
|
||||
[[t("statistics.statistics_type_swaps.without_category"),
|
||||
t("statistics.statistics_type_swaps.without_tags"),
|
||||
offer.sum_of_transfers, offer.count_of_transfers]]
|
||||
else
|
||||
offer.tags.map do |tag|
|
||||
total += offer.count_of_transfers
|
||||
[t("statistics.statistics_type_swaps.without_category"), tag,
|
||||
offer.sum_of_transfers, offer.count_of_transfers]
|
||||
end
|
||||
end
|
||||
elsif offer.tags.blank?
|
||||
total += offer.count_of_transfers
|
||||
[[offer.category.name,
|
||||
t("statistics.statistics_type_swaps.without_tags"),
|
||||
offer.sum_of_transfers, offer.count_of_transfers]]
|
||||
else
|
||||
offer.tags.map do |tag|
|
||||
total += offer.count_of_transfers
|
||||
[offer.category.name, tag, offer.sum_of_transfers,
|
||||
offer.count_of_transfers]
|
||||
end
|
||||
end
|
||||
end.flatten(1)
|
||||
# ["Clases", "clases", 11700, 2], ["Clases", "clases", 1320, 1], ...]
|
||||
# added %
|
||||
offers_array = offers_array.map { |a| a.push(a.last / total) }
|
||||
offers_array = offers_array.group_by { |a, b| [a, b] }
|
||||
# {["Clases", "clases"]=>[["Clases", "clases", 11700, 2, 0.2],
|
||||
# ["Clases", "clases", 1320, 1, 0.1]],,...}
|
||||
@offers = []
|
||||
offers_array.each do |cat_tag, values|
|
||||
sum_of_transfers, count_of_transfers, percent = 0, 0, 0
|
||||
values.each do |value|
|
||||
sum_of_transfers += value[2]
|
||||
count_of_transfers += value[3]
|
||||
percent += value[4]
|
||||
end
|
||||
@offers.push([cat_tag, sum_of_transfers,
|
||||
count_of_transfers, percent].flatten)
|
||||
end
|
||||
# [["Clases", "clases", 13020, 3, 0.30],
|
||||
# ["Domestic", "coche", 2220, 1, 0.1],...]
|
||||
@offers = @offers.sort_by(&:last).reverse
|
||||
|
||||
@offers = count_offers_by_label(offers).to_a.each { |a| a.flatten!(1) }.
|
||||
sort_by(&:last).reverse
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def age(date_of_birth)
|
||||
now = DateTime.now
|
||||
age = now.year - date_of_birth.year
|
||||
age -= 1 if (now.month < date_of_birth.month) ||
|
||||
(now.month == date_of_birth.month &&
|
||||
now.day < date_of_birth.day)
|
||||
age
|
||||
return unless date_of_birth
|
||||
age_in_days = Date.today - date_of_birth
|
||||
(age_in_days / 365.26).to_i
|
||||
end
|
||||
|
||||
# returns a hash of
|
||||
# {
|
||||
# [ category_label, tag_label ] => [ sum, count, ratio ],
|
||||
# ...
|
||||
# }
|
||||
def count_offers_by_label(offers)
|
||||
# Cannot use Hash.new([0, 0]) because then
|
||||
# counters[key][0] += n
|
||||
# will modify directly the "global default" instead of
|
||||
# first assigning a new array with the zeroed counters.
|
||||
counters = Hash.new { |h, k| h[k] = [0, 0] }
|
||||
offers.each do |offer|
|
||||
labels_for_offer(offer).each do |labels|
|
||||
# labels = [ category_label, tag_label ]
|
||||
counters[labels][0] += offer.sum_of_transfers
|
||||
counters[labels][1] += offer.count_of_transfers
|
||||
end
|
||||
end
|
||||
add_ratios!(counters)
|
||||
counters
|
||||
end
|
||||
|
||||
def add_ratios!(counters)
|
||||
# add the ratio at the end of each value
|
||||
total_count = counters.values.map { |_, counts| counts }.sum
|
||||
counters.each do |_, v|
|
||||
v << v[1].to_f / total_count
|
||||
end
|
||||
end
|
||||
|
||||
# returns an array of
|
||||
# [category_name, tag_name]
|
||||
# one item per each tag. If the category or the tags are missing, they are
|
||||
# replaced with a fallback "Unknown" label.
|
||||
def labels_for_offer(offer)
|
||||
tag_labels = offer.tags.presence ||
|
||||
[t("statistics.statistics_type_swaps.without_tags")]
|
||||
|
||||
category_label = offer.category.try(:name) ||
|
||||
t("statistics.statistics_type_swaps.without_category")
|
||||
|
||||
[category_label].product(tag_labels)
|
||||
end
|
||||
|
||||
def age_counts
|
||||
@members.each_with_object(Hash.new(0)) do |member, counts|
|
||||
age = age(member.user_date_of_birth)
|
||||
age_label = AGE_GROUP_LABELS.detect do |range, _|
|
||||
range.include? age
|
||||
end.try(:last) || t("statistics.statistics_demographics.unknown")
|
||||
counts[age_label] += 1
|
||||
end
|
||||
end
|
||||
|
||||
def gender_counts
|
||||
@members.each_with_object(Hash.new(0)) do |member, counts|
|
||||
gender = member.user_gender || "unknown"
|
||||
gender_label = t("statistics.statistics_demographics.#{gender}")
|
||||
counts[gender_label] += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -10,5 +10,4 @@ class TermsController < ApplicationController
|
||||
current_user.touch :terms_accepted_at
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -1,18 +1,39 @@
|
||||
class TransfersController < ApplicationController
|
||||
def create
|
||||
@source = if admin?
|
||||
Account.find(transfer_params[:source])
|
||||
else
|
||||
current_user.members.find_by(organization: current_organization).account
|
||||
end
|
||||
@source = find_source
|
||||
Transfer.create(transfer_params.merge source: @source)
|
||||
account = Account.find(transfer_params[:destination])
|
||||
redirect_to account.accountable_type == "Organization" ? account.accountable : account.accountable.user
|
||||
@account = Account.find(transfer_params[:destination])
|
||||
redirect_to redirect_target
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def transfer_params
|
||||
params.require(:transfer).permit(*[:destination, :amount, :reason, :post_id, (:source if admin?)].compact)
|
||||
def find_source
|
||||
if admin?
|
||||
Account.find(transfer_params[:source])
|
||||
else
|
||||
current_user.members.find_by(organization: current_organization).account
|
||||
end
|
||||
end
|
||||
|
||||
def redirect_target
|
||||
case accountable = @account.accountable
|
||||
when Organization
|
||||
accountable
|
||||
when Member
|
||||
accountable.user
|
||||
else
|
||||
raise ArgumentError
|
||||
end
|
||||
end
|
||||
|
||||
def transfer_params
|
||||
params.
|
||||
require(:transfer).
|
||||
permit(:destination,
|
||||
:amount,
|
||||
:reason,
|
||||
:post_id,
|
||||
*[*(:source if admin?)])
|
||||
end
|
||||
end
|
||||
|
||||
@ -17,7 +17,7 @@ class UsersController < ApplicationController
|
||||
|
||||
def show
|
||||
@user = current_user if current_user.id == params[:id].to_i
|
||||
@user ||= scoped_users.find(params[:id])
|
||||
@user ||= scoped_users.find(params[:id])
|
||||
end
|
||||
|
||||
def new
|
||||
@ -40,7 +40,18 @@ class UsersController < ApplicationController
|
||||
|
||||
if @user.persisted?
|
||||
@user.tune_after_persisted(current_organization)
|
||||
redirect_to users_path
|
||||
id = @user.member(current_organization).member_uid
|
||||
if params[:more]
|
||||
redirect_to new_user_path,
|
||||
notice: I18n.t("users.new.user_created_add",
|
||||
uid: id,
|
||||
name: @user.username)
|
||||
else
|
||||
redirect_to users_path,
|
||||
notice: I18n.t("users.index.user_created",
|
||||
uid: id,
|
||||
name: @user.username)
|
||||
end
|
||||
else
|
||||
@user.email = "" if empty_email
|
||||
render action: "new"
|
||||
@ -61,18 +72,12 @@ class UsersController < ApplicationController
|
||||
@user = scoped_users.find(params[:id])
|
||||
@destination = @user.members.
|
||||
find_by(organization: current_organization).account.id
|
||||
@source = current_user.members.
|
||||
find_by(organization: current_organization).account.id
|
||||
@offer = current_organization.offers.
|
||||
find(params[:offer]) if params[:offer].present?
|
||||
@source = find_transfer_source
|
||||
@offer = find_transfer_offer
|
||||
@transfer = Transfer.new(source: @source,
|
||||
destination: @destination,
|
||||
post: @offer)
|
||||
if admin?
|
||||
@sources = [current_organization.account] +
|
||||
current_organization.
|
||||
member_accounts.where("members.active is true")
|
||||
end
|
||||
@sources = find_transfer_sources_for_admin
|
||||
end
|
||||
|
||||
def toggle_active
|
||||
@ -100,4 +105,20 @@ class UsersController < ApplicationController
|
||||
# params[:user].permit(*fields_to_permit).tap &method(:ap)
|
||||
params.require(:user).permit *fields_to_permit
|
||||
end
|
||||
|
||||
def find_transfer_offer
|
||||
current_organization.offers.
|
||||
find(params[:offer]) if params[:offer].present?
|
||||
end
|
||||
|
||||
def find_transfer_source
|
||||
current_user.members.
|
||||
find_by(organization: current_organization).account.id
|
||||
end
|
||||
|
||||
def find_transfer_sources_for_admin
|
||||
return unless admin?
|
||||
[current_organization.account] +
|
||||
current_organization.member_accounts.where("members.active is true")
|
||||
end
|
||||
end
|
||||
|
||||
@ -42,17 +42,12 @@ module ApplicationHelper
|
||||
end
|
||||
|
||||
def languages_list
|
||||
locales = I18n.available_locales
|
||||
|
||||
locales.map do |locale|
|
||||
content_tag(:li, class: I18n.locale == locale ? :disabled : "") do
|
||||
locale_key = "locales.#{locale}"
|
||||
link_to switch_lang_path(locale: locale) do
|
||||
concat t(locale_key, locale: locale)
|
||||
concat " (#{t(locale_key)})" unless I18n.locale == locale
|
||||
end
|
||||
end
|
||||
end.join.html_safe
|
||||
I18n.available_locales.each do |locale|
|
||||
concat content_tag(:li,
|
||||
link_to(locale_menu_item(locale),
|
||||
switch_lang_path(locale: locale)),
|
||||
class: ("disabled" if I18n.locale == locale))
|
||||
end
|
||||
end
|
||||
|
||||
def show_error_messages!(resource)
|
||||
@ -69,4 +64,12 @@ module ApplicationHelper
|
||||
|
||||
html.html_safe
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def locale_menu_item(locale)
|
||||
t("locales.#{locale}", locale: locale).tap do |s|
|
||||
s << " (#{t("locales.#{locale}")})" unless I18n.locale == locale
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,17 +1,22 @@
|
||||
module GlyphHelper
|
||||
|
||||
GLYPHS = Hash[
|
||||
GLYPHS = {
|
||||
"offer" => "hand-up",
|
||||
"inquiry" => "bell",
|
||||
"user" => "user",
|
||||
"tag" => "tag",
|
||||
"category" => "folder-open",
|
||||
"organization" => "tower"
|
||||
]
|
||||
}
|
||||
|
||||
def glyph(kind)
|
||||
kind = kind.to_s.underscore
|
||||
content_tag :span, "", class: "glyphicon glyphicon-#{GLYPHS.fetch kind, kind.gsub("_", "-")}"
|
||||
content_tag :span, "",
|
||||
class: "glyphicon glyphicon-#{glyph_name(kind)}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def glyph_name(kind)
|
||||
GLYPHS.fetch kind, kind.dasherize
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
module UsersHelper
|
||||
|
||||
# TODO refactor or eliminate - poosibly the second.
|
||||
def users_as_json
|
||||
@users = (admin? || superadmin?)? @users : @users.actives
|
||||
@users = (admin? || superadmin?) ? @users : @users.actives
|
||||
@users.map do |user|
|
||||
membership = @memberships[user.id]
|
||||
{
|
||||
@ -16,14 +16,48 @@ module UsersHelper
|
||||
balance: membership.account_balance.to_i,
|
||||
|
||||
url: user_path(user),
|
||||
edit_link: (superadmin? || admin? || user == current_user) ? edit_user_path(user) : "",
|
||||
cancel_link: (superadmin? || admin?) ? member_path(membership) : "",
|
||||
toggle_manager_link: ((superadmin? || admin?) && user != current_user) ? toggle_manager_member_path(membership) : "",
|
||||
edit_link: edit_user_path(user),
|
||||
cancel_link: cancel_member_path(membership),
|
||||
toggle_manager_link: toggle_manager_member_path(membership),
|
||||
manager: !!membership.manager,
|
||||
toggle_active_link: (superadmin? || admin?) ? toggle_active_member_path(membership) : "",
|
||||
toggle_active_link: toggle_active_member_path(membership),
|
||||
active: membership.active?,
|
||||
valid_email: user.has_valid_email?
|
||||
}
|
||||
end.to_json.html_safe
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def edit_user_path(user)
|
||||
can_edit_user?(user) ? super : ""
|
||||
end
|
||||
|
||||
def can_edit_user?(user)
|
||||
superadmin? || admin? || user == current_user
|
||||
end
|
||||
|
||||
def cancel_member_path(member)
|
||||
can_cancel_member?(member) ? member_path(member) : ""
|
||||
end
|
||||
|
||||
def can_cancel_member?(_member)
|
||||
superadmin? || admin?
|
||||
end
|
||||
|
||||
def toggle_manager_member_path(member)
|
||||
can_toggle_manager?(member) ? super : ""
|
||||
end
|
||||
|
||||
def can_toggle_manager?(member)
|
||||
(superadmin? || admin?) && member.user != current_user
|
||||
end
|
||||
|
||||
def toggle_active_member_path(member)
|
||||
can_toggle_active?(member) ? super : ""
|
||||
end
|
||||
|
||||
def can_toggle_active?(_member)
|
||||
superadmin? || admin?
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
class CollectionSelect2Input < SimpleForm::Inputs::CollectionSelectInput
|
||||
def input_html_classes
|
||||
super.push('select2')
|
||||
super.push("select2")
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
class DatepickerInput < SimpleForm::Inputs::Base
|
||||
def input
|
||||
@builder.text_field(attribute_name, input_html_options) + \
|
||||
@builder.hidden_field(attribute_name, { :class => attribute_name.to_s + "-alt" })
|
||||
@builder.hidden_field(attribute_name, class: attribute_name.to_s + "-alt")
|
||||
end
|
||||
end
|
||||
|
||||
20
app/mailers/organization_notifier.rb
Normal file
20
app/mailers/organization_notifier.rb
Normal file
@ -0,0 +1,20 @@
|
||||
class OrganizationNotifier < ActionMailer::Base
|
||||
default from: "\"TimeOverflow\" <info@timeoverflow.org>"
|
||||
|
||||
# Subject can be set in your I18n file at config/locales/en.yml
|
||||
# with the following lookup:
|
||||
#
|
||||
# en.organization_notifier.recent_posts.subject
|
||||
#
|
||||
def recent_posts(posts)
|
||||
# last 10 posts of offers and inquiries
|
||||
@offers = posts.where(type: "Offer").take(10)
|
||||
@inquiries = posts.where(type: "Inquiry").take(10)
|
||||
|
||||
@organization_name = posts.take.organization.name
|
||||
# users with email ok
|
||||
emails = posts.take.organization.users.online_active.actives.pluck(:email)
|
||||
|
||||
mail(bcc: emails)
|
||||
end
|
||||
end
|
||||
@ -16,7 +16,7 @@ class Account < ActiveRecord::Base
|
||||
new_balance = movements.sum(:amount)
|
||||
self.balance = new_balance
|
||||
if balance_changed?
|
||||
self.flagged = !allowed?(self.balance)
|
||||
self.flagged = !allowed?(balance)
|
||||
end
|
||||
save
|
||||
end
|
||||
@ -24,7 +24,11 @@ class Account < ActiveRecord::Base
|
||||
# Return the maximum allowed amount of time that the acccount is able to
|
||||
# spend without overflowing
|
||||
def allowance
|
||||
min_allowed_balance ? [0, balance - min_allowed_balance].min : Float::INFINITY
|
||||
if min_allowed_balance
|
||||
[0, balance - min_allowed_balance].min
|
||||
else
|
||||
Float::INFINITY
|
||||
end
|
||||
end
|
||||
|
||||
# Print the account as its accountable reference
|
||||
@ -35,8 +39,7 @@ class Account < ActiveRecord::Base
|
||||
private
|
||||
|
||||
def allowed?(new_balance)
|
||||
new_balance < (max_allowed_balance || Float::INFINITY) and
|
||||
new_balance < (max_allowed_balance || Float::INFINITY) &&
|
||||
new_balance > (min_allowed_balance || -Float::INFINITY)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
class Category < ActiveRecord::Base
|
||||
has_many :posts
|
||||
|
||||
|
||||
translates :name
|
||||
def to_s
|
||||
name
|
||||
|
||||
@ -8,7 +8,7 @@ class CsvDb
|
||||
gender: User::GENDERS[row[5].to_i - 1])
|
||||
end
|
||||
|
||||
def member_from_row(row, user)
|
||||
def member_from_row(row, user, organization, errors)
|
||||
member = organization.members.create(member_uid: row[0],
|
||||
entry_date: row[1],
|
||||
user_id: user.id)
|
||||
@ -17,12 +17,12 @@ class CsvDb
|
||||
) if member.errors.present?
|
||||
end
|
||||
|
||||
def process_row(row)
|
||||
def process_row(row, organization, errors)
|
||||
user = user_from_row(row)
|
||||
user.skip_confirmation! # auto-confirm, not sending confirmation email
|
||||
|
||||
if user.save
|
||||
member_from_row(row, user)
|
||||
member_from_row(row, user, organization, errors)
|
||||
else
|
||||
errors.push(member_id: row[0], email: row[9],
|
||||
errors: user.errors.full_messages)
|
||||
@ -36,7 +36,7 @@ class CsvDb
|
||||
organization = Organization.find(organization_id)
|
||||
errors = []
|
||||
CSV.parse(data, headers: false) do |row|
|
||||
process_row(row)
|
||||
process_row(row, organization, errors)
|
||||
end
|
||||
organization.ensure_reg_number_seq!
|
||||
errors
|
||||
|
||||
@ -4,5 +4,4 @@ class Document < ActiveRecord::Base
|
||||
def self.terms_and_conditions
|
||||
where(label: "t&c", documentable_id: nil).first
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -4,10 +4,11 @@ class Member < ActiveRecord::Base
|
||||
|
||||
has_one :account, as: :accountable
|
||||
delegate :balance, to: :account, prefix: true, allow_nil: true
|
||||
delegate :gender, to: :user, prefix: true, allow_nil: true
|
||||
delegate :gender, :date_of_birth, to: :user, prefix: true, allow_nil: true
|
||||
|
||||
after_create :create_account
|
||||
before_validation :assign_registration_number, on: :create
|
||||
after_destroy :remove_orphaned_users
|
||||
|
||||
scope :by_month, -> (month) {
|
||||
where(created_at: month.beginning_of_month..month.end_of_month)
|
||||
@ -34,4 +35,10 @@ class Member < ActiveRecord::Base
|
||||
def offers
|
||||
Post.where(organization: organization, user: user, type: "Offer")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def remove_orphaned_users
|
||||
user.destroy if user && user.members.empty?
|
||||
end
|
||||
end
|
||||
|
||||
@ -13,7 +13,13 @@ class Movement < ActiveRecord::Base
|
||||
account.update_balance
|
||||
end
|
||||
|
||||
has_one :other_side, (->(self_) { where ["NOT movements.id = #{self_.id}"] }), through: :transfer, source: :movements
|
||||
has_one :other_side,
|
||||
(->(self_) { where ["NOT movements.id = #{self_.id}"] }),
|
||||
through: :transfer,
|
||||
source: :movements
|
||||
|
||||
scope :by_month, ->(month) { where({ created_at: month.beginning_of_month..month.end_of_month})}
|
||||
scope :by_month,
|
||||
->(month) {
|
||||
where(created_at: month.beginning_of_month..month.end_of_month)
|
||||
}
|
||||
end
|
||||
|
||||
@ -1,3 +1,2 @@
|
||||
class Offer < Post
|
||||
|
||||
end
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
class Organization < ActiveRecord::Base
|
||||
before_validation :ensure_url
|
||||
validates_uniqueness_of :name
|
||||
has_many :members
|
||||
has_many :members, dependent: :destroy
|
||||
has_many :users, -> { order "members.created_at DESC" }, through: :members
|
||||
|
||||
has_one :account, as: :accountable
|
||||
@ -15,7 +15,8 @@ class Organization < ActiveRecord::Base
|
||||
|
||||
has_many :documents, as: :documentable
|
||||
|
||||
BOOTSWATCH_THEMES = %w[amelia cerulean cosmo cyborg flatly journal readable simplex slate spacelab united]
|
||||
BOOTSWATCH_THEMES = %w[amelia cerulean cosmo cyborg flatly journal readable
|
||||
simplex slate spacelab united]
|
||||
# validates :theme, allow_nil: true, inclusion: {in: BOOTSWATCH_THEMES}
|
||||
|
||||
scope :matching, ->(str) {
|
||||
@ -52,4 +53,5 @@ class Organization < ActiveRecord::Base
|
||||
errors.add(:web, :url_format_invalid)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -7,6 +7,7 @@ class Post < ActiveRecord::Base
|
||||
attr_reader :member_id
|
||||
|
||||
belongs_to :category
|
||||
delegate :name, to: :category, prefix: true, allow_nil: true
|
||||
belongs_to :user
|
||||
belongs_to :organization
|
||||
belongs_to :publisher, class_name: "User", foreign_key: "publisher_id"
|
||||
@ -42,7 +43,12 @@ class Post < ActiveRecord::Base
|
||||
) #{Post.table_name}")
|
||||
}
|
||||
|
||||
scope :from_last_week, -> {
|
||||
where("created_at >= ?", 1.week.ago.beginning_of_day)
|
||||
}
|
||||
|
||||
validates :user, presence: true
|
||||
validates :category, presence: true
|
||||
|
||||
def to_s
|
||||
title
|
||||
|
||||
@ -20,8 +20,9 @@ class User < ActiveRecord::Base
|
||||
default_scope -> { order("users.id ASC") }
|
||||
|
||||
scope :actives, -> { where(members: { active: true }) }
|
||||
scope :online_active, -> { where("sign_in_count > 0") }
|
||||
|
||||
validates :username, presence: true, uniqueness: true
|
||||
validates :username, presence: true
|
||||
validates :email, presence: true, uniqueness: true
|
||||
|
||||
# Allows @domain.com for dummy emails but does not allow pure invalid
|
||||
@ -31,7 +32,7 @@ class User < ActiveRecord::Base
|
||||
|
||||
# validates :gender, presence: true, inclusion: {in: GENDERS}
|
||||
|
||||
has_many :members
|
||||
has_many :members, dependent: :destroy
|
||||
accepts_nested_attributes_for :members
|
||||
has_many :organizations, through: :members
|
||||
has_many :accounts, through: :members
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
class PostPolicy < Struct.new(:user, :post)
|
||||
def destroy?
|
||||
user == post.user or user.admins?(post.organization)
|
||||
user == post.user || user.admins?(post.organization)
|
||||
end
|
||||
|
||||
def create?
|
||||
@ -8,7 +8,6 @@ class PostPolicy < Struct.new(:user, :post)
|
||||
end
|
||||
|
||||
def update?
|
||||
user == post.user or user.admins?(post.organization)
|
||||
user == post.user || user.admins?(post.organization)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
14
app/services/organization_notifier_service.rb
Normal file
14
app/services/organization_notifier_service.rb
Normal file
@ -0,0 +1,14 @@
|
||||
class OrganizationNotifierService
|
||||
def initialize(organization)
|
||||
@organization = organization
|
||||
end
|
||||
|
||||
def send_recent_posts_to_online_members
|
||||
@organization.each do |org|
|
||||
posts = org.posts.from_last_week
|
||||
if posts.present?
|
||||
OrganizationNotifier.recent_posts(posts).deliver
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -136,4 +136,4 @@
|
||||
%li.disabled
|
||||
= link_to t("global.locales_header"), "#"
|
||||
%li.divider
|
||||
= languages_list
|
||||
- languages_list
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
= @category ? @category.name : Category.model_name.human
|
||||
%span.caret
|
||||
%ul.dropdown-menu{role: "menu"}
|
||||
%li= link_to '× #{t("global.all")}', inquiries_path
|
||||
%li= link_to "× #{t("global.all")}", inquiries_path
|
||||
- Category.all.sort_by { |a| a.name.downcase }.each do |c|
|
||||
- next if c == @category
|
||||
%li= link_to c.name, inquiries_path(cat: c.id)
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
= @category ? @category.name : Category.model_name.human
|
||||
%span.caret
|
||||
%ul.dropdown-menu{role: "menu"}
|
||||
%li= link_to '× #{t("global.all")}', dashboard_offers_path
|
||||
%li= link_to "× #{t("global.all")}", dashboard_offers_path
|
||||
- Category.all.sort_by { |a| a.name.downcase }.each do |c|
|
||||
- next if c == @category
|
||||
%li= link_to c.name, offers_path(cat: c.id)
|
||||
|
||||
46
app/views/organization_notifier/recent_posts.html.erb
Normal file
46
app/views/organization_notifier/recent_posts.html.erb
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<% if @offers.present? %>
|
||||
<p>
|
||||
<%= t("organization_notifier.recent_posts.text1") %>
|
||||
</p>
|
||||
<ul>
|
||||
<% @offers.each do |offer| %>
|
||||
<li>
|
||||
<a href="<%= offer_url(offer.id)%>">
|
||||
<%= "#{offer.title} (#{offer.try(&:category_name)})" %>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
<% if @inquiries.present? %>
|
||||
<p>
|
||||
<%= t("organization_notifier.recent_posts.text2") %>
|
||||
</p>
|
||||
<ul>
|
||||
<% @inquiries.each do |inquiry| %>
|
||||
<li>
|
||||
<a href="<%= inquiry_url(inquiry.id)%>">
|
||||
<%= "#{inquiry.title} (#{inquiry.try(&:category_name)})" %>
|
||||
</a>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
--
|
||||
<p>
|
||||
<%= t("mailers_globals.footer.text", organization_name: @organization_name) %>
|
||||
<a href="<%= page_url('home', only_path: false) %>">
|
||||
TimeOverflow
|
||||
<a>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@ -26,7 +26,8 @@
|
||||
};
|
||||
});
|
||||
|
||||
= form_for(post, html: { name: "form" }) do |f|
|
||||
= show_error_messages!(post)
|
||||
= form_for(post, html: { name: "form", novalidate: true }) do |f|
|
||||
.form-group
|
||||
= f.label :title
|
||||
= f.text_field :title, class: "form-control"
|
||||
@ -34,7 +35,7 @@
|
||||
= f.label :description
|
||||
= f.text_area :description, rows: "10", class: "form-control"
|
||||
.form-group
|
||||
= f.label :category
|
||||
= f.label :category, required: true
|
||||
= f.select :category_id, Category.all.sort_by{ |a| a.name.downcase }.map{ |cat| [cat.name, cat.id] }, { include_blank: true }, { class: "form-control" }
|
||||
.form-group
|
||||
= f.label :tag_list
|
||||
@ -47,6 +48,9 @@
|
||||
= f.select :user_id, options_for_select(current_organization.members.active.order("members.member_uid").map{ |mem| ["#{mem.member_uid} #{mem.user.to_s}", mem.user_id] }, selected: post.user.id || current_user.id), {}, { id: "select2", class: "form-control", required: true }
|
||||
= f.hidden_field :publisher_id, value: current_user.id
|
||||
|
||||
%p.help-block
|
||||
= t "global.required_field"
|
||||
|
||||
= f.button label_button, class: "btn btn-default", style: "margin-bottom: 20px;"
|
||||
|
||||
:javascript
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
%li
|
||||
= t ".users_reg"
|
||||
.badge
|
||||
= @members.count
|
||||
= @active_members.count
|
||||
%li
|
||||
= t ".num_swaps"
|
||||
.badge
|
||||
|
||||
@ -23,8 +23,10 @@
|
||||
= f.input :date_of_birth, start_year: Date.today.year - 90, end_year: Date.today.year - 12, include_blank: :true
|
||||
|
||||
= f.input :description, as: "text"
|
||||
|
||||
/ = f.association :categories, label_method: :fqn, input_html: {style: 'width: 100%'}
|
||||
|
||||
.form-actions
|
||||
= f.button :submit
|
||||
- if @user.new_record?
|
||||
= f.button :submit, t('users.new.create_more_users_button'), name: 'more'
|
||||
= link_to t('users.new.cancel'), users_path
|
||||
@ -15,7 +15,7 @@
|
||||
- if admin?
|
||||
.form-group
|
||||
= f.label :source
|
||||
= f.select :source, options_for_select(@sources.sort_by{ |source| [source.accountable_type, source.accountable_id]}.map{ |a| ["#{a.accountable_type == "Member" ? a.accountable.member_uid : a.accountable_id} #{a.accountable_type} #{a.accountable.to_s}", a.id]}, selected: current_user.member(current_organization).account.id), {}, { id: "select2-time", class: "form-control" }
|
||||
= f.select :source, options_for_select(@sources.sort_by{ |source| [source.accountable_type, source.accountable.try(:member_uid)]}.map{ |a| ["#{a.accountable_type == "Member" ? a.accountable.member_uid : ""} #{a.accountable_type} #{a.accountable.to_s}", a.id]}, selected: current_user.member(current_organization).account.id), {}, { id: "select2-time", class: "form-control" }
|
||||
- if @offer
|
||||
= f.input :post, readonly: true
|
||||
= f.input :post_id, as: :hidden
|
||||
|
||||
@ -26,11 +26,6 @@
|
||||
%a{href: edit_user_path(@user)}
|
||||
%span.glyphicon.glyphicon-pencil
|
||||
= t "global.edit"
|
||||
- else
|
||||
%li
|
||||
%a
|
||||
%span.glyphicon.glyphicon-envelope
|
||||
= t "send message"
|
||||
- if admin? || @user != current_user
|
||||
%li
|
||||
%a{href: give_time_user_path(@user)}
|
||||
|
||||
3
bin/bundle
Executable file
3
bin/bundle
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env ruby
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
||||
load Gem.bin_path('bundler', 'bundle')
|
||||
4
bin/rails
Executable file
4
bin/rails
Executable file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env ruby
|
||||
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||
require_relative '../config/boot'
|
||||
require 'rails/commands'
|
||||
4
bin/rake
Executable file
4
bin/rake
Executable file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env ruby
|
||||
require_relative '../config/boot'
|
||||
require 'rake'
|
||||
Rake.application.run
|
||||
29
bin/setup
Executable file
29
bin/setup
Executable file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env ruby
|
||||
require 'pathname'
|
||||
|
||||
# path to your application root.
|
||||
APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
|
||||
|
||||
Dir.chdir APP_ROOT do
|
||||
# This script is a starting point to setup your application.
|
||||
# Add necessary setup steps to this file:
|
||||
|
||||
puts "== Installing dependencies =="
|
||||
system "gem install bundler --conservative"
|
||||
system "bundle check || bundle install"
|
||||
|
||||
# puts "\n== Copying sample files =="
|
||||
# unless File.exist?("config/database.yml")
|
||||
# system "cp config/database.yml.sample config/database.yml"
|
||||
# end
|
||||
|
||||
puts "\n== Preparing database =="
|
||||
system "bin/rake db:setup"
|
||||
|
||||
puts "\n== Removing old logs and tempfiles =="
|
||||
system "rm -f log/*"
|
||||
system "rm -rf tmp/cache"
|
||||
|
||||
puts "\n== Restarting application server =="
|
||||
system "touch tmp/restart.txt"
|
||||
end
|
||||
@ -1,16 +1,10 @@
|
||||
require File.expand_path('../boot', __FILE__)
|
||||
|
||||
# Pick the frameworks you want:
|
||||
require "rails/all"
|
||||
require 'tilt'
|
||||
# require "rails/test_unit/railtie"
|
||||
require 'rails/all'
|
||||
|
||||
if defined?(Bundler)
|
||||
# If you precompile assets before deploying to production, use this line
|
||||
Bundler.require(*Rails.groups(:assets => %w(development test)))
|
||||
# If you want your assets lazily compiled in production, use this line
|
||||
# Bundler.require(:default, :assets, Rails.env)
|
||||
end
|
||||
# Require the gems listed in Gemfile, including any gems
|
||||
# you've limited to :test, :development, or :production.
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
module Timeoverflow
|
||||
class Application < Rails::Application
|
||||
@ -18,53 +12,18 @@ module Timeoverflow
|
||||
# Application configuration should go into files in config/initializers
|
||||
# -- all .rb files in that directory are automatically loaded.
|
||||
|
||||
# Custom directories with classes and modules you want to be autoloadable.
|
||||
# config.autoload_paths += %W(#{config.root}/extras)
|
||||
|
||||
# Only load the plugins named here, in the order given (default is alphabetical).
|
||||
# :all can be used as a placeholder for all plugins not explicitly named.
|
||||
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
|
||||
|
||||
# Activate observers that should always be running.
|
||||
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
|
||||
|
||||
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||
# config.time_zone = 'Central Time (US & Canada)'
|
||||
|
||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
# config.i18n.default_locale = :de
|
||||
config.i18n.default_locale = :es
|
||||
config.i18n.available_locales = [:es, :ca, :en]
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Configure the default encoding used in templates for Ruby 1.9.
|
||||
config.encoding = "utf-8"
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
config.filter_parameters += [:password, :assertion]
|
||||
|
||||
# Enable escaping HTML in JSON.
|
||||
config.active_support.escape_html_entities_in_json = true
|
||||
|
||||
# Use SQL instead of Active Record's schema dumper when creating the database.
|
||||
# This is necessary if your schema can't be completely dumped by the schema dumper,
|
||||
# like if you have constraints or database-specific column types
|
||||
# config.active_record.schema_format = :sql
|
||||
|
||||
# Enable the asset pipeline
|
||||
config.assets.enabled = true
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets
|
||||
config.assets.version = '1.0'
|
||||
|
||||
# Add fonts to assets
|
||||
# config.assets.paths << Rails.root.join("app", "assets", "fonts")
|
||||
# config.assets.paths << Rails.root.join("app", "assets", "templates")
|
||||
|
||||
# config.assets.register_engine '.haml', Tilt::HamlTemplate
|
||||
|
||||
# Avoid connecting to the database on precompilation
|
||||
config.assets.initialize_on_precompile = false
|
||||
# Do not swallow errors in after_commit/after_rollback callbacks.
|
||||
config.active_record.raise_in_transactional_callbacks = true
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,6 +1,3 @@
|
||||
require 'rubygems'
|
||||
|
||||
# Set up gems listed in the Gemfile.
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
||||
|
||||
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
|
||||
require 'bundler/setup' # Set up gems listed in the Gemfile.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
# Load the rails application
|
||||
# Load the Rails application.
|
||||
require File.expand_path('../application', __FILE__)
|
||||
|
||||
# Initialize the rails application
|
||||
Timeoverflow::Application.initialize!
|
||||
# Initialize the Rails application.
|
||||
Rails.application.initialize!
|
||||
|
||||
@ -1,32 +1,44 @@
|
||||
Timeoverflow::Application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# In the development environment your application's code is reloaded on
|
||||
# every request. This slows down response time but is perfect for development
|
||||
# since you don't have to restart the web server when you make code changes.
|
||||
config.cache_classes = false
|
||||
|
||||
# Do not eager load code on boot.
|
||||
config.eager_load = false
|
||||
|
||||
# Show full error reports and disable caching
|
||||
# Show full error reports and disable caching.
|
||||
config.consider_all_requests_local = true
|
||||
config.action_controller.perform_caching = false
|
||||
|
||||
# Action Mailer
|
||||
# Don't care if the mailer can't send.
|
||||
config.action_mailer.raise_delivery_errors = true
|
||||
config.action_mailer.perform_deliveries = false
|
||||
config.action_mailer.default_url_options = {
|
||||
:host => (ENV["MAIL_LINK_HOST"] || 'localhost:3000')
|
||||
host: (ENV["MAIL_LINK_HOST"] || "localhost:3000")
|
||||
}
|
||||
|
||||
# Print deprecation notices to the Rails logger
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
# Only use best-standards-support built into browsers
|
||||
config.action_dispatch.best_standards_support = :builtin
|
||||
# Raise an error on page load if there are pending migrations.
|
||||
config.active_record.migration_error = :page_load
|
||||
|
||||
# Do not compress assets
|
||||
config.assets.compress = false
|
||||
|
||||
# Expands the lines which load the assets
|
||||
# Debug mode disables concatenation and preprocessing of assets.
|
||||
# This option may cause significant delays in view rendering with a large
|
||||
# number of complex assets.
|
||||
config.assets.debug = true
|
||||
|
||||
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
||||
# yet still be able to expire them through the digest params.
|
||||
config.assets.digest = true
|
||||
|
||||
# Adds additional error checking when serving assets at runtime.
|
||||
# Checks for improperly declared sprockets dependencies.
|
||||
# Raises helpful error messages.
|
||||
config.assets.raise_runtime_errors = true
|
||||
|
||||
# Raises error for missing translations
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
end
|
||||
|
||||
@ -1,56 +1,68 @@
|
||||
Timeoverflow::Application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# Code is not reloaded between requests
|
||||
# Code is not reloaded between requests.
|
||||
config.cache_classes = true
|
||||
|
||||
# Eager load code on boot. This eager loads most of Rails and
|
||||
# your application in memory, allowing both threaded web servers
|
||||
# and those relying on copy on write to perform better.
|
||||
# Rake tasks automatically ignore this option for performance.
|
||||
config.eager_load = true
|
||||
|
||||
# Full error reports are disabled and caching is turned on
|
||||
# Full error reports are disabled and caching is turned on.
|
||||
config.consider_all_requests_local = false
|
||||
config.action_controller.perform_caching = true
|
||||
|
||||
# Disable Rails's static asset server (Apache or nginx will already do this)
|
||||
config.serve_static_assets = false
|
||||
# Enable Rack::Cache to put a simple HTTP cache in front of your application
|
||||
# Add `rack-cache` to your Gemfile before enabling this.
|
||||
# For large-scale production use, consider using a caching reverse proxy like
|
||||
# NGINX, varnish or squid.
|
||||
# config.action_dispatch.rack_cache = true
|
||||
|
||||
# Compress JavaScripts and CSS
|
||||
config.assets.compress = true
|
||||
# Disable serving static files from the `/public` folder by default since
|
||||
# Apache or NGINX already handles this.
|
||||
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
|
||||
|
||||
# Don't fallback to assets pipeline if a precompiled asset is missed
|
||||
# Compress JavaScripts and CSS.
|
||||
config.assets.js_compressor = :uglifier
|
||||
# config.assets.css_compressor = :sass
|
||||
|
||||
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
||||
config.assets.compile = true # false
|
||||
|
||||
# Generate digests for assets URLs
|
||||
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
||||
# yet still be able to expire them through the digest params.
|
||||
config.assets.digest = true
|
||||
|
||||
# Defaults to nil and saved in location specified by config.assets.prefix
|
||||
# config.assets.manifest = YOUR_PATH
|
||||
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
|
||||
|
||||
# Specifies the header that your server uses for sending files
|
||||
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
|
||||
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
|
||||
# Specifies the header that your server uses for sending files.
|
||||
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
|
||||
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
|
||||
|
||||
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
||||
# config.force_ssl = true
|
||||
|
||||
# See everything in the log (default is :info)
|
||||
# config.log_level = :debug
|
||||
# Use the lowest log level to ensure availability of diagnostic information
|
||||
# when problems arise.
|
||||
config.log_level = :debug
|
||||
|
||||
# Prepend all log lines with the following tags
|
||||
# Prepend all log lines with the following tags.
|
||||
# config.log_tags = [ :subdomain, :uuid ]
|
||||
|
||||
# Use a different logger for distributed setups
|
||||
# Use a different logger for distributed setups.
|
||||
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
|
||||
|
||||
# Use a different cache store in production
|
||||
# Use a different cache store in production.
|
||||
# config.cache_store = :mem_cache_store
|
||||
config.cache_store = :dalli_store
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||
# config.action_controller.asset_host = "http://assets.example.com"
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server.
|
||||
# config.action_controller.asset_host = 'http://assets.example.com'
|
||||
|
||||
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
|
||||
# config.assets.precompile += %w( search.js )
|
||||
|
||||
# Action Mailer
|
||||
# Ignore bad email addresses and do not raise email delivery errors.
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
config.action_mailer.raise_delivery_errors = true
|
||||
|
||||
config.action_mailer.delivery_method = :smtp
|
||||
@ -69,13 +81,16 @@ Timeoverflow::Application.configure do
|
||||
config.action_mailer.smtp_settings = smtp_env
|
||||
end
|
||||
|
||||
# Enable threaded mode
|
||||
# config.threadsafe!
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation can not be found)
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Send deprecation notices to registered listeners
|
||||
# Send deprecation notices to registered listeners.
|
||||
config.active_support.deprecation = :notify
|
||||
|
||||
# Use default logging formatter so that PID and timestamp are not suppressed.
|
||||
config.log_formatter = ::Logger::Formatter.new
|
||||
|
||||
# Do not dump schema after migrations.
|
||||
config.active_record.dump_schema_after_migration = false
|
||||
end
|
||||
|
||||
@ -1,26 +1,30 @@
|
||||
Timeoverflow::Application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb
|
||||
Rails.application.configure do
|
||||
# Settings specified here will take precedence over those in config/application.rb.
|
||||
|
||||
# The test environment is used exclusively to run your application's
|
||||
# test suite. You never need to work with it otherwise. Remember that
|
||||
# your test database is "scratch space" for the test suite and is wiped
|
||||
# and recreated between test runs. Don't rely on the data there!
|
||||
config.cache_classes = true
|
||||
|
||||
# Do not eager load code on boot. This avoids loading your whole application
|
||||
# just for the purpose of running a single test. If you are using a tool that
|
||||
# preloads Rails for running tests, you may have to set it to true.
|
||||
config.eager_load = false
|
||||
|
||||
# Configure static asset server for tests with Cache-Control for performance
|
||||
config.serve_static_assets = true
|
||||
config.static_cache_control = "public, max-age=3600"
|
||||
# Configure static file server for tests with Cache-Control for performance.
|
||||
config.serve_static_files = true
|
||||
config.static_cache_control = 'public, max-age=3600'
|
||||
|
||||
# Show full error reports and disable caching
|
||||
# Show full error reports and disable caching.
|
||||
config.consider_all_requests_local = true
|
||||
config.action_controller.perform_caching = false
|
||||
|
||||
# Raise exceptions instead of rendering exception templates
|
||||
# Raise exceptions instead of rendering exception templates.
|
||||
config.action_dispatch.show_exceptions = false
|
||||
|
||||
# Disable request forgery protection in test environment
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
# Disable request forgery protection in test environment.
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
|
||||
config.action_mailer.default_url_options = { host: "localhost:3000" }
|
||||
|
||||
@ -29,8 +33,12 @@ Timeoverflow::Application.configure do
|
||||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
# Print deprecation notices to the stderr
|
||||
# Randomize the order test cases are executed.
|
||||
config.active_support.test_order = :random
|
||||
|
||||
# Print deprecation notices to the stderr.
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
config.log_level = :error
|
||||
# Raises error for missing translations
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
end
|
||||
|
||||
13
config/initializers/assets.rb
Normal file
13
config/initializers/assets.rb
Normal file
@ -0,0 +1,13 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets.
|
||||
Rails.application.config.assets.version = '1.0'
|
||||
|
||||
# Add additional assets to the asset load path
|
||||
# Rails.application.config.assets.paths << Emoji.images_path
|
||||
|
||||
# Precompile additional assets.
|
||||
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
||||
# Rails.application.config.assets.precompile += %w( search.js )
|
||||
|
||||
Rails.application.config.assets.initialize_on_precompile = false
|
||||
3
config/initializers/cookies_serializer.rb
Normal file
3
config/initializers/cookies_serializer.rb
Normal file
@ -0,0 +1,3 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
Rails.application.config.action_dispatch.cookies_serializer = :marshal
|
||||
4
config/initializers/filter_parameter_logging.rb
Normal file
4
config/initializers/filter_parameter_logging.rb
Normal file
@ -0,0 +1,4 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Configure sensitive parameters which will be filtered from the log file.
|
||||
Rails.application.config.filter_parameters += [:password, :assertion]
|
||||
@ -1,15 +1,16 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Add new inflection rules using the following format
|
||||
# (all these examples are active by default):
|
||||
# ActiveSupport::Inflector.inflections do |inflect|
|
||||
# Add new inflection rules using the following format. Inflections
|
||||
# are locale specific, and you may define rules for as many different
|
||||
# locales as you wish. All of these examples are active by default:
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.plural /^(ox)$/i, '\1en'
|
||||
# inflect.singular /^(ox)en/i, '\1'
|
||||
# inflect.irregular 'person', 'people'
|
||||
# inflect.uncountable %w( fish sheep )
|
||||
# end
|
||||
#
|
||||
|
||||
# These inflection rules are supported but not enabled by default:
|
||||
# ActiveSupport::Inflector.inflections do |inflect|
|
||||
# ActiveSupport::Inflector.inflections(:en) do |inflect|
|
||||
# inflect.acronym 'RESTful'
|
||||
# end
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||
# Rails.application.config.time_zone = 'Central Time (US & Canada)'
|
||||
|
||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||
# Rails.application.config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
# Rails.application.config.i18n.default_locale = :de
|
||||
@ -2,4 +2,3 @@
|
||||
|
||||
# Add new mime types for use in respond_to blocks:
|
||||
# Mime::Type.register "text/richtext", :rtf
|
||||
# Mime::Type.register_alias "text/html", :iphone
|
||||
|
||||
@ -1,8 +1,3 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
Timeoverflow::Application.config.session_store :cookie_store, key: '_timeoverflow_session'
|
||||
|
||||
# Use the database for sessions instead of the cookie-based default,
|
||||
# which shouldn't be used to store highly confidential information
|
||||
# (create the session table with "rails generate session_migration")
|
||||
# Timeoverflow::Application.config.session_store :active_record_store
|
||||
Rails.application.config.session_store :cookie_store, key: '_timeoverflow_session'
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
#
|
||||
|
||||
# This file contains settings for ActionController::ParamsWrapper which
|
||||
# is enabled by default.
|
||||
|
||||
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
|
||||
ActiveSupport.on_load(:action_controller) do
|
||||
wrap_parameters format: [:json]
|
||||
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
|
||||
end
|
||||
|
||||
# Disable root element in JSON by default.
|
||||
# To enable root element in JSON for ActiveRecord objects.
|
||||
ActiveSupport.on_load(:active_record) do
|
||||
self.include_root_in_json = false
|
||||
end
|
||||
|
||||
@ -150,8 +150,12 @@ ca:
|
||||
cancel_warning_angular: "Vas a eliminar del banc a l'usuari {{username}}"
|
||||
active_warning_angular: "Vas a canviar l'estat del compte de l'usuari {{username}}"
|
||||
actions: Accions
|
||||
user_created: "Usuari %{uid} %{name} guardat"
|
||||
new:
|
||||
new_user: Nou usuari
|
||||
create_more_users_button: Crear i introduir un nou usuari
|
||||
user_created_add: "Usuari %{uid} %{name} guardat, crea ara el següent"
|
||||
cancel: Cancel·lar
|
||||
edit:
|
||||
edit_user: Canviar usuari
|
||||
show:
|
||||
@ -306,6 +310,7 @@ ca:
|
||||
promote: Convertir en administrador
|
||||
statistics: Estadístiques
|
||||
locales_header: canviar llengua
|
||||
required_field: "* Camp obligatori"
|
||||
|
||||
locales:
|
||||
en: Anglès
|
||||
|
||||
10
config/locales/email.ca.yml
Normal file
10
config/locales/email.ca.yml
Normal file
@ -0,0 +1,10 @@
|
||||
ca:
|
||||
mailers_globals:
|
||||
footer:
|
||||
text: "%{organization_name} en"
|
||||
|
||||
organization_notifier:
|
||||
recent_posts:
|
||||
subject: Boletín semanal
|
||||
text1: "Últimas ofertas publicadas:"
|
||||
text2: "Últimas demandas publicadas:"
|
||||
10
config/locales/email.en.yml
Normal file
10
config/locales/email.en.yml
Normal file
@ -0,0 +1,10 @@
|
||||
en:
|
||||
mailers_globals:
|
||||
footer:
|
||||
text: "%{organization_name} from"
|
||||
|
||||
organization_notifier:
|
||||
recent_posts:
|
||||
subject: Newsletter
|
||||
text1: "Latest offers published:"
|
||||
text2: "Lastest inquiries published:"
|
||||
10
config/locales/email.es.yml
Normal file
10
config/locales/email.es.yml
Normal file
@ -0,0 +1,10 @@
|
||||
es:
|
||||
mailers_globals:
|
||||
footer:
|
||||
text: "%{organization_name} en"
|
||||
|
||||
organization_notifier:
|
||||
recent_posts:
|
||||
subject: Boletín semanal
|
||||
text1: "Últimas ofertas publicadas:"
|
||||
text2: "Últimas demandas publicadas:"
|
||||
@ -150,8 +150,12 @@ en:
|
||||
cancel_warning_angular: "You are going to delete account from the Time Bank for user {{username}}"
|
||||
active_warning_angular: "You are going to change user account status for {{username}}"
|
||||
actions: Actions
|
||||
user_created: "User %{uid} %{name} saved"
|
||||
new:
|
||||
new_user: New user
|
||||
create_more_users_button: Create and add another user
|
||||
user_created_add: "User %{uid} %{name} saved, now create next one"
|
||||
cancel: Cancel
|
||||
edit:
|
||||
edit_user: Update user
|
||||
show:
|
||||
@ -326,6 +330,7 @@ en:
|
||||
promote: Promote to administrator
|
||||
statistics: Statistics
|
||||
locales_header: change language
|
||||
required_field: "* Required field"
|
||||
|
||||
locales:
|
||||
en: English
|
||||
|
||||
@ -150,8 +150,12 @@ es:
|
||||
cancel_warning_angular: "Va a eliminar del banco al usuario {{username}}"
|
||||
active_warning_angular: "Va a cambiar el estado de la cuenta del usuario {{username}}"
|
||||
actions: Acciones
|
||||
user_created: "Usuario %{uid} %{name} guardado"
|
||||
new:
|
||||
new_user: Nuevo usuario
|
||||
create_more_users_button: Crear e introducir otro usuario
|
||||
cancel: Cancelar
|
||||
user_created_add: "Usuario %{uid} %{name} guardado. Introduce ahora el siguiente"
|
||||
edit:
|
||||
edit_user: Cambiar usuario
|
||||
show:
|
||||
@ -310,6 +314,7 @@ es:
|
||||
promote: Convertir en administrador
|
||||
statistics: Estadísticas
|
||||
locales_header: cambiar idioma
|
||||
required_field: "* Campo obligatorio"
|
||||
|
||||
locales:
|
||||
en: Inglés
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Timeoverflow::Application.routes.draw do
|
||||
Rails.application.routes.draw do
|
||||
get "global/switch_lang", as: :switch_lang
|
||||
get 'tags/index'
|
||||
|
||||
|
||||
34
config/schedule.rb
Normal file
34
config/schedule.rb
Normal file
@ -0,0 +1,34 @@
|
||||
set :environment, "production"
|
||||
set :output, "log/cron_log.log"
|
||||
|
||||
every :monday, at: "9am" do
|
||||
runner "OrganizationNotifierService.new(Organization.all).
|
||||
send_recent_posts_to_online_members"
|
||||
end
|
||||
|
||||
# Cada vez que se modifique este archivo, crontab debe actualizarse:
|
||||
# whenever --update-crontab
|
||||
|
||||
# Use this file to easily define all of your cron jobs.
|
||||
#
|
||||
# It's helpful, but not entirely necessary to understand cron before proceeding.
|
||||
# http://en.wikipedia.org/wiki/Cron
|
||||
|
||||
# Example:
|
||||
#
|
||||
# set :output, "/path/to/my/cron_log.log"
|
||||
#
|
||||
# every 2.hours do
|
||||
# command "/usr/bin/some_great_command"
|
||||
# runner "MyModel.some_method"
|
||||
# rake "some:great:rake:task"
|
||||
# end
|
||||
#
|
||||
# every 4.days do
|
||||
# runner "AnotherModel.prune_old_records"
|
||||
# end
|
||||
|
||||
# Learn more: http://github.com/javan/whenever
|
||||
|
||||
# rake "pruebas:hello" #task en lib/tasks para comprobar el funcionamiento de
|
||||
# whenever
|
||||
@ -1,2 +0,0 @@
|
||||
Use this README file to introduce your application and point to useful places in the API for learning more.
|
||||
Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
|
||||
2
logfile
2
logfile
@ -1,2 +0,0 @@
|
||||
LOG: could not open configuration file "/usr/local/pgsql/data/postgresql.conf": Permiso denegado
|
||||
FATAL: configuration file "/usr/local/pgsql/data/postgresql.conf" contains errors
|
||||
@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
||||
|
||||
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||
require File.expand_path('../../config/boot', __FILE__)
|
||||
require 'rails/commands'
|
||||
@ -1,32 +1,37 @@
|
||||
require 'spec_helper'
|
||||
require "spec_helper"
|
||||
|
||||
describe InquiriesController do
|
||||
let (:test_organization) { Fabricate(:organization)}
|
||||
let (:member) { Fabricate(:member, organization: test_organization)}
|
||||
let (:another_member) { Fabricate(:member, organization: test_organization)}
|
||||
let! (:inquiry) { Fabricate(:inquiry, user: member.user, organization: test_organization)}
|
||||
let (:test_organization) { Fabricate(:organization) }
|
||||
let (:member) { Fabricate(:member, organization: test_organization) }
|
||||
let (:another_member) { Fabricate(:member, organization: test_organization) }
|
||||
let (:test_category) { Fabricate(:category) }
|
||||
let! (:inquiry) do
|
||||
Fabricate(:inquiry,
|
||||
user: member.user,
|
||||
organization: test_organization,
|
||||
category: test_category)
|
||||
end
|
||||
include_context "stub browser locale"
|
||||
before { set_browser_locale('ca') }
|
||||
before { set_browser_locale("ca") }
|
||||
|
||||
describe "GET #index" do
|
||||
context "with a logged user" do
|
||||
it "populates and array of inquiries" do
|
||||
login(another_member.user)
|
||||
|
||||
get 'index'
|
||||
get "index"
|
||||
expect(assigns(:inquiries)).to eq([inquiry])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "GET #show" do
|
||||
context "with valid params" do
|
||||
context "with a logged user" do
|
||||
it "assigns the requested inquiry to @inquiry" do
|
||||
login(another_member.user)
|
||||
|
||||
get 'show', id: inquiry.id
|
||||
get "show", id: inquiry.id
|
||||
expect(assigns(:inquiry)).to eq(inquiry)
|
||||
end
|
||||
end
|
||||
@ -39,9 +44,10 @@ describe InquiriesController do
|
||||
it "creates a new inquiry" do
|
||||
login(another_member.user)
|
||||
|
||||
expect {
|
||||
post 'create', inquiry: Fabricate.to_params(:inquiry)
|
||||
}.to change(Inquiry,:count).by(1)
|
||||
expect do
|
||||
post "create", inquiry: { user: another_member.user,
|
||||
category_id: test_category.id }
|
||||
end.to change(Inquiry, :count).by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -53,14 +59,19 @@ describe InquiriesController do
|
||||
it "located the requested @inquiry" do
|
||||
login(member.user)
|
||||
|
||||
put 'update', id: inquiry.id, inquiry: Fabricate.to_params(:inquiry)
|
||||
put "update", id: inquiry.id, inquiry: Fabricate.to_params(:inquiry)
|
||||
expect(assigns(:inquiry)).to eq(inquiry)
|
||||
end
|
||||
|
||||
it "changes @inquiry's attributes" do
|
||||
login(member.user)
|
||||
|
||||
put 'update', id: inquiry.id, inquiry: Fabricate.to_params(:inquiry, user: member, title: "New title", description: "New description")
|
||||
put "update",
|
||||
id: inquiry.id,
|
||||
inquiry: Fabricate.to_params(:inquiry,
|
||||
user: member,
|
||||
title: "New title",
|
||||
description: "New description")
|
||||
|
||||
inquiry.reload
|
||||
expect(inquiry.title).to eq("New title")
|
||||
@ -74,7 +85,12 @@ describe InquiriesController do
|
||||
it "does not change @inquiry's attributes" do
|
||||
login(member.user)
|
||||
|
||||
put :update, id: inquiry.id, inquiry: Fabricate.to_params(:inquiry, user: nil, title: "New title", description: "New description")
|
||||
put :update,
|
||||
id: inquiry.id,
|
||||
inquiry: Fabricate.to_params(:inquiry,
|
||||
user: nil,
|
||||
title: "New title",
|
||||
description: "New description")
|
||||
|
||||
expect(inquiry.title).not_to eq("New title")
|
||||
expect(inquiry.description).not_to eq("New description")
|
||||
|
||||
@ -1,32 +1,37 @@
|
||||
require 'spec_helper'
|
||||
require "spec_helper"
|
||||
|
||||
describe OffersController do
|
||||
let (:test_organization) { Fabricate(:organization)}
|
||||
let (:member) { Fabricate(:member, organization: test_organization)}
|
||||
let (:another_member) { Fabricate(:member, organization: test_organization)}
|
||||
let! (:offer) { Fabricate(:offer, user: member.user, organization: test_organization)}
|
||||
let (:test_organization) { Fabricate(:organization) }
|
||||
let (:member) { Fabricate(:member, organization: test_organization) }
|
||||
let (:another_member) { Fabricate(:member, organization: test_organization) }
|
||||
let (:test_category) { Fabricate(:category) }
|
||||
let! (:offer) do
|
||||
Fabricate(:offer,
|
||||
user: member.user,
|
||||
organization: test_organization,
|
||||
category: test_category)
|
||||
end
|
||||
include_context "stub browser locale"
|
||||
before { set_browser_locale('ca') }
|
||||
before { set_browser_locale("ca") }
|
||||
|
||||
describe "GET #index" do
|
||||
context "with a logged user" do
|
||||
it "populates and array of offers" do
|
||||
login(another_member.user)
|
||||
|
||||
get 'index'
|
||||
get "index"
|
||||
expect(assigns(:offers)).to eq([offer])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "GET #show" do
|
||||
context "with valid params" do
|
||||
context "with a logged user" do
|
||||
it "assigns the requested offer to @offer" do
|
||||
login(another_member.user)
|
||||
|
||||
get 'show', id: offer.id
|
||||
get "show", id: offer.id
|
||||
expect(assigns(:offer)).to eq(offer)
|
||||
end
|
||||
end
|
||||
@ -39,9 +44,10 @@ describe OffersController do
|
||||
it "creates a new offer" do
|
||||
login(another_member.user)
|
||||
|
||||
expect {
|
||||
post 'create', offer: Fabricate.to_params(:offer)
|
||||
}.to change(Offer,:count).by(1)
|
||||
expect do
|
||||
post "create", offer: { user: another_member.user,
|
||||
category_id: test_category }
|
||||
end.to change(Offer, :count).by(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -53,14 +59,19 @@ describe OffersController do
|
||||
it "located the requested @offer" do
|
||||
login(member.user)
|
||||
|
||||
put 'update', id: offer.id, offer: Fabricate.to_params(:offer)
|
||||
put "update", id: offer.id, offer: Fabricate.to_params(:offer)
|
||||
expect(assigns(:offer)).to eq(offer)
|
||||
end
|
||||
|
||||
it "changes @offer's attributes" do
|
||||
login(member.user)
|
||||
|
||||
put 'update', id: offer.id, offer: Fabricate.to_params(:offer, user: member, title: "New title", description: "New description")
|
||||
put "update",
|
||||
id: offer.id,
|
||||
offer: Fabricate.to_params(:offer,
|
||||
user: member,
|
||||
title: "New title",
|
||||
description: "New description")
|
||||
|
||||
offer.reload
|
||||
expect(offer.title).to eq("New title")
|
||||
@ -74,7 +85,12 @@ describe OffersController do
|
||||
it "does not change @offer's attributes" do
|
||||
login(member.user)
|
||||
|
||||
put :update, id: offer.id, offer: Fabricate.to_params(:offer, user: nil, title: "New title", description: "New description")
|
||||
put :update,
|
||||
id: offer.id,
|
||||
offer: Fabricate.to_params(:offer,
|
||||
user: nil,
|
||||
title: "New title",
|
||||
description: "New description")
|
||||
|
||||
expect(offer.title).not_to eq("New title")
|
||||
expect(offer.description).not_to eq("New description")
|
||||
|
||||
@ -7,7 +7,7 @@ describe TransfersController do
|
||||
let (:member_taker) { Fabricate(:member, organization: test_organization) }
|
||||
include_context "stub browser locale"
|
||||
before { set_browser_locale('ca') }
|
||||
|
||||
|
||||
describe "POST #create" do
|
||||
before { login(user) }
|
||||
|
||||
@ -73,7 +73,7 @@ describe TransfersController do
|
||||
end
|
||||
|
||||
it "redirects to destination" do
|
||||
expect(subject).to redirect_to(member_taker)
|
||||
expect(subject).to redirect_to(member_taker.user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
5
spec/fabricators/category_fabricator.rb
Normal file
5
spec/fabricators/category_fabricator.rb
Normal file
@ -0,0 +1,5 @@
|
||||
Fabricator(:category) do
|
||||
name_translations do
|
||||
{ "es" => "Idiomas", "en" => "Languages", "ca" => "Idiomes" }
|
||||
end
|
||||
end
|
||||
@ -4,4 +4,4 @@ Fabricator(:member) do
|
||||
organization { Fabricate(:organization) }
|
||||
manager false
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -3,6 +3,7 @@ Fabricator(:post) do
|
||||
title { Faker::Lorem.sentence }
|
||||
user { Fabricate(:user) }
|
||||
description { Faker::Lorem.paragraph }
|
||||
category { Fabricate(:category) }
|
||||
permanent { false }
|
||||
joinable { false }
|
||||
global { false }
|
||||
@ -16,6 +17,7 @@ Fabricator(:inquiry) do
|
||||
title { Faker::Lorem.sentence }
|
||||
user { Fabricate(:user) }
|
||||
description { Faker::Lorem.paragraph }
|
||||
category { Fabricate(:category) }
|
||||
permanent { false }
|
||||
joinable { false }
|
||||
global { false }
|
||||
@ -29,8 +31,9 @@ Fabricator(:offer) do
|
||||
title { Faker::Lorem.sentence }
|
||||
user { Fabricate(:user) }
|
||||
description { Faker::Lorem.paragraph }
|
||||
category { Fabricate(:category) }
|
||||
permanent { false }
|
||||
joinable { false }
|
||||
global { false }
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@ -13,4 +13,4 @@ Fabricator(:user) do
|
||||
|
||||
terms_accepted_at DateTime.now.utc
|
||||
confirmed_at DateTime.now.utc
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,5 +1,61 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Member do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
subject { Fabricate(:member) }
|
||||
|
||||
it { should belong_to(:user) }
|
||||
it { should belong_to(:organization) }
|
||||
it { should have_one(:account) }
|
||||
it { should delegate_method(:balance).to(:account).with_prefix }
|
||||
it { should delegate_method(:gender).to(:user).with_prefix }
|
||||
it { should delegate_method(:date_of_birth).to(:user).with_prefix }
|
||||
|
||||
it { should validate_presence_of(:organization_id) }
|
||||
it { should validate_presence_of(:member_uid) }
|
||||
|
||||
describe "#offers" do
|
||||
let(:member) { Fabricate(:member) }
|
||||
let(:member_offer) { Fabricate(
|
||||
:offer,
|
||||
user: member.user,
|
||||
organization: member.organization)
|
||||
}
|
||||
|
||||
it "should be a list of Offers matching user and organization" do
|
||||
another_member_offer = Fabricate(:offer)
|
||||
another_organization_offer = Fabricate(
|
||||
:offer,
|
||||
user: member.user,
|
||||
organization: Fabricate(:organization)
|
||||
)
|
||||
|
||||
expect(member.offers).to include(member_offer)
|
||||
expect(member.offers).to_not include(another_member_offer)
|
||||
expect(member.offers).to_not include(another_organization_offer)
|
||||
end
|
||||
end
|
||||
|
||||
context "callbacks" do
|
||||
context "#after_create" do
|
||||
let(:member) { Fabricate(:member) }
|
||||
|
||||
it "should have an account" do
|
||||
expect(member.account).to_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "#after_destroy" do
|
||||
let!(:member) { Fabricate(:member) }
|
||||
|
||||
it "destroy user if it was last membership" do
|
||||
expect { member.destroy }.to change(User, :count).by(-1)
|
||||
end
|
||||
|
||||
it "do not destroy user if it has more memberships" do
|
||||
second_member = Fabricate(:member, user: member.user)
|
||||
|
||||
expect { second_member.destroy }.not_to change(User, :count)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -9,6 +9,14 @@ require 'capybara/rails'
|
||||
# in spec/support/ and its subdirectories.
|
||||
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
|
||||
|
||||
# Make sure schem persists when running tests.
|
||||
# We ran into an error that forced us to run rake db:migrate RAILS_ENV=test
|
||||
# before running tests. This kind of fixes it, although we should have a closer
|
||||
# look at this and find a better solution
|
||||
# Ref:
|
||||
# https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks
|
||||
ActiveRecord::Migration.maintain_test_schema!
|
||||
|
||||
# Checks for pending migrations before tests are run.
|
||||
# If you are not using ActiveRecord, you can remove this line.
|
||||
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
|
||||
|
||||
BIN
vendor/assets/images/blank.png
vendored
BIN
vendor/assets/images/blank.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 90 B |
BIN
vendor/assets/images/flags.png
vendored
BIN
vendor/assets/images/flags.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 77 KiB |
257
vendor/assets/stylesheets/flags.css
vendored
257
vendor/assets/stylesheets/flags.css
vendored
@ -1,257 +0,0 @@
|
||||
.flag {
|
||||
width: 16px;
|
||||
height: 11px;
|
||||
background:url('/assets/flags.png') no-repeat
|
||||
}
|
||||
|
||||
.flag.flag-ad {background-position: -16px 0}
|
||||
.flag.flag-ae {background-position: -32px 0}
|
||||
.flag.flag-af {background-position: -48px 0}
|
||||
.flag.flag-ag {background-position: -64px 0}
|
||||
.flag.flag-ai {background-position: -80px 0}
|
||||
.flag.flag-al {background-position: -96px 0}
|
||||
.flag.flag-am {background-position: -112px 0}
|
||||
.flag.flag-an {background-position: -128px 0}
|
||||
.flag.flag-ao {background-position: -144px 0}
|
||||
.flag.flag-ar {background-position: -160px 0}
|
||||
.flag.flag-as {background-position: -176px 0}
|
||||
.flag.flag-at {background-position: -192px 0}
|
||||
.flag.flag-au {background-position: -208px 0}
|
||||
.flag.flag-aw {background-position: -224px 0}
|
||||
.flag.flag-az {background-position: -240px 0}
|
||||
.flag.flag-ba {background-position: 0 -11px}
|
||||
.flag.flag-bb {background-position: -16px -11px}
|
||||
.flag.flag-bd {background-position: -32px -11px}
|
||||
.flag.flag-be {background-position: -48px -11px}
|
||||
.flag.flag-bf {background-position: -64px -11px}
|
||||
.flag.flag-bg {background-position: -80px -11px}
|
||||
.flag.flag-bh {background-position: -96px -11px}
|
||||
.flag.flag-bi {background-position: -112px -11px}
|
||||
.flag.flag-bj {background-position: -128px -11px}
|
||||
.flag.flag-bm {background-position: -144px -11px}
|
||||
.flag.flag-bn {background-position: -160px -11px}
|
||||
.flag.flag-bo {background-position: -176px -11px}
|
||||
.flag.flag-br {background-position: -192px -11px}
|
||||
.flag.flag-bs {background-position: -208px -11px}
|
||||
.flag.flag-bt {background-position: -224px -11px}
|
||||
.flag.flag-bv {background-position: -240px -11px}
|
||||
.flag.flag-bw {background-position: 0 -22px}
|
||||
.flag.flag-by {background-position: -16px -22px}
|
||||
.flag.flag-bz {background-position: -32px -22px}
|
||||
.flag.flag-ca {background-position: -48px -22px}
|
||||
.flag.flag-catalonia {background-position: -64px -22px}
|
||||
.flag.flag-cd {background-position: -80px -22px}
|
||||
.flag.flag-cf {background-position: -96px -22px}
|
||||
.flag.flag-cg {background-position: -112px -22px}
|
||||
.flag.flag-ch {background-position: -128px -22px}
|
||||
.flag.flag-ci {background-position: -144px -22px}
|
||||
.flag.flag-ck {background-position: -160px -22px}
|
||||
.flag.flag-cl {background-position: -176px -22px}
|
||||
.flag.flag-cm {background-position: -192px -22px}
|
||||
.flag.flag-cn {background-position: -208px -22px}
|
||||
.flag.flag-co {background-position: -224px -22px}
|
||||
.flag.flag-cr {background-position: -240px -22px}
|
||||
.flag.flag-cu {background-position: 0 -33px}
|
||||
.flag.flag-cv {background-position: -16px -33px}
|
||||
.flag.flag-cw {background-position: -32px -33px}
|
||||
.flag.flag-cy {background-position: -48px -33px}
|
||||
.flag.flag-cz {background-position: -64px -33px}
|
||||
.flag.flag-de {background-position: -80px -33px}
|
||||
.flag.flag-dj {background-position: -96px -33px}
|
||||
.flag.flag-dk {background-position: -112px -33px}
|
||||
.flag.flag-dm {background-position: -128px -33px}
|
||||
.flag.flag-do {background-position: -144px -33px}
|
||||
.flag.flag-dz {background-position: -160px -33px}
|
||||
.flag.flag-ec {background-position: -176px -33px}
|
||||
.flag.flag-ee {background-position: -192px -33px}
|
||||
.flag.flag-eg {background-position: -208px -33px}
|
||||
.flag.flag-eh {background-position: -224px -33px}
|
||||
.flag.flag-england {background-position: -240px -33px}
|
||||
.flag.flag-er {background-position: 0 -44px}
|
||||
.flag.flag-es {background-position: -16px -44px}
|
||||
.flag.flag-et {background-position: -32px -44px}
|
||||
.flag.flag-eu {background-position: -48px -44px}
|
||||
.flag.flag-fi {background-position: -64px -44px}
|
||||
.flag.flag-fj {background-position: -80px -44px}
|
||||
.flag.flag-fk {background-position: -96px -44px}
|
||||
.flag.flag-fm {background-position: -112px -44px}
|
||||
.flag.flag-fo {background-position: -128px -44px}
|
||||
.flag.flag-fr {background-position: -144px -44px}
|
||||
.flag.flag-ga {background-position: -160px -44px}
|
||||
.flag.flag-gb {background-position: -176px -44px}
|
||||
.flag.flag-gd {background-position: -192px -44px}
|
||||
.flag.flag-ge {background-position: -208px -44px}
|
||||
.flag.flag-gf {background-position: -224px -44px}
|
||||
.flag.flag-gg {background-position: -240px -44px}
|
||||
.flag.flag-gh {background-position: 0 -55px}
|
||||
.flag.flag-gi {background-position: -16px -55px}
|
||||
.flag.flag-gl {background-position: -32px -55px}
|
||||
.flag.flag-gm {background-position: -48px -55px}
|
||||
.flag.flag-gn {background-position: -64px -55px}
|
||||
.flag.flag-gp {background-position: -80px -55px}
|
||||
.flag.flag-gq {background-position: -96px -55px}
|
||||
.flag.flag-gr {background-position: -112px -55px}
|
||||
.flag.flag-gs {background-position: -128px -55px}
|
||||
.flag.flag-gt {background-position: -144px -55px}
|
||||
.flag.flag-gu {background-position: -160px -55px}
|
||||
.flag.flag-gw {background-position: -176px -55px}
|
||||
.flag.flag-gy {background-position: -192px -55px}
|
||||
.flag.flag-hk {background-position: -208px -55px}
|
||||
.flag.flag-hm {background-position: -224px -55px}
|
||||
.flag.flag-hn {background-position: -240px -55px}
|
||||
.flag.flag-hr {background-position: 0 -66px}
|
||||
.flag.flag-ht {background-position: -16px -66px}
|
||||
.flag.flag-hu {background-position: -32px -66px}
|
||||
.flag.flag-ic {background-position: -48px -66px}
|
||||
.flag.flag-id {background-position: -64px -66px}
|
||||
.flag.flag-ie {background-position: -80px -66px}
|
||||
.flag.flag-il {background-position: -96px -66px}
|
||||
.flag.flag-im {background-position: -112px -66px}
|
||||
.flag.flag-in {background-position: -128px -66px}
|
||||
.flag.flag-io {background-position: -144px -66px}
|
||||
.flag.flag-iq {background-position: -160px -66px}
|
||||
.flag.flag-ir {background-position: -176px -66px}
|
||||
.flag.flag-is {background-position: -192px -66px}
|
||||
.flag.flag-it {background-position: -208px -66px}
|
||||
.flag.flag-je {background-position: -224px -66px}
|
||||
.flag.flag-jm {background-position: -240px -66px}
|
||||
.flag.flag-jo {background-position: 0 -77px}
|
||||
.flag.flag-jp {background-position: -16px -77px}
|
||||
.flag.flag-ke {background-position: -32px -77px}
|
||||
.flag.flag-kg {background-position: -48px -77px}
|
||||
.flag.flag-kh {background-position: -64px -77px}
|
||||
.flag.flag-ki {background-position: -80px -77px}
|
||||
.flag.flag-km {background-position: -96px -77px}
|
||||
.flag.flag-kn {background-position: -112px -77px}
|
||||
.flag.flag-kp {background-position: -128px -77px}
|
||||
.flag.flag-kr {background-position: -144px -77px}
|
||||
.flag.flag-kurdistan {background-position: -160px -77px}
|
||||
.flag.flag-kw {background-position: -176px -77px}
|
||||
.flag.flag-ky {background-position: -192px -77px}
|
||||
.flag.flag-kz {background-position: -208px -77px}
|
||||
.flag.flag-la {background-position: -224px -77px}
|
||||
.flag.flag-lb {background-position: -240px -77px}
|
||||
.flag.flag-lc {background-position: 0 -88px}
|
||||
.flag.flag-li {background-position: -16px -88px}
|
||||
.flag.flag-lk {background-position: -32px -88px}
|
||||
.flag.flag-lr {background-position: -48px -88px}
|
||||
.flag.flag-ls {background-position: -64px -88px}
|
||||
.flag.flag-lt {background-position: -80px -88px}
|
||||
.flag.flag-lu {background-position: -96px -88px}
|
||||
.flag.flag-lv {background-position: -112px -88px}
|
||||
.flag.flag-ly {background-position: -128px -88px}
|
||||
.flag.flag-ma {background-position: -144px -88px}
|
||||
.flag.flag-mc {background-position: -160px -88px}
|
||||
.flag.flag-md {background-position: -176px -88px}
|
||||
.flag.flag-me {background-position: -192px -88px}
|
||||
.flag.flag-mg {background-position: -208px -88px}
|
||||
.flag.flag-mh {background-position: -224px -88px}
|
||||
.flag.flag-mk {background-position: -240px -88px}
|
||||
.flag.flag-ml {background-position: 0 -99px}
|
||||
.flag.flag-mm {background-position: -16px -99px}
|
||||
.flag.flag-mn {background-position: -32px -99px}
|
||||
.flag.flag-mo {background-position: -48px -99px}
|
||||
.flag.flag-mp {background-position: -64px -99px}
|
||||
.flag.flag-mq {background-position: -80px -99px}
|
||||
.flag.flag-mr {background-position: -96px -99px}
|
||||
.flag.flag-ms {background-position: -112px -99px}
|
||||
.flag.flag-mt {background-position: -128px -99px}
|
||||
.flag.flag-mu {background-position: -144px -99px}
|
||||
.flag.flag-mv {background-position: -160px -99px}
|
||||
.flag.flag-mw {background-position: -176px -99px}
|
||||
.flag.flag-mx {background-position: -192px -99px}
|
||||
.flag.flag-my {background-position: -208px -99px}
|
||||
.flag.flag-mz {background-position: -224px -99px}
|
||||
.flag.flag-na {background-position: -240px -99px}
|
||||
.flag.flag-nc {background-position: 0 -110px}
|
||||
.flag.flag-ne {background-position: -16px -110px}
|
||||
.flag.flag-nf {background-position: -32px -110px}
|
||||
.flag.flag-ng {background-position: -48px -110px}
|
||||
.flag.flag-ni {background-position: -64px -110px}
|
||||
.flag.flag-nl {background-position: -80px -110px}
|
||||
.flag.flag-no {background-position: -96px -110px}
|
||||
.flag.flag-np {background-position: -112px -110px}
|
||||
.flag.flag-nr {background-position: -128px -110px}
|
||||
.flag.flag-nu {background-position: -144px -110px}
|
||||
.flag.flag-nz {background-position: -160px -110px}
|
||||
.flag.flag-om {background-position: -176px -110px}
|
||||
.flag.flag-pa {background-position: -192px -110px}
|
||||
.flag.flag-pe {background-position: -208px -110px}
|
||||
.flag.flag-pf {background-position: -224px -110px}
|
||||
.flag.flag-pg {background-position: -240px -110px}
|
||||
.flag.flag-ph {background-position: 0 -121px}
|
||||
.flag.flag-pk {background-position: -16px -121px}
|
||||
.flag.flag-pl {background-position: -32px -121px}
|
||||
.flag.flag-pm {background-position: -48px -121px}
|
||||
.flag.flag-pn {background-position: -64px -121px}
|
||||
.flag.flag-pr {background-position: -80px -121px}
|
||||
.flag.flag-ps {background-position: -96px -121px}
|
||||
.flag.flag-pt {background-position: -112px -121px}
|
||||
.flag.flag-pw {background-position: -128px -121px}
|
||||
.flag.flag-py {background-position: -144px -121px}
|
||||
.flag.flag-qa {background-position: -160px -121px}
|
||||
.flag.flag-re {background-position: -176px -121px}
|
||||
.flag.flag-ro {background-position: -192px -121px}
|
||||
.flag.flag-rs {background-position: -208px -121px}
|
||||
.flag.flag-ru {background-position: -224px -121px}
|
||||
.flag.flag-rw {background-position: -240px -121px}
|
||||
.flag.flag-sa {background-position: 0 -132px}
|
||||
.flag.flag-sb {background-position: -16px -132px}
|
||||
.flag.flag-sc {background-position: -32px -132px}
|
||||
.flag.flag-scotland {background-position: -48px -132px}
|
||||
.flag.flag-sd {background-position: -64px -132px}
|
||||
.flag.flag-se {background-position: -80px -132px}
|
||||
.flag.flag-sg {background-position: -96px -132px}
|
||||
.flag.flag-sh {background-position: -112px -132px}
|
||||
.flag.flag-si {background-position: -128px -132px}
|
||||
.flag.flag-sk {background-position: -144px -132px}
|
||||
.flag.flag-sl {background-position: -160px -132px}
|
||||
.flag.flag-sm {background-position: -176px -132px}
|
||||
.flag.flag-sn {background-position: -192px -132px}
|
||||
.flag.flag-so {background-position: -208px -132px}
|
||||
.flag.flag-somaliland {background-position: -224px -132px}
|
||||
.flag.flag-sr {background-position: -240px -132px}
|
||||
.flag.flag-ss {background-position: 0 -143px}
|
||||
.flag.flag-st {background-position: -16px -143px}
|
||||
.flag.flag-sv {background-position: -32px -143px}
|
||||
.flag.flag-sx {background-position: -48px -143px}
|
||||
.flag.flag-sy {background-position: -64px -143px}
|
||||
.flag.flag-sz {background-position: -80px -143px}
|
||||
.flag.flag-tc {background-position: -96px -143px}
|
||||
.flag.flag-td {background-position: -112px -143px}
|
||||
.flag.flag-tf {background-position: -128px -143px}
|
||||
.flag.flag-tg {background-position: -144px -143px}
|
||||
.flag.flag-th {background-position: -160px -143px}
|
||||
.flag.flag-tj {background-position: -176px -143px}
|
||||
.flag.flag-tk {background-position: -192px -143px}
|
||||
.flag.flag-tl {background-position: -208px -143px}
|
||||
.flag.flag-tm {background-position: -224px -143px}
|
||||
.flag.flag-tn {background-position: -240px -143px}
|
||||
.flag.flag-to {background-position: 0 -154px}
|
||||
.flag.flag-tr {background-position: -16px -154px}
|
||||
.flag.flag-tt {background-position: -32px -154px}
|
||||
.flag.flag-tv {background-position: -48px -154px}
|
||||
.flag.flag-tw {background-position: -64px -154px}
|
||||
.flag.flag-tz {background-position: -80px -154px}
|
||||
.flag.flag-ua {background-position: -96px -154px}
|
||||
.flag.flag-ug {background-position: -112px -154px}
|
||||
.flag.flag-um {background-position: -128px -154px}
|
||||
.flag.flag-us {background-position: -144px -154px}
|
||||
.flag.flag-uy {background-position: -160px -154px}
|
||||
.flag.flag-uz {background-position: -176px -154px}
|
||||
.flag.flag-va {background-position: -192px -154px}
|
||||
.flag.flag-vc {background-position: -208px -154px}
|
||||
.flag.flag-ve {background-position: -224px -154px}
|
||||
.flag.flag-vg {background-position: -240px -154px}
|
||||
.flag.flag-vi {background-position: 0 -165px}
|
||||
.flag.flag-vn {background-position: -16px -165px}
|
||||
.flag.flag-vu {background-position: -32px -165px}
|
||||
.flag.flag-wales {background-position: -48px -165px}
|
||||
.flag.flag-wf {background-position: -64px -165px}
|
||||
.flag.flag-ws {background-position: -80px -165px}
|
||||
.flag.flag-ye {background-position: -96px -165px}
|
||||
.flag.flag-yt {background-position: -112px -165px}
|
||||
.flag.flag-za {background-position: -128px -165px}
|
||||
.flag.flag-zanzibar {background-position: -144px -165px}
|
||||
.flag.flag-zm {background-position: -160px -165px}
|
||||
.flag.flag-zw {background-position: -176px -165px}
|
||||
Reference in New Issue
Block a user