Add tag filtering to task table [SCI-12289]

This commit is contained in:
Oleksii Kriuchykhin 2025-09-03 15:42:14 +02:00
parent c5bb0fe8e2
commit c2aee2b4fe
8 changed files with 34 additions and 14 deletions

View file

@ -2,6 +2,11 @@
class TagsController < ApplicationController
def index
@tags = current_team.tags.order(:name)
@tags = if params[:teams].present?
Tag.where(team: current_user.teams.where(id: params[:teams])).order(:name)
else
current_team.tags.order(:name)
end
@tags = @tags.where_attributes_like(['tags.name'], params[:query]) if params[:query].present?
end
end

View file

@ -9,7 +9,7 @@ class TeamsController < ApplicationController
before_action :load_vars, only: %i(sidebar export_projects export_projects_modal
disable_tasks_sharing_modal shared_tasks_toggle)
before_action :load_current_folder, only: :sidebar
before_action :check_read_permissions, except: %i(view_type visible_teams visible_users visible_tags current_team_users)
before_action :check_read_permissions, except: %i(view_type visible_teams visible_users current_team_users)
before_action :check_export_projects_permissions, only: %i(export_projects_modal export_projects)
def visible_teams
@ -26,16 +26,6 @@ class TeamsController < ApplicationController
render json: users, each_serializer: UserSerializer, user: current_user
end
def visible_tags
teams = if params[:teams].present?
current_user.teams.where(id: params[:teams])
else
current_team
end
tags = Tag.where(team: teams)
render json: tags, each_serializer: TagSerializer
end
def current_team_users
users = current_team.users.order(:full_name)
render json: users, each_serializer: UserSerializer, user: current_user

View file

@ -64,6 +64,7 @@
/* global HelperModule */
import axios from '../../packs/custom_axios.js';
import escapeHtml from '../shared/escape_html.js';
import DataTable from '../shared/datatable/table.vue';
import ConfirmationModal from '../shared/confirmation_modal.vue';
import ExperimentDescriptionModal from '../shared/datatable/modals/description.vue';
@ -113,6 +114,7 @@ export default {
canvasUrl: { type: String, required: true },
tagsColors: { type: Array, required: true },
projectTagsUrl: { type: String, required: true },
teamTagsUrl: { type: String, required: true },
assignedUsersUrl: { type: String, required: true },
usersFilterUrl: { type: String, required: true },
statusesList: { type: Array, required: true },
@ -288,6 +290,17 @@ export default {
placeholder: this.i18n.t('experiments.table.filters.status_placeholder')
});
filters.push({
key: 'tags',
type: 'Select',
searchable: true,
optionsUrl: this.teamTagsUrl,
optionRenderer: this.tagsFilterRenderer,
labelRenderer: this.tagsFilterRenderer,
label: this.i18n.t('experiments.table.filters.tags'),
placeholder: this.i18n.t('experiments.table.filters.tags_placeholder')
});
this.columnDefs = columns;
this.filters = filters;
},
@ -426,9 +439,12 @@ export default {
usersFilterRenderer(option) {
return `<div class="flex items-center gap-2">
<img src="${option[2].avatar_url}" class="rounded-full w-6 h-6" />
<span title="${option[1]}" class="truncate">${option[1]}</span>
<span title="${escapeHtml(option[1])}" class="truncate">${escapeHtml(option[1])}</span>
</div>`;
},
tagsFilterRenderer(option) {
return `<div class="sci-tag text-white" style="background-color: ${escapeHtml(option[2])};">${escapeHtml(option[1])}</div>`;
},
updateFavorite(value, params) {
const url = value ? params.data.urls.favorite : params.data.urls.unfavorite;
axios.post(url).then(() => {

View file

@ -10,6 +10,8 @@
:placeholder="filter.placeholder"
:optionRenderer="filter.optionRenderer"
:labelRenderer="filter.labelRenderer"
:tagsView="filter.tagsView"
:searchable="filter.searchable"
@change="change"
> </SelectDropdown>
</div>

View file

@ -158,5 +158,9 @@ module Lists
def statuses_filter(statuses)
@records = @records.where(my_module_status_id: statuses.values)
end
def tags_filter(tags)
@records = @records.joins(:tags).where(tags: { id: tags.values })
end
end
end

View file

@ -19,6 +19,7 @@
project-name="<%= @experiment.project.name %>"
:statuses-list="<%= MyModuleStatus.all.order(:id).map{ |i| [i.id, i.name] }.to_json %>"
project-tags-url=""
team-tags-url="<%= tags_path %>"
canvas-url="<%= view_mode == 'active' ? canvas_experiment_path(@experiment) : module_archive_experiment_path(@experiment) %>"
:archived="<%= @experiment.archived_branch?%>"
/>

View file

@ -8,7 +8,7 @@
unseen-notifications-url="<%= unseen_counter_user_notifications_path %>"
teams-url="<%= visible_teams_teams_path %>"
users-url="<%= visible_users_teams_path %>"
tags-url="<%= visible_tags_teams_path %>"
tags-url="<%= tags_path %>"
logo-url="<%= application_logo_url %>"
/>
</div>

View file

@ -1972,6 +1972,8 @@ en:
due_date: 'Due date'
status: 'Status'
status_placeholder: 'Select task status'
tags: 'Tags'
tags_placeholder: 'Select task tags'
assigned: 'Assigned to'
assigned_placeholder: 'Select a person assigned to a task'
view: