diff --git a/Gemfile b/Gemfile
index 2f068cbf..d58616d3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,7 +1,7 @@
source 'https://rubygems.org'
gem 'rails', '~> 6.1.1'
-gem 'rails-i18n', '~> 6.0.0'
+gem 'rails-i18n', '~> 7.0'
gem 'rdiscount', '~> 2.2.7'
gem 'rubyzip', '~> 2.3.0'
gem 'activeadmin', '~> 2.9.0'
@@ -21,8 +21,8 @@ gem 'prawn', '~> 2.4.0'
gem 'prawn-table', '~> 0.2.2'
gem 'pg_search', '~> 2.3.5'
gem 'skylight', '~> 5.0'
-gem 'sidekiq', '~> 6.4.0'
-gem 'sidekiq-cron', '~> 1.2.0'
+gem 'sidekiq', '~> 6.5'
+gem 'sidekiq-cron', '~> 1.9.1'
gem 'aws-sdk-s3', '~> 1.94', require: false
gem 'image_processing', '~> 1.12'
@@ -58,7 +58,7 @@ group :test do
gem 'fabrication', '~> 2.20'
gem 'faker', '~> 2.15'
gem 'capybara', '~> 3.29'
- gem 'selenium-webdriver', '~> 3.142'
- gem 'webdrivers', '~> 4.4'
- gem 'simplecov', '~> 0.17', require: false
+ gem 'selenium-webdriver', '~> 4.1.0'
+ gem 'webdrivers', '~> 5.3'
+ gem 'simplecov', '~> 0.22', require: false
end
diff --git a/Gemfile.lock b/Gemfile.lock
index b3e84b05..7792343b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,40 +1,40 @@
GEM
remote: https://rubygems.org/
specs:
- actioncable (6.1.7.3)
- actionpack (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ actioncable (6.1.7.6)
+ actionpack (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.1.7.3)
- actionpack (= 6.1.7.3)
- activejob (= 6.1.7.3)
- activerecord (= 6.1.7.3)
- activestorage (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ actionmailbox (6.1.7.6)
+ actionpack (= 6.1.7.6)
+ activejob (= 6.1.7.6)
+ activerecord (= 6.1.7.6)
+ activestorage (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
mail (>= 2.7.1)
- actionmailer (6.1.7.3)
- actionpack (= 6.1.7.3)
- actionview (= 6.1.7.3)
- activejob (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ actionmailer (6.1.7.6)
+ actionpack (= 6.1.7.6)
+ actionview (= 6.1.7.6)
+ activejob (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.1.7.3)
- actionview (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ actionpack (6.1.7.6)
+ actionview (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
rack (~> 2.0, >= 2.0.9)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.1.7.3)
- actionpack (= 6.1.7.3)
- activerecord (= 6.1.7.3)
- activestorage (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ actiontext (6.1.7.6)
+ actionpack (= 6.1.7.6)
+ activerecord (= 6.1.7.6)
+ activestorage (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
nokogiri (>= 1.8.5)
- actionview (6.1.7.3)
- activesupport (= 6.1.7.3)
+ actionview (6.1.7.6)
+ activesupport (= 6.1.7.6)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
@@ -48,29 +48,29 @@ GEM
kaminari (~> 1.0, >= 1.2.1)
railties (>= 5.2, < 6.2)
ransack (~> 2.1, >= 2.1.1)
- activejob (6.1.7.3)
- activesupport (= 6.1.7.3)
+ activejob (6.1.7.6)
+ activesupport (= 6.1.7.6)
globalid (>= 0.3.6)
- activemodel (6.1.7.3)
- activesupport (= 6.1.7.3)
- activerecord (6.1.7.3)
- activemodel (= 6.1.7.3)
- activesupport (= 6.1.7.3)
- activestorage (6.1.7.3)
- actionpack (= 6.1.7.3)
- activejob (= 6.1.7.3)
- activerecord (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ activemodel (6.1.7.6)
+ activesupport (= 6.1.7.6)
+ activerecord (6.1.7.6)
+ activemodel (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
+ activestorage (6.1.7.6)
+ actionpack (= 6.1.7.6)
+ activejob (= 6.1.7.6)
+ activerecord (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
- activesupport (6.1.7.3)
+ activesupport (6.1.7.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
- addressable (2.8.0)
- public_suffix (>= 2.0.2, < 5.0)
+ addressable (2.8.5)
+ public_suffix (>= 2.0.2, < 6.0)
airbrussh (1.4.0)
sshkit (>= 1.6.1, != 1.7.0)
arbre (1.4.0)
@@ -117,20 +117,21 @@ GEM
capistrano-rbenv (2.2.0)
capistrano (~> 3.1)
sshkit (~> 1.3)
- capybara (3.35.3)
+ capybara (3.36.0)
addressable
+ matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
- childprocess (3.0.0)
+ childprocess (4.1.0)
concurrent-ruby (1.2.2)
- connection_pool (2.2.5)
+ connection_pool (2.4.1)
crass (1.0.6)
database_cleaner (1.8.5)
- date (3.3.3)
+ date (3.3.4)
devise (4.9.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
@@ -140,7 +141,7 @@ GEM
devise-i18n (1.11.0)
devise (>= 4.9.0)
diff-lcs (1.4.4)
- docile (1.3.5)
+ docile (1.4.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.7.6)
@@ -148,7 +149,7 @@ GEM
dotenv (= 2.7.6)
railties (>= 3.2)
erubi (1.12.0)
- et-orbi (1.2.4)
+ et-orbi (1.2.7)
tzinfo
execjs (2.8.1)
fabrication (2.22.0)
@@ -158,12 +159,12 @@ GEM
formtastic (4.0.0)
actionpack (>= 5.2.0)
formtastic_i18n (0.6.0)
- fugit (1.4.5)
- et-orbi (~> 1.1, >= 1.1.8)
+ fugit (1.9.0)
+ et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4)
gli (2.21.0)
- globalid (1.1.0)
- activesupport (>= 5.0)
+ globalid (1.2.1)
+ activesupport (>= 6.1)
has_scope (0.7.2)
actionpack (>= 4.1)
activesupport (>= 4.1)
@@ -214,7 +215,7 @@ GEM
i18n (>= 0.7, < 2)
json (>= 1.7.7)
rest-client (>= 1.8.0)
- loofah (2.21.3)
+ loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@@ -223,29 +224,30 @@ GEM
net-pop
net-smtp
marcel (1.0.2)
+ matrix (0.4.2)
method_source (1.0.0)
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
mini_magick (4.11.0)
- mini_mime (1.1.2)
- mini_portile2 (2.8.2)
- minitest (5.18.0)
+ mini_mime (1.1.5)
+ mini_portile2 (2.8.5)
+ minitest (5.20.0)
msgpack (1.5.2)
- net-imap (0.3.4)
+ net-imap (0.3.7)
date
net-protocol
net-pop (0.1.2)
net-protocol
- net-protocol (0.2.1)
+ net-protocol (0.2.2)
timeout
net-scp (3.0.0)
net-ssh (>= 2.6.5, < 7.0.0)
- net-smtp (0.3.3)
+ net-smtp (0.4.0)
net-protocol
net-ssh (6.1.0)
netrc (0.11.0)
- nio4r (2.5.8)
+ nio4r (2.6.0)
nokogiri (1.13.10)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
@@ -263,50 +265,51 @@ GEM
ttfunk (~> 1.7)
prawn-table (0.2.2)
prawn (>= 1.3.0, < 3.0.0)
- public_suffix (4.0.6)
+ public_suffix (5.0.4)
pundit (2.1.0)
activesupport (>= 3.0.0)
raabro (1.4.0)
- racc (1.7.0)
- rack (2.2.7)
+ racc (1.7.3)
+ rack (2.2.8)
rack-test (2.1.0)
rack (>= 1.3)
- rails (6.1.7.3)
- actioncable (= 6.1.7.3)
- actionmailbox (= 6.1.7.3)
- actionmailer (= 6.1.7.3)
- actionpack (= 6.1.7.3)
- actiontext (= 6.1.7.3)
- actionview (= 6.1.7.3)
- activejob (= 6.1.7.3)
- activemodel (= 6.1.7.3)
- activerecord (= 6.1.7.3)
- activestorage (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ rails (6.1.7.6)
+ actioncable (= 6.1.7.6)
+ actionmailbox (= 6.1.7.6)
+ actionmailer (= 6.1.7.6)
+ actionpack (= 6.1.7.6)
+ actiontext (= 6.1.7.6)
+ actionview (= 6.1.7.6)
+ activejob (= 6.1.7.6)
+ activemodel (= 6.1.7.6)
+ activerecord (= 6.1.7.6)
+ activestorage (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
bundler (>= 1.15.0)
- railties (= 6.1.7.3)
+ railties (= 6.1.7.6)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
- rails-dom-testing (2.0.3)
- activesupport (>= 4.2.0)
+ rails-dom-testing (2.2.0)
+ activesupport (>= 5.0.0)
+ minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.5.0)
loofah (~> 2.19, >= 2.19.1)
- rails-i18n (6.0.0)
+ rails-i18n (7.0.8)
i18n (>= 0.7, < 2)
- railties (>= 6.0.0, < 7)
- railties (6.1.7.3)
- actionpack (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ railties (>= 6.0.0, < 8)
+ railties (6.1.7.6)
+ actionpack (= 6.1.7.6)
+ activesupport (= 6.1.7.6)
method_source
rake (>= 12.2)
thor (~> 1.0)
rainbow (3.0.0)
raindrops (0.19.1)
- rake (13.0.6)
+ rake (13.1.0)
ransack (2.4.2)
activerecord (>= 5.2.4)
activesupport (>= 5.2.4)
@@ -315,8 +318,8 @@ GEM
rb-inotify (0.10.1)
ffi (~> 1.0)
rdiscount (2.2.7)
- redis (4.5.1)
- regexp_parser (2.1.1)
+ redis (4.8.1)
+ regexp_parser (2.8.2)
responders (3.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
@@ -363,7 +366,7 @@ GEM
ruby-vips (2.1.4)
ffi (~> 1.12)
ruby2_keywords (0.0.4)
- rubyzip (2.3.0)
+ rubyzip (2.3.2)
sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
@@ -373,30 +376,31 @@ GEM
sprockets-rails
tilt
select2-rails (4.0.13)
- selenium-webdriver (3.142.7)
- childprocess (>= 0.5, < 4.0)
+ selenium-webdriver (4.1.0)
+ childprocess (>= 0.5, < 5.0)
+ rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2)
shoulda-matchers (4.5.1)
activesupport (>= 4.2.0)
- sidekiq (6.4.0)
- connection_pool (>= 2.2.2)
+ sidekiq (6.5.12)
+ connection_pool (>= 2.2.5, < 3)
rack (~> 2.0)
- redis (>= 4.2.0)
- sidekiq-cron (1.2.0)
- fugit (~> 1.1)
+ redis (>= 4.5.0, < 5)
+ sidekiq-cron (1.9.1)
+ fugit (~> 1.8)
sidekiq (>= 4.2.1)
simple_form (5.0.3)
actionpack (>= 5.0)
activemodel (>= 5.0)
- simplecov (0.21.2)
+ simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
- simplecov_json_formatter (0.1.3)
+ simplecov_json_formatter (0.1.4)
skylight (5.0.1)
activesupport (>= 5.2.0)
- sprockets (4.2.0)
+ sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
@@ -406,9 +410,9 @@ GEM
sshkit (1.21.2)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
- thor (1.2.2)
+ thor (1.3.0)
tilt (2.0.10)
- timeout (0.3.2)
+ timeout (0.4.1)
ttfunk (1.7.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
@@ -428,16 +432,16 @@ GEM
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
- webdrivers (4.6.0)
+ webdrivers (5.3.1)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
- selenium-webdriver (>= 3.0, < 4.0)
- websocket-driver (0.7.5)
+ selenium-webdriver (~> 4.0, < 4.11)
+ websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.6.8)
+ zeitwerk (2.6.12)
PLATFORMS
ruby
@@ -474,7 +478,7 @@ DEPENDENCIES
pundit (~> 2.1.0)
rails (~> 6.1.1)
rails-controller-testing
- rails-i18n (~> 6.0.0)
+ rails-i18n (~> 7.0)
rdiscount (~> 2.2.7)
rollbar (~> 2.22.1)
rspec-rails (~> 4.0.0)
@@ -483,17 +487,17 @@ DEPENDENCIES
rubyzip (~> 2.3.0)
sassc-rails (~> 2.1.2)
select2-rails (~> 4.0.13)
- selenium-webdriver (~> 3.142)
+ selenium-webdriver (~> 4.1.0)
shoulda-matchers (~> 4.4)
- sidekiq (~> 6.4.0)
- sidekiq-cron (~> 1.2.0)
+ sidekiq (~> 6.5)
+ sidekiq-cron (~> 1.9.1)
simple_form (~> 5.0.2)
- simplecov (~> 0.17)
+ simplecov (~> 0.22)
skylight (~> 5.0)
uglifier (~> 4.2.0)
unicorn (~> 5.5.1)
web-console (~> 4.1.0)
- webdrivers (~> 4.4)
+ webdrivers (~> 5.3)
BUNDLED WITH
2.1.4
diff --git a/app/admin/post.rb b/app/admin/post.rb
index 43c32daf..39ad8d60 100644
--- a/app/admin/post.rb
+++ b/app/admin/post.rb
@@ -1,4 +1,19 @@
ActiveAdmin.register Post do
+ action_item :upload_csv, 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 = PostImporter.call(params[:dump][:organization_id], params[:dump][:file])
+ flash[:error] = errors.join("
").html_safe if errors.present?
+
+ redirect_to action: :index
+ end
+
index do
id_column
column :class
diff --git a/app/models/user.rb b/app/models/user.rb
index 771dbfea..49f462f1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -9,6 +9,10 @@ class User < ApplicationRecord
:timeoutable
]
+ ransacker :username do
+ Arel.sql('unaccent(users.username)')
+ end
+
GENDERS = %w(
female
male
@@ -34,7 +38,7 @@ class User < ApplicationRecord
accepts_nested_attributes_for :members, allow_destroy: true
default_scope { order("users.id ASC") }
- scope :actives, -> { references(:members).where(members: { active: true }) }
+ scope :actives, -> { joins(:members).where(members: { active: true }) }
scope :online_active, -> { where("sign_in_count > 0") }
scope :notifications, -> { where(notifications: true) }
diff --git a/app/services/post_importer.rb b/app/services/post_importer.rb
new file mode 100644
index 00000000..19cc7b05
--- /dev/null
+++ b/app/services/post_importer.rb
@@ -0,0 +1,60 @@
+# Used in the Admin section to import posts
+# to a specific organization, from a CSV file.
+
+require "csv"
+
+class PostImporter
+ Row = Struct.new(
+ :user_id,
+ :type,
+ :title,
+ :description,
+ :category_id,
+ :created_at,
+ :start_on,
+ :end_on
+ ) do
+ def post_from_row
+ Object.const_get(type).new(
+ user_id: user_id,
+ title: title,
+ description: description,
+ category_id: category_id,
+ created_at: created_at,
+ start_on: start_on,
+ end_on: end_on
+ )
+ end
+ end
+
+ class << self
+ def call(organization_id, csv_data)
+ data = csv_data.read
+ errors = []
+
+ CSV.parse(data, headers: false) do |data_row|
+ row = Row.new(
+ data_row[0],
+ data_row[1],
+ data_row[2],
+ data_row[3],
+ data_row[4],
+ data_row[5],
+ data_row[6],
+ data_row[7]
+ )
+ process_row(row, organization_id, errors)
+ end
+
+ errors
+ end
+
+ def process_row(row, organization_id, errors)
+ post = row.post_from_row
+ post.organization_id = organization_id
+ return if post.save
+
+ errors.push(user_id: row.user_id, title: row.title, errors: post.errors.full_messages)
+ end
+ end
+end
diff --git a/config/application.rb b/config/application.rb
index 1179e636..2598506d 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -11,11 +11,9 @@ class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 6.1
- # 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
+ # I18n configuration
config.i18n.default_locale = :es
- config.i18n.available_locales = [:es, :ca, :eu, :gl, :en, :'pt-BR']
+ config.i18n.available_locales = [:es, :ca, :eu, :gl, :en, :'pt-BR', :fr]
config.i18n.fallbacks = true
# This tells Rails to serve error pages from the app itself, rather than using static error pages in public/
diff --git a/config/locales/es.yml b/config/locales/es.yml
index cc68059e..da201547 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -147,7 +147,7 @@ es:
statistics_all_transfers: Todas las transferencias
stats: Estadísticas
tags: Etiquetas
- type_of_swaps: Tipos de intecambios
+ type_of_swaps: Tipos de intercambios
users: Usuarios
without_offers: Sin ofertas publicadas
terms_conditions: Términos del servicio
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
new file mode 100644
index 00000000..75a97ce3
--- /dev/null
+++ b/config/locales/fr.yml
@@ -0,0 +1,588 @@
+fr:
+ active_admin:
+ users:
+ organization: Banque de temps
+ upload_csv: Fichier
+ upload_from_csv: Uploader un CSV
+ activerecord:
+ attributes:
+ account:
+ balance: Solde
+ organization: Organisation
+ category:
+ created_at: Créée le
+ name: Nom
+ name_translations: Nom (traductions)
+ parent: Catégorie parente
+ updated_at: Mise à jour le
+ common:
+ created_at: Créé·e le
+ updated_at: Mis·e à jour le
+ inquiry:
+ is_group: Demande de groupe
+ offer:
+ is_group: Offre de groupe
+ organization:
+ address: Adresse
+ city: Ville
+ created_at: Créée le
+ description: Description
+ email: Adresse email
+ name: Nom
+ neighborhood: Quartier
+ phone: Téléphone
+ public_opening_times: Horaires d'ouverture
+ reg_number_seq: Numéro de séquence utilisateur
+ updated_at: Mise à jour le
+ post:
+ category: Catégorie
+ created_at: Créée le
+ description: Description
+ end_on: Termine le
+ start_on: Commence le
+ tag_list: Tags
+ title: Titre
+ updated_at: Mise à jour le
+ transfer:
+ amount: Quantité
+ created_at: Créé le
+ hours: Heures
+ minutes: Minutes
+ post: Annonce
+ reason: Commentaires
+ source: Origine
+ updated_at: Mis à jour le
+ user:
+ admin: Administrateur de l'organisation
+ alt_phone: Téléphone (secondaire)
+ created_at: Créé·e le
+ date_of_birth: Date de naissance
+ deactivated: Désactivé·e
+ description: Description
+ email: Adresse email
+ gender: Genre
+ last_sign_in_at: Dernière connexion
+ notifications: Recevoir des notifications
+ organization: Organisation
+ phone: Téléphone
+ postcode: Code postal
+ push_notifications: Recevoir des notifications sur mon téléphone
+ registration_date: Date d'inscription
+ registration_number: Numéro d'inscription
+ superadmin: Administrateur système
+ unconfirmed_email: Adresse email non-confirmée
+ updated_at: Mis·e à jour le
+ username: Nom
+ errors:
+ models:
+ organization:
+ attributes:
+ web:
+ url_format_invalid: format du lien invalide
+ transfer:
+ attributes:
+ base:
+ same_account: Un tranfert ne peut pas être fait vers le même compte.
+ user:
+ attributes:
+ email:
+ invalid: invalide
+ models:
+ category:
+ one: Catégorie
+ other: Catégories
+ comment:
+ one: Commentaire
+ other: Commentaires
+ inquiry:
+ one: Demande
+ other: Demandes
+ offer:
+ one: Offre
+ other: Offres
+ organization:
+ one: Banque de temps
+ other: Banques de temps
+ post:
+ one: Annonce
+ other: Annonces
+ transfer:
+ one: Transfert
+ other: Transferts
+ user:
+ one: Utilisateur·rice
+ other: Utilisateurs·rices
+ application:
+ landing:
+ button: Entrer
+ slogan: Valorisons notre temps
+ sub_slogan: Il y a une banque de temps près de chez vous
+ login_form:
+ button: Se connecter
+ email: Adresse email
+ password: Mot de passe
+ remember_check: Se souvenir de moi
+ menu:
+ sign_in: Se connecter
+ sing_out: Se déconnecter
+ menus:
+ offers_by_tag_link:
+ tags: Tags
+ navbar:
+ admin: Administrer
+ administration: Administration
+ adminshort: Admin
+ all_transfers: Tous les transferts
+ categories: Services
+ demographics: Données démographiques
+ global_activity: Activité globale
+ inactive_users: Utilisateurs·rices inactifs·ives
+ inquiry_public_link: Lien public des demandes
+ last_login: Dernière connexion le
+ offer_public_link: Lien public des offres
+ organizations: Organisations
+ reports: Rapports
+ sign_out: Se déconnecter
+ statistics: Statistiques
+ statistics_all_transfers: Tous les transferts
+ stats: Statistiques
+ tags: Tags
+ type_of_swaps: Type d'échanges
+ users: Utilisateurs·ices
+ without_offers: Sans offres
+ terms_conditions: Conditions d'utilisation
+ tips:
+ entertag: Saisir des tags séparés par des virgules
+ user_not_found: Utilisateur·rice non trouvé·e
+ devise:
+ confirmations:
+ confirmed: Votre compte a bien été confirmé.
+ confirmed_and_signed_in: Votre compte a bien été confirmé. Vous êtes maintenant connecté.
+ new:
+ resend_instructions: Envoyer de nouveau les instructions de confirmation
+ resend_instructions_button: Renvoyer
+ resend_instructions_description: Si vous avez changé d'adresse email, vous devez réaliser cette étape pour valider le changement
+ send_instructions: Vous allez recevoir un email avec des instructions pour confirmer votre compte dans quelques instants.
+ send_paranoid_instructions: Si votre adresse email existe, vous allez recevoir un email avec des instructions pour confirmer votre compte dans quelques instants.
+ failure:
+ already_authenticated: Vous êtes déjà connecté.
+ inactive: Votre compte n'est pas encore activé.
+ invalid: Adresse email ou mot de passe invalide.
+ invalid_token: Jeton d'authentification invalide.
+ locked: Votre compte est bloqué.
+ not_found_in_database: Adresse email ou mot de passe invalide.
+ timeout: Votre session est expirée. Veuillez vous reconnecter pour continuer.
+ unauthenticated: Vous devez vous connecter ou vous inscrire pour continuer.
+ unconfirmed: Vous devez valider votre compte pour continuer.
+ user:
+ last_attempt: Attention, plus qu'un essai avant le blocage de votre compte
+ mailer:
+ confirmation_instructions:
+ subject: Instructions de confirmation
+ reset_password_instructions:
+ subject: Instructions de réinitialisation de mot de passe
+ unlock_instructions:
+ subject: Instructions de déblocage
+ omniauth_callbacks:
+ failure: Impossible de vous connecter par %{kind} à cause de "%{reason}".
+ success: Connexion réussie par votre compte %{kind}.
+ passwords:
+ edit:
+ change_password: Modifier mon mot de passe
+ confirm_password: Confirmer votre nouveau mot de passe
+ new_password: Nouveau mot de passe
+ passwords_not_match: Les mots de passe ne correspondent pas
+ new:
+ forgot_question: Créer un nouveau mot de passe
+ forgot_question_description: Saisissez l'adresse email associée à votre compte et nous vous enverrons un email avec un lien pour définir un nouveau mot de passe.
+ send_instructions: Envoyer le lien
+ no_token: Vous ne pouvez pas accéder à cette page si vous n'arrivez pas d'un email de réinitialisation de mot de passe. Si vous venez d'un email de réinitialisation de mot de passe, assurez-vous d'avoir bien copier le lien en entier.
+ send_instructions: Vous allez recevoir un email avec les instructions de réinitialisation de mot de passe dans quelques instants.
+ send_paranoid_instructions: Si votre adresse email existe, vous allez recevoir un lien par email pour récupérer votre mot de passe dans quelques instants.
+ updated: Votre mot de passe a été changé avec succès. Vous êtes maintenant connecté.
+ updated_not_active: Votre mot de passe a été changé avec succès.
+ registrations:
+ destroyed: Au revoir! Votre compte a bien été supprimé. On espère vous revoir bientôt.
+ edit:
+ cancel_account: Supprimer mon compte
+ current_password: Mot de passe actuel
+ edit_user: Modifier mes paramètres
+ help_current_password: Saisissez votre mot de passe actuel
+ help_password: Laissez vide si vous ne voulez pas le changer
+ password: Mot de passe
+ password_confirmation: Confirmation du mot de passe
+ unhappy: Pas content ?
+ update: Mettre à jour
+ new:
+ password: Mot de passe
+ password_confirmation: Confirmation du mot de passe
+ sign_me_up: Créez-moi un compte
+ sign_up: Créer un compte
+ signed_up: Bienvenue! Compte créé avec succès.
+ signed_up_but_inactive: Compte créé avec succès. Cependant, vous ne pouvez pas encore vous connecter tant que votre compte n'est pas activé.
+ signed_up_but_locked: Compte créé avec succès. Cependant, vous ne pouvez pas encore vous connecter car votre compte est bloqué.
+ signed_up_but_unconfirmed: Un message contenant un lien de confirmation a été envoyé à votre adresse email. Ouvrez ce lien pour activer votre compte.
+ update_needs_confirmation: Compte mis à jour avec succès, mais nous devons vérifier votre adresse email. Un message contenant un lien de confirmation a été envoyé à votre adresse email. Ouvrez ce lien pour valider votre adresse email.
+ updated: Compte mis à jour avec succès.
+ sessions:
+ new:
+ remember_me: Se souvenir de moi
+ sign_in: Se connecter
+ user:
+ signed_in: Connecté
+ signed_out: Déconnecté
+ shared:
+ links:
+ didnt_receive_confirmation_instructions: Envoyer de nouveau les instructions de confirmation
+ didnt_receive_unlock_instructions: Recevoir les instructions de déblocage
+ forgot_your_password: J'ai oublié mon mot de passe
+ sign_in: Se connecter
+ sign_in_with: Se connecter avec %{provider}
+ sign_up: Créer un compte
+ unlocks:
+ new:
+ resend_instructions: Recevoir les instructions de déblocage
+ resend_instructions_button: Renvoyer
+ resend_instructions_description: Si vous avez échoué à vous connecter plus de 5 fois, vous devez débloquer votre compte
+ send_instructions: Vous allez recevoir un email avec des instructions pour débloquer votre compte dans quelques instants.
+ send_paranoid_instructions: Si votre compte existe, vous allez recevoir un email avec des instructions pour débloquer votre compte dans quelques instants.
+ unlocked: Votre compte a été débloqué avec succès. Merci de vous connecter pour continuer.
+ errors:
+ internal_server_error:
+ description: Nous sommes désolé, il semble que cette requête ait provoqué une erreur. Une notification nous a été envoyé afin de résoudre le problème rapidement.
+ title: Erreur serveur interne
+ messages:
+ already_confirmed: a déjà été confirmé, merci d'essayer de vous connecter
+ confirmation_period_expired: doit être confirmé en %{period}, merci de renouveler votre demande
+ expired: est expiré, merci de renouveler votre demande
+ not_found: non trouvé
+ not_locked: n'était pas bloqué
+ not_saved:
+ one: Une erreur a empêché cet·te %{resource} d'être sauvegardé·e.
+ other: "%{count} erreurs ont empêché cet·te %{resource} d'être sauvegardé·e."
+ not_found:
+ description: La page que vous cherchez n'existe pas. L'adresse est peut-être incorrecte ou la page a été déplacée.
+ title: Non trouvé
+ global:
+ add_new: Créer nouveau·elle
+ all: Tous·tes
+ amount: Quantité
+ announcements: Annonce
+ back: Retour
+ balance: 'Solde :'
+ cancel_membership: Suppression définitive
+ contact_details: Informations de contact
+ create: Créer
+ date: Données
+ decline: décliner
+ delete: Supprimer
+ demote: Convertir en utilisateur·rice normal·e
+ edit: Mettre à jour
+ enter_to_timebank: Entrer dans la banque de temps
+ filter: Filtrer
+ from: Depuis
+ give_time: Donner du temps
+ here: Ici
+ home: Accueil
+ information: Informations
+ locales_header: changer de langue
+ member_count: 'Nombre d''utilisateurs·rices :'
+ more: Plus
+ movements: Échanges
+ next: Suivant
+ or: ou
+ promote: Convertir en administrateur
+ reason: Raison
+ required_field: "* Champ requis"
+ save: Enregistrer
+ search: Rechercher
+ search_location: Rechercher par localisation
+ show: Voir
+ source_destination: Depuis/vers
+ statistics: Statistiques
+ table:
+ actions: Actions
+ to: Vers
+ inquiries:
+ edit:
+ submit: Modifier la demande
+ index:
+ new_inquiry: Nouvelle demande
+ new:
+ submit: Créer la demande
+ layouts:
+ application:
+ about: À propos de TimeOverflow
+ bdtnear: Chercher une Banque de temps
+ edit_org: Mettre à jour %{organization}
+ edit_profile: Mettre à jour mon profil
+ help: Aide
+ login: Connexion
+ manage_memberships: Gérer les inscriptions
+ report:
+ report_title: RAPPORT
+ locales:
+ ar: Arabe
+ ca: Catalan
+ en: Anglais
+ es: Espagnol
+ eu: Basque
+ fr: Français
+ gl: Galicien
+ pt: Portugais
+ pt-BR: Portugais
+ mailers_globals:
+ footer:
+ text: "%{organization_name} de"
+ text_donation: L'association ADBdT offre TimeOverflow gratuitement aux Banques de temps. Si vous voulez aider à maintenir et améliorer l'application %{href}.
+ text_donation_link: Visiter le site web
+ multi_transfers:
+ multi_transfers: Multi transferts
+ step:
+ confirm:
+ description: Confirmer les changements
+ type_of_transfer: Type de transfert
+ select_type:
+ description: Sélectionner le type de transfert
+ set_params:
+ description: Spécifier la quantité à transférer, la raison et l'annonce (si elle existe).
+ set_source:
+ description: Sélectionner le compte qui donne le temps
+ set_target:
+ description: Sélectionner le compte qui reçoit le temps
+ success: Transferts créés avec succès
+ types:
+ many_to_one: Plusieurs vers un·e
+ one_to_many: Un·e vers plusieurs
+ one_to_one: un·e vers un·e
+ offers:
+ edit:
+ submit: Modifier l'offre
+ index:
+ by_category: Par catégorie
+ by_tag: Par tag
+ filter: Filtrer
+ new_offer: Nouvelle offre
+ offered_by: Offert par %{size} personnes
+ new:
+ submit: Créer l'offre
+ show:
+ give_time_for: Donner du temps pour cette offre
+ offered_by: Offert par
+ organization_notifier:
+ recent_posts:
+ subject: Newsletter
+ text1: 'Dernières offres publiées :'
+ text2: 'Dernières demandes publiées :'
+ organizations:
+ give_time:
+ give_time: Donner du temps à
+ index:
+ member_count: Nombre d'utilisateurs·rices
+ new:
+ new: Nouvelle Banque
+ show:
+ contact_information: Informations de contact
+ join_timebank: N'hésitez pas à contacter la Banque de temps pour la rejoindre ou poser des questions.
+ pages:
+ about:
+ app-mobile: Application Mobile
+ app-mobile-text: L'application mobile TimeOverflow est disponible.
Cette application a été réalisée grâce à la collaboration de la municipalité de Barcelone, programe %{impulsem_link} (Barcelona Activa) 2017-2018
+ banner-button: Demander un accès à TimeOverflow
+ banner-subtitle: Nous vous contacterons pour démarrer ou vous faire une démonstration
+ banner-title: Êtes-vous une Banque de temps ?
+ empower-adbdt: ADBdT
+ empower-adbdt-title: Association pour le développement des Banques de temps
+ empower-coopdevs: CoopDevs
+ empower-coopdevs-title: CoopDevs
+ empower-github: Github
+ empower-github-title: Github
+ empower-showmap: Voir la map
+ empower-showmap-title: Banques de temps
+ empower-text-1: TimeOverflow est spécialement conçu par et pour les Banques de temps qui existent physiquement — %{showmap_link}, son but est de les propulser à l'aide d'internet.
+ empower-text-2: Grâce au travail d'équipe de %{coopdevs_link} et %{abdt_link}, nous pouvons aujourd'hui offrir l'application TimeOverflow à toutes les Banques de temps qui le désirent, de manière ouverte et gratuite.
+ empower-text-3: Le code source de TimeOverflow est disponible via une licence open-source et vous pouvez le télécharger sur %{github_link}
+ empower-title: Donnons du pouvoir aux Banques de temps
+ feature-group-1: Gestion de la Banque de temps avec des rôles d'administration
+ feature-group-2: Réseaux sociaux et échanges de temps accessibles par les membres
+ feature-text-1: Création/Suppression/Mise à jour des membres
+ feature-text-2: Publication d'offres et de demandes
+ feature-text-3: Entrer des chèques et gérer la comptabilité
+ feature-text-4: Les membres de la Banque de temps peuvent avoir accès au système et se connecter avec d'autres membres.
+ feature-text-5: Publication d'offres et de demandes
+ feature-text-6: Donner des heures à d'autres membres
+ impulsem-link: Impulsem el que fas
+ subtitle: TimeOverflow est open-source, gratuit et collaboratif
+ title: L'application conçue par et pour
+ title2: Banques de temps
+ petitions:
+ application_sent: Demande envoyée avec succès
+ application_sent_body: Bonjour! votre demande à %{organization_name} a bien été envoyée.
+ application_status: Demande %{status}
+ applications: Applications
+ apply: Demande à nous rejoindre
+ new: Nouvelle demande
+ new_body: Bonjour! Nouvelle demande de %{username}. Gérer vos demandes %{here_link}.
+ status:
+ accepted: acceptée
+ declined: déclinée
+ pending: en attente
+ sent: envoyée
+ status_applications: "%{status} demandes"
+ posts:
+ show:
+ info: Cette %{type} appartient à %{organization}.
+ reports:
+ download: Télécharger
+ download_all: Tout télécharger
+ shared:
+ movements:
+ delete_reason: Êtes-vous sûr de vouloir supprimer ce commentaire ?
+ movements: Échanges
+ post_form:
+ group_inquiry: Est-une demande de groupe ?
+ group_offer: Est-ce une offre de groupe ?
+ you_can_use: Vous pouvez utiliser
+ simple_form:
+ error_notification:
+ default_message: 'Merci de vérifier les problèmes ci-dessous :'
+ 'no': Non
+ options:
+ user:
+ gender:
+ female: Femme
+ male: Homme
+ others: Autre
+ prefer_not_to_answer: Je préfère ne pas répondre
+ required:
+ mark: "*"
+ text: Requis
+ 'yes': Oui
+ statistics:
+ all_transfers:
+ date: Date
+ delete_reason: Êtes-vous sur de vouloir supprimer ce commentaire ?
+ from: Depuis
+ post: Annonce
+ quantity: Quantité
+ reason: Raison
+ to: Vers
+ transfers: Tous les transferts
+ demographics:
+ by_ages: Par âges
+ by_gender: Par genre
+ demographics: Données démographiques
+ female: Femme
+ male: Homme
+ num_people: Nb de personnes
+ unknown: Non connu
+ global_activity:
+ bank_activity: Activité de la Banque
+ global_activity: Activité globale
+ num_swaps: Transferts
+ per_month: Par mois
+ show: Voir
+ total_hours: Heures transférées
+ users_reg: Inscriptions
+ inactive_users:
+ days_without_swaps: Jours sans transferts
+ inactive_users: Utilisateurs·rices inactifs·ives
+ last_movement: Dernier transfert
+ no_movements: Sans échanges
+ last_login:
+ last_login: Dernière connexion
+ never_login: Jamais connecté
+ type_swaps:
+ type_of_swaps: Type de transferts
+ without_category: Sans catégorie
+ without_tags: Sans tags
+ without_offers:
+ without_offers: Sans offres
+ stats:
+ min_balance:
+ title: Solde minimum des utilisateurs·rices
+ tags:
+ alpha_grouped_index:
+ maintitle: Tags disponibles
+ terms:
+ accept: Accept
+ show:
+ accept: Accept
+ transfers:
+ computation:
+ hour:
+ one: "%{count} heure"
+ other: "%{count} heures"
+ joiner: et
+ minute:
+ one: "%{count} minute"
+ other: "%{count} minutes"
+ new:
+ error_amount: Le temps doit être supérieur à 0
+ users:
+ avatar:
+ change_your_image: Changer l'image
+ crop_the_image: Redimensionner l'image
+ max_size_warning: L'image est trop lourde, la taille maximum est %{size}MB
+ confirm_email:
+ email_sent: Un email a été envoyé à %{email}. Après votre confirmation, vous pourrez faire une demande à une organisation.
+ please: Merci de confirmer votre adresse email
+ edit:
+ edit_user: Mise à jour de mon compte
+ form:
+ notifications: Notifications
+ give_time:
+ give_time: Donner du temps à
+ index:
+ account_deactivated: Votre compte a été désactivé de cette Banque de temps
+ actions: Actions
+ active_warning: Vous êtes sur le point de changer le statut du compte de %{username}
+ cancel_warning: Vous êtes sur le point de supprimer le compte %{username}
+ create: Créer un·e nouveau·elle utilisateur·rice
+ deactivated_warning: Si vous pensez que votre compte a été désactivé par erreur, merci de contacter l'administrateur·rice avec les informations ci-dessous.
+ manage_warning: Vous êtes sur le point de changer les privilèges de %{username}
+ members: Membres
+ user_created: Utilisateur·rice %{uid} %{name} sauvegardé·e
+ member_card:
+ active_ago: Actif·ive il y a %{time}
+ no_activity: Pas d'activité
+ new:
+ cancel: Annuler
+ create_more_users_button: Créer et ajouter un·e autre utilisateur·rice
+ new_user: Nouveau·elle utilisateur·rice
+ user_created_add: Utilisateur·rice %{uid} %{name} sauvegardé·e, maintenant créer un·e autre
+ show:
+ account: Derniers échanges
+ accounts: Comptes
+ balance: 'Solde :'
+ categories: Services
+ created_at: 'Inscription le :'
+ data: Détails de l'utilisateur·rice
+ date: Date
+ deleted_user: Cet·te utilisateur·rice n'existe plus
+ from_to: Depuis/Vers
+ inactive: "(Inactif·ive)"
+ inactive_user: L'utilisateur·rice n'est pas actif·ive
+ invalid_format: Format invalide, merci de choisir ".jpg", ".jpeg" ou ".png".
+ phone:
+ one: Téléphone
+ other: Téléphones
+ post: Annonce
+ quantity: Quantité
+ reason: Raison
+ user_no: 'Utilisateur·rice # :'
+ user_rows:
+ activate: Activer
+ active_warning: Vous êtes sur le point de changer le statut du compte de %{user}
+ cancel_warning: Vous êtes sur le point de supprimer le compte de %{user}
+ deactivate: Désactiver
+ delete_membership: Supprimer l'inscription
+ manage_warning: Vous êtes sur le point modifier les privilèges de %{user}
+ sure_delete: Êtes-vous de vouloir supprimer votre inscription à %{organization_name} ?
+ views:
+ pagination:
+ first: "« Première"
+ last: Dernière »
+ next: Suivante ›
+ previous: "‹ Précédente"
+ truncate: "…"
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index f8a3f7a2..a677d6d1 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -87,8 +87,14 @@
it "populates and array of users" do
get "index"
+ expected_users = [user, another_user, admin_user, wrong_user, empty_email_user]
+
+ expected_users.each_with_index do |user, i|
+ user.update!(last_sign_in_at: Time.current - i.days)
+ end
+
expect(assigns(:members).map(&:user))
- .to eq([user, another_user, admin_user, wrong_user, empty_email_user])
+ .to eq(expected_users)
end
end
@@ -140,6 +146,15 @@
expect(assigns(:members)).to include(member)
end
+
+ it 'allows to search a member ignoring accents of user\'s username' do
+ user = Fabricate(:user, username: 'fôô', email: 'test@email.com')
+ member = Fabricate(:member, user: user, organization: test_organization)
+
+ get :index, params: { q: { member_search_cont: "foo" } }
+
+ expect(assigns(:members)).to include(member)
+ end
end
end
@@ -326,7 +341,7 @@
it 'creates the user' do
expect do
- post :create, params: { user: Fabricate.to_params(:user, password: '1234test'), from_signup: 'true' }
+ post :create, params: { user: Fabricate.to_params(:user, password: '1234test'), from_signup: 'true' }
end.to change(User, :count).by(1)
expect(subject).to redirect_to(terms_path)
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 43835d9e..2b48e506 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -56,8 +56,7 @@
end
describe ".actives" do
- skip "should list users with active members" do
- # The join at User.actives is failing
+ it "should list users with active members" do
user_w_inactive = Fabricate(:user)
user_w_active = Fabricate(:user)
inactive_member = Fabricate(:member, user: user_w_inactive, active: false)