Add infinite scroll to results [SCI-9108]

This commit is contained in:
Anton 2023-08-30 15:47:54 +02:00
parent f5235a9b9d
commit 2d76e628be
4 changed files with 61 additions and 25 deletions

View file

@ -16,8 +16,17 @@ class ResultsController < ApplicationController
apply_sort!
apply_filters!
@results = @results.page(params[:page] || 1)
render(
json: @results,
json: {
results: @results.map do |r|
{
attributes: ResultSerializer.new(r, scope: current_user).as_json
}
end,
next_page: @results.next_page
},
formats: :json
)
end

View file

@ -20,11 +20,11 @@
<div class="result-head-right flex">
<input type="file" class="hidden" ref="fileSelector" @change="loadFromComputer" multiple />
<div ref="elementsDropdownButton" v-if="urls.update_url" class="dropdown">
<button class="btn btn-light dropdown-toggle insert-button" type="button" :id="'resultInsertMenu_' + result.id" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<button class="btn btn-light dropdown-toggle insert-button" type="button" :id="'resultInsertMenu_' + result.attributes.id" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
{{ i18n.t('protocols.steps.insert.button') }}
<span class="sn-icon sn-icon-down"></span>
</button>
<ul ref="elementsDropdown" class="dropdown-menu insert-element-dropdown dropdown-menu-right" :aria-labelledby="'resultInsertMenu_' + result.id">
<ul ref="elementsDropdown" class="dropdown-menu insert-element-dropdown dropdown-menu-right" :aria-labelledby="'resultInsertMenu_' + result.attributes.id">
<li class="title">
<a>
{{ i18n.t('protocols.steps.insert.title') }}
@ -78,7 +78,7 @@
<a class="cursor-point er">
<span
class="new-marvinjs-upload-button text-sn-black text-decoration-none"
:data-object-id="result.id"
:data-object-id="result.attributes.id"
ref="marvinJsButton"
:data-marvin-url="result.attributes.marvinjs_context.marvin_js_asset_url"
:data-object-type="result.attributes.type"
@ -97,14 +97,14 @@
class="open-comments-sidebar btn icon-btn btn-light"
data-turbolinks="false"
data-object-type="Result"
:data-object-id="result.id">
:data-object-id="result.attributes.id">
<i class="sn-icon sn-icon-comments"></i>
</a>
<div ref="actionsDropdownButton" class="dropdown">
<button class="btn btn-light icon-btn dropdown-toggle insert-button" type="button" :id="'resultOptionsMenu_' + result.id" data-toggle="dropdown" data-display="static" aria-haspopup="true" aria-expanded="true">
<button class="btn btn-light icon-btn dropdown-toggle insert-button" type="button" :id="'resultOptionsMenu_' + result.attributes.id" data-toggle="dropdown" data-display="static" aria-haspopup="true" aria-expanded="true">
<i class="sn-icon sn-icon-more-hori"></i>
</button>
<ul ref="actionsDropdown" class="dropdown-menu dropdown-menu-right insert-element-dropdown" :aria-labelledby="'resultOptionsMenu_' + result.id">
<ul ref="actionsDropdown" class="dropdown-menu dropdown-menu-right insert-element-dropdown" :aria-labelledby="'resultOptionsMenu_' + result.attributes.id">
<li class="action" @click="openReorderModal">
<a class="cursor-pointer">{{ i18n.t('my_modules.results.actions.rearrange') }}</a>
</li>
@ -202,7 +202,7 @@
},
watch: {
resultToReload() {
if (this.resultToReload == this.result.id) {
if (this.resultToReload == this.result.attributes.id) {
this.loadElements();
}
}

View file

@ -9,12 +9,12 @@
class="mb-3"
/>
<div class="results-list">
<Result v-for="result in results" :key="result.id"
<Result v-for="result in results" :key="result.attributes.id"
:result="result"
:resultToReload="resultToReload"
@result:elements:loaded="resultToReload = null"
@result:move_element="reloadResult"
@duplicated="loadResults"
@duplicated="resetPageAndReload"
/>
</div>
</div>
@ -36,37 +36,60 @@
results: [],
sort: 'created_at_desc',
filters: {},
resultToReload: null
resultToReload: null,
nextPage: 1,
loadingPage: false
}
},
created() {
mounted() {
window.addEventListener('scroll', this.loadResults, false);
this.loadResults();
},
beforeDestroy() {
window.removeEventListener('scroll', this.loadResults, false);
},
methods: {
reloadResult(result) {
this.resultToReload = result;
},
resetPageAndReload(){
this.nextPage = 1;
this.results = [];
this.$nextTick(() => {
this.loadResults();
});
},
loadResults() {
axios.get(
`${this.url}`,
{
params: {
sort: this.sort,
...this.filters
if (this.nextPage == null || this.loadingPage) return;
if (window.scrollY + window.innerHeight >= document.body.scrollHeight - 20) {
this.loadingPage = true;
axios.get(
`${this.url}`,
{
params: {
sort: this.sort,
page: this.nextPage,
...this.filters
},
headers: {
'Accept': 'application/json'
}
},
headers: {
'Accept': 'application/json'
}
},
).then((response) => this.results = response.data.data);
).then((response) => {
this.results = this.results.concat(response.data.results);
this.nextPage = response.data.next_page;
this.loadingPage = false;
});
}
},
setSort(sort) {
this.sort = sort;
this.loadResults();
this.resetPageAndReload();
},
setFilters(filters) {
this.filters = filters;
this.loadResults();
this.resetPageAndReload();
},
createResult() {
axios.post(

View file

@ -19,6 +19,10 @@ class ResultSerializer < ActiveModel::Serializer
'Result'
end
def current_user
scope
end
def marvinjs_context
if marvinjs_enabled
{