Merge pull request #6198 from artoscinote/ma_SCI_9285

Fix result pagination, fix new step/result buttons [SCI-9285]
This commit is contained in:
Martin Artnik 2023-09-13 10:00:01 +02:00 committed by GitHub
commit c5eb1759b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 64 additions and 67 deletions

View file

@ -23,19 +23,9 @@ class ResultsController < ApplicationController
apply_sort! apply_sort!
apply_filters! apply_filters!
@results = @results.page(params[:page] || 1) @results = @results.page(params.dig(:page, :number) || 1)
render( render json: @results, each_serializer: ResultSerializer, scope: current_user
json: {
results: @results.map do |r|
{
attributes: ResultSerializer.new(r, scope: current_user).as_json
}
end,
next_page: @results.next_page
},
formats: :json
)
end end
format.html do format.html do

View file

@ -26,6 +26,7 @@
<div class="protocol-buttons-group"> <div class="protocol-buttons-group">
<a v-if="urls.add_step_url" <a v-if="urls.add_step_url"
class="btn btn-secondary" class="btn btn-secondary"
:title="i18n.t('protocols.steps.new_step_title')"
@keyup.enter="addStep(steps.length)" @keyup.enter="addStep(steps.length)"
@click="addStep(steps.length)" @click="addStep(steps.length)"
tabindex="0"> tabindex="0">
@ -131,29 +132,39 @@
<div class="border-0 border-b border-dashed border-sn-light-grey" v-if="!inRepository"></div> <div class="border-0 border-b border-dashed border-sn-light-grey" v-if="!inRepository"></div>
<div id="protocol-steps-container" :class=" inRepository ? 'protocol-steps collapse in' : ''"> <div id="protocol-steps-container" :class=" inRepository ? 'protocol-steps collapse in' : ''">
<div class="protocol-steps"> <div class="protocol-steps">
<template v-for="(step, index) in steps"> <div v-for="(step, index) in steps" :key="step.id" class="step-block">
<div class="step-block" :key="step.id"> <div v-if="index > 0 && urls.add_step_url" class="insert-step" @click="addStep(index)">
<div v-if="index > 0 && urls.add_step_url" class="insert-step" @click="addStep(index)"> <i class="sn-icon sn-icon-new-task"></i>
<i class="sn-icon sn-icon-new-task"></i>
</div>
<Step
:step.sync="steps[index]"
@reorder="startStepReorder"
:inRepository="inRepository"
:stepToReload="stepToReload"
@step:delete="updateStepsPosition"
@step:update="updateStep"
@stepUpdated="refreshProtocolStatus"
@step:insert="updateStepsPosition"
@step:elements:loaded="stepToReload = null"
@step:move_element="reloadStep"
@step:attachemnts:loaded="stepToReload = null"
@step:move_attachment="reloadStep"
:reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null"
:assignableMyModuleId="protocol.attributes.assignable_my_module_id"
/>
</div> </div>
</template> <Step
:step.sync="steps[index]"
@reorder="startStepReorder"
:inRepository="inRepository"
:stepToReload="stepToReload"
@step:delete="updateStepsPosition"
@step:update="updateStep"
@stepUpdated="refreshProtocolStatus"
@step:insert="updateStepsPosition"
@step:elements:loaded="stepToReload = null"
@step:move_element="reloadStep"
@step:attachemnts:loaded="stepToReload = null"
@step:move_attachment="reloadStep"
:reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null"
:assignableMyModuleId="protocol.attributes.assignable_my_module_id"
/>
</div>
<div class="insert-step"></div>
<div v-if="steps.length > 0" class="py-5">
<a v-if="urls.add_step_url"
class="btn btn-secondary"
:title="i18n.t('protocols.steps.new_step_title')"
@keyup.enter="addStep(steps.length)"
@click="addStep(steps.length)"
tabindex="0">
<span class="sn-icon sn-icon-new-task" aria-hidden="true"></span>
<span>{{ i18n.t("protocols.steps.new_step") }}</span>
</a>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -26,11 +26,11 @@
<div class="result-head-right flex elements-actions-container"> <div class="result-head-right flex elements-actions-container">
<input type="file" class="hidden" ref="fileSelector" @change="loadFromComputer" multiple /> <input type="file" class="hidden" ref="fileSelector" @change="loadFromComputer" multiple />
<div ref="elementsDropdownButton" v-if="urls.update_url" class="dropdown"> <div ref="elementsDropdownButton" v-if="urls.update_url" class="dropdown">
<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"> <button class="btn btn-light dropdown-toggle insert-button" type="button" :id="'resultInsertMenu_' + result.id" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
{{ i18n.t('my_modules.results.insert.button') }} {{ i18n.t('my_modules.results.insert.button') }}
<span class="sn-icon sn-icon-down"></span> <span class="sn-icon sn-icon-down"></span>
</button> </button>
<ul ref="elementsDropdown" class="dropdown-menu insert-element-dropdown dropdown-menu-right" :aria-labelledby="'resultInsertMenu_' + result.attributes.id"> <ul ref="elementsDropdown" class="dropdown-menu insert-element-dropdown dropdown-menu-right" :aria-labelledby="'resultInsertMenu_' + result.id">
<li class="title"> <li class="title">
{{ i18n.t('my_modules.results.insert.title') }} {{ i18n.t('my_modules.results.insert.title') }}
</li> </li>
@ -67,7 +67,7 @@
<li class="action" v-if="result.attributes.marvinjs_enabled" @click="openMarvinJsModal($refs.marvinJsButton)"> <li class="action" v-if="result.attributes.marvinjs_enabled" @click="openMarvinJsModal($refs.marvinJsButton)">
<span <span
class="new-marvinjs-upload-button text-sn-black text-decoration-none" class="new-marvinjs-upload-button text-sn-black text-decoration-none"
:data-object-id="result.attributes.id" :data-object-id="result.id"
ref="marvinJsButton" ref="marvinJsButton"
:data-marvin-url="result.attributes.marvinjs_context.marvin_js_asset_url" :data-marvin-url="result.attributes.marvinjs_context.marvin_js_asset_url"
:data-object-type="result.attributes.type" :data-object-type="result.attributes.type"
@ -85,14 +85,14 @@
class="open-comments-sidebar btn icon-btn btn-light" class="open-comments-sidebar btn icon-btn btn-light"
data-turbolinks="false" data-turbolinks="false"
data-object-type="Result" data-object-type="Result"
:data-object-id="result.attributes.id"> :data-object-id="result.id">
<i class="sn-icon sn-icon-comments"></i> <i class="sn-icon sn-icon-comments"></i>
</a> </a>
<div v-if="!locked" ref="actionsDropdownButton" class="dropdown"> <div v-if="!locked" ref="actionsDropdownButton" class="dropdown">
<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"> <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">
<i class="sn-icon sn-icon-more-hori"></i> <i class="sn-icon sn-icon-more-hori"></i>
</button> </button>
<ul ref="actionsDropdown" class="dropdown-menu dropdown-menu-right insert-element-dropdown" :aria-labelledby="'resultOptionsMenu_' + result.attributes.id"> <ul ref="actionsDropdown" class="dropdown-menu dropdown-menu-right insert-element-dropdown" :aria-labelledby="'resultOptionsMenu_' + result.id">
<li class="action" @click="openReorderModal" v-if="urls.reorder_elements_url"> <li class="action" @click="openReorderModal" v-if="urls.reorder_elements_url">
{{ i18n.t('my_modules.results.actions.rearrange') }} {{ i18n.t('my_modules.results.actions.rearrange') }}
</li> </li>
@ -201,7 +201,7 @@
}, },
watch: { watch: {
resultToReload() { resultToReload() {
if (this.resultToReload == this.result.attributes.id) { if (this.resultToReload == this.result.id) {
this.loadElements(); this.loadElements();
this.loadAttachments(); this.loadAttachments();
} }
@ -350,17 +350,17 @@
}, },
archiveResult() { archiveResult() {
axios.post(this.urls.archive_url).then((response) => { axios.post(this.urls.archive_url).then((response) => {
this.$emit('result:archived', this.result.attributes.id); this.$emit('result:archived', this.result.id);
}); });
}, },
restoreResult() { restoreResult() {
axios.post(this.urls.restore_url).then((response) => { axios.post(this.urls.restore_url).then((response) => {
this.$emit('result:restored', this.result.attributes.id); this.$emit('result:restored', this.result.id);
}); });
}, },
deleteResult() { deleteResult() {
axios.delete(this.urls.delete_url).then((response) => { axios.delete(this.urls.delete_url).then((response) => {
this.$emit('result:deleted', this.result.attributes.id); this.$emit('result:deleted', this.result.id);
}); });
}, },
duplicateResult() { duplicateResult() {

View file

@ -13,7 +13,7 @@
class="my-4" class="my-4"
/> />
<div class="results-list"> <div class="results-list">
<Result v-for="result in results" :key="result.attributes.id" <Result v-for="result in results" :key="result.id"
:result="result" :result="result"
:resultToReload="resultToReload" :resultToReload="resultToReload"
@result:elements:loaded="resultToReload = null" @result:elements:loaded="resultToReload = null"
@ -26,6 +26,12 @@
@result:restored="removeResult" @result:restored="removeResult"
/> />
</div> </div>
<div v-if="results.length > 0" class="p-3 rounded-md bg-sn-white my-4">
<button v-if="canCreate" :title="i18n.t('my_modules.results.add_title')" class="btn btn-secondary" @click="createResult">
<i class="sn-icon sn-icon-new-task"></i>
{{ i18n.t('my_modules.results.add_label') }}
</button>
</div>
</div> </div>
</template> </template>
@ -50,12 +56,13 @@
sort: 'created_at_desc', sort: 'created_at_desc',
filters: {}, filters: {},
resultToReload: null, resultToReload: null,
nextPage: 1, nextPageUrl: null,
loadingPage: false loadingPage: false
} }
}, },
mounted() { mounted() {
window.addEventListener('scroll', this.loadResults, false); window.addEventListener('scroll', this.loadResults, false);
this.nextPageUrl = this.url;
this.loadResults(); this.loadResults();
}, },
beforeDestroy() { beforeDestroy() {
@ -66,32 +73,20 @@
this.resultToReload = result; this.resultToReload = result;
}, },
resetPageAndReload(){ resetPageAndReload(){
this.nextPage = 1; this.nextPageUrl = this.url;
this.results = []; this.results = [];
this.$nextTick(() => { this.$nextTick(() => {
this.loadResults(); this.loadResults();
}); });
}, },
loadResults() { loadResults() {
if (this.nextPage == null || this.loadingPage) return; if (this.nextPageUrl === null || this.loadingPage) return;
if (window.scrollY + window.innerHeight >= document.body.scrollHeight - 20) { if (window.scrollY + window.innerHeight >= document.body.scrollHeight - 20) {
this.loadingPage = true; this.loadingPage = true;
axios.get( axios.get(this.nextPageUrl, { params: { sort: this.sort, ...this.filters } }).then((response) => {
`${this.url}`, this.results = this.results.concat(response.data.data);
{ this.nextPageUrl = response.data.links.next;
params: {
sort: this.sort,
page: this.nextPage,
...this.filters
},
headers: {
'Accept': 'application/json'
}
},
).then((response) => {
this.results = this.results.concat(response.data.results);
this.nextPage = response.data.next_page;
this.loadingPage = false; this.loadingPage = false;
}); });
} }
@ -114,11 +109,10 @@
} }
).then( ).then(
(response) => { (response) => {
this.results.unshift(response.data.data) this.results = [response.data.data, ...this.results];
window.scrollTo(0, 0);
} }
); );
}, },
expandAll() { expandAll() {
$('.result-wrapper .collapse').collapse('show') $('.result-wrapper .collapse').collapse('show')

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="result-toolbar p-3 flex justify-between rounded-md bg-sn-white"> <div class="result-toolbar p-3 flex justify-between rounded-md bg-sn-white">
<div class="result-toolbar__left"> <div class="result-toolbar__left">
<button v-if="canCreate" class="btn btn-secondary" @click="$emit('newResult')"> <button v-if="canCreate" :title="i18n.t('my_modules.results.add_title')" class="btn btn-secondary" @click="$emit('newResult')">
<i class="sn-icon sn-icon-new-task"></i> <i class="sn-icon sn-icon-new-task"></i>
{{ i18n.t('my_modules.results.add_label') }} {{ i18n.t('my_modules.results.add_label') }}
</button> </button>

View file

@ -1257,6 +1257,7 @@ en:
default_name: "New result" default_name: "New result"
placeholder: "Enter result name" placeholder: "Enter result name"
add_label: "New result" add_label: "New result"
add_title: "Create new result"
new_text_result: "Text" new_text_result: "Text"
new_table_result: "Table" new_table_result: "Table"
new_asset_result: "File" new_asset_result: "File"
@ -3099,6 +3100,7 @@ en:
expand_label: "Expand All" expand_label: "Expand All"
collapse_label: "Collapse All" collapse_label: "Collapse All"
new_step: "New step" new_step: "New step"
new_step_title: "Create new step"
subtitle: "Protocol Steps" subtitle: "Protocol Steps"
no_steps: "Protocol has no steps." no_steps: "Protocol has no steps."
published_on_html: "Published on <em>%{timestamp}</em> by <em>%{user}</em>" published_on_html: "Published on <em>%{timestamp}</em> by <em>%{user}</em>"