diff --git a/app/assets/javascripts/my_modules/repositories.js b/app/assets/javascripts/my_modules/repositories.js index 8d10fb7e3..64c1fde4d 100644 --- a/app/assets/javascripts/my_modules/repositories.js +++ b/app/assets/javascripts/my_modules/repositories.js @@ -1,6 +1,5 @@ /* eslint-disable no-param-reassign, no-use-before-define */ -/* global DataTableHelpers PerfectScrollbar FilePreviewModal animateSpinner HelperModule */ - +/* global DataTableHelpers PerfectScrollbar FilePreviewModal animateSpinner HelperModule initAssignedTasksDropdown */ var MyModuleRepositories = (function() { const FULL_VIEW_MODAL = $('#myModuleRepositoryFullViewModal'); @@ -59,7 +58,10 @@ var MyModuleRepositories = (function() { targets: 1, searchable: false, className: 'assigned-column', - sWidth: '1%' + sWidth: '1%', + render: function(data) { + return $.fn.dataTable.render.AssignedTasksValue(data); + } }, { targets: 3, render: function(data, type, row) { @@ -158,6 +160,7 @@ var MyModuleRepositories = (function() { } else { $('.table-container .toolbar').html($('#repositoryToolbarButtonsTemplate').html()); } + initAssignedTasksDropdown(tableContainer); }, drawCallback: function() { diff --git a/app/assets/javascripts/repositories/renderers/view_renderers.js b/app/assets/javascripts/repositories/renderers/view_renderers.js index ac0b9bf4f..9ed919d25 100644 --- a/app/assets/javascripts/repositories/renderers/view_renderers.js +++ b/app/assets/javascripts/repositories/renderers/view_renderers.js @@ -154,3 +154,26 @@ $.fn.dataTable.render.RepositoryNumberValue = function(data) { ${data.value} `; }; + +$.fn.dataTable.render.AssignedTasksValue = function(data) { + if (data.tasks > 0) { + let tooltip = I18n.t('repositories.table.assigned_tooltip', { + tasks: data.tasks, + experiments: data.experiments, + projects: data.projects + }); + return ``; + } + return "
0
"; +}; diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 3f0aa3f45..2752c903f 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -1,6 +1,7 @@ /* globals I18n _ SmartAnnotation FilePreviewModal animateSpinner Promise DataTableHelpers HelperModule animateLoading hideAssignUnasignModal RepositoryDatatableRowEditor + initAssignedTasksDropdown */ //= require jquery-ui/widgets/sortable @@ -442,7 +443,7 @@ var RepositoryDatatable = (function(global) { className: 'assigned-column', sWidth: '1%', render: function(data, type, row) { - let content = data; + let content = $.fn.dataTable.render.AssignedTasksValue(data); let icon; if (!row.recordEditable) { icon = ``; @@ -582,6 +583,8 @@ var RepositoryDatatable = (function(global) { $(TABLE_ID).find('tr[data-editable=false]').each(function(_, e) { rowsLocked.push(parseInt($(e).attr('id'), 10)); }); + + initAssignedTasksDropdown(TABLE_ID); } }); diff --git a/app/assets/javascripts/sitewide/repository_helper.js b/app/assets/javascripts/sitewide/repository_helper.js index 436f92264..60059dbd4 100644 --- a/app/assets/javascripts/sitewide/repository_helper.js +++ b/app/assets/javascripts/sitewide/repository_helper.js @@ -18,3 +18,28 @@ initUnsavedWorkDialog(); }()); + +function initAssignedTasksDropdown(table) { + function loadTasks(counterContainer) { + var tasksContainer = counterContainer.find('.tasks'); + var tasksUrl = counterContainer.data('task-list-url'); + var searchQuery = counterContainer.find('.search-tasks').val(); + $.get(tasksUrl, { query: searchQuery }, function(result) { + tasksContainer.html(result.html); + }); + } + + $(table).on('show.bs.dropdown', '.assign-counter-container', function() { + var cell = $(this); + loadTasks(cell); + }); + + $(table).on('click', '.assign-counter-container .dropdown-menu', function(e) { + e.stopPropagation(); + }); + + $(table).on('change', '.assign-counter-container .search-tasks', function() { + var cell = $(this).closest('.assign-counter-container'); + loadTasks(cell); + }); +} diff --git a/app/assets/stylesheets/my_modules/repositories.scss b/app/assets/stylesheets/my_modules/repositories.scss index 5c086dc83..d70a26e71 100644 --- a/app/assets/stylesheets/my_modules/repositories.scss +++ b/app/assets/stylesheets/my_modules/repositories.scss @@ -267,6 +267,10 @@ width: calc(100% - 16px); .assign-counter { + display: inline-block; + height: 100%; + width: 100%; + &.has-assigned { color: $brand-primary; } @@ -275,6 +279,11 @@ &:hover { background-color: $color-alto; } + + .dropdown-menu { + min-width: 320px; + padding: 8px; + } } } } diff --git a/app/assets/stylesheets/repository/repository_table.scss b/app/assets/stylesheets/repository/repository_table.scss index 70ec10044..512c8fdde 100644 --- a/app/assets/stylesheets/repository/repository_table.scss +++ b/app/assets/stylesheets/repository/repository_table.scss @@ -41,7 +41,6 @@ .assign-counter-container { border-radius: $border-radius-tag; - cursor: pointer; display: inline-block; line-height: 35px; position: absolute; @@ -49,7 +48,16 @@ width: calc(100% - 40px); .assign-counter { - margin-left: 5px; + display: inline-block; + height: 100%; + padding-left: 5px; + width: 100%; + + &:hover, + &:visited, + &:focus { + text-decoration: none; + } &.has-assigned { color: $brand-primary; @@ -59,6 +67,11 @@ &:hover { background-color: $color-alto; } + + .dropdown-menu { + min-width: 320px; + padding: 8px; + } } .circle-icon { diff --git a/app/assets/stylesheets/shared/my_modules_list_partial.scss b/app/assets/stylesheets/shared/my_modules_list_partial.scss index cf3be7bb5..e42834c12 100644 --- a/app/assets/stylesheets/shared/my_modules_list_partial.scss +++ b/app/assets/stylesheets/shared/my_modules_list_partial.scss @@ -56,4 +56,14 @@ } } } + + .archived { + @include font-small; + background: $brand-warning; + border-radius: $border-radius-tag; + color: $color-white; + line-height: 14px; + margin-right: 3px; + padding: 2px 3px; + } } diff --git a/app/controllers/dashboard/calendars_controller.rb b/app/controllers/dashboard/calendars_controller.rb index 65afdd28d..5f098cfdf 100644 --- a/app/controllers/dashboard/calendars_controller.rb +++ b/app/controllers/dashboard/calendars_controller.rb @@ -3,6 +3,7 @@ module Dashboard class CalendarsController < ApplicationController include IconsHelper + include MyModulesHelper def show date = DateTime.parse(params[:date]) @@ -26,9 +27,10 @@ module Dashboard .where(projects: { archived: false }) .where('DATE(my_modules.due_date) = DATE(?)', date) .where(projects: { team_id: current_team.id }) - .my_modules_list_partial render json: { - html: render_to_string(partial: 'shared/my_modules_list_partial.html.erb', locals: { task_groups: my_modules }) + html: render_to_string(partial: 'shared/my_modules_list_partial.html.erb', locals: { + my_modules: my_modules + }) } end end diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index f13fd2990..79f9ad8c4 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -2,8 +2,9 @@ class RepositoryRowsController < ApplicationController include InputSanitizeHelper include ActionView::Helpers::TextHelper include ApplicationHelper + include MyModulesHelper - before_action :load_info_modal_vars, only: :show + before_action :load_info_modal_vars, only: %i(show assigned_task_list) before_action :load_vars, only: %i(edit update) before_action :load_repository, only: %i(create @@ -180,6 +181,16 @@ class RepositoryRowsController < ApplicationController end end + def assigned_task_list + my_modules = @repository_row.my_modules.joins(experiment: :project) + .search_by_name(current_user, current_team, params[:query]) + render json: { + html: render_to_string(partial: 'shared/my_modules_list_partial.html.erb', locals: { + my_modules: my_modules + }) + } + end + private include StringUtility diff --git a/app/helpers/my_modules_helper.rb b/app/helpers/my_modules_helper.rb index bb31c0e8a..9e6c1d420 100644 --- a/app/helpers/my_modules_helper.rb +++ b/app/helpers/my_modules_helper.rb @@ -55,4 +55,22 @@ module MyModulesHelper def is_results_page? action_name == 'results' end + + def grouped_by_prj_exp(my_modules) + ungrouped_tasks = my_modules.joins(experiment: :project) + .select('experiments.name as experiment_name, + experiments.archived as experiment_archived, + projects.name as project_name, + projects.archived as project_archived, + my_modules.*') + ungrouped_tasks.group_by { |i| [i[:project_name], i[:experiment_name]] }.map do |group, tasks| + { + project_name: group[0], + project_archived: tasks[0]&.project_archived, + experiment_name: group[1], + experiment_archived: tasks[0]&.experiment_archived, + tasks: tasks + } + end + end end diff --git a/app/helpers/repository_datatable_helper.rb b/app/helpers/repository_datatable_helper.rb index e082b9aff..b27dfd8ba 100644 --- a/app/helpers/repository_datatable_helper.rb +++ b/app/helpers/repository_datatable_helper.rb @@ -67,17 +67,12 @@ module RepositoryDatatableHelper end def assigned_row(record) - if record.assigned_my_modules_count.positive? - tooltip = t('repositories.table.assigned_tooltip', - tasks: record.assigned_my_modules_count, + { + tasks: record.assigned_my_modules_count, experiments: record.assigned_experiments_count, - projects: record.assigned_projects_count) - - "
"\ - "#{record.assigned_my_modules_count}
" - else - "
0
" - end + projects: record.assigned_projects_count, + task_list_url: assigned_task_list_repository_repository_row_path(record.repository, record) + } end def can_perform_repository_actions(repository) diff --git a/app/models/my_module.rb b/app/models/my_module.rb index b70441a95..86503139b 100644 --- a/app/models/my_module.rb +++ b/app/models/my_module.rb @@ -523,21 +523,6 @@ class MyModule < ApplicationRecord self.completed_on = nil end - def self.my_modules_list_partial - ungrouped_tasks = joins(experiment: :project) - .select('experiments.name as experiment_name, - projects.name as project_name, - my_modules.name as task_name, - my_modules.id') - ungrouped_tasks.group_by { |i| [i[:project_name], i[:experiment_name]] }.map do |group, tasks| - { - project_name: group[0], - experiment_name: group[1], - tasks: tasks.map { |task| { id: task.id, task_name: task.task_name } } - } - end - end - def assign_user(user, assigned_by = nil) user_my_modules.create( assigned_by: assigned_by || user, diff --git a/app/views/shared/_my_modules_list_partial.html.erb b/app/views/shared/_my_modules_list_partial.html.erb index 94f3ca145..d35776e66 100644 --- a/app/views/shared/_my_modules_list_partial.html.erb +++ b/app/views/shared/_my_modules_list_partial.html.erb @@ -1,16 +1,29 @@
- <% task_groups.each do |task_group| %> + <% grouped_by_prj_exp(my_modules).each do |task_group| %>
+ <% if task_group[:project_archived]%> + <%= t('general.archived') %> + <% end %> <%= task_group[:project_name] %> / + <% if task_group[:experiment_archived] %> + <%= t('general.archived') %> + <% end %> <%= task_group[:experiment_name] %>
<% task_group[:tasks].each do |task| %>
<%= draw_custom_icon('task-icon') %> - <%= link_to(task[:task_name], protocols_my_module_path(task[:id]), {class: "task-link", title: task[:task_name]}) %> + <% if task.archived %> + <%= t('general.archived') %> + <% end %> + <% if can_read_experiment?(current_user, task.experiment) %> + <%= link_to(task.name, protocols_my_module_path(task.id), {class: "task-link", title: task.name, target: "_blank"}) %> + <% else %> + <%= task.name %> + <% end %>
<% end %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 673848449..d602e7882 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1100,6 +1100,7 @@ en: table: id: 'ID' assigned: "Assigned" + assigned_search: 'Search...' assigned_tooltip: "%{tasks} tasks in %{experiments} experiments, %{projects} projects" row_name: "Name" added_on: "Added on" @@ -2202,6 +2203,7 @@ en: more_comments: "More comments" comment_placeholder: "Your Message" comment_placeholder_new: "Add new comment…" + archived: "Archived" sort: new_html: "Newest first ↓" old_html: "Oldest first ↑" diff --git a/config/routes.rb b/config/routes.rb index 6948417ea..4287683b2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -633,7 +633,11 @@ Rails.application.routes.draw do defaults: { format: 'json' } resources :repository_columns, only: %i(create edit update destroy) - resources :repository_rows, only: %i(create edit update) + resources :repository_rows, only: %i(create edit update) do + member do + get :assigned_task_list + end + end member do post 'parse_sheet', defaults: { format: 'json' } post 'import_records' diff --git a/spec/support/api/schemas/repository_row_datatables.json b/spec/support/api/schemas/repository_row_datatables.json index 5c209e998..4e136a4ef 100644 --- a/spec/support/api/schemas/repository_row_datatables.json +++ b/spec/support/api/schemas/repository_row_datatables.json @@ -11,7 +11,7 @@ "required": ["DT_RowId", "1", "2", "3", "4", "5", "recordEditUrl", "recordUpdateUrl", "recordInfoUrl"], "properties": { "DT_RowId": { "type": "integer" }, - "1": { "type": "string" }, + "1": { "type": "object" }, "2": { "type": "integer" }, "3": { "type": "string" }, "4": { "type": "string" },