diff --git a/common/decorators.py b/common/decorators.py index 7c1f4d85f75fdb2f0296f0a8e9c304767b963264..729224c2d66e02b2958a3fdd2d2c9a24b513bf60 100644 --- a/common/decorators.py +++ b/common/decorators.py @@ -29,8 +29,7 @@ def json_decode_fallback(value): def ajax(login_required=False, method=None, encode_result=True): def decorator(fun): @wraps(fun) - def ajax_view(request): - kwargs = {} + def ajax_view(request, *args, **kwargs): request_params = None if method == 'post': request_params = request.POST @@ -43,11 +42,11 @@ def ajax(login_required=False, method=None, encode_result=True): if fun_kwargs or key in fun_params) kwargs.update(stringify_keys(request_params)) res = None - if login_required and not request.user.is_authenticated(): + if login_required and not request.user.is_authenticated: res = {'result': 'logout'} if not res: try: - res = fun(request, **kwargs) + res = fun(request, *args, **kwargs) except AjaxError as e: res = {'result': e.args[0]} transaction.rollback() diff --git a/common/migrations/__init__.py b/common/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/common/static/common/js/utils.js b/common/static/common/js/utils.js index 8e8763c8ea943aa416c74b3fb6d32c7ab5f47464..ff58cb14da15a71973043d8dac662422f52d42ff 100644 --- a/common/static/common/js/utils.js +++ b/common/static/common/js/utils.js @@ -7,6 +7,11 @@ jQuery.fn.immediateText = function() { return this.contents().not(this.children()).text(); }; +jQuery.urlParam = function (name) { + var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.search); + return (results !== null) ? results[1] || 0 : false; +} + function tooltipped_span(text, tooltip_text, cls) { var html = tooltip_text.includes('<') ? ' data-html="true"' : ''; cls = cls ? ' class="' + cls + '"' : ''; diff --git a/connections/migrations/__init__.py b/connections/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/entries/static/entries/js/entries.js b/entries/static/entries/js/entries.js index 6970a543d94caec865b6697e1821a9608dd91411..4e9ab7d93f59ce8f119729f9f1e05b199810b01b 100644 --- a/entries/static/entries/js/entries.js +++ b/entries/static/entries/js/entries.js @@ -795,13 +795,13 @@ function show_unmatched_examples() { } } -function get_entry(entry_id, related) { +function get_entry(entry_id, related, lexical_unit_id) { check_import_status(); clear_entry(); show_entry_spinners(); //var data = { 'forms' : serialize_forms($('#main-form')), 'entry' : entry_id }; - var data = { 'entry' : entry_id, 'no_filters' : related }; - $.ajax({ + var data = { 'entry' : entry_id, 'no_filters' : related, 'lexical_unit_id': lexical_unit_id }; + return $.ajax({ type : 'post', url : '/' + lang + '/entries/get_entry/', dataType : 'json', @@ -822,7 +822,7 @@ function get_entry(entry_id, related) { show_syntax(response.subentries); show_semantics(response.frames, response.subentries); show_unmatched_examples(); - + // if current tab is empty, switch to an active tab var active_tab = $('#entryTabs').find('.nav-link.active').attr('id'); if (active_tab === 'semantics-tab' && $('.frame').length === 0) { @@ -837,7 +837,7 @@ function get_entry(entry_id, related) { $('#syntax-tab').tab('show'); } } - + // tooltips with meaning gloss activate_tooltips($('.frame')); // tooltips with phrase descriptions diff --git a/entries/static/entries/js/selectional_preference.js b/entries/static/entries/js/selectional_preference.js index a802f135a18c7ecc89d74e3c3f70833b95904a7e..52cf001acdfaadb253c0e07c5a887fbd3512e7ea 100644 --- a/entries/static/entries/js/selectional_preference.js +++ b/entries/static/entries/js/selectional_preference.js @@ -148,7 +148,7 @@ function addSelectivePreferenceBase(frame, complement_id) { state0: { title: 'Typ preferencji selekcyjnej', html: 'Wybierz typ preferencji selekcyjnej', - buttons: { Predefiniowana: 1, Słowosieć: 2, Relacja: 3, Koniec: -1 }, + buttons: { Istniejąca: 0, Predefiniowana: 1, Słowosieć: 2, Relacja: 3, Koniec: -1 }, focus: -1, submit: function(e,v,m,f){ if (v == -1) { @@ -158,20 +158,21 @@ function addSelectivePreferenceBase(frame, complement_id) { $.prompt.close(); } + if (v === 0) { + e.preventDefault(); + $.prompt.goToState('state4'); + } if (v == 1) { e.preventDefault(); $.prompt.goToState('state1'); - } if (v == 2) { e.preventDefault(); $.prompt.goToState('state2'); - } if (v == 3) { e.preventDefault(); $.prompt.goToState('state3'); - } } }, @@ -241,6 +242,25 @@ function addSelectivePreferenceBase(frame, complement_id) { } } + $.prompt.goToState('state0'); + } + } + }, + state4: { + title: 'Wybierz z istniejących', + html: relationArgument(frame, complement_id), + buttons: { Anuluj: -1, Zatwierdź: 1 }, + focus: 1, + submit: function(e,v,m,f){ + if (v == -1) { + e.preventDefault(); + $.prompt.goToState('state0'); + } + if (v == 1) { + e.preventDefault(); + + // TODO + $.prompt.goToState('state0'); } } diff --git a/entries/static/entries/js/unification.js b/entries/static/entries/js/unification.js index 516919ea016447ba8e380821f262d9b648054daa..7dc4e68bd05c398c08aba98eaef7ab7ea9ae436e 100644 --- a/entries/static/entries/js/unification.js +++ b/entries/static/entries/js/unification.js @@ -49,9 +49,7 @@ function get_unified_frame(unified_frame_id, related) { } // tooltips with meaning gloss - activate_tooltips($('.frame')); - // tooltips with phrase descriptions - activate_tooltips($('.schema')); + activate_tooltips($('#semantics-frames-pane')); update_last_visited(response.last_visited); }, error: function(request, errorType, errorMessage) { @@ -146,7 +144,6 @@ function unifiedFrame2dom(unifiedFrame, slowal_frames) { tbody.append(preferences_row); table.append(tbody); div.append(table); - return div; } @@ -180,6 +177,7 @@ function frames2lexical_units(frames) { for (var j in frame.lexical_units) { var lexical_unit = frame.lexical_units[j]; lexical_unit.opinion = frame.opinion; + lexical_unit.opinion_key = frame.opinion_key; lexical_units.push(lexical_unit); } } @@ -203,7 +201,7 @@ function frames2lexical_unitsHTML(frames) { let lexical_unit = lexical_units[j]; let lexical_unit_row = document.createElement('tr'); lexical_unit_row.innerHTML += '<td class="argument py-2 px-1 border-top border-left border-secondary">' + gettext(lexical_unit.str) + '</td>'; - lexical_unit_row.innerHTML += '<td class="argument py-2 px-1 border-top border-left border-secondary">' + gettext(lexical_unit.opinion) + '</td>'; + lexical_unit_row.innerHTML += '<td class="argument py-2 px-1 border-top border-left border-secondary">' + '<img src="' + window.STATIC_URL + 'entries/img/' + lexical_unit.opinion_key + '.svg" width="12" height="12" alt="' + lexical_unit.opinion + '"> ' + gettext(lexical_unit.opinion) + '</td>'; tbody.append(lexical_unit_row); } table.append(tbody); diff --git a/entries/static/entries/js/unification_entries_list.js b/entries/static/entries/js/unification_entries_list.js index cad878f4673672070f6a9e6b8f93a54cba33ecba..4f2fd5b1806865541a24935eb4f92b6619ee709c 100644 --- a/entries/static/entries/js/unification_entries_list.js +++ b/entries/static/entries/js/unification_entries_list.js @@ -26,7 +26,6 @@ function update_entries() { if (!row.data()) return; var drilldown = $("<div>").addClass("drilldown").data("row", this); row.child(drilldown).show(); - // tutaj zmiana na liste zunifikowanych ram setup_lexical_units_table(drilldown, row.data().lexical_units, can_see_assignees); drilldown.closest("td").addClass("p-0 pl-4"); } @@ -77,7 +76,7 @@ function setup_lexical_units_table(drilldown, lexical_units, can_see_assignees) }); } -function setup_notes($container, $template, lexical_unit_pk, entry) { +function setup_notes($container, $template, lexical_unit_pk, entry_pk) { $container.html($template.children().clone()); $('.show-note-form', $container).click(function () { $('.note-form', $container).html($('#note-form-template > div', $container).clone()); @@ -91,7 +90,7 @@ function setup_notes($container, $template, lexical_unit_pk, entry) { data : { note: $('.note-form textarea[name=note]').val() }, timeout : 5000, success : function (response) { - get_lexical_unit(lexical_unit_pk, entry); + get_lexical_unit(lexical_unit_pk, entry_pk); }, error : function () { alert(gettext('Nie udało się dodać notatki.')); @@ -111,7 +110,76 @@ function setup_notes($container, $template, lexical_unit_pk, entry) { }) } -function get_lexical_unit(pk, entry) { - get_entry(entry, false); // TODO replace with loading LU details view - setup_notes($('#lexical-unit-notes'), $('#lexical-unit-notes-template'), pk, entry); +function setup_unified_frame($container, frame, unified_frame, refresh) { + $container.html(''); + if (unified_frame) { + var $button_container = $('<div>').addClass("text-center"); + var $button = $('<a>').addClass('btn btn-sm btn-outline-dark mr-2'); + function go_to_unified_frame () { + window.location = `/${window.lang}/entries/unification_frames`; // TODO redirect properly + } + function invalid () { + $.ajax({ + type : 'post', + url : `/${lang}/semantics/frame_mark_as_invalid/${frame.id}/`, + dataType : 'json', + timeout : 60000, + }).then(refresh); + } + function take () { + $.ajax({ + type : 'post', + url : `/${lang}/semantics/frame_assign/${frame.id}/`, + dataType : 'json', + timeout : 60000, + }).then(go_to_unified_frame); + } + function confirm_invalid () { + $.ajax({ + type : 'post', + url : `/${lang}/semantics/frame_confirm_invalid/${frame.id}/`, + dataType : 'json', + timeout : 60000, + }).then(refresh); + } + function reject_invalid () { + $.ajax({ + type : 'post', + url : `/${lang}/semantics/frame_reject_invalid/${frame.id}/`, + dataType : 'json', + timeout : 60000, + }).then(refresh); + } + if (frame.status === 'N') { + $button_container.append($button.clone().html(gettext("Błędna")).click(invalid)); + $button_container.append($button.clone().html(gettext("Pobierz")).click(take)); + } else if (frame.status === 'O') { + $button_container.append($button.clone().html(gettext("Obrabiaj")).click(go_to_unified_frame)); + } else if (frame.status === 'G' && unified_frame.status === 'O') { + $button_container.append($button.clone().html(gettext("Obrabiaj")).click(go_to_unified_frame)); + } else if (frame.status === 'S' && unified_frame.status === 'S') { + $button_container.append($button.clone().html(gettext("Obejrzyj")).click(go_to_unified_frame)); + } else if (frame.status === 'B' && has_permission('semantics.manage_invalid_lexical_units')) { + $button_container.append($button.clone().html(gettext("Potwierdź")).click(confirm_invalid)); + $button_container.append($button.clone().html(gettext("Odrzuć")).click(reject_invalid)); + } + $container.append($button_container); + } else { + $container.append($('<p>').html(gettext("Brak ramy unifikacyjnej."))); + } +} + +function get_lexical_unit(lexical_unit_pk, entry_pk) { + $('#lexical-unit-notes').html(''); + $('#unified-frame').html(''); + get_entry(entry_pk, false, lexical_unit_pk).then(function (entry) { + var frame = entry.frames[0]; + setup_unified_frame( + $('#unified-frame'), + frame, + entry.unified_frame, + function () { get_lexical_unit(lexical_unit_pk, entry_pk); update_entries(); } + ); + setup_notes($('#lexical-unit-notes'), $('#lexical-unit-notes-template'), lexical_unit_pk, entry_pk); + }); } diff --git a/entries/templates/unification_lexical_unit_display.html b/entries/templates/unification_lexical_unit_display.html index cd6bcb568d4bdcfa6faaa5444cf63085649fc721..1668b5264a07dcc0715424a3eab416cddb5b3e85 100644 --- a/entries/templates/unification_lexical_unit_display.html +++ b/entries/templates/unification_lexical_unit_display.html @@ -5,6 +5,7 @@ <div class="row m-0 p-0" id="semantics-top-pane"> <div class="col h-100 px-1 pt-0 pb-0 overflow-auto" id="semantics-frames-pane"> <div id="semantics-frames"></div> + <div id="unified-frame" class="mb-3"></div> <div id="lexical-unit-notes-template" class="d-none">{% include 'notes.html' %}</div> <div id="lexical-unit-notes"></div> </div> diff --git a/entries/views.py b/entries/views.py index bd41a844fbdef104ffbd6d82409eb64fe4f44078..f238216ba7e51ff5a08c89b9781fac1a019a3841 100644 --- a/entries/views.py +++ b/entries/views.py @@ -22,6 +22,7 @@ from syntax.models import NaturalLanguageDescription, Schema from semantics.models import Frame, PredefinedSelectionalPreference, SelectivePreferenceRelations from common.decorators import ajax_required, ajax +from unifier.models import UnifiedFrame from .forms import ( EntryForm, @@ -415,9 +416,9 @@ def get_entries(request): 'pk': lu.pk, 'display': str(lu), 'assignee_username': ( - assignment.user.username if (assignment := lu.assignments.first()) else None + assignment.user.username if (frame := lu.frames.first()) and (assignment := frame.assignments.first()) else None ), - 'status': frame.status if (frame := lu.frames.first()) else "" + 'status': frame.status if (frame := lu.frames.first()) else "", } for lu in e.lexical_units.all() ] } @@ -540,6 +541,7 @@ def frame2dict(frame, entry_meanings): 'opinion' : FRAME_OPINION()[frame.opinion.key], 'opinion_key' : frame.opinion.key, 'id' : frame.id, + 'status' : frame.status, 'lexical_units' : [ { 'str' : lu.text_rep, @@ -732,6 +734,7 @@ def get_entry(request): apply_filters = not simplejson.loads(request.POST['no_filters']) filter_schemata = apply_filters and entry_form.cleaned_data['filter_schemata'] filter_frames = apply_filters and entry_form.cleaned_data['filter_frames'] + lexical_unit = LexicalUnit.objects.get(pk=lu_id) if (lu_id := request.POST.get("lexical_unit_id")) else None if filter_schemata: schema_forms = [] # e.g. entry has schema that satisfies X & entry has schema that satisfies Y @@ -803,18 +806,26 @@ def get_entry(request): # filter out frames by frame properties if filter_frames: frame_objects = get_filtered_objects2(frame_forms, frame_objects) + if lexical_unit: + frame_objects = frame_objects.filter(lexical_units=lexical_unit) if local_frame_form: frame_objects = get_filtered_objects(local_frame_form, frame_objects) frames = [frame2dict(frame, entry.lexical_units.all()) for frame in frame_objects] alternations, realisation_phrases, realisation_descriptions = get_alternations(all_schema_objects, frame_objects) examples = get_examples(entry) + unified_frame = None + if lexical_unit and (unified_frame := UnifiedFrame.objects.all().for_lexical_unit(lexical_unit).first()): + unified_frame = { + 'pk': unified_frame.pk, + 'status': unified_frame.status, + } # https://docs.djangoproject.com/en/2.2/topics/http/sessions/#when-sessions-are-saved if [entry.name, entry.id] in request.session['last_visited']: request.session['last_visited'].remove([entry.name, entry.id]) request.session['last_visited'].insert(0, (entry.name, entry.id)) request.session['last_visited'] = request.session['last_visited'][:(MAX_LAST_VISITED + 1)] request.session.modified = True - return JsonResponse({ 'subentries' : subentries, 'frames' : frames, 'alternations' : alternations, 'realisation_phrases' : realisation_phrases, 'realisation_descriptions' : realisation_descriptions, 'examples' : examples, 'last_visited' : request.session['last_visited'] }) + return JsonResponse({ 'subentries' : subentries, 'frames' : frames, 'alternations' : alternations, 'realisation_phrases' : realisation_phrases, 'realisation_descriptions' : realisation_descriptions, 'examples' : examples, 'unified_frame': unified_frame, 'last_visited' : request.session['last_visited'] }) return JsonResponse({}) ''' diff --git a/examples/migrations/__init__.py b/examples/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/meanings/migrations/__init__.py b/meanings/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/meanings/models.py b/meanings/models.py index 3eaaabf2fc0b4eb360b98091e11248ec4975bebb..7a46b0a189ca129a82609ed3c9e6f893d1b0f00f 100644 --- a/meanings/models.py +++ b/meanings/models.py @@ -1,4 +1,3 @@ -from django.contrib.contenttypes.fields import GenericRelation from django.db import models @@ -13,7 +12,6 @@ class LexicalUnit(models.Model): definition = models.TextField(default='') gloss = models.TextField(default='') text_rep = models.TextField() - assignments = GenericRelation("users.Assignment", content_type_field="subject_ct", object_id_field="subject_id") class Meta: unique_together = ('base', 'sense', 'pos',) diff --git a/meanings/views.py b/meanings/views.py index 91ea44a218fbd2f408430959283f0419c921093e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/meanings/views.py +++ b/meanings/views.py @@ -1,3 +0,0 @@ -from django.shortcuts import render - -# Create your views here. diff --git a/phrase_expansions/migrations/__init__.py b/phrase_expansions/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/semantics/choices.py b/semantics/choices.py index d248493f6ee99ce0ad2417636c1fbe7f2b593730..2d644ab334711dccf2e8ada0855c350872397bae 100644 --- a/semantics/choices.py +++ b/semantics/choices.py @@ -2,7 +2,10 @@ from django.db import models from django.utils.translation import gettext_lazy as _ -class LexicalUnitStatus(models.TextChoices): +class FrameStatus(models.TextChoices): + NEW = "N", _("nowa") PROCESSING = "O", _("w obróbce") READY = "G", _("gotowe") VERIFIED = "S", _("sprawdzone") + INVALID = "B", _("błędna") # set by lexicographs + BAD = "Z", _("zła") # confirmed by super lexicographs diff --git a/semantics/migrations/__init__.py b/semantics/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/semantics/models.py b/semantics/models.py index c746064473c4caa2e02cf1e88001e77c27209a93..e9ddba0ab0c6d555ecfbfecbccde0ed486309afc 100644 --- a/semantics/models.py +++ b/semantics/models.py @@ -1,3 +1,4 @@ +from django.contrib.contenttypes.fields import GenericRelation from django.db import models from meanings.models import LexicalUnit, Synset @@ -11,9 +12,10 @@ class Frame(models.Model): arguments_count = models.PositiveIntegerField(null=False, default=0) #na potrzeby filtrowania status = models.TextField( max_length=10, - choices=choices.LexicalUnitStatus.choices, - default=choices.LexicalUnitStatus.PROCESSING, + choices=choices.FrameStatus.choices, + default=choices.FrameStatus.NEW, ) + assignments = GenericRelation("users.Assignment", content_type_field="subject_ct", object_id_field="subject_id") def sorted_arguments(self): # TODO: zaimplementowac wlasciwe sortowanie return Argument.objects.filter(frame=self) diff --git a/semantics/urls.py b/semantics/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..48d7e8569b2705f16df8dc77f8f8375a122231ff --- /dev/null +++ b/semantics/urls.py @@ -0,0 +1,12 @@ +from django.urls import path + +from . import views + +app_name = 'semantics' + +urlpatterns = [ + path('frame_mark_as_invalid/<int:frame_pk>/', views.frame_mark_as_invalid, name='frame_mark_as_invalid'), + path('frame_assign/<int:frame_pk>/', views.frame_assign, name='frame_assign'), + path('frame_confirm_invalid/<int:frame_pk>/', views.frame_confirm_invalid, name='frame_confirm_invalid'), + path('frame_reject_invalid/<int:frame_pk>/', views.frame_reject_invalid, name='frame_reject_invalid'), +] diff --git a/semantics/views.py b/semantics/views.py index 91ea44a218fbd2f408430959283f0419c921093e..719f55e2cc916f80a2ba7d48798f6f68fc046c22 100644 --- a/semantics/views.py +++ b/semantics/views.py @@ -1,3 +1,52 @@ -from django.shortcuts import render +from django.contrib.auth.decorators import permission_required +from django.core.exceptions import ValidationError +from django.db import transaction +from django.shortcuts import get_object_or_404 -# Create your views here. +from common.decorators import ajax +from users.models import Assignment + +from . import choices +from .models import Frame + + +@ajax(login_required=True, method='post') +@transaction.atomic +def frame_mark_as_invalid(request, frame_pk): + frame = get_object_or_404(Frame.objects.filter(status=choices.FrameStatus.NEW).select_for_update(), pk=frame_pk) + frame.status = choices.FrameStatus.INVALID + frame.save() + return {} + + +@ajax(login_required=True, method='post') +@transaction.atomic +def frame_assign(request, frame_pk): + frame = get_object_or_404( + Frame.objects.filter(status=choices.FrameStatus.NEW).select_for_update(), + pk=frame_pk, + ) + frame.status = choices.FrameStatus.PROCESSING + Assignment.assign(user=request.user, subject=frame) + frame.save() + return {} + + +@ajax(login_required=True, method='post') +@transaction.atomic +@permission_required('semantics.manage_invalid_lexical_units') +def frame_confirm_invalid(request, frame_pk): + frame = get_object_or_404(Frame.objects.filter(status=choices.FrameStatus.INVALID).select_for_update(), pk=frame_pk) + frame.status = choices.FrameStatus.BAD + frame.save() + return {} + + +@ajax(login_required=True, method='post') +@transaction.atomic +@permission_required('semantics.manage_invalid_lexical_units') +def frame_reject_invalid(request, frame_pk): + frame = get_object_or_404(Frame.objects.filter(status=choices.FrameStatus.INVALID).select_for_update(), pk=frame_pk) + frame.status = choices.FrameStatus.NEW + frame.save() + return {} diff --git a/shellvalier/urls.py b/shellvalier/urls.py index 985cf8e775a3c636ae593934bf3d41250d12ee69..9f5e11f22bdd76b9a2f319160ef0d955a0bc62b4 100644 --- a/shellvalier/urls.py +++ b/shellvalier/urls.py @@ -16,6 +16,7 @@ urlpatterns = i18n_patterns( path('users/', include('users.urls')), path('jsi18n/', JavaScriptCatalog.as_view(), name='javascript-catalog'), path('admin/', admin.site.urls, name='admin'), + path('semantics/', include('semantics.urls')), path('unifier/', include('unifier.urls')), path('', dash, name='dash'), # uncomment to leave default (Polish) urls unchanged diff --git a/syntax/migrations/__init__.py b/syntax/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/unifier/choices.py b/unifier/choices.py new file mode 100644 index 0000000000000000000000000000000000000000..756468815f3a83c24d521a9f400779f7f32661f9 --- /dev/null +++ b/unifier/choices.py @@ -0,0 +1,8 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class UnifiedFrameStatus(models.TextChoices): + PROCESSING = "O", _("w obróbce") + READY = "G", _("gotowe") + VERIFIED = "S", _("sprawdzone") diff --git a/unifier/migrations/__init__.py b/unifier/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/unifier/models.py b/unifier/models.py index fc2d74a20ad8b57d6ebf0ddd1ece8a3f2b5900fe..2408c485d44b4c48e57f18d926b75d852a3be946 100644 --- a/unifier/models.py +++ b/unifier/models.py @@ -1,23 +1,45 @@ -from django.db import models +from copy import deepcopy +from typing import List, Optional + +from django.db import models, transaction from meanings.models import LexicalUnit, Synset -from semantics.models import choices, PredefinedSelectionalPreference, RelationalSelectionalPreference, ArgumentRole, \ +from semantics.models import PredefinedSelectionalPreference, RelationalSelectionalPreference, ArgumentRole, \ RoleType, Argument, Frame, SelectionalPreferenceRelation +from . import choices + + +class UnifiedFrameQueryset(models.QuerySet): + def for_lexical_unit(self, lexical_unit): + return self.filter(unified_frame_2_slowal_frame__slowal_frame__lexical_units=lexical_unit) + class UnifiedFrame(models.Model): status = models.TextField( max_length=10, - choices=choices.LexicalUnitStatus.choices, - default=choices.LexicalUnitStatus.PROCESSING, + choices=choices.UnifiedFrameStatus.choices, + default=choices.UnifiedFrameStatus.PROCESSING, ) title = models.CharField(max_length=200, default=None, blank=True, null=True) + objects = models.Manager.from_queryset(UnifiedFrameQueryset)() + def sorted_arguments(self): # TODO: zaimplementowac wlasciwe sortowanie return UnifiedFrameArgument.objects.filter(frame=self) def __str__(self): return '%s: %s' % (self.opinion, ' + '.join([str(arg) for arg in self.sorted_arguments()])) + + @transaction.atomic + def extract_frames_to( + self, slowal_frames: List[Frame], new_frame: Optional["UnifiedFrame"] = None + ) -> "UnifiedFrame": + if not new_frame: + new_frame = UnifiedFrame.objects.create(title=self.title) + raise NotImplementedError() # TODO move slowal frames to `new_frame` + return new_frame + class UnifiedFrameArgument(models.Model): id = models.CharField(max_length=20, primary_key=True) diff --git a/unifier/views.py b/unifier/views.py index a114f106e47631c7313b783f439743ad878d923b..c9426e74851b965d0ce5b4a6e44f720c67060b61 100644 --- a/unifier/views.py +++ b/unifier/views.py @@ -68,7 +68,7 @@ def get_unified_frames(request): 'title': title, 'status': value[0].unified_frame.status, 'assignee_username': ( - assignment.user.username if (assignment := value[0].slowal_frame.lexical_units.first().assignments.first()) else None + assignment.user.username if (assignment := value[0].slowal_frame.assignments.first()) else None ), }) diff --git a/users/management/commands/create_groups_and_permissions.py b/users/management/commands/create_groups_and_permissions.py index d6f71f3d2402252801da7f4b7e0d72e0c2d14684..b05773230c9550175225e71490a9f4c67b77c9d2 100644 --- a/users/management/commands/create_groups_and_permissions.py +++ b/users/management/commands/create_groups_and_permissions.py @@ -3,6 +3,7 @@ from django.contrib.auth.models import Group, Permission, User from django.contrib.contenttypes.models import ContentType from django.core.management.base import BaseCommand +from semantics.models import Frame from users.models import Assignment, Note @@ -11,7 +12,12 @@ class Command(BaseCommand): Permission.objects.update_or_create( content_type=ContentType.objects.get_for_model(Note), codename="view_all_notes", - defaults={"name": "View all notes"} + defaults={"name": "View all Notes"} + ) + Permission.objects.update_or_create( + content_type=ContentType.objects.get_for_model(Frame), + codename="manage_invalid_lexical_units", + defaults={"name": "Manage invalid Lexical Units"} ) admins, __ = Group.objects.get_or_create(name='Admini') admins.permissions.add( @@ -30,6 +36,7 @@ class Command(BaseCommand): super_lexicographs.permissions.add( self._get_permission(Assignment, 'view_assignment'), self._get_permission(Note, 'view_all_notes'), + self._get_permission(Frame, 'manage_invalid_lexical_units'), ) def _get_permission(self, model, codename) -> Permission: diff --git a/users/migrations/__init__.py b/users/migrations/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/users/models.py b/users/models.py index 10496b8a218808f581b6e074d3e3d111be7e6222..df1755846d324e36822827e7fa5f6e4c3a4dd879 100644 --- a/users/models.py +++ b/users/models.py @@ -16,6 +16,14 @@ class Assignment(models.Model): ("subject_ct", "subject_id"), ] + @classmethod + def assign(cls, user, subject): + Assignment.objects.get_or_create( + user=user, + subject_ct=ContentType.objects.get_for_model(subject), + subject_id=subject.pk, + ) + class NoteQuerySet(models.QuerySet): def for_user(self, user):