Add pagination for experiments [SCI-6656]

This commit is contained in:
Anton 2022-04-12 15:03:06 +02:00
parent d96103d714
commit d091c56e9f
10 changed files with 243 additions and 25 deletions

View file

@ -7,7 +7,8 @@
// - refresh project users tab after manage user modal is closed
// - refactor view handling using library, ex. backbone.js
/* global HelperModule dropdownSelector Sidebar Turbolinks filterDropdown InfiniteScroll */
/* global HelperModule dropdownSelector Sidebar Turbolinks filterDropdown InfiniteScroll GLOBAL_CONSTANTS */
/* eslint-disable no-use-before-define */
var ProjectsIndex = (function() {
const PERMISSIONS = ['editable', 'archivable', 'restorable', 'moveable', 'deletable'];
@ -16,7 +17,7 @@ var ProjectsIndex = (function() {
var cardsWrapper = '#cardsWrapper';
var editProjectModal = '#edit-modal';
var moveToModal = '#move-to-modal';
var pageSize = 20;
var pageSize = GLOBAL_CONSTANTS.DEFAULT_ELEMENTS_PER_PAGE;
var exportProjectsModal = null;
var exportProjectsModalHeader = null;

View file

@ -1,6 +1,8 @@
/* global animateSpinner filterDropdown Sidebar Turbolinks HelperModule */
/* global animateSpinner filterDropdown Sidebar Turbolinks HelperModule InfiniteScroll GLOBAL_CONSTANTS */
/* eslint-disable no-use-before-define */
(function() {
const PERMISSIONS = ['editable', 'archivable', 'restorable', 'moveable', 'duplicable'];
const pageSize = GLOBAL_CONSTANTS.DEFAULT_ELEMENTS_PER_PAGE;
var cardsWrapper = '#cardsWrapper';
var experimentsPage = '#projectShowWrapper';
@ -67,23 +69,35 @@
});
}
function loadPlaceHolder() {
let palceholder = '';
$.each(Array(pageSize), function() {
palceholder += $('#experimentPlaceholder').html();
});
$(palceholder).insertAfter($(cardsWrapper).find('.table-header'));
}
function loadCardsView() {
var requestParams = {
view_mode: $(experimentsPage).data('view-mode'),
sort: experimentsCurrentSort,
search: experimentsViewSearch,
created_on_from: startedOnFromFilter,
created_on_to: startedOnToFilter,
updated_on_from: modifiedOnFromFilter,
updated_on_to: modifiedOnToFilter,
archived_on_from: archivedOnFromFilter,
archived_on_to: archivedOnToFilter
};
var viewContainer = $(cardsWrapper);
var cardsUrl = viewContainer.data('experiments-cards-url');
loadPlaceHolder();
$.ajax({
url: viewContainer.data('experiments-cards-url'),
url: cardsUrl,
type: 'GET',
dataType: 'json',
data: {
view_mode: $(experimentsPage).data('view-mode'),
sort: experimentsCurrentSort,
search: experimentsViewSearch,
created_on_from: startedOnFromFilter,
created_on_to: startedOnToFilter,
updated_on_from: modifiedOnFromFilter,
updated_on_to: modifiedOnToFilter,
archived_on_from: archivedOnFromFilter,
archived_on_to: archivedOnToFilter
},
data: requestParams,
success: function(data) {
viewContainer.find('.card, .no-results-container').remove();
viewContainer.removeClass('no-results');
@ -94,6 +108,20 @@
selectedExperiments.length = 0;
updateExperimentsToolbar();
loadExperimentWorkflowImages();
InfiniteScroll.init(cardsWrapper, {
url: cardsUrl,
eventTarget: window,
placeholderTemplate: '#experimentPlaceholder',
endOfListTemplate: '#experimentEndOfList',
pageSize: pageSize,
customResponse: (response) => {
$(response.cards_html).appendTo(cardsWrapper);
},
customParams: (params) => {
return { ...params, ...requestParams };
}
});
},
error: function() {
viewContainer.html('Error loading project list');

View file

@ -9,5 +9,6 @@ const GLOBAL_CONSTANTS = {
REPOSITORY_LIST_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN %>,
REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN %>,
REPOSITORY_STOCK_UNIT_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_STOCK_UNIT_ITEMS_PER_COLUMN %>,
HAS_UNSAVED_DATA_CLASS_NAME: 'has-unsaved-data'
HAS_UNSAVED_DATA_CLASS_NAME: 'has-unsaved-data',
DEFAULT_ELEMENTS_PER_PAGE: <%= Constants::DEFAULT_ELEMENTS_PER_PAGE %>
};

View file

@ -1,10 +1,7 @@
/* eslint-disable no-use-before-define */
/* eslint-disable no-unused-vars */
var InfiniteScroll = (function() {
function getScrollHeight($container) {
return $container[0].scrollHeight;
}
function scrollNotVisible($container) {
let eventTarget = $($container.data('config').eventTarget || $container);
return scrollHitBottom(eventTarget[0]);

View file

@ -173,6 +173,78 @@
}
}
}
&.experiment-placeholder {
align-items: center;
background-color: $color-white;
border-radius: $border-radius-default;
box-shadow: $flyout-shadow;
display: flex;
.placeholder-body {
display: flex;
flex-basis: 70%;
flex-wrap: wrap;
height: 80px;
}
.image-container {
margin-left: auto;
.image-text {
display: none;
}
}
.placeholder-element {
animation-duration: 2s;
animation-iteration-count: infinite;
animation-name: placeholder-pulsing;
background-color: $color-alto;
border-radius: $border-radius-default;
height: 18px;
&.header,
&.footer {
flex-basis: 100%;
}
&.footer {
height: 36px;
}
&.line-0 {
flex-basis: 100%;
}
&.line-1 {
flex-basis: 90%;
}
&.line-2 {
flex-basis: 80%;
}
&.image {
height: 80px;
width: 80px;
}
@keyframes placeholder-pulsing {
0% {
opacity: 1;
}
50% {
opacity: .5;
}
100% {
opacity: 1;
}
}
}
}
}
&.list {
@ -281,6 +353,72 @@
background: linear-gradient(to right, $color-transparent, $color-concrete 50%);
}
}
&.experiment-placeholder {
display: contents;
.placeholder-body {
display: contents;
}
.placeholder-element {
align-self: flex-start;
display: none;
margin-top: .5em;
padding: .5em 0;
}
.footer {
display: block;
grid-column: 6;
height: 18px;
width: 80%;
}
.header {
display: block;
grid-column: 7;
width: 80%;
}
.image-container {
display: flex;
grid-column: 2;
margin-left: 0;
.image {
display: block;
flex-basis: 56px;
height: 56px;
margin: 0;
}
.image-text {
display: block;
flex-basis: calc(100% - 80px);
margin: 0 10px 0 auto;
}
}
.line-0 {
display: block;
grid-column: 3;
width: 80%;
}
.line-1 {
display: block;
grid-column: 4;
width: 80%;
}
.line-2 {
display: block;
grid-column: 5;
width: 80%;
}
}
}
}
@ -289,6 +427,29 @@
margin-left: 0 !important;
}
}
&.last-page {
padding-bottom: 5em;
position: relative;
}
.experiment-list-end-placeholder {
align-items: center;
background-color: $color-concrete;
bottom: 1em;
display: flex;
height: 3em;
left: calc(50% - 150px);
margin: 0 auto;
padding: 1em;
position: absolute;
width: 300px;
> * {
flex-grow: 1;
text-align: center;
}
}
}
}

View file

@ -624,8 +624,8 @@ li.module-hover {
--list-columns-number: 6;
&.last-page {
position: relative;
padding-bottom: 5em;
position: relative;
}
.projects-group {
@ -798,9 +798,9 @@ li.module-hover {
display: flex;
.placeholder-element {
animation-name: placeholder-pulsing;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-name: placeholder-pulsing;
background-color: $color-alto;
border-radius: $border-radius-default;
height: 18px;
@ -832,9 +832,11 @@ li.module-hover {
0% {
opacity: 1;
}
50% {
opacity: .5;
}
100% {
opacity: 1;
}

View file

@ -65,7 +65,7 @@ class ProjectsController < ApplicationController
end
cards = Kaminari.paginate_array(overview_service.project_and_folder_cards)
.page(params[:page] || 1).per(20)
.page(params[:page] || 1).per(Constants::DEFAULT_ELEMENTS_PER_PAGE)
render json: {
projects_cards_url: projects_cards_url,
@ -292,10 +292,12 @@ class ProjectsController < ApplicationController
def experiments_cards
overview_service = ExperimentsOverviewService.new(@project, current_user, params)
cards = overview_service.experiments.page(params[:page] || 1).per(Constants::DEFAULT_ELEMENTS_PER_PAGE)
render json: {
next_page: cards.next_page,
cards_html: render_to_string(
partial: 'projects/show/experiments_list.html.erb',
locals: { cards: overview_service.experiments,
locals: { cards: cards,
filters_included: filters_included? }
)
}

View file

@ -45,7 +45,7 @@ class ExperimentsOverviewService
.select('experiments.*')
.select('COUNT(DISTINCT active_tasks.id) AS task_count')
.select('COUNT(DISTINCT active_completed_tasks.id) AS completed_task_count')
.group('experiments.id, user_assignments.id, user_roles.id')
.group('experiments.id')
end
def filter_records(records)

View file

@ -37,5 +37,29 @@
</div>
</div>
<template id="experimentPlaceholder">
<div class="experiment-placeholder card">
<div class="placeholder-element header"></div>
<div class="placeholder-body">
<% 3.times do |i| %>
<div class="placeholder-element line-<%= i %>"></div>
<% end %>
</div>
<div class="placeholder image-container">
<div class="placeholder-element image"></div>
<div class="placeholder-element image-text"></div>
</div>
<div class="placeholder-element footer"></div>
</div>
</template>
<template id="experimentEndOfList">
<div class="experiment-list-end-placeholder">
<i class="fas fa-flag-checkered"></i>
<span><%= t('projects.index.end_of_list_placeholder') %></span>
<i class="fas fa-flag-checkered"></i>
</div>
</template>
<%= javascript_include_tag("projects/show") %>
<i data-hook="project-show-js"></i>

View file

@ -71,6 +71,8 @@ class Constants
RESULTS_PER_PAGE_LIMIT = 10
#Experiments more button appears
EXPERIMENT_LONG_DESCRIPTION = 80
# Infinite scroll default elements per page
DEFAULT_ELEMENTS_PER_PAGE = 20
#=============================================================================
# File and data memory size