From ac1d518ddcd7ef8832b07d001875c0bebca6a427 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 11 May 2022 11:54:00 +0200 Subject: [PATCH] (ui) option to disable the machines module --- CHANGELOG.md | 3 + .../javascript/controllers/admin/calendar.js | 5 +- .../javascript/controllers/admin/graphs.js | 3 +- .../javascript/controllers/admin/pricing.js | 18 +- .../controllers/admin/statistics.js | 3 +- .../src/javascript/controllers/main_nav.js | 110 +++---- app/frontend/src/javascript/models/setting.ts | 3 +- app/frontend/src/javascript/router.js | 5 +- .../templates/admin/calendar/calendar.html | 2 +- .../templates/admin/calendar/eventModal.html | 5 +- app/frontend/templates/admin/plans/edit.html | 75 ++--- .../templates/admin/pricing/credits.html | 294 +++++++++--------- .../templates/admin/pricing/index.html | 2 +- .../templates/admin/settings/general.html | 20 +- .../admin/settings/reservations.html | 2 +- app/models/setting.rb | 3 +- app/views/application/index.html.erb | 1 + config/locales/app.admin.en.yml | 6 + config/locales/en.yml | 1 + db/seeds.rb | 2 + 20 files changed, 292 insertions(+), 271 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 551e88d46..e06501084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## next deploy +- Option to disable the 'machines' module - Ability to define social networks for the FabLab "about page" - Support for OpenID Connect in Sign-Sign-On authentication providers - ICS file attached to the reservation notification email @@ -20,10 +21,12 @@ - Webpack overlay will now report eslint issues - Linted all code according to eslint rules - when generating an avoir, the option "by_wallet" is not present anymore if wallet module is off +- Fix a bug: when enabled, the statistics module is still not shown in the menu - Fix a bug: Refused to connect to 'wss://localhost:3035/ws' when using a https tunnel in development mode - Fix a bug: edge case of birthday in the future in seeds.rb, we should use Date.current instead of DateTime.current since birthday is a date (see https://github.com/sleede/fab-manager/issues/344) - Fix a security issue: updated ruby to 2.6.10 to fix [CVE-2022-28739](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-28739) - Fix a security issue: updated rails to 5.2.7.1 to fix [CVE-2022-22577](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22577) and [CVE-2022-27777](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-27777) +- [TODO DEPLOY] `rails db:seed` ## v5.3.13 2022 May 02 diff --git a/app/frontend/src/javascript/controllers/admin/calendar.js b/app/frontend/src/javascript/controllers/admin/calendar.js index 79cf80724..9a5a073b1 100644 --- a/app/frontend/src/javascript/controllers/admin/calendar.js +++ b/app/frontend/src/javascript/controllers/admin/calendar.js @@ -621,7 +621,7 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui $scope.availability = { start_at: start, end_at: end, - available_type: 'machines', // default + available_type: $scope.$root.modules.machines ? 'machines' : undefined, // default to machines if enabled tag_ids: [], is_recurrent: false, period: 'week', @@ -927,6 +927,9 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui * Initialize some settings, depending on the availability type, before continuing to step 2 (select a machine/training/space) */ const validateType = function () { + if ($scope.availability.available_type === null || $scope.availability.available_type === undefined) { + return growl.error(_t('app.admin.calendar.select_type')); + } $scope.setNbTotalPlaces(); if ($scope.availability.available_type === 'training') { $scope.availability.slot_duration = undefined; diff --git a/app/frontend/src/javascript/controllers/admin/graphs.js b/app/frontend/src/javascript/controllers/admin/graphs.js index d5ec66f1b..32b239f78 100644 --- a/app/frontend/src/javascript/controllers/admin/graphs.js +++ b/app/frontend/src/javascript/controllers/admin/graphs.js @@ -125,7 +125,8 @@ Application.Controllers.controller('GraphsController', ['$scope', '$state', '$ro $scope.hiddenTab = function (tab) { if (tab.graph) { return !((tab.es_type_key === 'subscription' && !$rootScope.modules.plans) || - (tab.es_type_key === 'training' && !$rootScope.modules.trainings)); + (tab.es_type_key === 'training' && !$rootScope.modules.trainings) || + (tab.es_type_key === 'machine' && !$rootScope.modules.machines)); } return false; }; diff --git a/app/frontend/src/javascript/controllers/admin/pricing.js b/app/frontend/src/javascript/controllers/admin/pricing.js index b213702ff..63af4beca 100644 --- a/app/frontend/src/javascript/controllers/admin/pricing.js +++ b/app/frontend/src/javascript/controllers/admin/pricing.js @@ -685,14 +685,16 @@ Application.Controllers.controller('EditPricingController', ['$scope', '$state', placement: 'bottom' }); } - uitour.createStep({ - selector: '.plans-pricing .machines-tab', - stepId: 'machines', - order: 3, - title: _t('app.admin.tour.pricing.machines.title'), - content: _t('app.admin.tour.pricing.machines.content'), - placement: 'bottom' - }); + if ($scope.$root.modules.machines) { + uitour.createStep({ + selector: '.plans-pricing .machines-tab', + stepId: 'machines', + order: 3, + title: _t('app.admin.tour.pricing.machines.title'), + content: _t('app.admin.tour.pricing.machines.content'), + placement: 'bottom' + }); + } if ($scope.$root.modules.spaces) { uitour.createStep({ selector: '.plans-pricing .spaces-tab', diff --git a/app/frontend/src/javascript/controllers/admin/statistics.js b/app/frontend/src/javascript/controllers/admin/statistics.js index 1472d3bc0..6a45242ce 100644 --- a/app/frontend/src/javascript/controllers/admin/statistics.js +++ b/app/frontend/src/javascript/controllers/admin/statistics.js @@ -186,7 +186,8 @@ Application.Controllers.controller('StatisticsController', ['$scope', '$state', if (tab.table) { return ((tab.es_type_key === 'subscription' && !$rootScope.modules.plans) || (tab.es_type_key === 'training' && !$rootScope.modules.trainings) || - (tab.es_type_key === 'space' && !$rootScope.modules.spaces) + (tab.es_type_key === 'space' && !$rootScope.modules.spaces) || + (tab.es_type_key === 'machine' && !$rootScope.modules.machines) ); } else { return true; diff --git a/app/frontend/src/javascript/controllers/main_nav.js b/app/frontend/src/javascript/controllers/main_nav.js index 443a01c0c..898e9ee60 100644 --- a/app/frontend/src/javascript/controllers/main_nav.js +++ b/app/frontend/src/javascript/controllers/main_nav.js @@ -23,12 +23,30 @@ Application.Controllers.controller('MainNavController', ['$scope', 'settingsProm class: 'home-link' }, { class: 'menu-spacer' }, - { + $scope.$root.modules.publicAgenda && { + state: 'app.public.calendar', + linkText: 'app.public.common.public_calendar', + linkIcon: 'calendar', + class: 'public-calendar-link' + }, + $scope.$root.modules.machines && { state: 'app.public.machines_list', linkText: 'app.public.common.reserve_a_machine', linkIcon: 'cogs', class: 'reserve-machine-link' }, + $scope.$root.modules.trainings && { + state: 'app.public.trainings_list', + linkText: 'app.public.common.trainings_registrations', + linkIcon: 'graduation-cap', + class: 'reserve-training-link' + }, + $scope.$root.modules.spaces && { + state: 'app.public.spaces_list', + linkText: 'app.public.common.reserve_a_space', + linkIcon: 'rocket', + class: 'reserve-space-link' + }, { state: 'app.public.events_list', linkText: 'app.public.common.events_registrations', @@ -42,60 +60,40 @@ Application.Controllers.controller('MainNavController', ['$scope', 'settingsProm linkIcon: 'th', class: 'projects-gallery-link' }, - { class: 'menu-spacer' } - - ]; - - if ($scope.$root.modules.plans) { - $scope.navLinks.push({ + $scope.$root.modules.plans && { class: 'menu-spacer' }, + $scope.$root.modules.plans && { state: 'app.public.plans', linkText: 'app.public.common.subscriptions', linkIcon: 'credit-card', class: 'plans-link' - }); - } - - if ($scope.$root.modules.trainings) { - $scope.navLinks.splice(4, 0, { - state: 'app.public.trainings_list', - linkText: 'app.public.common.trainings_registrations', - linkIcon: 'graduation-cap', - class: 'reserve-training-link' - }); - } - - if ($scope.$root.modules.spaces) { - $scope.navLinks.splice(4, 0, { - state: 'app.public.spaces_list', - linkText: 'app.public.common.reserve_a_space', - linkIcon: 'rocket', - class: 'reserve-space-link' - }); - } - - if ($scope.$root.modules.publicAgenda) { - $scope.navLinks.splice(2, 0, { - state: 'app.public.calendar', - linkText: 'app.public.common.public_calendar', - linkIcon: 'calendar', - class: 'public-calendar-link' - }); - } + } + ].filter(Boolean); Fablab.adminNavLinks = Fablab.adminNavLinks || []; - const adminNavLinks = [ + $scope.adminNavLinks = [ { state: 'app.admin.calendar', linkText: 'app.public.common.manage_the_calendar', linkIcon: 'calendar', authorizedRoles: ['admin', 'manager'] }, - { + $scope.$root.modules.machines && { state: 'app.public.machines_list', linkText: 'app.public.common.manage_the_machines', linkIcon: 'cogs', authorizedRoles: ['admin', 'manager'] }, + $scope.$root.modules.trainings && { + state: 'app.admin.trainings', + linkText: 'app.public.common.trainings_monitoring', + linkIcon: 'graduation-cap', + authorizedRoles: ['admin', 'manager'] + }, + $scope.$root.modules.spaces && { + state: 'app.public.spaces_list', + linkText: 'app.public.common.manage_the_spaces', + linkIcon: 'rocket' + }, { state: 'app.admin.events', linkText: 'app.public.common.manage_the_events', @@ -121,6 +119,12 @@ Application.Controllers.controller('MainNavController', ['$scope', 'settingsProm linkIcon: 'file-pdf-o', authorizedRoles: ['admin', 'manager'] }, + $scope.$root.modules.statistics && { + state: 'app.admin.statistics', + linkText: 'app.public.common.statistics', + linkIcon: 'bar-chart-o', + authorizedRoles: ['admin'] + }, { class: 'menu-spacer', authorizedRoles: ['admin'] @@ -143,35 +147,7 @@ Application.Controllers.controller('MainNavController', ['$scope', 'settingsProm linkIcon: 'cloud', authorizedRoles: ['admin'] } - ].concat(Fablab.adminNavLinks); - - $scope.adminNavLinks = adminNavLinks; - - if ($scope.$root.modules.trainings) { - $scope.adminNavLinks.splice(3, 0, { - state: 'app.admin.trainings', - linkText: 'app.public.common.trainings_monitoring', - linkIcon: 'graduation-cap', - authorizedRoles: ['admin', 'manager'] - }); - } - - if ($scope.$root.modules.spaces) { - $scope.adminNavLinks.splice(3, 0, { - state: 'app.public.spaces_list', - linkText: 'app.public.common.manage_the_spaces', - linkIcon: 'rocket' - }); - } - - if ($scope.$root.modules.statistics) { - $scope.adminNavLinks.splice($scope.$root.modules.spaces ? 9 : 8, 0, { - state: 'app.admin.statistics', - linkText: 'app.public.common.statistics', - linkIcon: 'bar-chart-o', - authorizedRoles: ['admin'] - }); - } + ].filter(Boolean).concat(Fablab.adminNavLinks); /** * Returns the current state of the public registration setting (allowed/blocked). diff --git a/app/frontend/src/javascript/models/setting.ts b/app/frontend/src/javascript/models/setting.ts index 5b48d6a5b..a250cb6c5 100644 --- a/app/frontend/src/javascript/models/setting.ts +++ b/app/frontend/src/javascript/models/setting.ts @@ -132,7 +132,8 @@ export enum SettingName { SocialsEchosciences = 'echosciences', SocialsPinterest = 'pinterest', SocialsLastfm = 'lastfm', - SocialsFlickr = 'flickr' + SocialsFlickr = 'flickr', + MachinesModule = 'machines_module', } export type SettingValue = string|boolean|number; diff --git a/app/frontend/src/javascript/router.js b/app/frontend/src/javascript/router.js index 811c14763..c27852a3d 100644 --- a/app/frontend/src/javascript/router.js +++ b/app/frontend/src/javascript/router.js @@ -27,7 +27,7 @@ angular.module('application.router', ['ui.router']) logoFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-file' }).$promise; }], logoBlackFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-black-file' }).$promise; }], sharedTranslations: ['Translations', function (Translations) { return Translations.query(['app.shared', 'app.public.common']).$promise; }], - modulesPromise: ['Setting', function (Setting) { return Setting.query({ names: "['spaces_module', 'plans_module', 'invoicing_module', 'wallet_module', 'statistics_module', 'trainings_module', 'public_agenda_module']" }).$promise; }], + modulesPromise: ['Setting', function (Setting) { return Setting.query({ names: "['machines_module', 'spaces_module', 'plans_module', 'invoicing_module', 'wallet_module', 'statistics_module', 'trainings_module', 'public_agenda_module']" }).$promise; }], settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['public_registrations']" }).$promise; }] }, onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', 'modulesPromise', 'CSRF', function ($rootScope, logoFile, logoBlackFile, modulesPromise, CSRF) { @@ -37,6 +37,7 @@ angular.module('application.router', ['ui.router']) $rootScope.logo = logoFile.custom_asset; $rootScope.logoBlack = logoBlackFile.custom_asset; $rootScope.modules = { + machines: (modulesPromise.machines_module === 'true'), spaces: (modulesPromise.spaces_module === 'true'), plans: (modulesPromise.plans_module === 'true'), trainings: (modulesPromise.trainings_module === 'true'), @@ -1071,7 +1072,7 @@ angular.module('application.router', ['ui.router']) "'renew_pack_threshold', 'pack_only_for_subscription', 'overlapping_categories', 'public_registrations'," + "'extended_prices_in_same_day', 'recaptcha_site_key', 'recaptcha_secret_key', 'user_validation_required', 'user_validation_required_machine', " + "'user_validation_required_training', 'user_validation_required_subscription', 'user_validation_required_space'," + - "'user_validation_required_event', 'user_validation_required_pack', 'user_validation_required_list']" + "'user_validation_required_event', 'user_validation_required_pack', 'user_validation_required_list', 'machines_module']" }).$promise; }], privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }], diff --git a/app/frontend/templates/admin/calendar/calendar.html b/app/frontend/templates/admin/calendar/calendar.html index 0d79a9bbc..13edb10b8 100644 --- a/app/frontend/templates/admin/calendar/calendar.html +++ b/app/frontend/templates/admin/calendar/calendar.html @@ -37,7 +37,7 @@
{{ 'app.admin.calendar.trainings' }}
{{ 'app.admin.calendar.machines' }}
- {{ 'app.admin.calendar.spaces' }} + {{ 'app.admin.calendar.spaces' }} {{ 'app.admin.calendar.events' }}
diff --git a/app/frontend/templates/admin/calendar/eventModal.html b/app/frontend/templates/admin/calendar/eventModal.html index d148ec256..12b0dac7d 100644 --- a/app/frontend/templates/admin/calendar/eventModal.html +++ b/app/frontend/templates/admin/calendar/eventModal.html @@ -12,7 +12,7 @@ {{ 'app.admin.calendar.training' }} -
+
+
+ {{ 'app.admin.calendar.no_modules_available' }} +
-

{{ 'app.admin.plans.edit.machines' }}

- + +
+

{{ 'app.admin.plans.edit.machines' }}

+
+ + + + + + + + + + + +
{{ 'app.admin.plans.edit.machine' }}{{ 'app.admin.plans.edit.hourly_rate' }}
{{ getMachine(price.priceable_id).name }} (id {{ price.priceable_id }}) * +
+ {{currencySymbol}} + + +
+
+ + +
+

{{ 'app.admin.plans.edit.spaces' }}

+ - - + + - - - + + + -
{{ 'app.admin.plans.edit.machine' }}{{ 'app.admin.plans.edit.hourly_rate' }}{{ 'app.admin.plans.edit.space' }}{{ 'app.admin.plans.edit.hourly_rate' }}
{{ getMachine(price.priceable_id).name }} (id {{ price.priceable_id }}) * -
- {{currencySymbol}} - - -
-
{{ getSpace(price.priceable_id).name }} * +
+ {{currencySymbol}} + + +
+
- -

{{ 'app.admin.plans.edit.spaces' }}

- - - - - - - - - - - - -
{{ 'app.admin.plans.edit.space' }}{{ 'app.admin.plans.edit.hourly_rate' }}
{{ getSpace(price.priceable_id).name }} * -
- {{currencySymbol}} - - -
-
+ +