Add pagination for current tasks on dashboard

This commit is contained in:
Mojca Lorber 2020-03-02 16:11:14 +01:00 committed by aignatov-bio
parent 73623da02c
commit 52493fd834
5 changed files with 148 additions and 61 deletions

View file

@ -1,4 +1,4 @@
/* global dropdownSelector I18n animateSpinner PerfectSb */
/* global dropdownSelector I18n animateSpinner PerfectSb InfiniteScroll */
/* eslint-disable no-param-reassign */
var DasboardCurrentTasksWidget = (function() {
@ -12,7 +12,58 @@ var DasboardCurrentTasksWidget = (function() {
<i class="fas fa-angle-double-down"></i>
</div>`;
function loadCurrentTasksList() {
function generateTasksListHtml(json, container) {
$.each(json.data, (i, task) => {
var currentTaskItem;
var stepsPercentage = task.steps_state.percentage + '%';
var stateText;
var dueDate = (task.due_date !== null) ? '<i class="fas fa-calendar-day"></i>'
+ I18n.t('dashboard.current_tasks.due_date', { date: task.due_date }) : '';
var overdue = (task.overdue) ? 'overdue' : '';
if (task.state === 'completed') {
stateText = I18n.t('dashboard.current_tasks.progress_bar.completed');
} else {
stateText = I18n.t('dashboard.current_tasks.progress_bar.in_progress');
if (task.overdue) { stateText = I18n.t('dashboard.current_tasks.progress_bar.overdue'); }
if (task.steps_state.all_steps !== 0) {
stateText += I18n.t('dashboard.current_tasks.progress_bar.completed_steps',
{ steps: task.steps_state.completed_steps, total_steps: task.steps_state.all_steps });
}
}
currentTaskItem = `<a class="current-task-item" href="${task.link}">
<div class="current-task-breadcrumbs">${task.project}/${task.experiment}</div>
<div class="item-row">
<div class="task-name">${task.name}</div>
<div class="task-due-date ${overdue}">${dueDate}</div>
<div class="task-progress-container ${task.state} ${overdue}">
<div class="task-progress" style="padding-left: ${stepsPercentage}"></div>
<div class="task-progress-label">${stateText}</div>
</div>
</div>
</a>`;
$(container).append(currentTaskItem);
});
}
function initInfiniteScroll() {
InfiniteScroll.init('.current-tasks-list', {
url: $('.current-tasks-list').data('tasksListUrl'),
customResponse: (json, container) => {
generateTasksListHtml(json, container);
},
customParams: (params) => {
params.project_id = dropdownSelector.getValues(projectFilter);
params.experiment_id = dropdownSelector.getValues(experimentFilter);
params.sort = dropdownSelector.getValues(sortFilter);
params.view = dropdownSelector.getValues(viewFilter);
params.query = $('.current-tasks-widget .task-search-field').val();
params.mode = $('.current-tasks-navbar .active').data('mode');
return params;
}
});
}
function loadCurrentTasksList(newList) {
var $currentTasksList = $('.current-tasks-list');
var params = {
project_id: dropdownSelector.getValues(projectFilter),
@ -24,44 +75,16 @@ var DasboardCurrentTasksWidget = (function() {
animateSpinner($currentTasksList, true);
$.get($currentTasksList.data('tasksListUrl'), params, function(data) {
// Toggle empty state
if (data.tasks_list.length === 0) {
if (data.data.length === 0) {
$currentTasksList.append(emptyState);
} else {
$currentTasksList.find('.no-tasks').remove();
}
// Clear the list
$currentTasksList.find('.current-task-item').remove();
$.each(data.tasks_list, (i, task) => {
var currentTaskItem;
var stepsPercentage = task.steps_state.percentage + '%';
var stateText;
var dueDate = (task.due_date !== null) ? '<i class="fas fa-calendar-day"></i>'
+ I18n.t('dashboard.current_tasks.due_date', { date: task.due_date }) : '';
var overdue = (task.overdue) ? 'overdue' : '';
if (task.state === 'completed') {
stateText = I18n.t('dashboard.current_tasks.progress_bar.completed');
} else {
stateText = I18n.t('dashboard.current_tasks.progress_bar.in_progress');
if (task.overdue) { stateText = I18n.t('dashboard.current_tasks.progress_bar.overdue'); }
if (task.steps_state.all_steps !== 0) {
stateText += I18n.t('dashboard.current_tasks.progress_bar.completed_steps',
{ steps: task.steps_state.completed_steps, total_steps: task.steps_state.all_steps });
}
}
currentTaskItem = `<a class="current-task-item" href="${task.link}">
<div class="current-task-breadcrumbs">${task.project}/${task.experiment}</div>
<div class="item-row">
<div class="task-name">${task.name}</div>
<div class="task-due-date ${overdue}">${dueDate}</div>
<div class="task-progress-container ${task.state} ${overdue}">
<div class="task-progress" style="padding-left: ${stepsPercentage}"></div>
<div class="task-progress-label">${stateText}</div>
</div>
</div>
</a>`;
$currentTasksList.append(currentTaskItem);
});
generateTasksListHtml(data, $currentTasksList);
PerfectSb().update_all();
if (newList) InfiniteScroll.resetScroll('.current-tasks-list');
animateSpinner($currentTasksList, false);
});
}
@ -138,7 +161,7 @@ var DasboardCurrentTasksWidget = (function() {
$('.curent-tasks-filters').dropdown('toggle');
e.stopPropagation();
e.preventDefault();
loadCurrentTasksList();
loadCurrentTasksList(true);
});
}
@ -148,7 +171,7 @@ var DasboardCurrentTasksWidget = (function() {
e.preventDefault();
$('.current-tasks-navbar').find('a').removeClass('active');
$(this).addClass('active');
loadCurrentTasksList();
loadCurrentTasksList(true);
});
}
@ -158,6 +181,7 @@ var DasboardCurrentTasksWidget = (function() {
initNavbar();
initFilters();
loadCurrentTasksList();
initInfiniteScroll();
}
}
};

View file

@ -0,0 +1,68 @@
/* eslint-disable no-unused-vars */
var InfiniteScroll = (function() {
function getScrollHeight($container) {
return $container[0].scrollHeight;
}
function scrollNotVisible($container) {
return (getScrollHeight($container) - $container.height() - 150 <= 0);
}
function loadData($container, page = 1) {
var customParams = $container.data('config').customParams;
var params = (customParams ? customParams({ page: page }) : { page: page });
if ($container.hasClass('loading') || $container.hasClass('last-page')) return;
$container.addClass('loading');
$.get($container.data('config').url, params, function(result) {
if ($container.data('config').customResponse) {
$container.data('config').customResponse(result, $container);
} else {
$(result.data).appendTo($container);
}
if (result.next_page) {
$container.data('next-page', result.next_page);
} else {
$container.addClass('last-page');
}
$container.removeClass('loading');
if (scrollNotVisible($container)) {
loadData($container, $container.data('next-page'));
}
});
}
function initScroll(object, config = {}) {
var $container = $(object);
$container.data('next-page', 2);
$container.data('config', config);
if (config.loadFirstPage) {
loadData($container, 1);
} else if (scrollNotVisible($container)) {
loadData($container, $container.data('next-page'));
}
$container.on('scroll', () => {
if ($container.scrollTop() + $container.height() > getScrollHeight($container) - 150 && !$container.hasClass('last-page')) {
loadData($container, $container.data('next-page'));
}
});
}
return {
init: (object, config) => {
initScroll(object, config);
},
resetScroll: (object) => {
$(object).data('next-page', 2).removeClass('last-page');
if (scrollNotVisible($(object))) {
loadData($(object), $(object).data('next-page'));
}
}
};
}());

View file

@ -34,28 +34,25 @@ module Dashboard
tasks
end
tasks = tasks.with_step_statistics.preload(experiment: :project)
page = (params[:page] || 1).to_i
tasks_per_page = tasks.page(page).per(Constants::INFINITE_SCROLL_LIMIT)
respond_to do |format|
format.json do
render json: {
tasks_list: tasks.map do |task|
{ id: task.id,
link: protocols_my_module_path(task.id),
experiment: escape_input(task.experiment.name),
project: escape_input(task.experiment.project.name),
name: escape_input(task.name),
due_date: task.due_date.present? ? I18n.l(task.due_date, format: :full_with_comma) : nil,
overdue: task.is_overdue?,
state: task.state,
steps_state: { completed_steps: task.steps_completed,
all_steps: task.steps_total,
percentage: task.steps_completed_percentage } }
end,
status: :ok
}
end
tasks_per_page = tasks_per_page.with_step_statistics.preload(experiment: :project)
tasks_list = tasks_per_page.map do |task|
{ id: task.id,
link: protocols_my_module_path(task.id),
experiment: escape_input(task.experiment.name),
project: escape_input(task.experiment.project.name),
name: escape_input(task.name),
due_date: task.due_date.present? ? I18n.l(task.due_date, format: :full_with_comma) : nil,
overdue: task.is_overdue?,
state: task.state,
steps_state: { completed_steps: task.steps_completed,
all_steps: task.steps_total,
percentage: task.steps_completed_percentage } }
end
render json: { data: tasks_list, next_page: tasks_per_page.next_page }
end
def project_filter
@ -83,7 +80,7 @@ module Dashboard
private
def task_filters
params.permit(:project_id, :experiment_id, :mode, :view, :sort)
params.permit(:project_id, :experiment_id, :mode, :view, :sort, :page)
end
def load_project

View file

@ -56,7 +56,7 @@
</div>
<div class="widget-body">
<div class="current-tasks-list perfect-scrollbar"
<div id="current-tasks-list" class="current-tasks-list perfect-scrollbar"
data-tasks-list-url="<%= dashboard_current_tasks_path %>">
</div>
</div>

View file

@ -56,16 +56,14 @@ class Constants
COMMENTS_SEARCH_LIMIT = 10
# Activity limited query/display elements for pages
ACTIVITY_AND_NOTIF_SEARCH_LIMIT = 20
# Infinite Scroll load limit (elements per page)
INFINITE_SCROLL_LIMIT = 20
# Maximum number of users that can be invited in a single action
INVITE_USERS_LIMIT = 20
# Maximum nr. of search results for atwho (smart annotations)
ATWHO_SEARCH_LIMIT = 5
# Max characters for repository name in Atwho modal
ATWHO_REP_NAME_LIMIT = 16
# Number of protocols in recent protocol dropdown
RECENT_PROTOCOL_LIMIT = 14