diff --git a/src/components/Projects/DropdownMenuItem.vue b/src/components/Projects/DropdownMenuItem.vue index 94006a4336a4519791bb43e40bbf45f3c032f65d..0173fcc1315dc155a246020a816928f54fa2b6c2 100644 --- a/src/components/Projects/DropdownMenuItem.vue +++ b/src/components/Projects/DropdownMenuItem.vue @@ -1,6 +1,7 @@ <template> <Multiselect v-model="selection" + :class="{ multiple }" :options="options" :allow-empty="true" track-by="label" @@ -157,3 +158,9 @@ export default { } }; </script> + +<style> +#filters-container .multiple .multiselect__option--selected:not(:hover) { + background-color: #e8e8e8 !important; +} +</style> \ No newline at end of file diff --git a/src/components/Projects/ProjectsMenu.vue b/src/components/Projects/ProjectsMenu.vue index da4bc6f2bd3d231c23a3b14950e40e4bfbe7544e..a5d4607621c87616a41d894e7cc15508c5b765c6 100644 --- a/src/components/Projects/ProjectsMenu.vue +++ b/src/components/Projects/ProjectsMenu.vue @@ -1,6 +1,7 @@ <template> <div id="filters-container" + v-if="displayedClassicFilters || displayedAttributeFilters" class="margin-bottom" > <div @@ -19,39 +20,25 @@ </div> </div> <div :class="['full-width', 'filters', { 'hidden': displayFilters }]"> - <div class="ui menu filter-row"> - <div class="item"> + <div + v-if="displayedClassicFilters.length > 0" + class="ui menu filter-row" + > + <div + v-for="filter in displayedClassicFilters" + :key="filter.name" + class="item" + > <label> - Niveau d'autorisation requis + {{ filter.label }} </label> - <DropdownMenuItem - :options="accessLevelOptions" + <search-projects + v-if="filter.name === 'search'" v-on="$listeners" /> - </div> - <div class="item"> - <label> - Mon niveau d'autorisation - </label> <DropdownMenuItem - :options="userAccessLevelOptions" - v-on="$listeners" - /> - </div> - <div class="item"> - <label> - Modération - </label> - <DropdownMenuItem - :options="moderationOptions" - v-on="$listeners" - /> - </div> - <div class="item"> - <label> - Recherche par nom - </label> - <search-projects + v-else + :options="filter.options" v-on="$listeners" /> </div> @@ -101,83 +88,115 @@ export default { data() { return { displayFilters: false, - moderationOptions: [ - { - label: 'Tous', - filter: 'moderation', - value: null - }, - { - label: 'Projet modéré', - filter: 'moderation', - value: 'true' - }, - { - label: 'Projet non modéré', - filter: 'moderation', - value: 'false' - }, - ], - accessLevelOptions: [ - { - label: 'Tous', - filter: 'access_level', - value: null - }, - { - label: 'Utilisateur anonyme', - filter: 'access_level', - value: 'anonymous' - }, - { - label: 'Utilisateur connecté', - filter: 'access_level', - value: 'logged_user' - }, - { - label: 'Contributeur', - filter: 'access_level', - value: 'contributor' - }, - ], - userAccessLevelOptions: [ + classicFilters: [ { - label: 'Tous', - filter: 'user_access_level', - value: null + name: 'access_level', + label: 'Niveau d\'autorisation requis', + options: [ + { + label: 'Utilisateur anonyme', + value: 'anonymous' + }, + { + label: 'Utilisateur connecté', + value: 'logged_user' + }, + { + label: 'Contributeur', + value: 'contributor' + }, + ], }, { - label: 'Utilisateur connecté', - filter: 'user_access_level', - value: '1' + name: 'user_access_level', + label: 'Mon niveau d\'autorisation', + options: [ + { + label: 'Utilisateur connecté', + value: '1' + }, + { + label: 'Contributeur', + value: '2' + }, + { + label: 'Super contributeur', + value: '3' + }, + { + label: 'Modérateur', + value: '4' + }, + { + label: 'Administrateur projet', + value: '5' + }, + ], }, { - label: 'Contributeur', - filter: 'user_access_level', - value: '2' + name: 'moderation', + label: 'Modération', + options: [ + { + label: 'Projet modéré', + value: 'true' + }, + { + label: 'Projet non modéré', + value: 'false' + }, + ] }, { - label: 'Super contributeur', - filter: 'user_access_level', - value: '3' - }, - { - label: 'Modérateur', - filter: 'user_access_level', - value: '4' - }, - { - label: 'Administrateur projet', - filter: 'user_access_level', - value: '5' - }, + name: 'search', + label: 'Recherche par nom', + } ], attributesFilter: {}, }; }, computed: { - ...mapState(['user', 'projectAttributes']), + ...mapState([ + 'user', + 'configuration', + 'projectAttributes' + ]), + /** + * Processes project filters to prepare them for display. + * It also adds a global 'Tous' (All) option to each attribute's options for filtering purposes. + * + * @returns {Array} An array of filter objects with modified options for display. + */ + displayedClassicFilters() { + const projectFilters = this.configuration.VUE_APP_PROJECT_FILTERS.split(','); + // Filter filters to be displayed according to configuration and process filters + const processedFilters = this.classicFilters.filter(filter => projectFilters.includes(filter.name)) + .map(filter => { + if (filter.options) { + // if user is not connected display its user access level corresponding to anonymous user + if (!this.user && filter.name ==='user_access_level') { + filter.options.unshift({ + label: 'Utilisateur anonyme', + value: '0' + }); + } + // Format the options to be displayed by dropdowns + const options = this.generateFilterOptions(filter); + // Add the global option at beginning + options.unshift({ + label: 'Tous', + filter: filter.name, + value: null, + }); + return { ...filter, options }; + } else { // Search input field doesn't take options + return filter; + } + }); + + return processedFilters; + }, /** * Processes project attributes to prepare them for display, adjusting the options based on the attribute type. * For boolean attributes, it creates specific options for true and false values. @@ -190,7 +209,9 @@ export default { // Filter and process attributes const processedAttributes = this.projectAttributes.filter(attribute => attribute.display_filter) .map(attribute => { - const options = this.generateOptionsForAttribute(attribute); + // Format the options to be displayed by dropdowns + const options = this.generateFilterOptions(attribute); + // Add the global option at beginning options.unshift({ label: 'Tous', filter: attribute.id, @@ -204,16 +225,6 @@ export default { }, }, - created() { - if (!this.user) { - this.userAccessLevelOptions.splice(1, 0, { - label: 'Utilisateur anonyme', - filter: 'user_access_level', - value: '0' - }); - } - }, - methods: { /** * Helper function to chunk an array into smaller arrays of a specified size. @@ -231,27 +242,27 @@ export default { }, /** - * Generates options for a given attribute based on its field type. + * Generates options for a given filter. * It handles boolean attributes specially by creating explicit true/false options. * Other attribute types use their predefined options. * * @param {Object} attribute - The project attribute for which to generate options. * @returns {Array} An array of options for the given attribute. */ - generateOptionsForAttribute(attribute) { + generateFilterOptions(filter) { // Handle boolean attributes specially by creating true/false options - if (attribute.field_type === 'boolean') { + if (filter.field_type === 'boolean') { return [ - { filter: attribute.id, label: 'Oui', value: 'true' }, - { filter: attribute.id, label: 'Non', value: 'false' }, + { filter: filter.id, label: 'Oui', value: 'true' }, + { filter: filter.id, label: 'Non', value: 'false' }, ]; } - // For other attribute types, map each option to the expected format - return attribute.options.map(option => ({ - filter: attribute.id, - label: option, - value: option, + // For other filter types, map each option to the expected format + return filter.options.map(option => ({ + filter: filter.id || filter.name, + label: option.label || option, + value: option.value || option, })); },