From d7783aad6402b643a5a36d0a5cf6b4cb4fe596f7 Mon Sep 17 00:00:00 2001 From: Robin Tissot <tissotrobin@gmail.com> Date: Fri, 12 Mar 2021 11:48:49 +0100 Subject: [PATCH] functional goto modal. --- app/apps/api/views.py | 18 +++++++++++++++ front/css/escriptorium.css | 4 ++++ front/src/editor/api.js | 4 +++- front/src/editor/store/document.js | 5 ++++ front/src/editor/store/parts.js | 30 ++++++++++++++++++++---- front/vue/components/Editor.vue | 5 +--- front/vue/components/ExtraInfo.vue | 36 ++++++++++++++++++++++++++++- front/vue/components/TabContent.vue | 3 --- 8 files changed, 91 insertions(+), 14 deletions(-) diff --git a/app/apps/api/views.py b/app/apps/api/views.py index 19fc3765..23722ea8 100644 --- a/app/apps/api/views.py +++ b/app/apps/api/views.py @@ -4,7 +4,9 @@ import logging from django.conf import settings from django.core.exceptions import PermissionDenied from django.db.models import Prefetch +from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 +from django.urls import reverse from rest_framework.decorators import action from rest_framework.response import Response @@ -193,6 +195,22 @@ class PartViewSet(DocumentPermissionMixin, ModelViewSet): else: # list & create return PartSerializer + @action(detail=False, methods=['get']) + def byorder(self, request, document_pk=None): + try: + order = int(request.GET.get('order')) + except ValueError: + return Response({'error': 'invalid order.'}) + if not order: + return Response({'error': 'pass order as an url parameter.'}) + try: + part = self.get_queryset().get(order=order) + except DocumentPart.DoesNotExist: + return Response({'error': 'Out of bounds.'}) + return HttpResponseRedirect(reverse('api:part-detail', + kwargs={'document_pk': self.kwargs.get('document_pk'), + 'pk': part.pk})) + @action(detail=True, methods=['post']) def move(self, request, document_pk=None, pk=None): part = DocumentPart.objects.get(document=document_pk, pk=pk) diff --git a/front/css/escriptorium.css b/front/css/escriptorium.css index f6e86791..9070c273 100644 --- a/front/css/escriptorium.css +++ b/front/css/escriptorium.css @@ -386,6 +386,10 @@ form.inline-form { color: grey; } +#gotoModal .modal-dialog { + max-width: 355px; +} + .col-sides { width: 30px; margin: 0 15px; diff --git a/front/src/editor/api.js b/front/src/editor/api.js index 2cf9820b..52851785 100644 --- a/front/src/editor/api.js +++ b/front/src/editor/api.js @@ -10,6 +10,8 @@ export const retrieveDocument = async document_id => (await axios.get(`/document export const retrieveDocumentPart = async (document_id, part_id) => (await axios.get(`/documents/${document_id}/parts/${part_id}/`)) +export const retrieveDocumentPartByOrder = async (document_id, order) => (await axios.get(`/documents/${document_id}/parts/byorder/?order=${order}`)) + export const retrievePage = async (document_id, part_id, transcription, page) => (await axios.get(`/documents/${document_id}/parts/${part_id}/transcriptions/?transcription=${transcription}&page=${page}`)) export const createContent = async (document_id, part_id, data) => (await axios.post(`/documents/${document_id}/parts/${part_id}/transcriptions/`, data)) @@ -40,4 +42,4 @@ export const bulkCreateLineTranscriptions = async (document_id, part_id, data) = export const bulkUpdateLineTranscriptions = async (document_id, part_id, data) => (await axios.put(`/documents/${document_id}/parts/${part_id}/transcriptions/bulk_update/`, data)) -export const moveLines = async (document_id, part_id, data) => (await axios.post(`/documents/${document_id}/parts/${part_id}/lines/move/`, data)) \ No newline at end of file +export const moveLines = async (document_id, part_id, data) => (await axios.post(`/documents/${document_id}/parts/${part_id}/lines/move/`, data)) diff --git a/front/src/editor/store/document.js b/front/src/editor/store/document.js index 88bf2074..ee3ffe0a 100644 --- a/front/src/editor/store/document.js +++ b/front/src/editor/store/document.js @@ -4,6 +4,7 @@ import * as api from '../api' export const initialState = () => ({ id: null, name: "", + partsCount: 0, defaultTextDirection: null, mainTextDirection: null, readDirection: null, @@ -39,6 +40,9 @@ export const mutations = { setTypes (state, types) { state.types = types }, + setPartsCount(state, count) { + state.partsCount = count + }, setBlockShortcuts(state, block) { state.blockShortcuts = block }, @@ -56,6 +60,7 @@ export const actions = { let data = resp.data commit('transcriptions/set', data.transcriptions, {root: true}) commit('setTypes', { 'regions': data.valid_block_types, 'lines': data.valid_line_types }) + commit('setPartsCount', data.parts_count) }, async togglePanel ({state, commit}, panel) { diff --git a/front/src/editor/store/parts.js b/front/src/editor/store/parts.js index ed1ce964..3d366ad3 100644 --- a/front/src/editor/store/parts.js +++ b/front/src/editor/store/parts.js @@ -31,12 +31,19 @@ export const mutations = { } export const actions = { - async fetchPart ({commit, dispatch, rootState}, pk) { - commit('setPartPk', pk) + async fetchPart ({commit, dispatch, rootState}, {pk, order}) { if (!rootState.transcriptions.all.length) { await dispatch('document/fetchDocument', rootState.document.id, {root: true}) } - const resp = await api.retrieveDocumentPart(rootState.document.id, pk) + var resp + if (pk) { + commit('setPartPk', pk) + resp = await api.retrieveDocumentPart(rootState.document.id, pk) + } else { + resp = await api.retrieveDocumentPartByOrder(rootState.document.id, order) + commit('setPartPk', resp.data.pk) + } + let data = resp.data data.lines.forEach(function(line) { @@ -63,7 +70,20 @@ export const actions = { commit('regions/reset', {}, {root: true}) commit('lines/reset', {}, {root: true}) commit('reset') - await dispatch('fetchPart', pk) + await dispatch('fetchPart', {pk: pk}) + }, + + async loadPartByOrder({state, commit, dispatch, rootState}, order) { + commit('regions/reset', {}, {root: true}) + commit('lines/reset', {}, {root: true}) + commit('reset') + try { + await dispatch('fetchPart', {order: order}) + await dispatch('transcriptions/getCurrentContent', rootState.transcriptions.selectedTranscription, {root: true}) + await dispatch('transcriptions/getComparisonContent', {}, {root: true}) + } catch (err) { + console.log('couldnt fetch part data!', err) + } }, async loadPart({state, commit, dispatch, rootState}, direction) { @@ -73,7 +93,7 @@ export const actions = { commit('lines/reset', {}, {root: true}) commit('reset') try { - await dispatch('fetchPart', part) + await dispatch('fetchPart', {pk: part}) await dispatch('transcriptions/getCurrentContent', rootState.transcriptions.selectedTranscription, {root: true}) await dispatch('transcriptions/getComparisonContent', {}, {root: true}) } catch (err) { diff --git a/front/vue/components/Editor.vue b/front/vue/components/Editor.vue index 68a426eb..ca623312 100644 --- a/front/vue/components/Editor.vue +++ b/front/vue/components/Editor.vue @@ -4,7 +4,6 @@ <div class="nav nav-tabs mb-3" id="nav-tab" role="tablist"> <slot></slot> <extrainfo></extrainfo> - <gotoelement></gotoelement> <transmanagement></transmanagement> <extranav></extranav> </div> @@ -16,7 +15,6 @@ <script> import ExtraInfo from './ExtraInfo.vue'; -import GotoElement from './GotoElement.vue'; import TranscriptionManagement from './TranscriptionManagement.vue'; import ExtraNav from './ExtraNav.vue'; import TabContent from './TabContent.vue'; @@ -71,7 +69,6 @@ export default { components: { 'extrainfo': ExtraInfo, - 'gotoelement': GotoElement, 'transmanagement': TranscriptionManagement, 'extranav': ExtraNav, 'tabcontent': TabContent, @@ -84,7 +81,7 @@ export default { this.$store.commit('document/setMainTextDirection', this.mainTextDirection); this.$store.commit('document/setReadDirection', this.readDirection); try { - await this.$store.dispatch('parts/fetchPart', this.partId); + await this.$store.dispatch('parts/fetchPart', {pk: this.partId}); let tr = userProfile.get('initialTranscriptions') && userProfile.get('initialTranscriptions')[this.$store.state.document.id] || this.$store.state.transcriptions.all[0].pk; diff --git a/front/vue/components/ExtraInfo.vue b/front/vue/components/ExtraInfo.vue index 218f0ae6..6dc3d618 100644 --- a/front/vue/components/ExtraInfo.vue +++ b/front/vue/components/ExtraInfo.vue @@ -2,18 +2,52 @@ <div> <div class="nav-div nav-item ml-2"> <span v-if="$store.state.document.name" id="part-name">{{ $store.state.document.name }}</span> - <span id="part-title" v-if="$store.state.parts.loaded">{{ $store.state.parts.title }} - {{ $store.state.parts.filename }} - ({{ imageSize }})</span> + <span id="part-title" v-if="$store.state.parts.loaded" data-toggle="modal" data-target="#gotoModal" role="button">{{ $store.state.parts.title }} - {{ $store.state.parts.filename }} - ({{ imageSize }})</span> <span class="loading" v-if="!$store.state.parts.loaded">Loading…</span> </div> + + <div id="gotoModal" + class="modal ui-draggable show" + tabindex="-1" + role="dialog"> + <div class="modal-dialog modal-dialog-centered"> + <div class="modal-content"> + <div class="modal-body"> + Element # + <input type="number" + v-if="$store.state.parts.loaded" + min="1" + :max="$store.state.document.partsCount" + width="100%" + v-bind:value="$store.state.parts.order+1" + @change.lazy="goTo"/> + / {{$store.state.document.partsCount}} + </div> + </div> + </div> + </div> </div> </template> <script> export default { + async created() { + document.addEventListener('keyup', async function(event) { + if (event.ctrlKey && event.keyCode == 36) { // Home + $('#gotoModal').modal('show'); + } + }); + }, computed: { imageSize() { return this.$store.state.parts.image.size[0]+'x'+this.$store.state.parts.image.size[1]; }, + }, + methods: { + async goTo(ev) { + await this.$store.dispatch('parts/loadPartByOrder', ev.target.value-1); + $('#gotoModal').modal('hide'); + } } } </script> diff --git a/front/vue/components/TabContent.vue b/front/vue/components/TabContent.vue index e07e81a2..b51bd7eb 100644 --- a/front/vue/components/TabContent.vue +++ b/front/vue/components/TabContent.vue @@ -156,9 +156,6 @@ export default { resetZoom() { this.zoom.reset(); }, - async goTo(ev) { - await this.$store.dispatch('parts/loadPart', 'previous'); - }, async getPrevious(ev) { await this.$store.dispatch('parts/loadPart', 'previous'); }, -- GitLab