mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-25 13:37:12 +08:00
Merge pull request #6198 from artoscinote/ma_SCI_9285
Fix result pagination, fix new step/result buttons [SCI-9285]
This commit is contained in:
commit
c5eb1759b6
6 changed files with 64 additions and 67 deletions
|
|
@ -23,19 +23,9 @@ class ResultsController < ApplicationController
|
|||
apply_sort!
|
||||
apply_filters!
|
||||
|
||||
@results = @results.page(params[:page] || 1)
|
||||
@results = @results.page(params.dig(:page, :number) || 1)
|
||||
|
||||
render(
|
||||
json: {
|
||||
results: @results.map do |r|
|
||||
{
|
||||
attributes: ResultSerializer.new(r, scope: current_user).as_json
|
||||
}
|
||||
end,
|
||||
next_page: @results.next_page
|
||||
},
|
||||
formats: :json
|
||||
)
|
||||
render json: @results, each_serializer: ResultSerializer, scope: current_user
|
||||
end
|
||||
|
||||
format.html do
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
<div class="protocol-buttons-group">
|
||||
<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">
|
||||
|
|
@ -131,29 +132,39 @@
|
|||
<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 class="protocol-steps">
|
||||
<template v-for="(step, index) in steps">
|
||||
<div class="step-block" :key="step.id">
|
||||
<div v-if="index > 0 && urls.add_step_url" class="insert-step" @click="addStep(index)">
|
||||
<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 v-for="(step, index) in steps" :key="step.id" class="step-block">
|
||||
<div v-if="index > 0 && urls.add_step_url" class="insert-step" @click="addStep(index)">
|
||||
<i class="sn-icon sn-icon-new-task"></i>
|
||||
</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>
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@
|
|||
<div class="result-head-right flex elements-actions-container">
|
||||
<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.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') }}
|
||||
<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.attributes.id">
|
||||
<ul ref="elementsDropdown" class="dropdown-menu insert-element-dropdown dropdown-menu-right" :aria-labelledby="'resultInsertMenu_' + result.id">
|
||||
<li class="title">
|
||||
{{ i18n.t('my_modules.results.insert.title') }}
|
||||
</li>
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
<li class="action" v-if="result.attributes.marvinjs_enabled" @click="openMarvinJsModal($refs.marvinJsButton)">
|
||||
<span
|
||||
class="new-marvinjs-upload-button text-sn-black text-decoration-none"
|
||||
:data-object-id="result.attributes.id"
|
||||
:data-object-id="result.id"
|
||||
ref="marvinJsButton"
|
||||
:data-marvin-url="result.attributes.marvinjs_context.marvin_js_asset_url"
|
||||
:data-object-type="result.attributes.type"
|
||||
|
|
@ -85,14 +85,14 @@
|
|||
class="open-comments-sidebar btn icon-btn btn-light"
|
||||
data-turbolinks="false"
|
||||
data-object-type="Result"
|
||||
:data-object-id="result.attributes.id">
|
||||
:data-object-id="result.id">
|
||||
<i class="sn-icon sn-icon-comments"></i>
|
||||
</a>
|
||||
<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>
|
||||
</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">
|
||||
{{ i18n.t('my_modules.results.actions.rearrange') }}
|
||||
</li>
|
||||
|
|
@ -201,7 +201,7 @@
|
|||
},
|
||||
watch: {
|
||||
resultToReload() {
|
||||
if (this.resultToReload == this.result.attributes.id) {
|
||||
if (this.resultToReload == this.result.id) {
|
||||
this.loadElements();
|
||||
this.loadAttachments();
|
||||
}
|
||||
|
|
@ -350,17 +350,17 @@
|
|||
},
|
||||
archiveResult() {
|
||||
axios.post(this.urls.archive_url).then((response) => {
|
||||
this.$emit('result:archived', this.result.attributes.id);
|
||||
this.$emit('result:archived', this.result.id);
|
||||
});
|
||||
},
|
||||
restoreResult() {
|
||||
axios.post(this.urls.restore_url).then((response) => {
|
||||
this.$emit('result:restored', this.result.attributes.id);
|
||||
this.$emit('result:restored', this.result.id);
|
||||
});
|
||||
},
|
||||
deleteResult() {
|
||||
axios.delete(this.urls.delete_url).then((response) => {
|
||||
this.$emit('result:deleted', this.result.attributes.id);
|
||||
this.$emit('result:deleted', this.result.id);
|
||||
});
|
||||
},
|
||||
duplicateResult() {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
class="my-4"
|
||||
/>
|
||||
<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"
|
||||
:resultToReload="resultToReload"
|
||||
@result:elements:loaded="resultToReload = null"
|
||||
|
|
@ -26,6 +26,12 @@
|
|||
@result:restored="removeResult"
|
||||
/>
|
||||
</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>
|
||||
</template>
|
||||
|
||||
|
|
@ -50,12 +56,13 @@
|
|||
sort: 'created_at_desc',
|
||||
filters: {},
|
||||
resultToReload: null,
|
||||
nextPage: 1,
|
||||
nextPageUrl: null,
|
||||
loadingPage: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('scroll', this.loadResults, false);
|
||||
this.nextPageUrl = this.url;
|
||||
this.loadResults();
|
||||
},
|
||||
beforeDestroy() {
|
||||
|
|
@ -66,32 +73,20 @@
|
|||
this.resultToReload = result;
|
||||
},
|
||||
resetPageAndReload(){
|
||||
this.nextPage = 1;
|
||||
this.nextPageUrl = this.url;
|
||||
this.results = [];
|
||||
this.$nextTick(() => {
|
||||
this.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) {
|
||||
this.loadingPage = true;
|
||||
axios.get(
|
||||
`${this.url}`,
|
||||
{
|
||||
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;
|
||||
axios.get(this.nextPageUrl, { params: { sort: this.sort, ...this.filters } }).then((response) => {
|
||||
this.results = this.results.concat(response.data.data);
|
||||
this.nextPageUrl = response.data.links.next;
|
||||
this.loadingPage = false;
|
||||
});
|
||||
}
|
||||
|
|
@ -114,11 +109,10 @@
|
|||
}
|
||||
).then(
|
||||
(response) => {
|
||||
this.results.unshift(response.data.data)
|
||||
this.results = [response.data.data, ...this.results];
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
},
|
||||
expandAll() {
|
||||
$('.result-wrapper .collapse').collapse('show')
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="result-toolbar p-3 flex justify-between rounded-md bg-sn-white">
|
||||
<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>
|
||||
{{ i18n.t('my_modules.results.add_label') }}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1257,6 +1257,7 @@ en:
|
|||
default_name: "New result"
|
||||
placeholder: "Enter result name"
|
||||
add_label: "New result"
|
||||
add_title: "Create new result"
|
||||
new_text_result: "Text"
|
||||
new_table_result: "Table"
|
||||
new_asset_result: "File"
|
||||
|
|
@ -3099,6 +3100,7 @@ en:
|
|||
expand_label: "Expand All"
|
||||
collapse_label: "Collapse All"
|
||||
new_step: "New step"
|
||||
new_step_title: "Create new step"
|
||||
subtitle: "Protocol Steps"
|
||||
no_steps: "Protocol has no steps."
|
||||
published_on_html: "Published on <em>%{timestamp}</em> by <em>%{user}</em>"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue