From 2ccc9e9dbd36a6030af62a766bddb073e9a262d6 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 24 Aug 2017 12:46:58 +0200 Subject: [PATCH 01/23] [bug] missing translation for EN and PT --- config/locales/app.shared.en.yml | 2 +- config/locales/app.shared.pt.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/app.shared.en.yml b/config/locales/app.shared.en.yml index 146a5d7c1..f582b87bb 100644 --- a/config/locales/app.shared.en.yml +++ b/config/locales/app.shared.en.yml @@ -424,7 +424,7 @@ en: _subscription: "subscription" cost_of_the_subscription: "Cost of the subscription" confirm_and_pay: "Confirm and pay" - you_have_settled_the_following_machine_hours: "You have settled the following {TYPE, select, Machine{machine hours} Training{training} other{elements}}:" # messageFormat interpolation + you_have_settled_the_following_TYPE: "You have settled the following {TYPE, select, Machine{machine hours} Training{training} other{elements}}:" # messageFormat interpolation you_have_settled_a_: "You have settled a" total_: "TOTAL :" thank_you_your_payment_has_been_successfully_registered: "Thank you. Your payment has been successfully registered !" diff --git a/config/locales/app.shared.pt.yml b/config/locales/app.shared.pt.yml index ed9b5343d..d5936ddf8 100755 --- a/config/locales/app.shared.pt.yml +++ b/config/locales/app.shared.pt.yml @@ -424,7 +424,7 @@ pt: _subscription: "inscrição" cost_of_the_subscription: "Custo da inscrição" confirm_and_pay: "Confirmar e pagar" - you_have_settled_the_following_machine_hours: "Você liquidou o seguinte {TYPE, select, Machine{horas máquina} Training{training} other{elements}}:" # messageFormat interpolation + you_have_settled_the_following_TYPE: "Você liquidou o seguinte {TYPE, select, Machine{horas máquina} Training{training} other{elements}}:" # messageFormat interpolation you_have_settled_a_: "Você tem liquidado:" total_: "TOTAL :" thank_you_your_payment_has_been_successfully_registered: "Obrigado. Seu pagamento foi registrado com sucesso !" From b279b14318aefc02a4aa8dcaccfee416a21a3781 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 24 Aug 2017 12:47:51 +0200 Subject: [PATCH 02/23] updated changelog & version --- .fabmanager-version | 2 +- CHANGELOG.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.fabmanager-version b/.fabmanager-version index ff3b2cd99..a51f76bd5 100644 --- a/.fabmanager-version +++ b/.fabmanager-version @@ -1 +1 @@ -2.5.10 +2.5.11-dev \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f171b3878..d47b9a904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog Fab Manager +## next release + +- Fix a bug: missing translation after payment in english and portuguese + ## v2.5.10 2017 August 16 - Updated axlsx gem for excel files generation, possible fix for #489 From 9f235d5c3bc2773b6c253c02b9f23cfa7307acfa Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 24 Aug 2017 16:08:42 +0200 Subject: [PATCH 03/23] ArchLinux compatibility --- CHANGELOG.md | 2 ++ Gemfile | 2 +- Gemfile.lock | 5 ++--- README.md | 1 + doc/archlinux_readme.md | 13 +++++++++++++ 5 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 doc/archlinux_readme.md diff --git a/CHANGELOG.md b/CHANGELOG.md index d47b9a904..59957d279 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## next release - Fix a bug: missing translation after payment in english and portuguese +- Updated puma for compatibility with openSSL > 1.0 +- Documented installation on ArchLinux ## v2.5.10 2017 August 16 diff --git a/Gemfile b/Gemfile index 94257d0e0..5686d6664 100644 --- a/Gemfile +++ b/Gemfile @@ -43,7 +43,7 @@ group :development do gem 'mailcatcher' gem 'awesome_print' - gem "puma" + gem 'puma' gem 'foreman' gem 'capistrano' diff --git a/Gemfile.lock b/Gemfile.lock index f992737be..e611da0fb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -301,8 +301,7 @@ GEM prawn-table (0.2.1) protected_attributes (1.1.3) activemodel (>= 4.0.1, < 5.0) - puma (2.11.1) - rack (>= 1.1, < 2.0) + puma (3.10.0) pundit (1.0.0) activesupport (>= 3.0.0) rack (1.6.8) @@ -568,4 +567,4 @@ DEPENDENCIES webmock BUNDLED WITH - 1.15.3 + 1.15.4 diff --git a/README.md b/README.md index cbd6a1f8b..ae1a09838 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ In you only intend to run fab-manager on your local machine for testing purposes 1. Install RVM with the ruby version specified in the [.ruby-version file](.ruby-version). For more details about the process, Please read the [official RVM documentation](http://rvm.io/rvm/install). + If you're using ArchLinux, you may have to [read this](doc/archlinux_readme.md) before. 2. Retrieve the project from Git diff --git a/doc/archlinux_readme.md b/doc/archlinux_readme.md new file mode 100644 index 000000000..33a3098a1 --- /dev/null +++ b/doc/archlinux_readme.md @@ -0,0 +1,13 @@ +# Specific instructions concerning installation on ArchLinux + +## Ruby 2.3.0 +Ruby 2.3.0 has a known issue with openSSL version > 1.0 (which is ArchLinux default). +To overpass this problem, you must install ruby with special indication of the openSSL installation to use. + +```bash +sudo pacman -S gcc5 +rvm pkg install openssl +CC=gcc-5 rvm install 2.3.0 -C --with-openssl-dir=$HOME/.rvm/usr +``` + +There's also an issue with openSSL and `puma` but this is fixed by using puma version > 3. \ No newline at end of file From eb4f97000d8ddf80ecbbaa35c7e868e8cb5b38b0 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 24 Aug 2017 16:53:27 +0200 Subject: [PATCH 04/23] [bug] admin cannot see all space availabilities --- CHANGELOG.md | 1 + app/controllers/api/availabilities_controller.rb | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59957d279..5330dbbc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## next release +- Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese - Updated puma for compatibility with openSSL > 1.0 - Documented installation on ArchLinux diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index c51063a15..ffd3c45a8 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -190,7 +190,7 @@ class API::AvailabilitiesController < API::ApiController @space = Space.friendly.find(params[:space_id]) @slots = [] @reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @space.class.to_s, @space.id).includes(:slots, user: [:profile]).references(:slots, :user).where('slots.start_at > ?', Time.now) - if @user.is_admin? + if current_user.is_admin? @availabilities = @space.availabilities.includes(:tags).where("end_at > ? AND available_type = 'space'", Time.now) else end_at = 1.month.since From cf6afb817dc835eba52d740ae762db5a8ba64226 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 24 Aug 2017 18:34:18 +0200 Subject: [PATCH 05/23] [feature] configuration of max visibility for reservations --- CHANGELOG.md | 4 +- .../controllers/admin/settings.coffee | 14 +- app/assets/javascripts/router.coffee.erb | 4 +- .../admin/settings/reservations.html | 31 ++- .../api/availabilities_controller.rb | 18 +- app/models/setting.rb | 4 +- config/locales/app.admin.en.yml | 5 + config/locales/app.admin.fr.yml | 5 + config/locales/app.admin.pt.yml | 5 + db/schema.rb | 180 +++++++++--------- db/seeds.rb | 12 ++ 11 files changed, 178 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5330dbbc3..e68441c52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,12 @@ ## next release +- Ability for admins to configure the maximum visibility for availabilities reservation - Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese -- Updated puma for compatibility with openSSL > 1.0 +- Updated puma for compatibility with openSSL > 1.0 - Documented installation on ArchLinux +- [TODO DEPLOY] `rake db:seed` ## v2.5.10 2017 August 16 diff --git a/app/assets/javascripts/controllers/admin/settings.coffee b/app/assets/javascripts/controllers/admin/settings.coffee index 1bb3ff416..a549c3cdf 100644 --- a/app/assets/javascripts/controllers/admin/settings.coffee +++ b/app/assets/javascripts/controllers/admin/settings.coffee @@ -66,7 +66,7 @@ Application.Controllers.controller "SettingsController", ["$scope", 'Setting', ' $scope.moveDelay = name: 'booking_move_delay' - value: parseInt(settingsPromise.booking_move_delay) + value: parseInt(settingsPromise.booking_move_delay, 10) $scope.enableCancel = name: 'booking_cancel_enable' @@ -74,7 +74,7 @@ Application.Controllers.controller "SettingsController", ["$scope", 'Setting', ' $scope.cancelDelay = name: 'booking_cancel_delay' - value: parseInt(settingsPromise.booking_cancel_delay) + value: parseInt(settingsPromise.booking_cancel_delay, 10) $scope.enableReminder = name: 'reminder_enable' @@ -82,7 +82,15 @@ Application.Controllers.controller "SettingsController", ["$scope", 'Setting', ' $scope.reminderDelay = name: 'reminder_delay' - value: parseInt(settingsPromise.reminder_delay) + value: parseInt(settingsPromise.reminder_delay, 10) + + $scope.visibilityYearly = + name: 'visibility_yearly' + value: parseInt(settingsPromise.visibility_yearly, 10) + + $scope.visibilityOthers = + name: 'visibility_others' + value: parseInt(settingsPromise.visibility_others, 10) diff --git a/app/assets/javascripts/router.coffee.erb b/app/assets/javascripts/router.coffee.erb index 7ffadb9ea..badac5113 100644 --- a/app/assets/javascripts/router.coffee.erb +++ b/app/assets/javascripts/router.coffee.erb @@ -1156,7 +1156,9 @@ angular.module('application.router', ['ui.router']). 'fablab_name', 'name_genre', 'reminder_enable', - 'reminder_delay' + 'reminder_delay', + 'visibility_yearly', + 'visibility_others' ]").$promise ] cguFile: ['CustomAsset', (CustomAsset) -> diff --git a/app/assets/templates/admin/settings/reservations.html b/app/assets/templates/admin/settings/reservations.html index df88aeb22..a86517865 100644 --- a/app/assets/templates/admin/settings/reservations.html +++ b/app/assets/templates/admin/settings/reservations.html @@ -22,7 +22,34 @@
-

{{ 'settings.ability_for_the_users_to_move_their_reservations' }}

+

{{ 'settings.max_visibility' }}

+
+ +
+
+
+ +
+ +
+
+ +
+
+ +
+
+
+ +
+ +
+
+ +
+
+
+

{{ 'settings.ability_for_the_users_to_move_their_reservations' }}

-

{{ 'settings.ability_for_the_users_to_cancel_their_reservations' }}

+

{{ 'settings.ability_for_the_users_to_cancel_their_reservations' }}

? AND available_type = 'machines'", Time.now) else - end_at = 1.month.since - end_at = 3.months.since if is_subscription_year(@user) + end_at = @visi_max_other + end_at = @visi_max_year if is_subscription_year(@user) @availabilities = @machine.availabilities.includes(:tags).where("end_at > ? AND end_at < ? AND available_type = 'machines'", Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) end @availabilities.each do |a| @@ -169,8 +170,8 @@ class API::AvailabilitiesController < API::ApiController @availabilities = @availabilities.includes(:tags, :slots, trainings: [:machines]).where('availabilities.start_at > ?', Time.now) # 2) an user (he cannot see availabilities further than 1 (or 3) months) else - end_at = 1.month.since - end_at = 3.months.since if can_show_slot_plus_three_months(@user) + end_at = @visi_max_year + end_at = @visi_max_year if can_show_slot_plus_three_months(@user) @availabilities = @availabilities.includes(:tags, :slots, :availability_tags, trainings: [:machines]).where('availabilities.start_at > ? AND availabilities.start_at < ?', Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) end @@ -193,8 +194,8 @@ class API::AvailabilitiesController < API::ApiController if current_user.is_admin? @availabilities = @space.availabilities.includes(:tags).where("end_at > ? AND available_type = 'space'", Time.now) else - end_at = 1.month.since - end_at = 3.months.since if is_subscription_year(@user) + end_at = @visi_max_other + end_at = @visi_max_year if is_subscription_year(@user) @availabilities = @space.availabilities.includes(:tags).where("end_at > ? AND end_at < ? AND available_type = 'space'", Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) end @availabilities.each do |a| @@ -371,4 +372,9 @@ class API::AvailabilitiesController < API::ApiController end end end + + def define_max_visibility + @visi_max_year = Setting.find_by(name: 'visibility_yearly').value.to_i.months.since + @visi_max_other = Setting.find_by(name: 'visibility_others').value.to_i.months.since + end end diff --git a/app/models/setting.rb b/app/models/setting.rb index 6b0e0e314..a52c62f51 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -32,7 +32,9 @@ class Setting < ActiveRecord::Base reminder_enable reminder_delay event_explications_alert - space_explications_alert ) + space_explications_alert + visibility_yearly + visibility_others ) } after_update :update_stylesheet if :value_changed? diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index 5d797a7f2..f32d52ae4 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -574,6 +574,9 @@ en: confine_the_booking_agenda: "Confine the booking agenda" opening_time: "Opening time" closing_time: "Closing time" + max_visibility: "Maximum visibility (in months)" + visibility_for_yearly_members: "For currently running subscriptions, at least 1 year long" + visibility_for_other_members: "For all other members" ability_for_the_users_to_move_their_reservations: "Ability for the users to move their reservations" reservations_shifting: "Reservations shifting" prior_period_(hours): "Prior period (hours)" @@ -608,6 +611,8 @@ en: reminder_enable: "reservation reminding enabling" reminder_delay: "delay before sending the reminder" default_value_is_24_hours: "If the field is leaved empty: 24 hours." + visibility_yearly: "maximum visibility for annual subscribers" + visibility_others: "maximum visibility for other members" open_api_clients: add_new_client: "Create new API client" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 7a12737db..aa8daf267 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -574,6 +574,9 @@ fr: confine_the_booking_agenda: "Borner l'agenda de réservation" opening_time: "Heure d'ouverture" closing_time: "Heure de fermeture" + max_visibility: "Visibilité maximum (en mois)" + visibility_for_yearly_members: "Pour les abonnements en cours d'au moins 1 an" + visibility_for_other_members: "Pour tous les autres membres" ability_for_the_users_to_move_their_reservations: "Possibilité pour l'utilisateur de déplacer ses réservations" reservations_shifting: "Déplacement des réservations" prior_period_(hours): "Délai préalable (en heures)" @@ -608,6 +611,8 @@ fr: reminder_enable: "l'activation du rappel de réservation" reminder_delay: "délai avant envoi de la notification de rappel" default_value_is_24_hours: "Si aucune valeur n'est renseignée : 24 heures." + visibility_yearly: "la visibilité maximum pour les abonnées annuels" + visibility_others: "la visibilité maximum pour les autres membres" open_api_clients: add_new_client: "Créer un compte client" diff --git a/config/locales/app.admin.pt.yml b/config/locales/app.admin.pt.yml index 259835680..a08fa3990 100755 --- a/config/locales/app.admin.pt.yml +++ b/config/locales/app.admin.pt.yml @@ -574,6 +574,9 @@ pt: confine_the_booking_agenda: "Confine a agenda de reserva" opening_time: "Horário de abertura" closing_time: "Horário de fechamento" + max_visibility: "Visibilidade máxima (em meses)" + visibility_for_yearly_members: "Para inscrições atuais de pelo menos 1 ano" + visibility_for_other_members: "Para todos os outros membros" ability_for_the_users_to_move_their_reservations: "Habilidade para os usuários mover suas reservas" reservations_shifting: "Mudança de reservas" prior_period_(hours): "Período anterior (horas)" @@ -608,6 +611,8 @@ pt: reminder_enable: "Recordar reserva ativo" reminder_delay: "Atraso antes de enviar o lembrete" default_value_is_24_hours: "Se o campo estiver vazio: 24 horas." + visibility_yearly: "visibilidade máxima para assinantes anuais" + visibility_others: "visibilidade máxima para outros membros" open_api_clients: add_new_client: "Criar novo cliente de API" diff --git a/db/schema.rb b/db/schema.rb index a76ff5499..372d18c04 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -15,8 +15,8 @@ ActiveRecord::Schema.define(version: 20170227114634) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - enable_extension "unaccent" enable_extension "pg_trgm" + enable_extension "unaccent" create_table "abuses", force: :cascade do |t| t.integer "signaled_id" @@ -32,14 +32,14 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "abuses", ["signaled_type", "signaled_id"], name: "index_abuses_on_signaled_type_and_signaled_id", using: :btree create_table "addresses", force: :cascade do |t| - t.string "address" - t.string "street_number" - t.string "route" - t.string "locality" - t.string "country" - t.string "postal_code" + t.string "address", limit: 255 + t.string "street_number", limit: 255 + t.string "route", limit: 255 + t.string "locality", limit: 255 + t.string "country", limit: 255 + t.string "postal_code", limit: 255 t.integer "placeable_id" - t.string "placeable_type" + t.string "placeable_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -55,9 +55,9 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "assets", force: :cascade do |t| t.integer "viewable_id" - t.string "viewable_type" - t.string "attachment" - t.string "type" + t.string "viewable_type", limit: 255 + t.string "attachment", limit: 255 + t.string "type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -74,11 +74,11 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "availabilities", force: :cascade do |t| t.datetime "start_at" t.datetime "end_at" - t.string "available_type" + t.string "available_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.boolean "destroying", default: false + t.boolean "destroying", default: false end create_table "availability_tags", force: :cascade do |t| @@ -92,7 +92,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "availability_tags", ["tag_id"], name: "index_availability_tags_on_tag_id", using: :btree create_table "categories", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.string "slug" @@ -101,7 +101,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "categories", ["slug"], name: "index_categories_on_slug", unique: true, using: :btree create_table "components", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false end create_table "coupons", force: :cascade do |t| @@ -119,7 +119,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "credits", force: :cascade do |t| t.integer "creditable_id" - t.string "creditable_type" + t.string "creditable_type", limit: 255 t.integer "plan_id" t.integer "hours" t.datetime "created_at" @@ -160,7 +160,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "event_themes", ["slug"], name: "index_event_themes_on_slug", unique: true, using: :btree create_table "events", force: :cascade do |t| - t.string "title" + t.string "title", limit: 255 t.text "description" t.datetime "created_at" t.datetime "updated_at" @@ -198,10 +198,10 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "exports", ["user_id"], name: "index_exports_on_user_id", using: :btree create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", null: false - t.integer "sluggable_id", null: false + t.string "slug", limit: 255, null: false + t.integer "sluggable_id", null: false t.string "sluggable_type", limit: 50 - t.string "scope" + t.string "scope", limit: 255 t.datetime "created_at" end @@ -211,17 +211,17 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree create_table "groups", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 end add_index "groups", ["slug"], name: "index_groups_on_slug", unique: true, using: :btree create_table "invoice_items", force: :cascade do |t| t.integer "invoice_id" - t.string "stp_invoice_item_id" + t.string "stp_invoice_item_id", limit: 255 t.integer "amount" t.datetime "created_at" t.datetime "updated_at" @@ -234,17 +234,17 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "invoices", force: :cascade do |t| t.integer "invoiced_id" - t.string "invoiced_type" - t.string "stp_invoice_id" + t.string "invoiced_type", limit: 255 + t.string "stp_invoice_id", limit: 255 t.integer "total" t.datetime "created_at" t.datetime "updated_at" t.integer "user_id" - t.string "reference" - t.string "avoir_mode" + t.string "reference", limit: 255 + t.string "avoir_mode", limit: 255 t.datetime "avoir_date" t.integer "invoice_id" - t.string "type" + t.string "type", limit: 255 t.boolean "subscription_to_expire" t.text "description" t.integer "wallet_amount" @@ -258,17 +258,17 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "invoices", ["wallet_transaction_id"], name: "index_invoices_on_wallet_transaction_id", using: :btree create_table "licences", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false t.text "description" end create_table "machines", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false t.text "description" t.text "spec" t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 end add_index "machines", ["slug"], name: "index_machines_on_slug", unique: true, using: :btree @@ -284,14 +284,14 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "notifications", force: :cascade do |t| t.integer "receiver_id" t.integer "attached_object_id" - t.string "attached_object_type" + t.string "attached_object_type", limit: 255 t.integer "notification_type_id" - t.boolean "is_read", default: false + t.boolean "is_read", default: false t.datetime "created_at" t.datetime "updated_at" t.string "receiver_type" - t.boolean "is_send", default: false - t.jsonb "meta_data", default: {} + t.boolean "is_send", default: false + t.jsonb "meta_data", default: {} end add_index "notifications", ["notification_type_id"], name: "index_notifications_on_notification_type_id", using: :btree @@ -360,20 +360,20 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "organizations", ["profile_id"], name: "index_organizations_on_profile_id", using: :btree create_table "plans", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "amount" - t.string "interval" + t.string "interval", limit: 255 t.integer "group_id" - t.string "stp_plan_id" + t.string "stp_plan_id", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.integer "training_credit_nb", default: 0 - t.boolean "is_rolling", default: true + t.integer "training_credit_nb", default: 0 + t.boolean "is_rolling", default: true t.text "description" t.string "type" t.string "base_name" - t.integer "ui_weight", default: 0 - t.integer "interval_count", default: 1 + t.integer "ui_weight", default: 0 + t.integer "interval_count", default: 1 t.string "slug" end @@ -402,11 +402,11 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "profiles", force: :cascade do |t| t.integer "user_id" - t.string "first_name" - t.string "last_name" + t.string "first_name", limit: 255 + t.string "last_name", limit: 255 t.boolean "gender" t.date "birthday" - t.string "phone" + t.string "phone", limit: 255 t.text "interest" t.text "software_mastered" t.datetime "created_at" @@ -436,7 +436,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do t.integer "project_id" t.datetime "created_at" t.datetime "updated_at" - t.string "title" + t.string "title", limit: 255 t.integer "step_nb" end @@ -447,27 +447,27 @@ ActiveRecord::Schema.define(version: 20170227114634) do t.integer "user_id" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_valid", default: false - t.string "valid_token" + t.boolean "is_valid", default: false + t.string "valid_token", limit: 255 end add_index "project_users", ["project_id"], name: "index_project_users_on_project_id", using: :btree add_index "project_users", ["user_id"], name: "index_project_users_on_user_id", using: :btree create_table "projects", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.text "description" t.datetime "created_at" t.datetime "updated_at" t.integer "author_id" t.text "tags" t.integer "licence_id" - t.string "state" - t.string "slug" + t.string "state", limit: 255 + t.string "slug", limit: 255 t.datetime "published_at" end - add_index "projects", ["slug"], name: "index_projects_on_slug", unique: true, using: :btree + add_index "projects", ["slug"], name: "index_projects_on_slug", using: :btree create_table "projects_components", force: :cascade do |t| t.integer "project_id" @@ -507,19 +507,19 @@ ActiveRecord::Schema.define(version: 20170227114634) do t.datetime "created_at" t.datetime "updated_at" t.integer "reservable_id" - t.string "reservable_type" - t.string "stp_invoice_id" + t.string "reservable_type", limit: 255 + t.string "stp_invoice_id", limit: 255 t.integer "nb_reserve_places" end - add_index "reservations", ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id", using: :btree + add_index "reservations", ["reservable_id", "reservable_type"], name: "index_reservations_on_reservable_id_and_reservable_type", using: :btree add_index "reservations", ["stp_invoice_id"], name: "index_reservations_on_stp_invoice_id", using: :btree add_index "reservations", ["user_id"], name: "index_reservations_on_user_id", using: :btree create_table "roles", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.integer "resource_id" - t.string "resource_type" + t.string "resource_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -593,18 +593,18 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "statistic_fields", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "data_type" + t.string "data_type", limit: 255 end add_index "statistic_fields", ["statistic_index_id"], name: "index_statistic_fields_on_statistic_index_id", using: :btree create_table "statistic_graphs", force: :cascade do |t| t.integer "statistic_index_id" - t.string "chart_type" + t.string "chart_type", limit: 255 t.integer "limit" t.datetime "created_at" t.datetime "updated_at" @@ -613,17 +613,17 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "statistic_graphs", ["statistic_index_id"], name: "index_statistic_graphs_on_statistic_index_id", using: :btree create_table "statistic_indices", force: :cascade do |t| - t.string "es_type_key" - t.string "label" + t.string "es_type_key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.boolean "table", default: true - t.boolean "ca", default: true + t.boolean "table", default: true + t.boolean "ca", default: true end create_table "statistic_sub_types", force: :cascade do |t| - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.datetime "created_at" t.datetime "updated_at" end @@ -640,8 +640,8 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "statistic_types", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key" - t.string "label" + t.string "key", limit: 255 + t.string "label", limit: 255 t.boolean "graph" t.datetime "created_at" t.datetime "updated_at" @@ -659,7 +659,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "subscriptions", force: :cascade do |t| t.integer "plan_id" t.integer "user_id" - t.string "stp_subscription_id" + t.string "stp_subscription_id", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.datetime "expired_at" @@ -678,7 +678,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree create_table "themes", force: :cascade do |t| - t.string "name", null: false + t.string "name", limit: 255, null: false end create_table "tickets", force: :cascade do |t| @@ -693,13 +693,13 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "tickets", ["reservation_id"], name: "index_tickets_on_reservation_id", using: :btree create_table "trainings", force: :cascade do |t| - t.string "name" + t.string "name", limit: 255 t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.string "slug" + t.string "slug", limit: 255 t.text "description" - t.boolean "public_page", default: true + t.boolean "public_page", default: true end add_index "trainings", ["slug"], name: "index_trainings_on_slug", unique: true, using: :btree @@ -754,32 +754,32 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "user_trainings", ["user_id"], name: "index_user_trainings_on_user_id", using: :btree create_table "users", force: :cascade do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" + t.string "email", limit: 255, default: "", null: false + t.string "encrypted_password", limit: 255, default: "", null: false + t.string "reset_password_token", limit: 255 t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false + t.integer "sign_in_count", default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" + t.string "current_sign_in_ip", limit: 255 + t.string "last_sign_in_ip", limit: 255 + t.string "confirmation_token", limit: 255 t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.integer "failed_attempts", default: 0, null: false - t.string "unlock_token" + t.string "unconfirmed_email", limit: 255 + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token", limit: 255 t.datetime "locked_at" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_allow_contact", default: true + t.boolean "is_allow_contact", default: true t.integer "group_id" - t.string "stp_customer_id" - t.string "username" - t.string "slug" - t.boolean "is_active", default: true - t.boolean "invoicing_disabled", default: false + t.string "stp_customer_id", limit: 255 + t.string "username", limit: 255 + t.string "slug", limit: 255 + t.boolean "is_active", default: true + t.boolean "invoicing_disabled", default: false t.string "provider" t.string "uid" t.string "auth_token" diff --git a/db/seeds.rb b/db/seeds.rb index 011bd0609..253e39d8e 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -397,6 +397,18 @@ unless Setting.find_by(name: 'reminder_delay').try(:value) setting.save end +unless Setting.find_by(name: 'visibility_yearly').try(:value) + setting = Setting.find_or_initialize_by(name: 'visibility_yearly') + setting.value = '3' + setting.save +end + +unless Setting.find_by(name: 'visibility_others').try(:value) + setting = Setting.find_or_initialize_by(name: 'visibility_others') + setting.value = '1' + setting.save +end + if StatisticCustomAggregation.count == 0 # available reservations hours for machines machine_hours = StatisticType.find_by(key: 'hour', statistic_index_id: 2) From dcf55d8351147a1cf6b5c5216cc76223e358ac3d Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 29 Aug 2017 16:10:16 +0200 Subject: [PATCH 06/23] [bug] invalid notification text when sending amount coupon --- CHANGELOG.md | 1 + .../_notify_member_about_coupon.json.jbuilder | 12 +++++++++--- .../notify_member_about_coupon.html.erb | 2 +- config/locales/en.yml | 1 + config/locales/fr.yml | 1 + config/locales/pt.yml | 1 + 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e68441c52..a544cd87d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Ability for admins to configure the maximum visibility for availabilities reservation - Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese +- Fix a bug: invalid notification when sending monetary coupon to users - Updated puma for compatibility with openSSL > 1.0 - Documented installation on ArchLinux - [TODO DEPLOY] `rake db:seed` diff --git a/app/views/api/notifications/_notify_member_about_coupon.json.jbuilder b/app/views/api/notifications/_notify_member_about_coupon.json.jbuilder index 674a0dd53..dc761bd64 100644 --- a/app/views/api/notifications/_notify_member_about_coupon.json.jbuilder +++ b/app/views/api/notifications/_notify_member_about_coupon.json.jbuilder @@ -1,5 +1,11 @@ json.title notification.notification_type -json.description t('.enjoy_a_discount_of_PERCENT_with_code_CODE', - PERCENT: notification.attached_object.percent_off, - CODE: notification.attached_object.code) +if notification.attached_object.type == 'percent_off' + json.description t('.enjoy_a_discount_of_PERCENT_with_code_CODE', + PERCENT: notification.attached_object.percent_off, + CODE: notification.attached_object.code) +else + json.description t('.enjoy_a_discount_of_AMOUNT_with_code_CODE', + AMOUNT: number_to_currency(notification.attached_object.amount_off / 100.00), + CODE: notification.attached_object.code) +end json.url notification_url(notification, format: :json) diff --git a/app/views/notifications_mailer/notify_member_about_coupon.html.erb b/app/views/notifications_mailer/notify_member_about_coupon.html.erb index 04f6fa0d5..6a664eecf 100644 --- a/app/views/notifications_mailer/notify_member_about_coupon.html.erb +++ b/app/views/notifications_mailer/notify_member_about_coupon.html.erb @@ -15,7 +15,7 @@ <% end %> <% - # we must tell the use if he could use the code just once or many times (in case we won't specify) + # we must tell the user if he can use the code just once or many times (== maximum wasn't specified) usages = 999 # just a number > 1 if @attached_object.validity_per_user == 'once' usages = 1 diff --git a/config/locales/en.yml b/config/locales/en.yml index a7aaed932..8c0778602 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -306,6 +306,7 @@ en: download_here: "Download here" notify_member_about_coupon: enjoy_a_discount_of_PERCENT_with_code_CODE: "Enjoy a discount of %{PERCENT}% with code %{CODE}" + enjoy_a_discount_of_AMOUNT_with_code_CODE: "Enjoy a discount of %{AMOUNT} with code %{CODE}" statistics: # statistics tools for admins diff --git a/config/locales/fr.yml b/config/locales/fr.yml index accf3c94d..c17571e4d 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -306,6 +306,7 @@ fr: download_here: "Téléchargez ici" notify_member_about_coupon: enjoy_a_discount_of_PERCENT_with_code_CODE: "Bénéficiez d'une remise de %{PERCENT} % avec le code %{CODE}" + enjoy_a_discount_of_AMOUNT_with_code_CODE: "Bénéficiez d'une remise de %{AMOUNT} avec le code %{CODE}" statistics: # outil de statistiques pour les administrateurs diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 266efe610..5d351b54d 100755 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -306,6 +306,7 @@ pt: download_here: "Baixe aqui" notify_member_about_coupon: enjoy_a_discount_of_PERCENT_with_code_CODE: "Desfrute de um desconto de %{PERCENT}% com o código %{CODE}" + enjoy_a_discount_of_AMOUNT_with_code_CODE: "Desfrute de um desconto de %{AMOUNT} com o código %{CODE}" statistics: # statistics tools for admins From 9c6143bd5effb9249a7135ad45012cf840591453 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 29 Aug 2017 17:50:57 +0200 Subject: [PATCH 07/23] tooltip about images insertion in medium editor --- CHANGELOG.md | 1 + app/assets/templates/admin/settings/about.html | 1 + config/locales/app.admin.en.yml | 1 + config/locales/app.admin.fr.yml | 1 + config/locales/app.admin.pt.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a544cd87d..ab0c2f91d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## next release +- Added tooltip concerning images insertion while configuring the about page - Ability for admins to configure the maximum visibility for availabilities reservation - Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese diff --git a/app/assets/templates/admin/settings/about.html b/app/assets/templates/admin/settings/about.html index 09e96e347..c58a5c440 100644 --- a/app/assets/templates/admin/settings/about.html +++ b/app/assets/templates/admin/settings/about.html @@ -17,6 +17,7 @@ }'>
+ {{ 'settings.drag_and_drop_to_insert_images' | translate }}
diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index f32d52ae4..abfae4858 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -568,6 +568,7 @@ en: title_of_the_about_page: "Title of the About page" shift_enter_to_force_carriage_return: "SHIFT + ENTER to force carriage return" input_the_main_content: "Input the main content" + drag_and_drop_to_insert_images: "Drap and drop to insert images" input_the_fablab_contacts: "Input the FabLab contacts" reservations: "Reservations" reservations_parameters: "Reservations parameters" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index aa8daf267..aa9ebc866 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -568,6 +568,7 @@ fr: title_of_the_about_page: "Titre page A propos" shift_enter_to_force_carriage_return: "MAJ. + ENTRÉE pour forcer le retour à la ligne" input_the_main_content: "Saisir le contenu principal" + drag_and_drop_to_insert_images: "Faites un glisser-déposer pour insérer des images" input_the_fablab_contacts: "Saisir les Contacts du FabLab" reservations: "Réservations" reservations_parameters: "Paramètres des réservations" diff --git a/config/locales/app.admin.pt.yml b/config/locales/app.admin.pt.yml index a08fa3990..5eebc6d9a 100755 --- a/config/locales/app.admin.pt.yml +++ b/config/locales/app.admin.pt.yml @@ -568,6 +568,7 @@ pt: title_of_the_about_page: "Título da página sobre" shift_enter_to_force_carriage_return: "SHIFT + ENTER para forçar o retorno" input_the_main_content: "Introduza o conteúdo principal" + drag_and_drop_to_insert_images: "Arrastar e soltar para inserir imagens" input_the_fablab_contacts: "Insira os contatos do FabLab" reservations: "Reservas" reservations_parameters: "Parâmetros das reservas" From 3d4260a3f7bb545db25d166f8f4f2f97820896ee Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 30 Aug 2017 14:57:06 +0200 Subject: [PATCH 08/23] [bug] unable to delete standard group --- CHANGELOG.md | 4 +- .../controllers/admin/members.coffee.erb | 2 +- .../controllers/admin/plans.coffee.erb | 2 +- .../controllers/admin/pricing.coffee.erb | 2 +- .../javascripts/controllers/plans.coffee.erb | 4 +- .../templates/admin/groups/index.html.erb | 2 +- .../admin/open_api_clients/index.html.erb | 4 +- .../templates/dashboard/settings.html.erb | 7 +- app/controllers/api/admins_controller.rb | 4 +- app/controllers/api/groups_controller.rb | 7 +- config/locales/en.yml | 4 + config/locales/fr.yml | 6 +- config/locales/pt.yml | 4 + db/schema.rb | 180 +++++++++--------- db/seeds.rb | 6 +- lib/tasks/fablab/fix.rake | 10 + 16 files changed, 143 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab0c2f91d..d45d77edf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,14 @@ - Added tooltip concerning images insertion while configuring the about page - Ability for admins to configure the maximum visibility for availabilities reservation +- Administrators isolation in a special group - Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese - Fix a bug: invalid notification when sending monetary coupon to users +- Fix a bug: unable to delete group "standard" - Updated puma for compatibility with openSSL > 1.0 - Documented installation on ArchLinux -- [TODO DEPLOY] `rake db:seed` +- [TODO DEPLOY] `rake db:seed` then `rake fablab:fix:migrate_admins_group` ## v2.5.10 2017 August 16 diff --git a/app/assets/javascripts/controllers/admin/members.coffee.erb b/app/assets/javascripts/controllers/admin/members.coffee.erb index 79d4ea3fe..86df205b0 100644 --- a/app/assets/javascripts/controllers/admin/members.coffee.erb +++ b/app/assets/javascripts/controllers/admin/members.coffee.erb @@ -25,7 +25,7 @@ class MembersController ## Retrieve the profiles groups (eg. students ...) Group.query (groups) -> - $scope.groups = groups + $scope.groups = groups.filter (g) -> g.slug != 'admins' ## Retrieve the list the available trainings Training.query().$promise.then (data)-> diff --git a/app/assets/javascripts/controllers/admin/plans.coffee.erb b/app/assets/javascripts/controllers/admin/plans.coffee.erb index 588718641..4c4486728 100644 --- a/app/assets/javascripts/controllers/admin/plans.coffee.erb +++ b/app/assets/javascripts/controllers/admin/plans.coffee.erb @@ -13,7 +13,7 @@ class PlanController ## groups list - $scope.groups = groups + $scope.groups = groups.filter (g) -> g.slug != 'admins' ## users with role 'partner', notifiables for a partner plan $scope.partners = partners.users diff --git a/app/assets/javascripts/controllers/admin/pricing.coffee.erb b/app/assets/javascripts/controllers/admin/pricing.coffee.erb index c77e181e4..53bd9a78d 100644 --- a/app/assets/javascripts/controllers/admin/pricing.coffee.erb +++ b/app/assets/javascripts/controllers/admin/pricing.coffee.erb @@ -17,7 +17,7 @@ Application.Controllers.controller "EditPricingController", ["$scope", "$state", $scope.plans = plans ## List of groups (eg. normal, student ...) - $scope.groups = groups + $scope.groups = groups.filter (g) -> g.slug != 'admins' ## Associate free machine hours with subscriptions $scope.machineCredits = machineCreditsPromise diff --git a/app/assets/javascripts/controllers/plans.coffee.erb b/app/assets/javascripts/controllers/plans.coffee.erb index 4396d03e9..f4f428e33 100644 --- a/app/assets/javascripts/controllers/plans.coffee.erb +++ b/app/assets/javascripts/controllers/plans.coffee.erb @@ -8,7 +8,7 @@ Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScop ### PUBLIC SCOPE ### ## list of groups - $scope.groups = groupsPromise + $scope.groups = groupsPromise.filter (g) -> g.slug != 'admins' ## default : do not show the group changing form ## group ID of the current/selected user @@ -18,7 +18,7 @@ Application.Controllers.controller "PlansIndexController", ["$scope", "$rootScop ## list of plans, classified by group $scope.plansClassifiedByGroup = [] - for group in groupsPromise + for group in $scope.groups groupObj = { id: group.id, name: group.name, plans: [] } for plan in plansPromise groupObj.plans.push(plan) if plan.group_id == group.id diff --git a/app/assets/templates/admin/groups/index.html.erb b/app/assets/templates/admin/groups/index.html.erb index 498c29c1c..27207c90d 100644 --- a/app/assets/templates/admin/groups/index.html.erb +++ b/app/assets/templates/admin/groups/index.html.erb @@ -23,7 +23,7 @@ -
+
diff --git a/app/assets/templates/admin/open_api_clients/index.html.erb b/app/assets/templates/admin/open_api_clients/index.html.erb index d478f5c9b..8f4e3bf70 100644 --- a/app/assets/templates/admin/open_api_clients/index.html.erb +++ b/app/assets/templates/admin/open_api_clients/index.html.erb @@ -44,13 +44,13 @@ {{ 'name' | translate }} - {{ 'calls_count' | translate }} + {{ 'calls_count' | translate }} {{ 'token' | translate }} {{ 'created_at' | translate }} - + diff --git a/app/assets/templates/dashboard/settings.html.erb b/app/assets/templates/dashboard/settings.html.erb index ed3b13fd1..87721459e 100644 --- a/app/assets/templates/dashboard/settings.html.erb +++ b/app/assets/templates/dashboard/settings.html.erb @@ -22,7 +22,12 @@ {{getUserGroup().name}} - +
diff --git a/app/controllers/api/admins_controller.rb b/app/controllers/api/admins_controller.rb index 175d6b4e5..8ddaa49c9 100644 --- a/app/controllers/api/admins_controller.rb +++ b/app/controllers/api/admins_controller.rb @@ -12,8 +12,8 @@ class API::AdminsController < API::ApiController @admin = User.new(admin_params.merge(password: generated_password)) @admin.send :set_slug - # we associate any random group to the admin as it is mandatory for users but useless for admins - @admin.group = Group.first + # we associate the admin group to prevent linking any other 'normal' group (which won't be deletable afterwards) + @admin.group = Group.find_by(slug: 'admins') # if the authentication is made through an SSO, generate a migration token unless AuthProvider.active.providable_type == DatabaseProvider.name diff --git a/app/controllers/api/groups_controller.rb b/app/controllers/api/groups_controller.rb index 6d68167c3..50aa41dff 100644 --- a/app/controllers/api/groups_controller.rb +++ b/app/controllers/api/groups_controller.rb @@ -2,7 +2,12 @@ class API::GroupsController < API::ApiController before_action :authenticate_user!, except: :index def index - @groups = Group.all + if current_user and current_user.is_admin? + @groups = Group.all + else + @groups = Group.where.not(slug: 'admins') + end + end def create diff --git a/config/locales/en.yml b/config/locales/en.yml index 8c0778602..36f41010d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -357,3 +357,7 @@ en: # initial price's category for events, created to replace the old "reduced amount" property reduced_fare: "Reduced fare" reduced_fare_if_you_are_under_25_student_or_unemployed: "Reduced fare if you are under 25, student or unemployed." + + group: + # name of the user's group for administrators + admins: 'Administrators' \ No newline at end of file diff --git a/config/locales/fr.yml b/config/locales/fr.yml index c17571e4d..aa9b8c0e8 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -356,4 +356,8 @@ fr: price_category: # catégorie initiale de prix pour les évènements, en remplacement de l'ancienne propriété "montant réduit" reduced_fare: "Tarif réduit" - reduced_fare_if_you_are_under_25_student_or_unemployed: "Tarif réduit si vous avez moins de 25 ans, que vous êtes étudiant ou demandeur d'emploi." \ No newline at end of file + reduced_fare_if_you_are_under_25_student_or_unemployed: "Tarif réduit si vous avez moins de 25 ans, que vous êtes étudiant ou demandeur d'emploi." + + group: + # nom du groupe utilisateur pour les administrateurs + admins: 'Administrateurs' \ No newline at end of file diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 5d351b54d..6db56287e 100755 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -357,3 +357,7 @@ pt: # initial price's category for events, created to replace the old "reduced amount" property reduced_fare: "Tarifa reduzida" reduced_fare_if_you_are_under_25_student_or_unemployed: "Tarifa reduzida se tiver menos de 25 anos, estudante ou desempregado." + + group: + # name of the user's group for administrators + admins: 'Administradores' \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index 372d18c04..a76ff5499 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -15,8 +15,8 @@ ActiveRecord::Schema.define(version: 20170227114634) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - enable_extension "pg_trgm" enable_extension "unaccent" + enable_extension "pg_trgm" create_table "abuses", force: :cascade do |t| t.integer "signaled_id" @@ -32,14 +32,14 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "abuses", ["signaled_type", "signaled_id"], name: "index_abuses_on_signaled_type_and_signaled_id", using: :btree create_table "addresses", force: :cascade do |t| - t.string "address", limit: 255 - t.string "street_number", limit: 255 - t.string "route", limit: 255 - t.string "locality", limit: 255 - t.string "country", limit: 255 - t.string "postal_code", limit: 255 + t.string "address" + t.string "street_number" + t.string "route" + t.string "locality" + t.string "country" + t.string "postal_code" t.integer "placeable_id" - t.string "placeable_type", limit: 255 + t.string "placeable_type" t.datetime "created_at" t.datetime "updated_at" end @@ -55,9 +55,9 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "assets", force: :cascade do |t| t.integer "viewable_id" - t.string "viewable_type", limit: 255 - t.string "attachment", limit: 255 - t.string "type", limit: 255 + t.string "viewable_type" + t.string "attachment" + t.string "type" t.datetime "created_at" t.datetime "updated_at" end @@ -74,11 +74,11 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "availabilities", force: :cascade do |t| t.datetime "start_at" t.datetime "end_at" - t.string "available_type", limit: 255 + t.string "available_type" t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.boolean "destroying", default: false + t.boolean "destroying", default: false end create_table "availability_tags", force: :cascade do |t| @@ -92,7 +92,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "availability_tags", ["tag_id"], name: "index_availability_tags_on_tag_id", using: :btree create_table "categories", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.datetime "created_at" t.datetime "updated_at" t.string "slug" @@ -101,7 +101,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "categories", ["slug"], name: "index_categories_on_slug", unique: true, using: :btree create_table "components", force: :cascade do |t| - t.string "name", limit: 255, null: false + t.string "name", null: false end create_table "coupons", force: :cascade do |t| @@ -119,7 +119,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "credits", force: :cascade do |t| t.integer "creditable_id" - t.string "creditable_type", limit: 255 + t.string "creditable_type" t.integer "plan_id" t.integer "hours" t.datetime "created_at" @@ -160,7 +160,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "event_themes", ["slug"], name: "index_event_themes_on_slug", unique: true, using: :btree create_table "events", force: :cascade do |t| - t.string "title", limit: 255 + t.string "title" t.text "description" t.datetime "created_at" t.datetime "updated_at" @@ -198,10 +198,10 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "exports", ["user_id"], name: "index_exports_on_user_id", using: :btree create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", limit: 255, null: false - t.integer "sluggable_id", null: false + t.string "slug", null: false + t.integer "sluggable_id", null: false t.string "sluggable_type", limit: 50 - t.string "scope", limit: 255 + t.string "scope" t.datetime "created_at" end @@ -211,17 +211,17 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree create_table "groups", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.datetime "created_at" t.datetime "updated_at" - t.string "slug", limit: 255 + t.string "slug" end add_index "groups", ["slug"], name: "index_groups_on_slug", unique: true, using: :btree create_table "invoice_items", force: :cascade do |t| t.integer "invoice_id" - t.string "stp_invoice_item_id", limit: 255 + t.string "stp_invoice_item_id" t.integer "amount" t.datetime "created_at" t.datetime "updated_at" @@ -234,17 +234,17 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "invoices", force: :cascade do |t| t.integer "invoiced_id" - t.string "invoiced_type", limit: 255 - t.string "stp_invoice_id", limit: 255 + t.string "invoiced_type" + t.string "stp_invoice_id" t.integer "total" t.datetime "created_at" t.datetime "updated_at" t.integer "user_id" - t.string "reference", limit: 255 - t.string "avoir_mode", limit: 255 + t.string "reference" + t.string "avoir_mode" t.datetime "avoir_date" t.integer "invoice_id" - t.string "type", limit: 255 + t.string "type" t.boolean "subscription_to_expire" t.text "description" t.integer "wallet_amount" @@ -258,17 +258,17 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "invoices", ["wallet_transaction_id"], name: "index_invoices_on_wallet_transaction_id", using: :btree create_table "licences", force: :cascade do |t| - t.string "name", limit: 255, null: false + t.string "name", null: false t.text "description" end create_table "machines", force: :cascade do |t| - t.string "name", limit: 255, null: false + t.string "name", null: false t.text "description" t.text "spec" t.datetime "created_at" t.datetime "updated_at" - t.string "slug", limit: 255 + t.string "slug" end add_index "machines", ["slug"], name: "index_machines_on_slug", unique: true, using: :btree @@ -284,14 +284,14 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "notifications", force: :cascade do |t| t.integer "receiver_id" t.integer "attached_object_id" - t.string "attached_object_type", limit: 255 + t.string "attached_object_type" t.integer "notification_type_id" - t.boolean "is_read", default: false + t.boolean "is_read", default: false t.datetime "created_at" t.datetime "updated_at" t.string "receiver_type" - t.boolean "is_send", default: false - t.jsonb "meta_data", default: {} + t.boolean "is_send", default: false + t.jsonb "meta_data", default: {} end add_index "notifications", ["notification_type_id"], name: "index_notifications_on_notification_type_id", using: :btree @@ -360,20 +360,20 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "organizations", ["profile_id"], name: "index_organizations_on_profile_id", using: :btree create_table "plans", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.integer "amount" - t.string "interval", limit: 255 + t.string "interval" t.integer "group_id" - t.string "stp_plan_id", limit: 255 + t.string "stp_plan_id" t.datetime "created_at" t.datetime "updated_at" - t.integer "training_credit_nb", default: 0 - t.boolean "is_rolling", default: true + t.integer "training_credit_nb", default: 0 + t.boolean "is_rolling", default: true t.text "description" t.string "type" t.string "base_name" - t.integer "ui_weight", default: 0 - t.integer "interval_count", default: 1 + t.integer "ui_weight", default: 0 + t.integer "interval_count", default: 1 t.string "slug" end @@ -402,11 +402,11 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "profiles", force: :cascade do |t| t.integer "user_id" - t.string "first_name", limit: 255 - t.string "last_name", limit: 255 + t.string "first_name" + t.string "last_name" t.boolean "gender" t.date "birthday" - t.string "phone", limit: 255 + t.string "phone" t.text "interest" t.text "software_mastered" t.datetime "created_at" @@ -436,7 +436,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do t.integer "project_id" t.datetime "created_at" t.datetime "updated_at" - t.string "title", limit: 255 + t.string "title" t.integer "step_nb" end @@ -447,27 +447,27 @@ ActiveRecord::Schema.define(version: 20170227114634) do t.integer "user_id" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_valid", default: false - t.string "valid_token", limit: 255 + t.boolean "is_valid", default: false + t.string "valid_token" end add_index "project_users", ["project_id"], name: "index_project_users_on_project_id", using: :btree add_index "project_users", ["user_id"], name: "index_project_users_on_user_id", using: :btree create_table "projects", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.text "description" t.datetime "created_at" t.datetime "updated_at" t.integer "author_id" t.text "tags" t.integer "licence_id" - t.string "state", limit: 255 - t.string "slug", limit: 255 + t.string "state" + t.string "slug" t.datetime "published_at" end - add_index "projects", ["slug"], name: "index_projects_on_slug", using: :btree + add_index "projects", ["slug"], name: "index_projects_on_slug", unique: true, using: :btree create_table "projects_components", force: :cascade do |t| t.integer "project_id" @@ -507,19 +507,19 @@ ActiveRecord::Schema.define(version: 20170227114634) do t.datetime "created_at" t.datetime "updated_at" t.integer "reservable_id" - t.string "reservable_type", limit: 255 - t.string "stp_invoice_id", limit: 255 + t.string "reservable_type" + t.string "stp_invoice_id" t.integer "nb_reserve_places" end - add_index "reservations", ["reservable_id", "reservable_type"], name: "index_reservations_on_reservable_id_and_reservable_type", using: :btree + add_index "reservations", ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id", using: :btree add_index "reservations", ["stp_invoice_id"], name: "index_reservations_on_stp_invoice_id", using: :btree add_index "reservations", ["user_id"], name: "index_reservations_on_user_id", using: :btree create_table "roles", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.integer "resource_id" - t.string "resource_type", limit: 255 + t.string "resource_type" t.datetime "created_at" t.datetime "updated_at" end @@ -593,18 +593,18 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "statistic_fields", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key", limit: 255 - t.string "label", limit: 255 + t.string "key" + t.string "label" t.datetime "created_at" t.datetime "updated_at" - t.string "data_type", limit: 255 + t.string "data_type" end add_index "statistic_fields", ["statistic_index_id"], name: "index_statistic_fields_on_statistic_index_id", using: :btree create_table "statistic_graphs", force: :cascade do |t| t.integer "statistic_index_id" - t.string "chart_type", limit: 255 + t.string "chart_type" t.integer "limit" t.datetime "created_at" t.datetime "updated_at" @@ -613,17 +613,17 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "statistic_graphs", ["statistic_index_id"], name: "index_statistic_graphs_on_statistic_index_id", using: :btree create_table "statistic_indices", force: :cascade do |t| - t.string "es_type_key", limit: 255 - t.string "label", limit: 255 + t.string "es_type_key" + t.string "label" t.datetime "created_at" t.datetime "updated_at" - t.boolean "table", default: true - t.boolean "ca", default: true + t.boolean "table", default: true + t.boolean "ca", default: true end create_table "statistic_sub_types", force: :cascade do |t| - t.string "key", limit: 255 - t.string "label", limit: 255 + t.string "key" + t.string "label" t.datetime "created_at" t.datetime "updated_at" end @@ -640,8 +640,8 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "statistic_types", force: :cascade do |t| t.integer "statistic_index_id" - t.string "key", limit: 255 - t.string "label", limit: 255 + t.string "key" + t.string "label" t.boolean "graph" t.datetime "created_at" t.datetime "updated_at" @@ -659,7 +659,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do create_table "subscriptions", force: :cascade do |t| t.integer "plan_id" t.integer "user_id" - t.string "stp_subscription_id", limit: 255 + t.string "stp_subscription_id" t.datetime "created_at" t.datetime "updated_at" t.datetime "expired_at" @@ -678,7 +678,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree create_table "themes", force: :cascade do |t| - t.string "name", limit: 255, null: false + t.string "name", null: false end create_table "tickets", force: :cascade do |t| @@ -693,13 +693,13 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "tickets", ["reservation_id"], name: "index_tickets_on_reservation_id", using: :btree create_table "trainings", force: :cascade do |t| - t.string "name", limit: 255 + t.string "name" t.datetime "created_at" t.datetime "updated_at" t.integer "nb_total_places" - t.string "slug", limit: 255 + t.string "slug" t.text "description" - t.boolean "public_page", default: true + t.boolean "public_page", default: true end add_index "trainings", ["slug"], name: "index_trainings_on_slug", unique: true, using: :btree @@ -754,32 +754,32 @@ ActiveRecord::Schema.define(version: 20170227114634) do add_index "user_trainings", ["user_id"], name: "index_user_trainings_on_user_id", using: :btree create_table "users", force: :cascade do |t| - t.string "email", limit: 255, default: "", null: false - t.string "encrypted_password", limit: 255, default: "", null: false - t.string "reset_password_token", limit: 255 + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0, null: false + t.integer "sign_in_count", default: 0, null: false t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip", limit: 255 - t.string "last_sign_in_ip", limit: 255 - t.string "confirmation_token", limit: 255 + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "unconfirmed_email", limit: 255 - t.integer "failed_attempts", default: 0, null: false - t.string "unlock_token", limit: 255 + t.string "unconfirmed_email" + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token" t.datetime "locked_at" t.datetime "created_at" t.datetime "updated_at" - t.boolean "is_allow_contact", default: true + t.boolean "is_allow_contact", default: true t.integer "group_id" - t.string "stp_customer_id", limit: 255 - t.string "username", limit: 255 - t.string "slug", limit: 255 - t.boolean "is_active", default: true - t.boolean "invoicing_disabled", default: false + t.string "stp_customer_id" + t.string "username" + t.string "slug" + t.boolean "is_active", default: true + t.boolean "invoicing_disabled", default: false t.string "provider" t.string "uid" t.string "auth_token" diff --git a/db/seeds.rb b/db/seeds.rb index 253e39d8e..e61e5ae9d 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -82,9 +82,13 @@ if Group.count == 0 ]) end +unless Group.find_by(slug: 'admins') + Group.create! name: I18n.t('group.admins'), slug: 'admins' +end + # Create the default admin if none exists yet if Role.where(name: 'admin').joins(:users).count === 0 - admin = User.new(username: 'admin', email: ENV["ADMIN_EMAIL"], password: ENV["ADMIN_PASSWORD"], password_confirmation: Rails.application.secrets.admin_password, group_id: Group.first.id, profile_attributes: {first_name: 'admin', last_name: 'admin', gender: true, phone: '0123456789', birthday: Time.now}) + admin = User.new(username: 'admin', email: ENV["ADMIN_EMAIL"], password: ENV["ADMIN_PASSWORD"], password_confirmation: Rails.application.secrets.admin_password, group_id: Group.find_by(slug: 'admins').id, profile_attributes: {first_name: 'admin', last_name: 'admin', gender: true, phone: '0123456789', birthday: Time.now}) admin.add_role 'admin' admin.save! end diff --git a/lib/tasks/fablab/fix.rake b/lib/tasks/fablab/fix.rake index aff34d4e1..23eaa049b 100644 --- a/lib/tasks/fablab/fix.rake +++ b/lib/tasks/fablab/fix.rake @@ -47,5 +47,15 @@ namespace :fablab do end end end + + task migrate_admins_group: :environment do + admins = Group.find_by(slug: 'admins') + User.all.each do |user| + if user.is_admin? + user.group = admins + user.save! + end + end + end end end From d602055e6748190833b4f65db4e0f1ae9109fe01 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Thu, 31 Aug 2017 17:11:46 +0200 Subject: [PATCH 09/23] In login modal, displays an alert if Caps lock key is pressed --- CHANGELOG.md | 1 + app/assets/javascripts/app.js.erb | 2 +- app/assets/javascripts/application.js.erb | 1 + .../templates/shared/deviseModal.html.erb | 4 ++ bower.json | 3 +- config/locales/app.public.en.yml | 1 + config/locales/app.public.fr.yml | 1 + config/locales/app.public.pt.yml | 1 + .../assets/components/ngCapsLock/.bower.json | 23 +++++++ vendor/assets/components/ngCapsLock/LICENSE | 21 +++++++ vendor/assets/components/ngCapsLock/README.md | 25 ++++++++ .../assets/components/ngCapsLock/bower.json | 13 ++++ .../components/ngCapsLock/ng-caps-lock.js | 61 +++++++++++++++++++ .../components/ngCapsLock/ng-caps-lock.min.js | 1 + 14 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 vendor/assets/components/ngCapsLock/.bower.json create mode 100644 vendor/assets/components/ngCapsLock/LICENSE create mode 100644 vendor/assets/components/ngCapsLock/README.md create mode 100644 vendor/assets/components/ngCapsLock/bower.json create mode 100644 vendor/assets/components/ngCapsLock/ng-caps-lock.js create mode 100644 vendor/assets/components/ngCapsLock/ng-caps-lock.min.js diff --git a/CHANGELOG.md b/CHANGELOG.md index d45d77edf..4d621e003 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Added tooltip concerning images insertion while configuring the about page - Ability for admins to configure the maximum visibility for availabilities reservation - Administrators isolation in a special group +- In login modal, displays an alert if Caps lock key is pressed - Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese - Fix a bug: invalid notification when sending monetary coupon to users diff --git a/app/assets/javascripts/app.js.erb b/app/assets/javascripts/app.js.erb index 7049d79b8..bb05f35c7 100644 --- a/app/assets/javascripts/app.js.erb +++ b/app/assets/javascripts/app.js.erb @@ -20,7 +20,7 @@ angular.module('application', ['ngCookies', 'ngResource', 'ngSanitize', 'ngCooki 'ui.select', 'ui.calendar', 'angularMoment', 'Devise', 'DeviseModal', 'angular-growl', 'xeditable', 'checklist-model', 'unsavedChanges', 'angular-loading-bar', 'ngTouch', 'angular-google-analytics', 'angularUtils.directives.dirDisqus', 'summernote', 'elasticsearch', 'angular-medium-editor', 'naif.base64', - 'minicolors', 'pascalprecht.translate', 'ngFitText', 'ngAside']). + 'minicolors', 'pascalprecht.translate', 'ngFitText', 'ngAside', 'ngCapsLock']). config(['$httpProvider', 'AuthProvider', "growlProvider", "unsavedWarningsConfigProvider", "AnalyticsProvider", "uibDatepickerPopupConfig", "$provide", "$translateProvider", function($httpProvider, AuthProvider, growlProvider, unsavedWarningsConfigProvider, AnalyticsProvider, uibDatepickerPopupConfig, $provide, $translateProvider) { diff --git a/app/assets/javascripts/application.js.erb b/app/assets/javascripts/application.js.erb index d9f900521..c77993ffd 100644 --- a/app/assets/javascripts/application.js.erb +++ b/app/assets/javascripts/application.js.erb @@ -68,6 +68,7 @@ //= require angular-translate-interpolation-messageformat/angular-translate-interpolation-messageformat //= require ngFitText/dist/ng-FitText.min //= require angular-aside/dist/js/angular-aside +//= require ngCapsLock/ng-caps-lock //= require_tree ./controllers //= require_tree ./services //= require_tree ./directives diff --git a/app/assets/templates/shared/deviseModal.html.erb b/app/assets/templates/shared/deviseModal.html.erb index 89ee86a48..4af3a8164 100644 --- a/app/assets/templates/shared/deviseModal.html.erb +++ b/app/assets/templates/shared/deviseModal.html.erb @@ -42,6 +42,10 @@ ng-minlength="8"/>
{{ 'password_forgotten' | translate }} +
diff --git a/bower.json b/bower.json index d245b9573..adf3fcd52 100644 --- a/bower.json +++ b/bower.json @@ -54,7 +54,8 @@ "messageformat": "=0.1.8", "moment-timezone": "~0.5.0", "ngFitText": "~4.1.1", - "angular-aside": "^1.3.2" + "angular-aside": "^1.3.2", + "ngCapsLock": "ng-caps-lock#^1.0.2" }, "resolutions": { "jquery": ">=1.10.2", diff --git a/config/locales/app.public.en.yml b/config/locales/app.public.en.yml index b8ca647e4..e045fea49 100644 --- a/config/locales/app.public.en.yml +++ b/config/locales/app.public.en.yml @@ -97,6 +97,7 @@ en: not_registered_to_the_fablab: "Not registered to the Fablab?" create_an_account: "Create an account" wrong_email_or_password: "Wrong e-mail or password." + caps_lock_is_on: "Caps lock key is on." # forgotten password modal your_email_address_is_unknown: "Your e-mail address is unknown." diff --git a/config/locales/app.public.fr.yml b/config/locales/app.public.fr.yml index d4f917674..62dfe62eb 100644 --- a/config/locales/app.public.fr.yml +++ b/config/locales/app.public.fr.yml @@ -97,6 +97,7 @@ fr: not_registered_to_the_fablab: "Vous n'êtes pas inscrit au FAB LAB ?" create_an_account: "Créer un compte" wrong_email_or_password: "Adresse courriel ou mot de passe incorrect." + caps_lock_is_on: "La touche de verrouillage des majuscules est activée." # mot de passe oublié your_email_address_is_unknown: "Votre adresse de courriel est inconnue." diff --git a/config/locales/app.public.pt.yml b/config/locales/app.public.pt.yml index 47e92ee40..d5788e3d5 100755 --- a/config/locales/app.public.pt.yml +++ b/config/locales/app.public.pt.yml @@ -97,6 +97,7 @@ pt: not_registered_to_the_fablab: "Ainda não registrado no Fablab?" create_an_account: "Criar conta" wrong_email_or_password: "E-mail ou senha incorretos." + caps_lock_is_on: "A tecla Caps Lock está ativada." # forgotten password modal your_email_address_is_unknown: "Seu e-mail não está cadastrado." diff --git a/vendor/assets/components/ngCapsLock/.bower.json b/vendor/assets/components/ngCapsLock/.bower.json new file mode 100644 index 000000000..53ed39fe6 --- /dev/null +++ b/vendor/assets/components/ngCapsLock/.bower.json @@ -0,0 +1,23 @@ +{ + "name": "ngCapsLock", + "version": "1.0.2", + "main": "./ng-caps-lock.js", + "license": "MIT", + "authors": [ + "Fábio Rodrigues " + ], + "dependencies": { + "angular": ">=1.1" + }, + "homepage": "https://github.com/FabioMR/ng-caps-lock", + "_release": "1.0.2", + "_resolution": { + "type": "version", + "tag": "1.0.2", + "commit": "f28192faa10107db6b5b7db7a77109d36b16c0b9" + }, + "_source": "https://github.com/FabioMR/ng-caps-lock.git", + "_target": "^1.0.2", + "_originalSource": "ng-caps-lock", + "_direct": true +} \ No newline at end of file diff --git a/vendor/assets/components/ngCapsLock/LICENSE b/vendor/assets/components/ngCapsLock/LICENSE new file mode 100644 index 000000000..c3a40b752 --- /dev/null +++ b/vendor/assets/components/ngCapsLock/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 FabioMR + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/assets/components/ngCapsLock/README.md b/vendor/assets/components/ngCapsLock/README.md new file mode 100644 index 000000000..7f621ef22 --- /dev/null +++ b/vendor/assets/components/ngCapsLock/README.md @@ -0,0 +1,25 @@ +# ngCapsLock + +ngCapsLock is a module for [AngularJS](http://angularjs.org/) to detect if caps-lock is on/off. + +Getting Started +--------------- + + * Download ngCapsLock or install it with [Bower](http://bower.io/) via `bower install ng-caps-lock` + * Include the script tag on your page after the AngularJS script tags + + + + + * Ensure that your application module specifies `ngCapsLock` as a dependency: + + angular.module('myApp', ['ngCapsLock']); + + * Use the property `isCapsLockOn` on a `ng-show` directive. + +

Caps lock is on

+ +License +------- + +ngCapsLock is licensed under the MIT license. See the LICENSE file for more details. diff --git a/vendor/assets/components/ngCapsLock/bower.json b/vendor/assets/components/ngCapsLock/bower.json new file mode 100644 index 000000000..2d378b80c --- /dev/null +++ b/vendor/assets/components/ngCapsLock/bower.json @@ -0,0 +1,13 @@ +{ + "name": "ngCapsLock", + "version": "1.0.2", + "main": "./ng-caps-lock.js", + "license": "MIT", + "authors": [ + "Fábio Rodrigues " + ], + "dependencies": { + "angular": ">=1.1" + }, + "homepage": "https://github.com/FabioMR/ng-caps-lock" +} diff --git a/vendor/assets/components/ngCapsLock/ng-caps-lock.js b/vendor/assets/components/ngCapsLock/ng-caps-lock.js new file mode 100644 index 000000000..ea50c580e --- /dev/null +++ b/vendor/assets/components/ngCapsLock/ng-caps-lock.js @@ -0,0 +1,61 @@ +(function () { + 'use strict'; + + angular.module('ngCapsLock', []).run(['$rootScope', '$document', '$timeout', function ($rootScope, $document, $timeout) { + + var bindingForAppleDevice = function () { + $document.bind("keydown", function (event) { + if (event.keyCode === 20) { setCapsLockOn(true); } + }); + + $document.bind("keyup", function (event) { + if (event.keyCode === 20) { setCapsLockOn(false); } + }); + + $document.bind("keypress", function (event) { + var code = event.charCode || event.keyCode; + var shift = event.shiftKey; + + if (code > 96 && code < 123) { setCapsLockOn(false); } + if (code > 64 && code < 91 && !shift) { setCapsLockOn(true); } + }); + }; + + var bindingForOthersDevices = function () { + var isKeyPressed = true; + + $document.bind("keydown", function (event) { + if (!isKeyPressed && event.keyCode === 20) { + isKeyPressed = true; + if ($rootScope.isCapsLockOn != null) { setCapsLockOn(!$rootScope.isCapsLockOn); } + } + }); + + $document.bind("keyup", function (event) { + if (event.keyCode === 20) { isKeyPressed = false; } + }); + + $document.bind("keypress", function (event) { + var code = event.charCode || event.keyCode; + var shift = event.shiftKey; + + if (code > 96 && code < 123) { setCapsLockOn(shift); } + if (code > 64 && code < 91) { setCapsLockOn(!shift); } + }); + }; + + if (/Mac|iPad|iPhone|iPod/.test(navigator.platform)) { + bindingForAppleDevice(); + } else { + bindingForOthersDevices(); + } + + var setCapsLockOn = function (isOn) { + $timeout(function () { + $rootScope.isCapsLockOn = isOn; + }); + }; + + }]); + +}()); diff --git a/vendor/assets/components/ngCapsLock/ng-caps-lock.min.js b/vendor/assets/components/ngCapsLock/ng-caps-lock.min.js new file mode 100644 index 000000000..237d2c997 --- /dev/null +++ b/vendor/assets/components/ngCapsLock/ng-caps-lock.min.js @@ -0,0 +1 @@ +!function(){"use strict";angular.module("ngCapsLock",[]).run(["$rootScope","$document","$timeout",function(n,o,e){var i=function(){o.bind("keydown",function(n){20===n.keyCode&&c(!0)}),o.bind("keyup",function(n){20===n.keyCode&&c(!1)}),o.bind("keypress",function(n){var o=n.charCode||n.keyCode,e=n.shiftKey;o>96&&123>o&&c(!1),o>64&&91>o&&!e&&c(!0)})},t=function(){var e=!0;o.bind("keydown",function(o){e||20!==o.keyCode||(e=!0,null!=n.isCapsLockOn&&c(!n.isCapsLockOn))}),o.bind("keyup",function(n){20===n.keyCode&&(e=!1)}),o.bind("keypress",function(n){var o=n.charCode||n.keyCode,e=n.shiftKey;o>96&&123>o&&c(e),o>64&&91>o&&c(!e)})};/Mac|iPad|iPhone|iPod/.test(navigator.platform)?i():t();var c=function(o){e(function(){n.isCapsLockOn=o})}}])}(); From 112b174e5fad5417a0083eca35c75e01751c4858 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 31 Aug 2017 17:32:04 +0200 Subject: [PATCH 10/23] [bug] invalid time for reccurent events after Daylight Saving Time change --- app/helpers/application_helper.rb | 12 ++++++++++++ app/models/event.rb | 3 +++ 2 files changed, 15 insertions(+) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ae40ef803..445acf540 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -80,6 +80,18 @@ module ApplicationHelper nil end + ## + # Apply a correction for a future DateTime due to change in Daylight Saving Time (DST) period + # @param datetime {DateTime} + # Inspired by https://stackoverflow.com/a/12065605 + ## + def dst_correction(datetime) + datetime = datetime.in_time_zone(Time.zone.tzinfo.name) + datetime = datetime - 1.hour if datetime.dst? && !Time.now.dst? + datetime = datetime + 1.hour if Time.now.dst? && !datetime.dst? + datetime + end + private ## inspired by gems/actionview-4.2.5/lib/action_view/helpers/translation_helper.rb diff --git a/app/models/event.rb b/app/models/event.rb index 4c9e28395..7d0678171 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -1,5 +1,6 @@ class Event < ActiveRecord::Base include NotifyWith::NotificationAttachedObject + include ApplicationHelper has_one :event_image, as: :viewable, dependent: :destroy accepts_nested_attributes_for :event_image, allow_destroy: true @@ -87,8 +88,10 @@ class Event < ActiveRecord::Base r.events.each do |date| days_diff = availability.end_at.day - availability.start_at.day start_at = DateTime.new(date.year, date.month, date.day, availability.start_at.hour, availability.start_at.min, availability.start_at.sec, availability.start_at.zone) + start_at = dst_correction(start_at) end_date = date + days_diff.days end_at = DateTime.new(end_date.year, end_date.month, end_date.day, availability.end_at.hour, availability.end_at.min, availability.end_at.sec, availability.end_at.zone) + end_at = dst_correction(end_at) if event_image ei = EventImage.new(attachment: event_image.attachment) end From 31cdc5c695b48118590ff6a9c587b639584e1e00 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 4 Sep 2017 16:50:07 +0200 Subject: [PATCH 11/23] [bug] reccursive events have difference with requested time when crossing DST (#77) --- app/helpers/application_helper.rb | 11 ++++++----- app/models/event.rb | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 445acf540..6f941cced 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -82,14 +82,15 @@ module ApplicationHelper ## # Apply a correction for a future DateTime due to change in Daylight Saving Time (DST) period + # @param reference {ActiveSupport::TimeWithZone} # @param datetime {DateTime} # Inspired by https://stackoverflow.com/a/12065605 ## - def dst_correction(datetime) - datetime = datetime.in_time_zone(Time.zone.tzinfo.name) - datetime = datetime - 1.hour if datetime.dst? && !Time.now.dst? - datetime = datetime + 1.hour if Time.now.dst? && !datetime.dst? - datetime + def dst_correction(reference, datetime) + res = datetime.in_time_zone(reference.time_zone.tzinfo.name) + res = res - 1.hour if res.dst? && !reference.dst? + res = res + 1.hour if reference.dst? && !res.dst? + res end diff --git a/app/models/event.rb b/app/models/event.rb index 7d0678171..6ad394788 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -88,10 +88,10 @@ class Event < ActiveRecord::Base r.events.each do |date| days_diff = availability.end_at.day - availability.start_at.day start_at = DateTime.new(date.year, date.month, date.day, availability.start_at.hour, availability.start_at.min, availability.start_at.sec, availability.start_at.zone) - start_at = dst_correction(start_at) + start_at = dst_correction(availability.start_at,start_at) end_date = date + days_diff.days end_at = DateTime.new(end_date.year, end_date.month, end_date.day, availability.end_at.hour, availability.end_at.min, availability.end_at.sec, availability.end_at.zone) - end_at = dst_correction(end_at) + end_at = dst_correction(availability.start_at,end_at) if event_image ei = EventImage.new(attachment: event_image.attachment) end From 1af07f5e549e7eede8cb446b152916e55a54d00d Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 4 Sep 2017 17:27:18 +0200 Subject: [PATCH 12/23] [ongoing] rake task to fix existing recursive events --- CHANGELOG.md | 1 + lib/tasks/fablab/fix.rake | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d45d77edf..7ea9b56b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Updated puma for compatibility with openSSL > 1.0 - Documented installation on ArchLinux - [TODO DEPLOY] `rake db:seed` then `rake fablab:fix:migrate_admins_group` +- [TODO DEPLAY] `rake fablab:fix:recursive_events_over_DST` ## v2.5.10 2017 August 16 diff --git a/lib/tasks/fablab/fix.rake b/lib/tasks/fablab/fix.rake index 23eaa049b..252563302 100644 --- a/lib/tasks/fablab/fix.rake +++ b/lib/tasks/fablab/fix.rake @@ -57,5 +57,20 @@ namespace :fablab do end end end + + task recursive_events_over_DST: :environment do + #TODO intensive testing before release + include ApplicationHelper + groups = Event.group(:recurrence_id).count + groups.keys.each do |recurrent_event_id| + initial_event = Event.find(recurrent_event_id) + Event.where(recurrence_id: recurrent_event_id).where.not(id: recurrent_event_id).each do |event| + availability = event.availability + availability.start_at = dst_correction(initial_event.availability.start_at, availability.start_at) + availability.end_at = dst_correction(initial_event.availability.end_at, availability.end_at) + availability.save! + end + end + end end end From 9f136b479a5e44eaf398d5b5d826b133cb31ff41 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 5 Sep 2017 10:36:49 +0200 Subject: [PATCH 13/23] rake task to fix existing recursive events --- lib/tasks/fablab/fix.rake | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/tasks/fablab/fix.rake b/lib/tasks/fablab/fix.rake index 252563302..a213fe79d 100644 --- a/lib/tasks/fablab/fix.rake +++ b/lib/tasks/fablab/fix.rake @@ -59,16 +59,17 @@ namespace :fablab do end task recursive_events_over_DST: :environment do - #TODO intensive testing before release include ApplicationHelper groups = Event.group(:recurrence_id).count groups.keys.each do |recurrent_event_id| initial_event = Event.find(recurrent_event_id) Event.where(recurrence_id: recurrent_event_id).where.not(id: recurrent_event_id).each do |event| availability = event.availability - availability.start_at = dst_correction(initial_event.availability.start_at, availability.start_at) - availability.end_at = dst_correction(initial_event.availability.end_at, availability.end_at) - availability.save! + if initial_event.availability.start_at.hour != availability.start_at.hour + availability.start_at = dst_correction(initial_event.availability.start_at, availability.start_at) + availability.end_at = dst_correction(initial_event.availability.end_at, availability.end_at) + availability.save! + end end end end From c43d0d816f2d47a769d51cea822119bc2e851ba7 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 5 Sep 2017 10:42:14 +0200 Subject: [PATCH 14/23] updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ea9b56b0..67366701f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Added tooltip concerning images insertion while configuring the about page - Ability for admins to configure the maximum visibility for availabilities reservation - Administrators isolation in a special group +- Fix a bug: recursive events crossing Daylight Saving Time period changes are shifted by 1 hour - Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese - Fix a bug: invalid notification when sending monetary coupon to users From 82511aa7812553b7ce92a5d3a9a883e7d29ef4b8 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 5 Sep 2017 17:01:09 +0200 Subject: [PATCH 15/23] [feature] prevent creation of irregular yearly plans --- CHANGELOG.md | 1 + app/models/plan.rb | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index de3e01bf3..a364bc49e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Ability for admins to configure the maximum visibility for availabilities reservation - Administrators isolation in a special group - In login modal, displays an alert if Caps lock key is pressed +- Prevent creation of irregular yearly plans (eg. 12 months) - Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese - Fix a bug: invalid notification when sending monetary coupon to users diff --git a/app/models/plan.rb b/app/models/plan.rb index 8db94ae01..8acd35146 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -27,6 +27,8 @@ class Plan < ActiveRecord::Base validates :amount, :group, :base_name, presence: true validates :interval_count, numericality: { only_integer: true, greater_than_or_equal_to: 1 } + validates :interval_count, numericality: { less_than: 12 }, if: Proc.new {|plan| plan.interval == 'month'} + validates :interval_count, numericality: { less_than: 52 }, if: Proc.new {|plan| plan.interval == 'week'} validates :interval, inclusion: { in: %w(year month week) } validates :base_name, :slug, presence: true From d092a1c5ead51eb04c16a6d2ad7df0d12243ba80 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Sep 2017 15:01:41 +0200 Subject: [PATCH 16/23] admin can lock and unlock availbilities --- .../controllers/admin/calendar.coffee.erb | 23 ++++++++ .../javascripts/services/availability.coffee | 3 + app/assets/stylesheets/app.layout.scss | 4 ++ .../admin/calendar/calendar.html.erb | 58 ++++++++++++------- .../api/availabilities_controller.rb | 15 ++++- app/policies/availability_policy.rb | 2 +- .../api/availabilities/index.json.jbuilder | 3 +- .../api/availabilities/show.json.jbuilder | 1 + config/locales/app.admin.fr.yml | 10 ++++ config/routes.rb | 1 + ...20170906100906_add_lock_to_availability.rb | 5 ++ db/schema.rb | 3 +- 12 files changed, 104 insertions(+), 24 deletions(-) create mode 100644 db/migrate/20170906100906_add_lock_to_availability.rb diff --git a/app/assets/javascripts/controllers/admin/calendar.coffee.erb b/app/assets/javascripts/controllers/admin/calendar.coffee.erb index 33f9394ad..fe56df5b2 100644 --- a/app/assets/javascripts/controllers/admin/calendar.coffee.erb +++ b/app/assets/javascripts/controllers/admin/calendar.coffee.erb @@ -132,6 +132,29 @@ Application.Controllers.controller "AdminCalendarController", ["$scope", "$state + ## + # Mark the selected slot as unavailable for new reservations or allow reservations again on it + ## + $scope.toggleLockReservations = -> + locked = $scope.availability.lock + # open a confirmation dialog + dialogs.confirm + resolve: + object: -> + title: _t('admin_calendar.confirmation_required') + msg: if locked then _t("admin_calendar.do_you_really_want_to_allow_reservations") else _t("admin_calendar.do_you_really_want_to_block_this_slot_html") + , -> + # the admin has confirmed, lock/unlock the slot + Availability.lock {id: $scope.availability.id}, {lock: !locked} + , (data) -> # success + $scope.availability = data + growl.success(if locked then _t('admin_calendar.unlocking_success') else _t('admin_calendar.locking_success') ) + uiCalendarConfig.calendars.calendar.fullCalendar 'refetchEvents' + , (error) -> # failed + growl.error(if locked then _t('admin_calendar.unlocking_failed') else _t('admin_calendar.locking_failed')) + + + ### PRIVATE SCOPE ### ## diff --git a/app/assets/javascripts/services/availability.coffee b/app/assets/javascripts/services/availability.coffee index 4bc448b13..c837977c1 100644 --- a/app/assets/javascripts/services/availability.coffee +++ b/app/assets/javascripts/services/availability.coffee @@ -24,4 +24,7 @@ Application.Services.factory 'Availability', ["$resource", ($resource)-> isArray: true update: method: 'PUT' + lock: + method: 'PUT' + url: '/api/availabilities/:id/lock' ] diff --git a/app/assets/stylesheets/app.layout.scss b/app/assets/stylesheets/app.layout.scss index bd693d343..3ad8383b8 100644 --- a/app/assets/stylesheets/app.layout.scss +++ b/app/assets/stylesheets/app.layout.scss @@ -360,6 +360,10 @@ body.container{ } +.reservations-locked { + background-color: #f5f5f5; +} + .reservation-canceled { color: #606060; border-radius: 0.2em; diff --git a/app/assets/templates/admin/calendar/calendar.html.erb b/app/assets/templates/admin/calendar/calendar.html.erb index 2e7c16dd3..e8909d26e 100644 --- a/app/assets/templates/admin/calendar/calendar.html.erb +++ b/app/assets/templates/admin/calendar/calendar.html.erb @@ -42,11 +42,12 @@
-
+ +

{{ 'admin_calendar.ongoing_reservations' }}

-
+
  • {{r.user.name}} @@ -55,25 +56,42 @@
-
{{ 'admin_calendar.no_reservations' }}
+
{{ 'admin_calendar.no_reservations' }}
+
{{ 'admin_calendar.reservations_locked' }}
+
+
+ +
+
+

{{ 'admin_calendar.machines' }}

+
+
+
    +
  • + {{m.name}} + +
  • +
+
+
+ +
+
+

{{ 'admin_calendar.actions' }}

+
+
+
-
-
-
-

{{ 'admin_calendar.machines' }}

-
-
-
    -
  • - {{m.name}} - -
  • -
-
-
-
- - + \ No newline at end of file diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index af00bfcea..10f7a6cd5 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -2,7 +2,7 @@ class API::AvailabilitiesController < API::ApiController include FablabConfiguration before_action :authenticate_user!, except: [:public] - before_action :set_availability, only: [:show, :update, :destroy, :reservations] + before_action :set_availability, only: [:show, :update, :destroy, :reservations, :lock] before_action :define_max_visibility, only: [:machine, :trainings, :spaces] respond_to :json @@ -235,6 +235,15 @@ class API::AvailabilitiesController < API::ApiController end end + def lock + authorize @availability + if @availability.update_attributes(lock: lock_params) + render :show, status: :ok, location: @availability + else + render json: @availability.errors, status: :unprocessable_entity + end + end + private def set_availability @availability = Availability.find(params[:id]) @@ -245,6 +254,10 @@ class API::AvailabilitiesController < API::ApiController :machines_attributes => [:id, :_destroy]) end + def lock_params + params.require(:lock) + end + def is_reserved_availability(availability, user_id) reserved_slots = [] availability.slots.each do |s| diff --git a/app/policies/availability_policy.rb b/app/policies/availability_policy.rb index 85f8eefe2..d298e641b 100644 --- a/app/policies/availability_policy.rb +++ b/app/policies/availability_policy.rb @@ -1,5 +1,5 @@ class AvailabilityPolicy < ApplicationPolicy - %w(index? show? create? update? destroy? reservations? export?).each do |action| + %w(index? show? create? update? destroy? reservations? export? lock?).each do |action| define_method action do user.is_admin? end diff --git a/app/views/api/availabilities/index.json.jbuilder b/app/views/api/availabilities/index.json.jbuilder index 606f92dee..8749f6ca8 100644 --- a/app/views/api/availabilities/index.json.jbuilder +++ b/app/views/api/availabilities/index.json.jbuilder @@ -6,11 +6,12 @@ json.array!(@availabilities) do |availability| json.available_type availability.available_type json.machine_ids availability.machine_ids json.training_ids availability.training_ids - json.backgroundColor 'white' + json.backgroundColor !availability.lock ? 'white' : '#f5f5f5' json.borderColor availability_border_color(availability) json.tag_ids availability.tag_ids json.tags availability.tags do |t| json.id t.id json.name t.name end + json.lock availability.lock end diff --git a/app/views/api/availabilities/show.json.jbuilder b/app/views/api/availabilities/show.json.jbuilder index 5c97a67b4..68706604f 100644 --- a/app/views/api/availabilities/show.json.jbuilder +++ b/app/views/api/availabilities/show.json.jbuilder @@ -11,3 +11,4 @@ json.tags @availability.tags do |t| json.id t.id json.name t.name end +json.lock @availability.lock diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index aa9ebc866..f43de6319 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -48,6 +48,16 @@ fr: unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member: "Le créneau {{START}} - {{END}} n'a pu être supprimé car il est déjà réservé par un membre" # angular interpolation you_should_select_at_least_a_machine: "Vous devriez sélectionne au moins une machine pour ce créneau." export_is_running_you_ll_be_notified_when_its_ready: "L'export est en cours. Vous serez notifié lorsqu'il sera prêt." + actions: "Actions" + block_reservations: "Bloquer les réservations" + do_you_really_want_to_block_this_slot_html: "Êtes vous sur de vouloir bloquer les nouvelles réservations sur ce créneau ? Il deviendra alors invisible pour les utilisateurs.
Attention : cela n'annulera pas les réservations existantes." + locking_success: "Le créneau a bien été verrouillé, il n'apparaitra plus dans le calendrier utilisateur" + locking_failed: "Une erreur est survenue. Le verrouillage du créneau a échoué" + allow_reservations: "Autoriser les réservations" + do_you_really_want_to_allow_reservations: "Êtes vous sur de vouloir autoriser de nouveau la prise de réservations sur ce créneau ? Il deviendra alors visible pour les utilisateurs." + unlocking_success: "Le créneau a bien été déverrouillé, il apparaîtra de nouveau dans le calendrier utilisateur" + unlocking_failed: "Une erreur est survenue. Le déverrouillage du créneau a échoué" + reservations_locked: "Réservations bloquées" project_elements: # gestion des éléments constituant les projets diff --git a/config/routes.rb b/config/routes.rb index 262e496c1..0b4596592 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -85,6 +85,7 @@ Rails.application.routes.draw do get 'reservations', on: :member get 'public', on: :collection get '/export_index', action: 'export_availabilities', on: :collection + put ':id/lock', action: 'lock', on: :collection end resources :groups, only: [:index, :create, :update, :destroy] diff --git a/db/migrate/20170906100906_add_lock_to_availability.rb b/db/migrate/20170906100906_add_lock_to_availability.rb new file mode 100644 index 000000000..8a27aad1e --- /dev/null +++ b/db/migrate/20170906100906_add_lock_to_availability.rb @@ -0,0 +1,5 @@ +class AddLockToAvailability < ActiveRecord::Migration + def change + add_column :availabilities, :lock, :boolean, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index a76ff5499..c6095c45a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170227114634) do +ActiveRecord::Schema.define(version: 20170906100906) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -79,6 +79,7 @@ ActiveRecord::Schema.define(version: 20170227114634) do t.datetime "updated_at" t.integer "nb_total_places" t.boolean "destroying", default: false + t.boolean "lock", default: false end create_table "availability_tags", force: :cascade do |t| From 9caa3ff56fd0c28a22d855be6eb9d8544a4a4269 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Sep 2017 17:09:40 +0200 Subject: [PATCH 17/23] hide slots in members calendars if locked --- ...otal_diffrent_error.rb => invoice_total_different_error.rb} | 0 app/exceptions/locked_error.rb | 3 +++ 2 files changed, 3 insertions(+) rename app/exceptions/{invoice_total_diffrent_error.rb => invoice_total_different_error.rb} (100%) create mode 100644 app/exceptions/locked_error.rb diff --git a/app/exceptions/invoice_total_diffrent_error.rb b/app/exceptions/invoice_total_different_error.rb similarity index 100% rename from app/exceptions/invoice_total_diffrent_error.rb rename to app/exceptions/invoice_total_different_error.rb diff --git a/app/exceptions/locked_error.rb b/app/exceptions/locked_error.rb new file mode 100644 index 000000000..b225b1958 --- /dev/null +++ b/app/exceptions/locked_error.rb @@ -0,0 +1,3 @@ +# Raised when debit wallet fail +class DebitWalletError < StandardError +end From 57228f4eec9f6123dc859ce40aa3fbda687affef Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Sep 2017 17:10:10 +0200 Subject: [PATCH 18/23] hide slots in members calendars if locked --- .../api/availabilities_controller.rb | 73 ++++++++++++++++--- .../invoice_total_different_error.rb | 4 +- app/exceptions/locked_error.rb | 4 +- app/models/reservation.rb | 9 ++- 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index 10f7a6cd5..57d96f802 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -21,22 +21,32 @@ class API::AvailabilitiesController < API::ApiController def public start_date = ActiveSupport::TimeZone[params[:timezone]].parse(params[:start]) end_date = ActiveSupport::TimeZone[params[:timezone]].parse(params[:end]).end_of_day - @reservations = Reservation.includes(:slots, user: [:profile]).references(:slots, :user).where('slots.start_at >= ? AND slots.end_at <= ?', start_date, end_date) + @reservations = Reservation.includes(:slots, user: [:profile]).references(:slots, :user) + .where('slots.start_at >= ? AND slots.end_at <= ?', start_date, end_date) # request for 1 single day if in_same_day(start_date, end_date) # trainings, events @training_and_event_availabilities = Availability.includes(:tags, :trainings, :event, :slots).where(available_type: %w(training event)) .where('start_at >= ? AND end_at <= ?', start_date, end_date) + .where(lock: false) # machines @machine_availabilities = Availability.includes(:tags, :machines).where(available_type: 'machines') .where('start_at >= ? AND end_at <= ?', start_date, end_date) + .where(lock: false) @machine_slots = [] @machine_availabilities.each do |a| a.machines.each do |machine| if params[:m] and params[:m].include?(machine.id.to_s) ((a.end_at - a.start_at)/ApplicationHelper::SLOT_DURATION.minutes).to_i.times do |i| - slot = Slot.new(start_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes, end_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes + ApplicationHelper::SLOT_DURATION.minutes, availability_id: a.id, availability: a, machine: machine, title: machine.name) + slot = Slot.new( + start_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes, + end_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes + ApplicationHelper::SLOT_DURATION.minutes, + availability_id: a.id, + availability: a, + machine: machine, + title: machine.name + ) slot = verify_machine_is_reserved(slot, @reservations, current_user, '') @machine_slots << slot end @@ -47,6 +57,7 @@ class API::AvailabilitiesController < API::ApiController # spaces @space_availabilities = Availability.includes(:tags, :spaces).where(available_type: 'space') .where('start_at >= ? AND end_at <= ?', start_date, end_date) + .where(lock: false) if params[:s] @space_availabilities.where(available_id: params[:s]) @@ -57,7 +68,14 @@ class API::AvailabilitiesController < API::ApiController space = a.spaces.first ((a.end_at - a.start_at)/ApplicationHelper::SLOT_DURATION.minutes).to_i.times do |i| if (a.start_at + (i * ApplicationHelper::SLOT_DURATION).minutes) > Time.now - slot = Slot.new(start_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes, end_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes + ApplicationHelper::SLOT_DURATION.minutes, availability_id: a.id, availability: a, space: space, title: space.name) + slot = Slot.new( + start_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes, + end_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes + ApplicationHelper::SLOT_DURATION.minutes, + availability_id: a.id, + availability: a, + space: space, + title: space.name + ) slot = verify_space_is_reserved(slot, @reservations, current_user, '') @space_slots << slot end @@ -69,6 +87,7 @@ class API::AvailabilitiesController < API::ApiController else @availabilities = Availability.includes(:tags, :machines, :trainings, :spaces, :event, :slots) .where('start_at >= ? AND end_at <= ?', start_date, end_date) + .where(lock: false) @availabilities.each do |a| if a.available_type == 'training' or a.available_type == 'event' a = verify_training_event_is_reserved(a, @reservations, current_user) @@ -125,16 +144,27 @@ class API::AvailabilitiesController < API::ApiController @slots = [] @reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @machine.class.to_s, @machine.id).includes(:slots, user: [:profile]).references(:slots, :user).where('slots.start_at > ?', Time.now) if @user.is_admin? - @availabilities = @machine.availabilities.includes(:tags).where("end_at > ? AND available_type = 'machines'", Time.now) + @availabilities = @machine.availabilities.includes(:tags) + .where("end_at > ? AND available_type = 'machines'", Time.now) + .where(lock: false) else end_at = @visi_max_other end_at = @visi_max_year if is_subscription_year(@user) - @availabilities = @machine.availabilities.includes(:tags).where("end_at > ? AND end_at < ? AND available_type = 'machines'", Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) + @availabilities = @machine.availabilities.includes(:tags).where("end_at > ? AND end_at < ? AND available_type = 'machines'", Time.now, end_at) + .where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) + .where(lock: false) end @availabilities.each do |a| ((a.end_at - a.start_at)/ApplicationHelper::SLOT_DURATION.minutes).to_i.times do |i| if (a.start_at + (i * ApplicationHelper::SLOT_DURATION).minutes) > Time.now - slot = Slot.new(start_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes, end_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes + ApplicationHelper::SLOT_DURATION.minutes, availability_id: a.id, availability: a, machine: @machine, title: '') + slot = Slot.new( + start_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes, + end_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes + ApplicationHelper::SLOT_DURATION.minutes, + availability_id: a.id, + availability: a, + machine: @machine, + title: '' + ) slot = verify_machine_is_reserved(slot, @reservations, current_user, @current_user_role) @slots << slot end @@ -167,12 +197,17 @@ class API::AvailabilitiesController < API::ApiController # who made the request? # 1) an admin (he can see all future availabilities) if current_user.is_admin? - @availabilities = @availabilities.includes(:tags, :slots, trainings: [:machines]).where('availabilities.start_at > ?', Time.now) + @availabilities = @availabilities.includes(:tags, :slots, trainings: [:machines]) + .where('availabilities.start_at > ?', Time.now) + .where(lock: false) # 2) an user (he cannot see availabilities further than 1 (or 3) months) else end_at = @visi_max_year end_at = @visi_max_year if can_show_slot_plus_three_months(@user) - @availabilities = @availabilities.includes(:tags, :slots, :availability_tags, trainings: [:machines]).where('availabilities.start_at > ? AND availabilities.start_at < ?', Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) + @availabilities = @availabilities.includes(:tags, :slots, :availability_tags, trainings: [:machines]) + .where('availabilities.start_at > ? AND availabilities.start_at < ?', Time.now, end_at) + .where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) + .where(lock: false) end # finally, we merge the availabilities with the reservations @@ -190,18 +225,32 @@ class API::AvailabilitiesController < API::ApiController @current_user_role = current_user.is_admin? ? 'admin' : 'user' @space = Space.friendly.find(params[:space_id]) @slots = [] - @reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @space.class.to_s, @space.id).includes(:slots, user: [:profile]).references(:slots, :user).where('slots.start_at > ?', Time.now) + @reservations = Reservation.where('reservable_type = ? and reservable_id = ?', @space.class.to_s, @space.id) + .includes(:slots, user: [:profile]).references(:slots, :user) + .where('slots.start_at > ?', Time.now) if current_user.is_admin? - @availabilities = @space.availabilities.includes(:tags).where("end_at > ? AND available_type = 'space'", Time.now) + @availabilities = @space.availabilities.includes(:tags) + .where("end_at > ? AND available_type = 'space'", Time.now) + .where(lock: false) else end_at = @visi_max_other end_at = @visi_max_year if is_subscription_year(@user) - @availabilities = @space.availabilities.includes(:tags).where("end_at > ? AND end_at < ? AND available_type = 'space'", Time.now, end_at).where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) + @availabilities = @space.availabilities.includes(:tags) + .where("end_at > ? AND end_at < ? AND available_type = 'space'", Time.now, end_at) + .where('availability_tags.tag_id' => @user.tag_ids.concat([nil])) + .where(lock: false) end @availabilities.each do |a| ((a.end_at - a.start_at)/ApplicationHelper::SLOT_DURATION.minutes).to_i.times do |i| if (a.start_at + (i * ApplicationHelper::SLOT_DURATION).minutes) > Time.now - slot = Slot.new(start_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes, end_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes + ApplicationHelper::SLOT_DURATION.minutes, availability_id: a.id, availability: a, space: @space, title: '') + slot = Slot.new( + start_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes, + end_at: a.start_at + (i*ApplicationHelper::SLOT_DURATION).minutes + ApplicationHelper::SLOT_DURATION.minutes, + availability_id: a.id, + availability: a, + space: @space, + title: '' + ) slot = verify_space_is_reserved(slot, @reservations, @user, @current_user_role) @slots << slot end diff --git a/app/exceptions/invoice_total_different_error.rb b/app/exceptions/invoice_total_different_error.rb index 110295f93..eb61da01b 100644 --- a/app/exceptions/invoice_total_different_error.rb +++ b/app/exceptions/invoice_total_different_error.rb @@ -1,3 +1,3 @@ -# Raised when total of reservation isnt equal total of strip's invoice -class InvoiceTotalDiffrentError < StandardError +# Raised when total of reservation isn't equal to the total of stripe's invoice +class InvoiceTotalDifferentError < StandardError end diff --git a/app/exceptions/locked_error.rb b/app/exceptions/locked_error.rb index b225b1958..a9f5e6110 100644 --- a/app/exceptions/locked_error.rb +++ b/app/exceptions/locked_error.rb @@ -1,3 +1,3 @@ -# Raised when debit wallet fail -class DebitWalletError < StandardError +# Raised when reserving on a locked availability +class LockedError < StandardError end diff --git a/app/models/reservation.rb b/app/models/reservation.rb index 3d2d66a4b..18a90bf22 100644 --- a/app/models/reservation.rb +++ b/app/models/reservation.rb @@ -47,6 +47,13 @@ class Reservation < ActiveRecord::Base plan = nil end + # check that none of the reserved availabilities was locked + slots.each do |slot| + if slot.availability.lock + raise LockedError + end + end + case reservable @@ -260,7 +267,7 @@ class Reservation < ActiveRecord::Base # this function only check reservation total is equal strip invoice total when # pay only reservation not reservation + subscription #if !is_equal_reservation_total_and_stp_invoice_total(stp_invoice, coupon_code) - #raise InvoiceTotalDiffrentError + #raise InvoiceTotalDifferentError #end stp_invoice.pay card.delete if card From 273ec5317d90917da5b3960c50d55b123570b475 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 6 Sep 2017 18:07:56 +0200 Subject: [PATCH 19/23] disallow locking availabilities if it has any non-cancelled reservations --- .../controllers/admin/calendar.coffee.erb | 41 ++++++++++++------- .../controllers/machines.coffee.erb | 4 ++ config/locales/app.admin.fr.yml | 1 + 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/app/assets/javascripts/controllers/admin/calendar.coffee.erb b/app/assets/javascripts/controllers/admin/calendar.coffee.erb index fe56df5b2..31574c081 100644 --- a/app/assets/javascripts/controllers/admin/calendar.coffee.erb +++ b/app/assets/javascripts/controllers/admin/calendar.coffee.erb @@ -136,22 +136,33 @@ Application.Controllers.controller "AdminCalendarController", ["$scope", "$state # Mark the selected slot as unavailable for new reservations or allow reservations again on it ## $scope.toggleLockReservations = -> + # first, define a shortcut to the lock property locked = $scope.availability.lock - # open a confirmation dialog - dialogs.confirm - resolve: - object: -> - title: _t('admin_calendar.confirmation_required') - msg: if locked then _t("admin_calendar.do_you_really_want_to_allow_reservations") else _t("admin_calendar.do_you_really_want_to_block_this_slot_html") - , -> - # the admin has confirmed, lock/unlock the slot - Availability.lock {id: $scope.availability.id}, {lock: !locked} - , (data) -> # success - $scope.availability = data - growl.success(if locked then _t('admin_calendar.unlocking_success') else _t('admin_calendar.locking_success') ) - uiCalendarConfig.calendars.calendar.fullCalendar 'refetchEvents' - , (error) -> # failed - growl.error(if locked then _t('admin_calendar.unlocking_failed') else _t('admin_calendar.locking_failed')) + # then check if we'll allow reservations locking + prevent = !locked # if currently locked, allow unlock anyway + if (!locked) + prevent = false + angular.forEach $scope.reservations, (r) -> + if r.canceled_at == null + prevent = true # if currently unlocked and has any non-cancelled reservation, disallow locking + if (!prevent) + # open a confirmation dialog + dialogs.confirm + resolve: + object: -> + title: _t('admin_calendar.confirmation_required') + msg: if locked then _t("admin_calendar.do_you_really_want_to_allow_reservations") else _t("admin_calendar.do_you_really_want_to_block_this_slot_html") + , -> + # the admin has confirmed, lock/unlock the slot + Availability.lock {id: $scope.availability.id}, {lock: !locked} + , (data) -> # success + $scope.availability = data + growl.success(if locked then _t('admin_calendar.unlocking_success') else _t('admin_calendar.locking_success') ) + uiCalendarConfig.calendars.calendar.fullCalendar 'refetchEvents' + , (error) -> # failed + growl.error(if locked then _t('admin_calendar.unlocking_failed') else _t('admin_calendar.locking_failed')) + else + growl.error(_t('admin_calendar.unlockable_because_reservations')) diff --git a/app/assets/javascripts/controllers/machines.coffee.erb b/app/assets/javascripts/controllers/machines.coffee.erb index fd3d0ed5e..ed4cfdade 100644 --- a/app/assets/javascripts/controllers/machines.coffee.erb +++ b/app/assets/javascripts/controllers/machines.coffee.erb @@ -256,6 +256,9 @@ Application.Controllers.controller "ShowMachineController", ['$scope', '$state', $state.go('app.public.machines_list') , (error)-> growl.warning(_t('the_machine_cant_be_deleted_because_it_is_already_reserved_by_some_users')) + + + ## # Callback to book a reservation for the current machine ## @@ -412,6 +415,7 @@ Application.Controllers.controller "ReserveMachineController", ["$scope", '$stat updateCalendar() + ## # When modifying an already booked reservation, callback when the modification was successfully done. ## diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index f43de6319..5c6bd48aa 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -58,6 +58,7 @@ fr: unlocking_success: "Le créneau a bien été déverrouillé, il apparaîtra de nouveau dans le calendrier utilisateur" unlocking_failed: "Une erreur est survenue. Le déverrouillage du créneau a échoué" reservations_locked: "Réservations bloquées" + unlockable_because_reservations: "Impossible de bloquer les réservations sur ce créneau car il existe des réservations non annulées sur celui-ci." project_elements: # gestion des éléments constituant les projets From 404101ccd4967ab8ee3de45c0ea4d98a2d806d20 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 7 Sep 2017 10:47:18 +0200 Subject: [PATCH 20/23] english and portuguese translations --- .../javascripts/controllers/admin/calendar.coffee.erb | 2 +- config/locales/app.admin.en.yml | 11 +++++++++++ config/locales/app.admin.fr.yml | 2 +- config/locales/app.admin.pt.yml | 11 +++++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/controllers/admin/calendar.coffee.erb b/app/assets/javascripts/controllers/admin/calendar.coffee.erb index 31574c081..bb9764117 100644 --- a/app/assets/javascripts/controllers/admin/calendar.coffee.erb +++ b/app/assets/javascripts/controllers/admin/calendar.coffee.erb @@ -151,7 +151,7 @@ Application.Controllers.controller "AdminCalendarController", ["$scope", "$state resolve: object: -> title: _t('admin_calendar.confirmation_required') - msg: if locked then _t("admin_calendar.do_you_really_want_to_allow_reservations") else _t("admin_calendar.do_you_really_want_to_block_this_slot_html") + msg: if locked then _t("admin_calendar.do_you_really_want_to_allow_reservations") else _t("admin_calendar.do_you_really_want_to_block_this_slot") , -> # the admin has confirmed, lock/unlock the slot Availability.lock {id: $scope.availability.id}, {lock: !locked} diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index abfae4858..f26c9f1fe 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -48,6 +48,17 @@ en: unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member: "Unable to delete the slot {{START}} - {{END}} because it's already reserved by a member" # angular interpolation you_should_select_at_least_a_machine: "You should select at least one machine on this slot." export_is_running_you_ll_be_notified_when_its_ready: "Export is running. You'll be notified when it's ready." + actions: "Actions" + block_reservations: "Block reservations" + do_you_really_want_to_block_this_slot: "Do you really want to block new reservations on this slot? It will become invisible to users." + locking_success: "Slot successfully locked, it won't appear any longer in the user calendar" + locking_failed: "An error occurred. Slot locking has failed" + allow_reservations: "Allow reservations" + do_you_really_want_to_allow_reservations: "Do you really want to allow booking again on this slot? It will become visible for the users." + unlocking_success: "Slot successfully unlocked, it will appear again in the user calendar" + unlocking_failed: "An error occurred. Slot unlocking has failed" + reservations_locked: "Booking is blocked" + unlockable_because_reservations: "Unable to block booking on this slot because some uncancelled reservations exist on it." project_elements: # management of the projects' components diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 5c6bd48aa..49fe46df4 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -50,7 +50,7 @@ fr: export_is_running_you_ll_be_notified_when_its_ready: "L'export est en cours. Vous serez notifié lorsqu'il sera prêt." actions: "Actions" block_reservations: "Bloquer les réservations" - do_you_really_want_to_block_this_slot_html: "Êtes vous sur de vouloir bloquer les nouvelles réservations sur ce créneau ? Il deviendra alors invisible pour les utilisateurs.
Attention : cela n'annulera pas les réservations existantes." + do_you_really_want_to_block_this_slot: "Êtes vous sur de vouloir bloquer les nouvelles réservations sur ce créneau ? Il deviendra alors invisible pour les utilisateurs." locking_success: "Le créneau a bien été verrouillé, il n'apparaitra plus dans le calendrier utilisateur" locking_failed: "Une erreur est survenue. Le verrouillage du créneau a échoué" allow_reservations: "Autoriser les réservations" diff --git a/config/locales/app.admin.pt.yml b/config/locales/app.admin.pt.yml index 5eebc6d9a..0938b9c0e 100755 --- a/config/locales/app.admin.pt.yml +++ b/config/locales/app.admin.pt.yml @@ -48,6 +48,17 @@ pt: unable_to_delete_the_slot_START-END_because_it_s_already_reserved_by_a_member: "Não é possível deletar o slot {{START}} - {{END}} porque já foi reservado por um membro" # angular interpolation you_should_select_at_least_a_machine: "Você deveria selecionar a última máquina neste slot." export_is_running_you_ll_be_notified_when_its_ready: "A Exportação está em andamento. Você será notificado quando terminar." + actions: "Ações" + block_reservations: "Impedir reservas" + do_you_really_want_to_block_this_slot: "Você realmente quer bloquear novas reservas neste slot? Isso se tornará invisível para os usuários." + locking_success: "Slot bloqueado com êxito, ela não aparecerá mais tempo no calendário do usuário" + locking_failed: "Um erro ocorreu. O bloqueio do slot falhou" + allow_reservations: "Permitir a reserva" + do_you_really_want_to_allow_reservations: "Você realmente quer permitir a reserva novamente neste slot? Será visível para os usuários." + unlocking_success: "Slot desbloqueado com sucesso, ele aparecerá novamente no calendário do usuário" + unlocking_failed: "Um erro ocorreu. O desbloqueio do slot falhou" + reservations_locked: "Reserva é bloqueado" + unlockable_because_reservations: "Não é possível bloquear a reserva neste slot porque existem algumas reservas não cancelados nele." project_elements: # management of the projects' components From a822481d39d2e882d55557c79157e19f69586e36 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 7 Sep 2017 10:54:42 +0200 Subject: [PATCH 21/23] updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a364bc49e..f571c4517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Administrators isolation in a special group - In login modal, displays an alert if Caps lock key is pressed - Prevent creation of irregular yearly plans (eg. 12 months) +- Ability to lock machine, space or training availability slots, to prevent new reservations on them - Fix a bug: admins cannot see all availabilities for spaces in reservation calendar when a user is selected - Fix a bug: missing translation after payment in english and portuguese - Fix a bug: invalid notification when sending monetary coupon to users From f5e2a44dcfbd1be935ecb8064d6fe8549d4fd581 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 7 Sep 2017 11:44:50 +0200 Subject: [PATCH 22/23] [bug] in public calendar, availabilities are not shown to visitors --- CHANGELOG.md | 1 + .../api/availabilities_controller.rb | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f571c4517..23affc17d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Fix a bug: invalid notification when sending monetary coupon to users - Fix a bug: unable to delete group "standard" - Fix a bug: recursive events crossing Daylight Saving Time period changes are shifted by 1 hour +- Fix a bug: unable to see availabilities in the public calendar when browsing as a visitor (non-connected) - Updated puma for compatibility with openSSL > 1.0 - Documented installation on ArchLinux - [TODO DEPLOY] `rake db:seed` then `rake fablab:fix:migrate_admins_group` diff --git a/app/controllers/api/availabilities_controller.rb b/app/controllers/api/availabilities_controller.rb index 57d96f802..1e52b66c0 100644 --- a/app/controllers/api/availabilities_controller.rb +++ b/app/controllers/api/availabilities_controller.rb @@ -92,7 +92,7 @@ class API::AvailabilitiesController < API::ApiController if a.available_type == 'training' or a.available_type == 'event' a = verify_training_event_is_reserved(a, @reservations, current_user) elsif a.available_type == 'space' - a.is_reserved = is_reserved_availability(a, current_user.id) + a.is_reserved = is_reserved_availability(a, current_user) end end end @@ -307,14 +307,18 @@ class API::AvailabilitiesController < API::ApiController params.require(:lock) end - def is_reserved_availability(availability, user_id) - reserved_slots = [] - availability.slots.each do |s| - if s.canceled_at.nil? - reserved_slots << s + def is_reserved_availability(availability, user) + if user + reserved_slots = [] + availability.slots.each do |s| + if s.canceled_at.nil? + reserved_slots << s + end end + reserved_slots.map(&:reservations).flatten.map(&:user_id).include? user.id + else + false end - reserved_slots.map(&:reservations).flatten.map(&:user_id).include? user_id end def is_reserved(start_at, reservations) From 75cb28e4019cb4a5542a605c73fb24648c704d09 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 7 Sep 2017 15:02:10 +0200 Subject: [PATCH 23/23] Version 2.5.11 --- .fabmanager-version | 2 +- CHANGELOG.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.fabmanager-version b/.fabmanager-version index a51f76bd5..06d0f343f 100644 --- a/.fabmanager-version +++ b/.fabmanager-version @@ -1 +1 @@ -2.5.11-dev \ No newline at end of file +2.5.11 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 23affc17d..aa5472ce5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog Fab Manager -## next release +## v2.5.11 2017 September 7 - Added tooltip concerning images insertion while configuring the about page - Ability for admins to configure the maximum visibility for availabilities reservation @@ -17,7 +17,7 @@ - Updated puma for compatibility with openSSL > 1.0 - Documented installation on ArchLinux - [TODO DEPLOY] `rake db:seed` then `rake fablab:fix:migrate_admins_group` -- [TODO DEPLAY] `rake fablab:fix:recursive_events_over_DST` +- [TODO DEPLOY] `rake fablab:fix:recursive_events_over_DST` ## v2.5.10 2017 August 16