Update projects filters [SCI-11796]

This commit is contained in:
Andrej 2025-04-24 14:42:13 +02:00
parent 2e9ccb8d07
commit a9c668de22
7 changed files with 79 additions and 19 deletions

View file

@ -19,7 +19,7 @@ class ProjectsController < ApplicationController
before_action :load_current_folder, only: :index
before_action :check_view_permissions, except: %i(index create update archive_group restore_group
inventory_assigning_project_filter
actions_toolbar user_roles users_filter)
actions_toolbar user_roles users_filter head_of_project_users_list)
before_action :check_create_permissions, only: :create
before_action :check_manage_permissions, only: :update
before_action :set_folder_inline_name_editing, only: %i(index cards)
@ -272,6 +272,14 @@ class ProjectsController < ApplicationController
render json: { data: users }, status: :ok
end
def head_of_project_users_list
users = User.where(id: current_team.projects.select(:supervised_by_id)).map do |u|
[u.id, u.name, { avatar_url: avatar_path(u, :icon_small) }]
end
render json: { data: users }, status: :ok
end
def assigned_users_list
users = User.where(id: @project.user_assignments.select(:user_id)).order('full_name ASC')

View file

@ -125,6 +125,7 @@ export default {
archivedPageUrl: { type: String },
currentViewMode: { type: String, required: true },
usersFilterUrl: { type: String },
headOfProjectUsersListUrl: { type: String },
userRolesUrl: { type: String },
currentFolderId: { type: String },
foldersTreeUrl: { type: String },
@ -142,7 +143,12 @@ export default {
exportLimitExceded: false,
folderDeleteDescription: '',
exportDescription: '',
descriptionModalObject: null
descriptionModalObject: null,
statusesList: [
['not_started', this.i18n.t('projects.index.status.not_started')],
['started', this.i18n.t('projects.index.status.started')],
['completed', this.i18n.t('projects.index.status.completed')]
]
};
},
computed: {
@ -164,6 +170,9 @@ export default {
headerName: this.i18n.t('projects.index.card.status'),
sortable: true,
cellRenderer: StatusRenderer,
cellRendererParams: {
statusesList: this.statusesList
},
notSelectable: true
},
{
@ -287,9 +296,16 @@ export default {
type: 'Text'
},
{
key: 'created_at',
key: 'start_on',
type: 'DateRange',
label: this.i18n.t('filters_modal.created_on.label')
label: this.i18n.t('filters_modal.created_on.label'),
mode: 'date'
},
{
key: 'due_date',
type: 'DateRange',
label: this.i18n.t('filters_modal.due_date.label'),
mode: 'date'
}
];
@ -311,6 +327,24 @@ export default {
placeholder: this.i18n.t('projects.index.filters_modal.members.placeholder')
});
filters.push({
key: 'head_of_project',
type: 'Select',
optionsUrl: this.headOfProjectUsersListUrl,
optionRenderer: this.usersFilterRenderer,
labelRenderer: this.usersFilterRenderer,
label: this.i18n.t('projects.index.filters_modal.head_of_project.label'),
placeholder: this.i18n.t('projects.index.filters_modal.head_of_project.placeholder')
});
filters.push({
key: 'statuses',
type: 'Select',
options: this.statusesList,
label: this.i18n.t('projects.index.filters_modal.status.label'),
placeholder: this.i18n.t('projects.index.filters_modal.status.placeholder')
});
filters.push({
key: 'folder_search',
type: 'Checkbox',

View file

@ -1,7 +1,7 @@
<template>
<div v-if="params.data.status" class="py-0.5">
<SelectDropdown
:options="statuses"
:options="params.statusesList"
:value="params.data.status"
@change="changeStatus"
size="xs"
@ -25,15 +25,6 @@ export default {
required: true
}
},
data() {
return {
statuses: [
['not_started', this.i18n.t('projects.index.status.not_started')],
['started', this.i18n.t('projects.index.status.started')],
['completed', this.i18n.t('projects.index.status.completed')]
]
};
},
methods: {
optionRenderer(option) {
let color = 'bg-sn-grey-500';

View file

@ -64,11 +64,17 @@ module Lists
if @filters[:members].present?
records = records.joins(:user_assignments).where(user_assignments: { user_id: @filters[:members].values })
end
if @filters[:created_at_from].present?
records = records.where('projects.created_at > ?',
@filters[:created_at_from])
end
records = records.where('projects.created_at < ?', @filters[:created_at_to]) if @filters[:created_at_to].present?
records = records.where(supervised_by_id: @filters[:head_of_project].values) if @filters[:head_of_project].present?
records = records.where('projects.start_on >= ?', @filters[:start_on_from]) if @filters[:start_on_from].present?
records = records.where('projects.start_on <= ?', @filters[:start_on_to]) if @filters[:start_on_to].present?
records = records.where('projects.due_date >= ?', @filters[:due_date_from]) if @filters[:due_date_from].present?
records = records.where('projects.due_date <= ?', @filters[:due_date_to]) if @filters[:due_date_to].present?
if @filters[:archived_on_to].present?
records = records.where('projects.archived_on < ?',
@filters[:archived_on_to])
@ -76,6 +82,19 @@ module Lists
if @filters[:archived_on_from].present?
records = records.where('projects.archived_on > ?', @filters[:archived_on_from])
end
if @filters[:statuses].present?
scopes = {
'not_started' => records.not_started,
'started' => records.started,
'completed' => records.completed
}
selected_scopes = @filters[:statuses].values.filter_map { |status| scopes[status] }
records = selected_scopes.reduce(records.none, :or) if selected_scopes.any?
end
records
end

View file

@ -10,6 +10,7 @@
<projects-list
actions-url="<%= actions_toolbar_projects_path %>"
users-filter-url="<%= users_filter_projects_path %>"
head-of-project-users-list-url="<%= head_of_project_users_list_projects_path %>"
data-source="<%= projects_path(project_folder_id: current_folder&.id, format: :json) %>"
active-page-url="<%= projects_path(project_folder_id: current_folder&.id, view_mode: :active) %>"
archived-page-url="<%= projects_path(project_folder_id: current_folder&.id, view_mode: :archived) %>"

View file

@ -725,6 +725,12 @@ en:
members:
label: "Members"
placeholder: "Select members of a project"
head_of_project:
label: "Head of project"
placeholder: "Select a person"
status:
label: "Status"
placeholder: "Select project status"
folders:
label: "Look inside folders"
popover_html: "When <strong>“Look inside folders”</strong> is active, the filters will also take all folders and their content into account."

View file

@ -398,6 +398,7 @@ Rails.application.routes.draw do
post 'restore_group'
post 'actions_toolbar'
get :user_roles
get :head_of_project_users_list
end
end