Commit 09b51d53bc4216f6aad15c2f81be830795742110

Authored by Marcel Kawski
1 parent f9027b33

Add merging chunks in documents

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
... ... @@ -86,7 +86,7 @@
86 86 <p>Poddokumenty:</p>
87 87 </div>
88 88  
89   - <table class="data-table doc-table text-align-center">
  89 + <table class="data-table doc-table" id="subdoc-list-table">
90 90 <thead>
91 91 <tr>
92 92 <th class="col-doc-name">Nazwa-ID</th>
... ...
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
... ...