mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-15 05:34:53 +08:00
181 lines
5.7 KiB
Vue
181 lines
5.7 KiB
Vue
<template>
|
|
<div class="results-wrapper">
|
|
<ResultsToolbar
|
|
ref="resultsToolbar"
|
|
:sort="sort"
|
|
:canCreate="canCreate == 'true'"
|
|
:archived="archived == 'true'"
|
|
:active_url="active_url"
|
|
:archived_url="archived_url"
|
|
:headerSticked="headerSticked"
|
|
:moduleName="moduleName"
|
|
@setSort="setSort"
|
|
@setFilters="setFilters"
|
|
@newResult="createResult"
|
|
@expandAll="expandAll"
|
|
@collapseAll="collapseAll"
|
|
class="my-4"
|
|
/>
|
|
<div class="results-list">
|
|
<Result v-for="result in results" :key="result.id"
|
|
ref="results"
|
|
:result="result"
|
|
:resultToReload="resultToReload"
|
|
:activeDragResult="activeDragResult"
|
|
:userSettingsUrl="userSettingsUrl"
|
|
@result:elements:loaded="resultToReload = null"
|
|
@result:move_element="reloadResult"
|
|
@result:attachments:loaded="resultToReload = null"
|
|
@result:move_attachment="reloadResult"
|
|
@result:duplicated="resetPageAndReload"
|
|
@result:archived="removeResult"
|
|
@result:deleted="removeResult"
|
|
@result:restored="removeResult"
|
|
@result:drag_enter="dragEnter"
|
|
/>
|
|
</div>
|
|
<clipboardPasteModal v-if="showClipboardPasteModal"
|
|
:image="pasteImages"
|
|
:objects="results"
|
|
:objectType="'result'"
|
|
:selectedObjectId="firstObjectInViewport()"
|
|
@files="uploadFilesToResult"
|
|
@cancel="showClipboardPasteModal = false"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import axios from '../../packs/custom_axios.js';
|
|
import ResultsToolbar from './results_toolbar.vue';
|
|
import Result from './result.vue';
|
|
|
|
import stackableHeadersMixin from '../mixins/stackableHeadersMixin';
|
|
import moduleNameObserver from '../mixins/moduleNameObserver';
|
|
|
|
import clipboardPasteModal from '../shared/content/attachments/clipboard_paste_modal.vue';
|
|
import AssetPasteMixin from '../shared/content/attachments/mixins/paste.js';
|
|
|
|
export default {
|
|
name: 'Results',
|
|
components: { ResultsToolbar, Result, clipboardPasteModal },
|
|
mixins: [stackableHeadersMixin, moduleNameObserver, AssetPasteMixin],
|
|
props: {
|
|
url: { type: String, required: true },
|
|
canCreate: { type: String, required: true },
|
|
archived: { type: String, required: true },
|
|
active_url: { type: String, required: true },
|
|
archived_url: { type: String, required: true },
|
|
userSettingsUrl: { type: String, required: false }
|
|
},
|
|
data() {
|
|
return {
|
|
results: [],
|
|
sort: null,
|
|
filters: {},
|
|
resultToReload: null,
|
|
nextPageUrl: null,
|
|
loadingPage: false,
|
|
activeDragResult: null,
|
|
userSettingsUrl: null
|
|
};
|
|
},
|
|
mounted() {
|
|
this.userSettingsUrl = document.querySelector('meta[name="user-settings-url"]').getAttribute('content');
|
|
window.addEventListener('scroll', this.loadResults, false);
|
|
window.addEventListener('scroll', this.initStackableHeaders, false);
|
|
this.nextPageUrl = this.url;
|
|
this.loadResults();
|
|
this.initStackableHeaders();
|
|
},
|
|
beforeUnmount() {
|
|
window.removeEventListener('scroll', this.loadResults, false);
|
|
window.removeEventListener('scroll', this.initStackableHeaders, false);
|
|
},
|
|
methods: {
|
|
getHeader() {
|
|
return this.$refs.resultsToolbar.$refs.resultsHeaderToolbar;
|
|
},
|
|
reloadResult(result) {
|
|
this.resultToReload = result;
|
|
},
|
|
resetPageAndReload() {
|
|
this.nextPageUrl = this.url;
|
|
this.results = [];
|
|
this.$nextTick(() => {
|
|
this.loadResults();
|
|
});
|
|
},
|
|
loadResults() {
|
|
if (this.nextPageUrl === null || this.loadingPage) return;
|
|
|
|
if (window.scrollY + window.innerHeight >= document.body.scrollHeight - 20) {
|
|
this.loadingPage = true;
|
|
const params = this.sort ? { ...this.filters, sort: this.sort } : { ...this.filters };
|
|
axios.get(this.nextPageUrl, { params }).then((response) => {
|
|
this.results = this.results.concat(response.data.data);
|
|
this.sort = response.data.meta.sort;
|
|
this.nextPageUrl = response.data.links.next;
|
|
this.loadingPage = false;
|
|
});
|
|
}
|
|
},
|
|
setSort(sort) {
|
|
this.sort = sort;
|
|
this.resetPageAndReload();
|
|
},
|
|
setFilters(filters) {
|
|
this.filters = filters;
|
|
this.resetPageAndReload();
|
|
},
|
|
createResult() {
|
|
axios.post(
|
|
`${this.url}`,
|
|
{
|
|
headers: {
|
|
Accept: 'application/json'
|
|
}
|
|
}
|
|
).then(
|
|
(response) => {
|
|
this.results = [{ newResult: true, ...response.data.data }, ...this.results];
|
|
window.scrollTo(0, 0);
|
|
}
|
|
);
|
|
},
|
|
expandAll() {
|
|
$('.result-wrapper .collapse').collapse('show');
|
|
this.toggleCollapsed(false);
|
|
},
|
|
collapseAll() {
|
|
$('.result-wrapper .collapse').collapse('hide');
|
|
this.toggleCollapsed(true);
|
|
},
|
|
toggleCollapsed(newState) {
|
|
this.results = this.results.map((result) => ({
|
|
...result,
|
|
attributes: {
|
|
...result.attributes,
|
|
collapsed: newState
|
|
}
|
|
}));
|
|
},
|
|
removeResult(result_id) {
|
|
this.results = this.results.filter((r) => r.id != result_id);
|
|
},
|
|
dragEnter(id) {
|
|
this.activeDragResult = id;
|
|
},
|
|
uploadFilesToResult(file, resultId) {
|
|
this.$refs.results.find((child) => child.result?.id == resultId).uploadFiles(file);
|
|
},
|
|
firstObjectInViewport() {
|
|
const result = $('.result-wrapper:not(.locked)').toArray().find((element) => {
|
|
const { top, bottom } = element.getBoundingClientRect();
|
|
return bottom > 0 && top < window.innerHeight;
|
|
});
|
|
return result ? result.dataset.id : null;
|
|
}
|
|
}
|
|
};
|
|
</script>
|