You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
9.2 KiB
269 lines
9.2 KiB
{% extends "base.html" %}
|
|
|
|
{% block header_script_files %}
|
|
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
|
<script src="//cdn.jsdelivr.net/npm/sortablejs@1.8.4/Sortable.min.js"></script>
|
|
{% endblock %}
|
|
|
|
{% block header %}
|
|
{{ emit_tep('reading_list_page_header') }}
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<div id="app">
|
|
<issues v-bind:issues='issues' ref="issues"></issues>
|
|
<modals v-bind:issue='issue'></modals>
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
{% block modals %}
|
|
{{ emit_tep('reading_list_page_modals') }}
|
|
{% endblock %}
|
|
|
|
{% block button_container %}
|
|
<button type="button" class="btn btn-outline-danger btn-circle btn-md" data-bs-toggle="tooltip" data-bs-placement="top" title="Clear Reading List" onclick="app.clearList()">
|
|
<i class="text-white fas fa-2x fa-minus"></i>
|
|
</button>
|
|
{{ emit_tep('reading_list_page_button_container') }}
|
|
{% endblock %}
|
|
|
|
{% block script %}
|
|
|
|
Vue.directive('sortable', {
|
|
inserted (el, binding, vnode) {
|
|
console.log(binding.value);
|
|
let options = binding.value;
|
|
options.onUpdate = (e) => vnode.data.on.sorted(e);
|
|
const sortable = Sortable.create(el, binding.value);
|
|
}
|
|
})
|
|
|
|
Vue.component('modals', {
|
|
props: ['issue'],
|
|
template: `
|
|
<div>
|
|
<div class="modal" id="modalRead" tabindex="-1" role="dialog" aria-labelledby="readModal" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="notesModalTitle">
|
|
[[ issue.volume.volume_name ]] #[[ issue.issue_number ]]
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body center">
|
|
<a :href="'/read/'+issue.issue_id" id="readRead" class="btn btn-success">
|
|
<i class="fas fa-book-open"></i>
|
|
Read
|
|
</a>
|
|
{% if (current_user.role.lower() == 'admin') or
|
|
(current_user.role.lower() == 'librarian') or
|
|
(current_user.role.lower() == 'patron') %}
|
|
<a :href="'/api/downloads/'+issue.issue_id" id="readDownload" class="btn btn-success">
|
|
<i class="fas fa-download"></i>
|
|
Download
|
|
</a>
|
|
{% endif %}
|
|
<hr />
|
|
<button id="actionToggle" class="btn btn-info my-1" @click="toggleRead" data-bs-dismiss="modal">
|
|
<i class="fas fa-check"></i>
|
|
Toggle Read
|
|
</button>
|
|
<button id="readRemove" class="btn btn-danger" @click="removeIssue" data-bs-dismiss="modal">
|
|
<i class="fas fa-minus"></i>
|
|
Remove From Reading List
|
|
</button>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{{ emit_tep('reading_list_page_issue_modals') }}
|
|
`,
|
|
methods: {
|
|
toggleRead() {
|
|
app.$refs.issues.$children.find(child => { return child.$vnode.key == this.issue.issue_id }).toggleRead()
|
|
},
|
|
removeIssue() {
|
|
app.removeIssue(this.issue.issue_id)
|
|
},
|
|
},
|
|
delimiters: ["[[","]]"]
|
|
})
|
|
|
|
Vue.component('issues', {
|
|
props: ['issues'],
|
|
template: `
|
|
<ul class="d-flex flex-wrap w-100 m-0 p-0 justify-content-center" v-sortable="$options.sortOptions" @sorted='handleSorted'>
|
|
<issue
|
|
v-for="issue in issues"
|
|
v-bind:issue="issue"
|
|
v-bind:key="issue.issue_id"
|
|
></issue>
|
|
</ul>
|
|
`,
|
|
methods: {
|
|
handleSorted(event) {
|
|
app.handleSorted(event)
|
|
},
|
|
},
|
|
sortOptions: {
|
|
draggable: '.js-sortable-block',
|
|
handle: '.js-drag-handle',
|
|
delay: 300,
|
|
delayOnTouchOnly: true
|
|
},
|
|
delimiters: ["[[","]]"]
|
|
})
|
|
|
|
Vue.component('issue', {
|
|
props: ['issue'],
|
|
template: `
|
|
<li class='stashr-cover_size m-2 js-sortable-block'
|
|
@mouseover="hover = true"
|
|
@mouseleave="hover = false"
|
|
>
|
|
<div class='stashr-poster_wrapper rounded'>
|
|
<div class="stashr-badge_tl badge rounded-pill bg-dark border js-drag-handle">
|
|
<i class="fas fa-arrows-alt"></i>
|
|
</div>
|
|
<div class="stashr-badge_br badge rounded-pill bg-dark border">
|
|
<i class="fas fa-eye" v-bind:class="statusRead" v-on:click="toggleRead"></i>
|
|
</div>
|
|
<!--
|
|
<div class="stashr-badge_tr badge badge-pill badge-info border">[[ issue.reading_list_position ]]</div>
|
|
-->
|
|
<div class="stashr-poster_container border rounded">
|
|
<div class="stashr-overlay_bottom w-100 center" v-if="hover">
|
|
<a href="#">[[ issue.volume.volume_name ]] #[[ issue.issue_number ]]</a>
|
|
</div>
|
|
<img class="stashr-poster_background w-100" loading="eager" src="/static/assets/cover.svg" />
|
|
<a class="stashr-poster_link" data-bs-toggle="modal" data-bs-target="#modalRead" v-on:click="this.changeModal">
|
|
<img class="w-100" loading="lazy" v-bind:src="'/images/issues/'+issue.issue_id+'.jpg'"/>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
`,
|
|
computed: {
|
|
statusRead() {
|
|
let classname = 'text-danger';
|
|
try {
|
|
if (this.issue.read_status[0].read_status) {
|
|
classname = 'text-success';
|
|
}
|
|
} finally {
|
|
return classname;
|
|
}
|
|
},
|
|
},
|
|
methods: {
|
|
toggleRead() {
|
|
axios.put('{{ url_for('api.api_put_single_issue', issue_id='ISSUEID') }}'.replace('ISSUEID', this.issue.issue_id), {
|
|
data: {
|
|
read_status: !this.issue.read_status[0].read_status
|
|
}
|
|
})
|
|
.then(res => {
|
|
if(res.data.status_code == '200') {
|
|
stashrToast('Toggled Read Status', 'success');
|
|
this.issue.read_status[0].read_status = !this.issue.read_status[0].read_status;
|
|
} else {
|
|
stashrToast(res.data.message, 'error')
|
|
}
|
|
})
|
|
.catch(err => console.log(err))
|
|
},
|
|
changeModal() {
|
|
app.changeModal(this.issue)
|
|
},
|
|
},
|
|
data() { return { hover: false } },
|
|
delimiters: ["[[","]]"]
|
|
})
|
|
|
|
var app = new Vue({
|
|
el: '#app',
|
|
data: {
|
|
issues: [],
|
|
issue: [],
|
|
},
|
|
created() {
|
|
this.getIssues()
|
|
},
|
|
methods: {
|
|
|
|
getIssues() {
|
|
axios.get('{{ url_for('api.api_get_reading_list') }}', {
|
|
params: {
|
|
offset: this.issues.length
|
|
}
|
|
})
|
|
.then( res => {
|
|
if(res.data.number_of_page_results > 0) {
|
|
res.data.results.forEach(result => {
|
|
this.issues.push(result)
|
|
})
|
|
if(this.issues.length < res.data.number_of_total_results) {
|
|
this.getIssues()
|
|
}
|
|
}
|
|
this.issue = this.issues[0]
|
|
})
|
|
.catch()
|
|
},
|
|
|
|
removeIssue(id) {
|
|
axios.delete('{{ url_for('api.api_delete_reading_list_single', issue_id='ISSUEID') }}'.replace('ISSUEID', id))
|
|
.then(
|
|
this.issues = this.issues.filter(issue => issue.issue_id !== id)
|
|
)
|
|
.catch(err => console.log(err))
|
|
},
|
|
|
|
handleSorted(event) {
|
|
axios.put('{{ url_for('api.api_put_reading_list') }}', {
|
|
data: {
|
|
old_index: event.oldIndex,
|
|
new_index: event.newIndex
|
|
}
|
|
})
|
|
.then(res => {
|
|
if(res.data.status_code == '200') {
|
|
stashrToast('Updated Order', 'success')
|
|
} else {
|
|
stashrToast(res.data.message, 'error')
|
|
}
|
|
})
|
|
.catch(err => console.log(err))
|
|
},
|
|
|
|
clearList() {
|
|
axios.delete('{{ url_for('api.api_delete_reading_list') }}')
|
|
.then(res => {
|
|
if(res.data.status_code == '200') {
|
|
stashrToast('Cleared Reading List', 'success')
|
|
this.issues = []
|
|
} else {
|
|
stashrToast(res.data.message, 'error')
|
|
}
|
|
})
|
|
.catch(err => console.log(err))
|
|
},
|
|
|
|
changeModal(issue) {
|
|
this.issue = issue
|
|
},
|
|
|
|
},
|
|
delimiters: ["[[","]]"]
|
|
})
|
|
|
|
{{ emit_tep('reading_list_page_script') }}
|
|
|
|
{% endblock %} |