Skip to content
Snippets Groups Projects
Commit 4e367b30 authored by Camille Blanchon's avatar Camille Blanchon
Browse files

Merge branch 'redmine-issues/19722' into 'develop'

REDMINE_ISSUE-19722 | Créer des filtres pour les attributs projet sur l'accueil de l'application

See merge request !760
parents cf478d51 e09fc51f
No related branches found
No related tags found
1 merge request!760REDMINE_ISSUE-19722 | Créer des filtres pour les attributs projet sur l'accueil de l'application
...@@ -19,7 +19,10 @@ ...@@ -19,7 +19,10 @@
@remove="remove" @remove="remove"
@close="close" @close="close"
> >
<template slot="option" slot-scope="props"> <template
slot="option"
slot-scope="props"
>
<span :title="props.option.label">{{ props.option.label }}</span> <span :title="props.option.label">{{ props.option.label }}</span>
</template> </template>
<template <template
......
<template> <template>
<div <div
v-if="displayedClassicFilters || displayedAttributeFilters" v-if="chunkedNsortedFilters"
id="filters-container" id="filters-container"
class="margin-bottom" class="margin-bottom"
> >
...@@ -21,11 +21,12 @@ ...@@ -21,11 +21,12 @@
</div> </div>
<div :class="['full-width', 'filters', { 'hidden': displayFilters }]"> <div :class="['full-width', 'filters', { 'hidden': displayFilters }]">
<div <div
v-if="displayedClassicFilters.length > 0" v-for="(chunkedFilters, index) in chunkedNsortedFilters"
:key="index"
class="ui menu filter-row" class="ui menu filter-row"
> >
<div <div
v-for="filter in displayedClassicFilters" v-for="filter in chunkedFilters"
:key="filter.name" :key="filter.name"
class="item" class="item"
> >
...@@ -37,31 +38,16 @@ ...@@ -37,31 +38,16 @@
v-on="$listeners" v-on="$listeners"
/> />
<DropdownMenuItem <DropdownMenuItem
v-else v-else-if="!filter.id"
:options="filter.options" :options="filter.options"
v-on="$listeners" v-on="$listeners"
/> />
</div>
</div>
<!-- Display several rows if more than 4 project attributes -->
<div
v-for="(groupedAttributes, index) in displayedAttributeFilters"
:key="index"
class="ui menu filter-row"
>
<div
v-for="attribute in groupedAttributes"
:key="attribute.id"
class="item"
>
<label>
{{ attribute.label }}
</label>
<DropdownMenuItem <DropdownMenuItem
:options="attribute.options" v-else
:multiple="attribute.field_type.includes('list')" :options="filter.options"
:current-selection="attributesFilter[attribute.id]" :multiple="filter.field_type.includes('list')"
:default-filter="attribute.default_filter_enabled ? attribute.default_filter_value : null" :current-selection="attributesFilter[filter.id]"
:default-filter="filter.default_filter_enabled ? filter.default_filter_value : null"
@filter="updateAttributeFilter" @filter="updateAttributeFilter"
@remove="removeAttributeFilter" @remove="removeAttributeFilter"
/> />
...@@ -171,7 +157,7 @@ export default { ...@@ -171,7 +157,7 @@ export default {
displayedClassicFilters() { displayedClassicFilters() {
const projectFilters = this.configuration.VUE_APP_PROJECT_FILTERS.split(','); const projectFilters = this.configuration.VUE_APP_PROJECT_FILTERS.split(',');
// Filter filters to be displayed according to configuration and process filters // Filter filters to be displayed according to configuration and process filters
const processedFilters = this.classicFilters.filter(filter => projectFilters.includes(filter.name)) return this.classicFilters.filter(filter => projectFilters.includes(filter.name))
.map(filter => { .map(filter => {
if (filter.options) { if (filter.options) {
// if user is not connected display its user access level corresponding to anonymous user // if user is not connected display its user access level corresponding to anonymous user
...@@ -194,8 +180,6 @@ export default { ...@@ -194,8 +180,6 @@ export default {
return filter; return filter;
} }
}); });
return processedFilters;
}, },
/** /**
* Processes project attributes to prepare them for display, adjusting the options based on the attribute type. * Processes project attributes to prepare them for display, adjusting the options based on the attribute type.
...@@ -207,7 +191,7 @@ export default { ...@@ -207,7 +191,7 @@ export default {
*/ */
displayedAttributeFilters() { displayedAttributeFilters() {
// Filter and process attributes // Filter and process attributes
const processedAttributes = this.projectAttributes.filter(attribute => attribute.display_filter) return this.projectAttributes.filter(attribute => attribute.display_filter)
.map(attribute => { .map(attribute => {
// Format the options to be displayed by dropdowns // Format the options to be displayed by dropdowns
const options = this.generateFilterOptions(attribute); const options = this.generateFilterOptions(attribute);
...@@ -219,9 +203,19 @@ export default { ...@@ -219,9 +203,19 @@ export default {
}); });
return { ...attribute, options }; return { ...attribute, options };
}); });
},
// Chunk the processed attributes into arrays of up to 4 elements /**
return this.chunkArray(processedAttributes, 4); * Merge all filters and place the search filters at the end of the array
* Then chunks the array into rows of 4 filters to display each chunk in a row
*/
chunkedNsortedFilters() {
const allFilters = [...this.displayedClassicFilters, ...this.displayedAttributeFilters];
const sortedFilters = [
...allFilters.filter(el => el.name !== 'search'),
...allFilters.filter(el => el.name === 'search'),
];
// Chunk the filters into arrays of up to 4 elements
return this.chunkArray(sortedFilters, 4);
}, },
}, },
...@@ -293,7 +287,7 @@ export default { ...@@ -293,7 +287,7 @@ export default {
* Handles both single-choice and multi-choice attribute types. * Handles both single-choice and multi-choice attribute types.
* @param {Object} newFilter - The new filter to be added, containing the attribute key and value. * @param {Object} newFilter - The new filter to be added, containing the attribute key and value.
*/ */
updateAttributeFilter({ value, filter }) { updateAttributeFilter({ filter, value }) {
// Retrieve the attribute type information to determine how to handle the update // Retrieve the attribute type information to determine how to handle the update
const attribute = this.getProjectAttribute(filter); const attribute = this.getProjectAttribute(filter);
// Check if the attribute allows multiple selections // Check if the attribute allows multiple selections
...@@ -326,10 +320,10 @@ export default { ...@@ -326,10 +320,10 @@ export default {
* Particularly useful for multi-choice attributes where individual values can be deselected. * Particularly useful for multi-choice attributes where individual values can be deselected.
* @param {Object} removedFilter - The filter to be removed, containing the attribute key and value. * @param {Object} removedFilter - The filter to be removed, containing the attribute key and value.
*/ */
removeAttributeFilter({ value, filter }) { removeAttributeFilter({ filter, value }) {
// Retrieve attribute information to determine if it's a multi-choice attribute // Retrieve attribute information to determine if it's a multi-choice attribute
const attribute = this.getProjectAttribute(filter); const attribute = this.getProjectAttribute(filter);
const isMultiChoice = attribute.field_type === 'multi_choices_list'; const isMultiChoice = attribute.field_type.includes('list');
if (isMultiChoice) { if (isMultiChoice) {
// For multi-choice attributes, convert the current filter value to an array for manipulation // For multi-choice attributes, convert the current filter value to an array for manipulation
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment