diff --git a/app/assets/javascripts/controllers/admin/projects.js b/app/assets/javascripts/controllers/admin/projects.js index 9dfe82e79..e44335227 100644 --- a/app/assets/javascripts/controllers/admin/projects.js +++ b/app/assets/javascripts/controllers/admin/projects.js @@ -182,6 +182,17 @@ Application.Controllers.controller('AdminProjectsController', ['$scope', '$state } }; + /** + * Remove the initial dot from the given extension, if any + * @param extension {String} + * @returns {String} + */ + $scope.removeInitialDot = function (extension) { + if (extension.substr(0, 1) === '.') return extension.substr(1); + + return extension; + }; + /** * Setup the feature-tour for the admin/projects page. * This is intended as a contextual help (when pressing F1) diff --git a/app/assets/javascripts/directives/settings/select-multiple-setting.js.erb b/app/assets/javascripts/directives/settings/select-multiple-setting.js.erb new file mode 100644 index 000000000..f7b40fd1c --- /dev/null +++ b/app/assets/javascripts/directives/settings/select-multiple-setting.js.erb @@ -0,0 +1,98 @@ +Application.Directives.directive('selectMultipleSetting', ['Setting', 'growl', '_t', '$uibModal', + function (Setting, growl, _t, $uibModal) { + return ({ + restrict: 'E', + scope: { + name: '@', + label: '@', + settings: '=', + classes: '@', + required: '<', + titleNew: '@', + descriptionNew: '@', + beforeAdd: '=' + }, + templateUrl: '<%= asset_path "admin/settings/select-multiple.html" %>', + link ($scope, element, attributes) { + // The setting + $scope.setting = { + name: $scope.name, + value: $scope.settings[$scope.name] + }; + + // the options + $scope.options = $scope.settings[$scope.name].split(' '); + + // the selected options + $scope.selection = []; + + /** + * Remove the items in the selection from the options and update setting.value + */ + $scope.removeItem = function() { + const options = $scope.options.filter(function (opt) { + return $scope.selection.indexOf(opt) < 0; + }) + $scope.options = options; + $scope.setting.value = options.join(' '); + growl.success(_t('app.admin.settings.COUNT_items_removed', { COUNT: $scope.selection.length })); + $scope.selection = []; + } + + /** + * Open a modal dialog asking for the value of a new item to add + */ + $scope.addItem = function() { + $uibModal.open({ + templateUrl: 'newSelectOption.html', + resolve: { + titleNew: function () { return $scope.titleNew; }, + descriptionNew: function () { return $scope.descriptionNew; } + }, + controller: function ($scope, $uibModalInstance, titleNew, descriptionNew) { + $scope.value = undefined; + $scope.titleNew = titleNew; + $scope.descriptionNew = descriptionNew; + $scope.ok = function () { + $uibModalInstance.close($scope.value); + }; + $scope.dismiss = function () { + $uibModalInstance.dismiss('cancel'); + }; + } + }).result['finally'](null).then(function(val) { + const options = Array.from($scope.options); + if (typeof $scope.beforeAdd === 'function') { val = $scope.beforeAdd(val); } + options.push(val); + $scope.options = options; + $scope.setting.value = options.join(' '); + growl.success(_t('app.admin.settings.item_added')); + }); + } + + /** + * Callback to save the setting value to the database + * @param setting {{value:*, name:string}} note that the value will be stringified + */ + $scope.save = function (setting) { + let { value } = setting; + + Setting.update( + { name: setting.name }, + { value }, + function () { + growl.success(_t('app.admin.settings.customization_of_SETTING_successfully_saved', { SETTING: _t(`app.admin.settings.${setting.name}`) })); + $scope.settings[$scope.name] = value; + }, + function (error) { + if (error.status === 304) return; + + growl.error(_t('app.admin.settings.an_error_occurred_saving_the_setting')); + console.log(error); + } + ); + }; + } + }); + } +]); diff --git a/app/assets/javascripts/router.js.erb b/app/assets/javascripts/router.js.erb index 1d790fe12..17ec7d1dd 100644 --- a/app/assets/javascripts/router.js.erb +++ b/app/assets/javascripts/router.js.erb @@ -627,7 +627,9 @@ angular.module('application.router', ['ui.router']) componentsPromise: ['Component', function (Component) { return Component.query().$promise; }], licencesPromise: ['Licence', function (Licence) { return Licence.query().$promise; }], themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }], - settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['feature_tour_display', 'disqus_shortname']" }).$promise; }] + settingsPromise: ['Setting', function (Setting) { + return Setting.query({ names: "['feature_tour_display', 'disqus_shortname', 'allowed_cad_extensions', 'allowed_cad_mime_types']" }).$promise; + }] } }) .state('app.admin.manage_abuses', { @@ -1040,8 +1042,8 @@ angular.module('application.router', ['ui.router']) 'booking_move_enable', 'booking_move_delay', 'booking_cancel_enable', 'feature_tour_display', \ 'booking_cancel_delay', 'main_color', 'secondary_color', 'spaces_module', 'twitter_analytics', \ 'fablab_name', 'name_genre', 'reminder_enable', 'plans_module', \ - 'reminder_delay', 'visibility_yearly', 'visibility_others', 'allowed_cad_extensions', \ - 'display_name_enable', 'machines_sort_by', 'fab_analytics', 'allowed_cad_mime_types' \ + 'reminder_delay', 'visibility_yearly', 'visibility_others', \ + 'display_name_enable', 'machines_sort_by', 'fab_analytics', \ 'link_name', 'home_content', 'home_css', 'phone_required']` }).$promise; }], privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }], diff --git a/app/assets/templates/admin/projects/settings.html.erb b/app/assets/templates/admin/projects/settings.html.erb index edfaee3db..a7c830d95 100644 --- a/app/assets/templates/admin/projects/settings.html.erb +++ b/app/assets/templates/admin/projects/settings.html.erb @@ -27,20 +27,21 @@

{{ 'app.admin.projects.settings.validation' }}

{{ 'app.admin.projects.settings.validation_info' }}

- - + +
- - + +
diff --git a/app/assets/templates/admin/settings/select-multiple.html b/app/assets/templates/admin/settings/select-multiple.html new file mode 100644 index 000000000..a133e8daa --- /dev/null +++ b/app/assets/templates/admin/settings/select-multiple.html @@ -0,0 +1,35 @@ + +
+ + +
+
+ + +
+ +
+ + diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index b26986bed..4913d1f8d 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -148,7 +148,11 @@ en: validation: "Validation" validation_info: "Users can upload CAD (Computer Aided Design) files with the documentation of their projects. You can specify which files types are allowed. Use the test input below to determine the MIME type of a file." extensions: "Allowed extensions" + new_extension: "New extension" + new_ext_info: "Specify a new file extension to allow these files to be uploaded." mime_types: "Allowed MIME types" + new_mime_type: "New MIME type" + new_type_info: "Specify a new MIME type to allow these files to be uploaded. Please use the test input to determine the MIME type of a file." test_file: "Test a file" set_a_file: "Select a file" file_is_TYPE: "MIME type of this file is {TYPE}" @@ -1066,6 +1070,8 @@ en: feature_tour_display: "feature tour display" email_from: "expeditor's address" disqus_shortname: "Disqus shortname" + COUNT_items_removed: "{COUNT, plural, =1{One item} other{{COUNT} items}} removed" + item_added: "One item added" general: general: "General" title: "Title" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 371eafb49..881c25161 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -148,7 +148,11 @@ fr: validation: "Validation" validation_info: "Les utilisateurs peuvent téléverser des fichiers de CAO (Conception Assistée par Ordinateur) avec la documentation de leurs projets. Vous pouvez spécifier quels types de fichiers sont autorisés. Utilisez le champ de test ci-dessous pour déterminer le type MIME d'un fichier." extensions: "Extensions autorisées" + new_extension: "Nouvelle extension" + new_info: "Spécifiez une nouvelle extension de fichier pour autoriser ces fichiers à être téléversés." mime_types: "Types MIME autorisés" + new_mime_type: "Nouveau type MIME" + new_type_info: "Spécifiez un nouveau type MIME pour autoriser ces fichiers à être téléversés. Veuillez utiliser le champ de test pour déterminer le type MIME d'un fichier." test_file: "Tester un fichier" set_a_file: "Sélectionner un fichier" file_is_TYPE: "Le type MIME de ce fichier est {TYPE}" @@ -1066,6 +1070,8 @@ fr: feature_tour_display: "l'affichage des visites guidées" email_from: "l'adresse de l'expéditeur" disqus_shortname: "nom court Disqus" + COUNT_items_removed: "{COUNT, plural, =1{Un élément retiré} other{{COUNT} éléments retirés}}" + item_added: "Un élément ajouté" general: general: "Général" title: "Titre"