Commit 09b51d53bc4216f6aad15c2f81be830795742110
1 parent
f9027b33
Add merging chunks in documents
Showing
7 changed files
with
89 additions
and
36 deletions
collector/storage/forms.py
... | ... | @@ -328,20 +328,18 @@ class DocSplitForm(Form): |
328 | 328 | def __init__(self, *args, **kwargs): |
329 | 329 | chunks = kwargs.pop('chunks') |
330 | 330 | super(DocSplitForm, self).__init__(*args, **kwargs) |
331 | - for chunk in chunks: | |
332 | - print(chunk.pk) | |
333 | 331 | self.fields['chunk_beg'].queryset = chunks |
334 | 332 | self.fields['chunk_end'].queryset = chunks |
335 | 333 | |
336 | 334 | |
337 | 335 | class MoveChunkForm(Form): |
338 | - move_doc = ModelChoiceField(queryset=None, label="Dokument docelowy") | |
336 | + target_doc = ModelChoiceField(queryset=None, label="Dokument docelowy") | |
339 | 337 | |
340 | 338 | def __init__(self, *args, **kwargs): |
341 | - poss_move_docs = kwargs.pop('poss_move_docs') | |
339 | + poss_target_docs = kwargs.pop('poss_target_docs') | |
342 | 340 | super(MoveChunkForm, self).__init__(*args, **kwargs) |
343 | - self.fields['move_doc'].label_from_instance = self.label_from_instance | |
344 | - self.fields['move_doc'].queryset = poss_move_docs | |
341 | + self.fields['target_doc'].label_from_instance = self.label_from_instance | |
342 | + self.fields['target_doc'].queryset = poss_target_docs | |
345 | 343 | |
346 | 344 | @staticmethod |
347 | 345 | def label_from_instance(obj): |
... | ... | @@ -349,3 +347,19 @@ class MoveChunkForm(Form): |
349 | 347 | return f'{obj} (fragment nr: {obj.sequence})' |
350 | 348 | else: |
351 | 349 | return f'{obj} (dokument główny)' |
350 | + | |
351 | + | |
352 | +class MergeChunkForm(Form): | |
353 | + target_chunk = ModelChoiceField(queryset=None, label="Połącz z sekcją:") | |
354 | + | |
355 | + def __init__(self, *args, **kwargs): | |
356 | + poss_target_chunks = kwargs.pop('poss_target_chunks') | |
357 | + super(MergeChunkForm, self).__init__(*args, **kwargs) | |
358 | + self.fields['target_chunk'].label_from_instance = self.label_from_instance | |
359 | + self.fields['target_chunk'].queryset = poss_target_chunks | |
360 | + self.fields['target_chunk'].widget.attrs['required'] = 'required' | |
361 | + | |
362 | + @staticmethod | |
363 | + def label_from_instance(obj): | |
364 | + if obj: | |
365 | + return obj.sequence | |
... | ... |
collector/storage/static/storage/css/document.css
... | ... | @@ -51,6 +51,10 @@ body { |
51 | 51 | text-align: center; |
52 | 52 | } |
53 | 53 | |
54 | +#subdoc-list-table { | |
55 | + text-align: center; | |
56 | +} | |
57 | + | |
54 | 58 | .doc-table { |
55 | 59 | text-align: left; |
56 | 60 | line-height: 40px; |
... | ... | @@ -151,6 +155,10 @@ a.nav-button:hover { |
151 | 155 | color: #ffcd00; |
152 | 156 | } |
153 | 157 | |
158 | +.merge:hover { | |
159 | + color: #96ff5e; | |
160 | +} | |
161 | + | |
154 | 162 | .arrow:hover { |
155 | 163 | color: #ff6600; |
156 | 164 | } |
... | ... |
collector/storage/static/storage/js/document.js
... | ... | @@ -24,6 +24,10 @@ $(function () { |
24 | 24 | $(this).modalForm({formURL: $(this).data("id")}); |
25 | 25 | }); |
26 | 26 | |
27 | + $(".merge-chunk").each( function () { | |
28 | + $(this).modalForm({formURL: $(this).data("id")}); | |
29 | + }); | |
30 | + | |
27 | 31 | $(".add-subchunk").each( function () { |
28 | 32 | $(this).modalForm({formURL: $(this).data("id")}); |
29 | 33 | }); |
... | ... |
collector/storage/templates/storage/annotation.html
... | ... | @@ -103,7 +103,7 @@ |
103 | 103 | <p>Poddokumenty:</p> |
104 | 104 | </div> |
105 | 105 | |
106 | - <table class="data-table doc-table text-align-center"> | |
106 | + <table class="data-table doc-table" id="subdoc-list-table"> | |
107 | 107 | <thead> |
108 | 108 | <tr> |
109 | 109 | <th class="col-doc-name">Nazwa-ID</th> |
... | ... | @@ -350,6 +350,9 @@ |
350 | 350 | <th></th> |
351 | 351 | <th class="actions"> |
352 | 352 | {% if user.is_authenticated %} |
353 | + <i class="merge-chunk material-icons button merge" | |
354 | + data-id="{% url 'merge_chunk' chunk.pk chunk.document.id %}" | |
355 | + title="Połącz z inną sekcją">merge_type</i> | |
353 | 356 | <i class="move-chunk material-icons button redo" data-id="{% url 'move_chunk' chunk.pk %}" |
354 | 357 | title="Przenieś do innego dokumentu">redo</i> |
355 | 358 | {% if not chunk.utterances.exists %} |
... | ... |
collector/storage/templates/storage/review.html
collector/storage/urls.py
... | ... | @@ -18,6 +18,7 @@ urlpatterns = [ |
18 | 18 | path('chunk/edit/<int:pk>', login_required(views.ChunkEditView.as_view()), name='edit_chunk'), |
19 | 19 | path('chunk/delete/<int:pk>', login_required(views.ChunkDeleteView.as_view()), name='delete_chunk'), |
20 | 20 | path('chunk/move/<int:pk>', login_required(views.move_chunk), name='move_chunk'), |
21 | + path('chunk/merge/<int:pk>/<str:doc_id>', login_required(views.merge_chunk), name='merge_chunk'), | |
21 | 22 | path('subchunk/add/<int:chunk_pk>', login_required(views.SubchunkAddView.as_view()), name='add_subchunk'), |
22 | 23 | path('subchunk/edit/<int:pk>', login_required(views.SubchunkEditView.as_view()), name='edit_subchunk'), |
23 | 24 | path('subchunk/delete/<int:pk>', login_required(views.SubchunkDeleteView.as_view()), name='delete_subchunk'), |
... | ... |
collector/storage/views.py
... | ... | @@ -19,7 +19,7 @@ from keras import backend |
19 | 19 | from sys import maxsize |
20 | 20 | |
21 | 21 | from .forms import ChunkForm, ParticipantForm, SubchunkForm, MetadataForm, DocDetailsForm, KeywordForm, DocSplitForm, \ |
22 | - MoveChunkForm, SubDocDetailsForm, AuthorForm | |
22 | + MoveChunkForm, SubDocDetailsForm, AuthorForm, MergeChunkForm | |
23 | 23 | from .models import Chunk, Document, Participant, Metadata, Keyword, Annotation |
24 | 24 | from projects.ppc.models import Utterance |
25 | 25 | from pipeline.models import ProcessingStatus |
... | ... | @@ -58,6 +58,23 @@ def handle_chunks_seq_uniqueness(chunks, target_doc_chunks): |
58 | 58 | return chunks |
59 | 59 | |
60 | 60 | |
61 | +def swap_subdocs(direction, subdoc, subdoc_seq, temp_seq, max_seq, parent_doc): | |
62 | + sign = None | |
63 | + if direction == 'up' and subdoc_seq > 1: | |
64 | + sign = '-' | |
65 | + elif direction == 'down' and subdoc_seq < max_seq: | |
66 | + sign = '+' | |
67 | + if sign is not None: | |
68 | + neighbour = Document.objects.get(parent=parent_doc, | |
69 | + sequence=eval(f'{str(subdoc_seq)} {sign} 1')) | |
70 | + neighbour.sequence = temp_seq | |
71 | + neighbour.save() | |
72 | + subdoc.sequence = eval(f'{str(subdoc_seq)} {sign} 1') | |
73 | + subdoc.save() | |
74 | + neighbour.sequence = subdoc_seq | |
75 | + neighbour.save() | |
76 | + | |
77 | + | |
61 | 78 | class DocumentView(View): |
62 | 79 | template_name = 'storage/document.html' |
63 | 80 | |
... | ... | @@ -300,29 +317,52 @@ def move_chunk(request, pk): |
300 | 317 | chunk = Chunk.objects.get(pk=pk) |
301 | 318 | document = chunk.document |
302 | 319 | if document.parent is not None: # subdocument |
303 | - poss_move_docs = Document.objects.filter(parent=document.parent) | |
304 | - poss_move_docs = poss_move_docs.exclude(id=document.id) | |
305 | - poss_move_docs |= Document.objects.filter(pk=document.parent.pk) | |
320 | + poss_target_docs = Document.objects.filter(parent=document.parent) | |
321 | + poss_target_docs = poss_target_docs.exclude(id=document.id) | |
322 | + poss_target_docs |= Document.objects.filter(pk=document.parent.pk) | |
306 | 323 | else: # main document |
307 | - poss_move_docs = Document.objects.filter(parent=document) | |
324 | + poss_target_docs = Document.objects.filter(parent=document) | |
308 | 325 | if request.method == 'POST': |
309 | - form = MoveChunkForm(request.POST, poss_move_docs=poss_move_docs) | |
326 | + form = MoveChunkForm(request.POST, poss_target_docs=poss_target_docs) | |
310 | 327 | if form.is_valid(): |
311 | - move_doc = form.cleaned_data['move_doc'] | |
312 | - chunk.document = move_doc | |
313 | - chunk = handle_chunks_seq_uniqueness([chunk], move_doc.chunks.all())[0] | |
328 | + target_doc = form.cleaned_data['target_doc'] | |
329 | + chunk.document = target_doc | |
330 | + chunk = handle_chunks_seq_uniqueness([chunk], target_doc.chunks.all())[0] | |
314 | 331 | chunk.save() |
315 | 332 | document.changed = True |
316 | 333 | document.save() |
317 | - return HttpResponseRedirect(reverse_lazy('annotation', kwargs={'doc_id': move_doc.id})) | |
334 | + return HttpResponseRedirect(reverse_lazy('annotation', kwargs={'doc_id': target_doc.id})) | |
318 | 335 | return HttpResponseRedirect(reverse_lazy('annotation', kwargs={'doc_id': document.id})) |
319 | 336 | else: |
320 | - form = MoveChunkForm(poss_move_docs=poss_move_docs) | |
337 | + form = MoveChunkForm(poss_target_docs=poss_target_docs) | |
321 | 338 | return render(request, 'storage/edit.html', {'form': form, |
322 | 339 | 'title': 'Przenoszenie sekcji', |
323 | 340 | 'submit_btn_text': 'Przenieś'}) |
324 | 341 | |
325 | 342 | |
343 | +def merge_chunk(request, pk, doc_id): | |
344 | + try: | |
345 | + chunk = Chunk.objects.get(pk=pk) | |
346 | + document = chunk.document | |
347 | + poss_target_chunks = document.chunks.all() | |
348 | + poss_target_chunks = poss_target_chunks.exclude(id=chunk.id) | |
349 | + form = MergeChunkForm(request.POST, poss_target_chunks=poss_target_chunks) | |
350 | + except Chunk.DoesNotExist: | |
351 | + form, chunk, poss_target_chunks, document = None, None, None, None | |
352 | + if request.method == 'POST': | |
353 | + if form is not None and form.is_valid(): | |
354 | + target_chunk = form.cleaned_data['target_chunk'] | |
355 | + target_chunk.text += f' {chunk.text}' | |
356 | + target_chunk.save() | |
357 | + chunk.delete() | |
358 | + return HttpResponseRedirect(reverse_lazy('annotation', kwargs={'doc_id': doc_id})) | |
359 | + else: | |
360 | + form = MergeChunkForm(poss_target_chunks=poss_target_chunks) | |
361 | + return render(request, 'storage/edit.html', {'form': form, | |
362 | + 'title': 'Łączenie sekcji', | |
363 | + 'submit_btn_text': 'Połącz'}) | |
364 | + | |
365 | + | |
326 | 366 | class SubchunkAddView(CreateView): |
327 | 367 | template_name = 'storage/edit.html' |
328 | 368 | form_class = SubchunkForm |
... | ... | @@ -856,23 +896,6 @@ def split_doc(request, doc_id): |
856 | 896 | 'submit_btn_text': 'Podziel'}) |
857 | 897 | |
858 | 898 | |
859 | -def swap_subdocs(direction, subdoc, subdoc_seq, temp_seq, max_seq, parent_doc): | |
860 | - sign = None | |
861 | - if direction == 'up' and subdoc_seq > 1: | |
862 | - sign = '-' | |
863 | - elif direction == 'down' and subdoc_seq < max_seq: | |
864 | - sign = '+' | |
865 | - if sign is not None: | |
866 | - neighbour = Document.objects.get(parent=parent_doc, | |
867 | - sequence=eval(f'{str(subdoc_seq)} {sign} 1')) | |
868 | - neighbour.sequence = temp_seq | |
869 | - neighbour.save() | |
870 | - subdoc.sequence = eval(f'{str(subdoc_seq)} {sign} 1') | |
871 | - subdoc.save() | |
872 | - neighbour.sequence = subdoc_seq | |
873 | - neighbour.save() | |
874 | - | |
875 | - | |
876 | 899 | def move_subdoc(request, subdoc_id, direction): |
877 | 900 | subdoc = Document.objects.get(id=subdoc_id) |
878 | 901 | subdoc_seq = subdoc.sequence |
... | ... |