diff --git a/entries/static/entries/css/unification_frames.css b/entries/static/entries/css/unification_frames.css index 7946523a1ae59a380d2bcb10d9754edd1660132a..bfe6d5fdc52b5d73530e7d37cc5ab817fd0ba5d7 100644 --- a/entries/static/entries/css/unification_frames.css +++ b/entries/static/entries/css/unification_frames.css @@ -26,3 +26,7 @@ table.table-button-menu { #unified-frame .argument.active { background-color: #dee1e4; } + +#free-lus-frame .argument.active { + background-color: #dee1e4; +} diff --git a/entries/views.py b/entries/views.py index 5435fcf62b622291bb47ce8685983d40dfcafd19..0de4763e1442c8a422ce0c4299a0f205731d726e 100644 --- a/entries/views.py +++ b/entries/views.py @@ -9,7 +9,7 @@ import simplejson from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required -from django.db.models import Prefetch, Q +from django.db.models import Prefetch, Q, Exists, OuterRef from django.http import JsonResponse, QueryDict from django.shortcuts import render from django.template.context_processors import csrf @@ -445,7 +445,9 @@ def get_entries(request): #entries = entries.filter(subentries__schema_hooks__alternation=2) if without_frames: - entries = entries.filter(lexical_units__frames__isnull=True) + entries = entries.filter(Exists(LexicalUnit.objects.filter(base=OuterRef('name'), frames__isnull=True))) + # entries = entries.filter(~Exists(LexicalUnit.objects.filter( + # ~Exists(Frame.objects.filter(frames=OuterRef('pk')))))) total = entries.count() if scroller_params['filter']: @@ -1130,11 +1132,10 @@ def ajax_synsets(request, base, pos): def lexical_units_without_empty_frames(obj_results): for lu in obj_results.all(): - lu._frames = lu._frames[0] if lu._frames and len(lu._frames) > 0 else None - if lu._frames is not None: - continue - else: + if lu._frames and len(lu._frames) > 0: yield lu + else: + continue @ajax(method='get', encode_result=True) diff --git a/freelus/urls.py b/freelus/urls.py index 6119d3ca7b568643f8194e2c1ef8c55aa09f8f62..9291677b99e2f44bcfc17e8af9d289c2ba9d62d6 100644 --- a/freelus/urls.py +++ b/freelus/urls.py @@ -6,4 +6,7 @@ app_name = 'freelus' urlpatterns = [ path('create_new_slowal_frame/', views.create_new_slowal_frame, name='create_new_slowal_frame'), + path('add_argument_to_frame/', views.add_argument_to_frame, name='add_argument_to_frame'), + path('change_role/', views.change_role, name='change_role'), + ] diff --git a/freelus/views.py b/freelus/views.py index f6832f993b2b3281c23c053c451957ea194ead5e..3c929bb96d717f57893379fc9700f2b8a839afa8 100644 --- a/freelus/views.py +++ b/freelus/views.py @@ -5,7 +5,8 @@ from django.http import JsonResponse from common.decorators import ajax_required from connections.models import Entry, Status from meanings.models import LexicalUnit -from semantics.models import Frame, FrameOpinion +from semantics.models import Frame, FrameOpinion, Argument, ArgumentRole, SemanticRole, RoleAttribute, RoleSubAttribute, \ + RoleType @ajax_required @@ -45,3 +46,53 @@ def create_new_slowal_frame(request): return JsonResponse({}) return JsonResponse({}) + + +@ajax_required +@transaction.atomic +def add_argument_to_frame(request): + if request.method == 'POST': + frame_id = request.POST['frame_id'] + frame = Frame.objects.get(id=frame_id) + + argument = Argument(frame=frame) + change_role_base(argument, request) + argument.save() + + return JsonResponse({}) + + return JsonResponse({}) + + +@ajax_required +@transaction.atomic +def change_role(request): + if request.method == 'POST': + frame_id = request.POST['frame_id'] + argument_id = request.POST['argument_id'] + + frame_argument = Argument.objects.get(frame_id=frame_id, id=argument_id) + change_role_base(frame_argument, request) + frame_argument.save() + return JsonResponse({}) + + +def change_role_base(frame_argument, request): + role_id = request.POST['role_id'] + role_type = request.POST['role_type'] + attribute_id = request.POST.get('attribute_id', None) + sub_attribute_id = request.POST.get('sub_attribute_id', None) + + argument_role = ArgumentRole.objects.filter(role_id=role_id, attribute_id=attribute_id, + sub_attribute_id=sub_attribute_id).first() + if argument_role is None: + argument_role = ArgumentRole(role=SemanticRole.objects.get(pk=role_id), + attribute=None if attribute_id is None else RoleAttribute.objects.get(pk=attribute_id), + sub_attribute=RoleSubAttribute.objects.get(pk=sub_attribute_id)) + argument_role.save() + + frame_argument.role = argument_role + frame_argument.role_type = RoleType.objects.get(type=role_type) + + + diff --git a/frontend/src/components/unification/Unification/LexicalUnitEdit.vue b/frontend/src/components/unification/Unification/LexicalUnitEdit.vue index f841afccb14992c97cff1f1a3c20becb1c527695..c6a76a386e4feb1217d47b81d1cec51734a63a15 100644 --- a/frontend/src/components/unification/Unification/LexicalUnitEdit.vue +++ b/frontend/src/components/unification/Unification/LexicalUnitEdit.vue @@ -735,7 +735,7 @@ Object.assign(LexicalUnitEdit, { (request, errorType, errorMessage) => { show_error(errorType + ' (' + errorMessage + ')'); alert(gettext("Status ramy niew został zmieniony. Błąd: "+errorType + ' (' + errorMessage + ')')); - }) + }); }); }, slowal_frame_ready_rollback(status) { diff --git a/frontend/src/components/unification/free_lu/FreeLuEdit.vue b/frontend/src/components/unification/free_lu/FreeLuEdit.vue index 4f552fa6d87f9195ca001dab3928b7e99ecf4000..1f9439147293d8bfce821859bac59edc562a0a51 100644 --- a/frontend/src/components/unification/free_lu/FreeLuEdit.vue +++ b/frontend/src/components/unification/free_lu/FreeLuEdit.vue @@ -8,7 +8,7 @@ import MeaningComponent from "../shared/frame-components/MeaningComponent.vue"; import SelectionalPreference from "../Unification/SelectionalPreference.js"; import FreeLuPreview from "./FreeLuPreview.vue"; import FreeLuElement from "./FreeLuElement.vue"; -import {frames2lexical_units} from "../shared/utils"; +import {frames2lexical_units, send_post_request} from "../shared/utils"; let FreeLuEdit = { components: {FreeLuElement, FreeLuPreview} @@ -55,10 +55,11 @@ Object.assign(FreeLuEdit, { hidden_frames: [], hierarchy_hyponyms: null, lexicalUnitsVisible: true, + selected_frame_argument_id: null, } }, components: {FreeLuElement, InfoTooltip, Spinner, FreeLuPreview, SlowalFrameComponent, ExamplesComponent, SemanticsSchemataComponent, MeaningComponent}, - emits: ['goToDisplay', 'refresh', 'swapFrames', 'refreshEntriesList', 'clearUnifiedFrameView'], + emits: ['frameSelectionChanged'], watch: { forceRefresh(newVal, oldVal) { this.loadFrame(); @@ -201,7 +202,151 @@ Object.assign(FreeLuEdit, { } } $.prompt(extract_frames_to_new_frame_popup); - } + }, + // add_argument() { + // if(this.frame_in_progress) { + // send_post_request('/freelus/add_argument_to_frame/', + // { + // 'frame_id': this.frame_in_progress.id, + // }, + // (reponse) => { + // show_info('Argument został dodany.'); + // alert(gettext("Argument został dodany.")); + // this.loadEntry(); + // }, + // (request, errorType, errorMessage) => { + // show_error(errorType + ' (' + errorMessage + ')'); + // alert(gettext("Dodanie argumentu nie powiodło się. Błąd: "+errorType + ' (' + errorMessage + ')')); + // }) + // } else { + // alert(gettext("Stwórz nową ramę.")); + // } + // }, + change_frame_opinion() { + if(this.frame_in_progress) { + send_post_request('/freelus/change_frame_opinion/', + { + 'frame_id': this.frame_in_progress.id, + 'opinion': frame.id, + }, + (reponse) => { + show_info('Opinia została zmieniona.'); + alert(gettext("Opinia została zmieniona.")); + this.loadEntry(); + }, + (request, errorType, errorMessage) => { + show_error(errorType + ' (' + errorMessage + ')'); + alert(gettext("Zmiana opinii nie powiodła się. Błąd: "+errorType + ' (' + errorMessage + ')')); + }) + } else { + alert(gettext("Stwórz nową ramę.")); + } + }, + roleStrMapping(roleName) { + if(roleName === 'role') { + return 'required'; + } else if(roleName === 'modifier') { + return 'typical'; + } else { + return roleName; + } + }, + change_role(selected_frame_argument_id, api_path) { + if (selected_frame_argument_id === null) { + alert(gettext("Zaznacz argument, dla którego chcesz wybrać rolę.")); + } else { + const newSelect = function () { + let rolesHTML = roles.map(role => { + return `<label style="background-color:rgb(${role.color})"><input type="radio" name="role" value="${role.id}" /> ${role.role}</label><br />`; + }).join(""); + let attributesHTML = role_attributes.map(attribute => { + return `<label><input type="radio" name="attribute" value="${attribute.id}" /> ${attribute.attribute}</label><br />`; + }).join(""); + let subAttributesHTML = role_sub_attributes.map(subAttribute => { + return `<label><input type="radio" name="sub_attribute" value="${subAttribute.id}" /> ${subAttribute.sub_attribute}</label><br />`; + }).join(""); + // const roleTypeHTML = ['required', 'typical'].map(type => { + const roleTypeHTML = ['role', 'modifier'].map(type => { + return `<label><input type="radio" name="role_type" value="${type}" /> ${this.roleStrMapping(type)}</label><br />`; + }).join(""); + return '<div class="row">' + + '<div class="column"><div class="role_select_header">Type</div>' + roleTypeHTML + '</div>' + + '<div class="column"><div class="role_select_header">Role</div>' + rolesHTML + '</div>' + + '<div class="column"><div class="role_select_header">Atrybuty</div>' + attributesHTML + '</div>' + + '<div class="column"><div class="role_select_header">Podatrybuty</div>' + subAttributesHTML + '</div>' + + '</div>'; + }.bind(this); + + let change_role_popup = { + state0: { + title: 'Dodaj rolę', + html: newSelect(), + buttons: {Anuluj: -1, Zatwierdź: 1}, + focus: -1, + submit: function (e, v, m, f) { + if (v == -1) { + $.prompt.close(); + } + if (v == 1) { + e.preventDefault(); + + const role_id = normalizeFormData(f.role)[0]; + const role_type = normalizeFormData(f.role_type)[0]; + + if (role_id != null && role_type != null) { + const attribute_id = normalizeFormData(f.attribute)[0]; + + const sub_attribute_id = normalizeFormData(f.sub_attribute)[0]; + + const data = { + 'frame_id': this.frame_in_progress.id, + 'argument_id': selected_frame_argument_id, + 'role_type': role_type, + 'role_id': role_id, + 'attribute_id': attribute_id, + 'sub_attribute_id': sub_attribute_id + }; + $.ajax({ + type: 'post', + url: '/' + lang + '/freelus/' + api_path + '/', + dataType: 'json', + data: data, + timeout: 60000, + success: function (response) { + alert(gettext("Nowa rola zosała zapisana.")); + show_info('Nowa rola zosała zapisana.'); + this.loadEntry(); + $.prompt.close(); + }.bind(this), + error: function (request, errorType, errorMessage) { + show_error(errorType + ' (' + errorMessage + ')'); + $.prompt.close(); + } + }); + } else { + alert(gettext("Musisz wybrać typ oraz rolę.")); + } + } + }.bind(this) + } + }; + $.prompt(change_role_popup); + } + }, + computeArgumentCSS(argument) { + const selectedExampleFrameArguments = this.selectedExamples && this.selectedExamples.length > 0 ? new Set(this.selectedExamples.map(e => e.argument_ids).flat()) : null; + return argument.role + ' ' + (argument.id === this.selected_frame_argument_id ? 'active' : argument.hover ? 'bg-highlight' : '') + + (selectedExampleFrameArguments != null ? selectedExampleFrameArguments.has(argument.id) ? 'example-yes' : 'example-no' : ''); + }, + selectArgument(argument) { + if(this.selected_frame_argument_id != argument.id) { + this.selected_frame_argument_id = argument.id; + } else { + this.selected_frame_argument_id = null; + } + // const selectedArguments = this.frame_in_progress.arguments.filter(argument => argument.selected) + // this.$emit('frameSelectionChanged', selectedArguments); + }, }, mounted() { if(this.entryId) { @@ -236,6 +381,9 @@ export default FreeLuEdit; <table class="table-button-menu sticky-top" cellspacing="1"> <tr style="background-color: white;"> <td id="create-new-frame" @click="create_new_slowal_frame()" style="padding: 10px 15px 10px 15px; color: #000000;">Nowa rama</td> + <td id="add-argument" @click="change_role(-1, 'add_argument_to_frame')" style="padding: 10px 15px 10px 15px; color: #000000;">Dodaj argument</td> + <td id="change-role" @click="change_role(selected_frame_argument_id ? selected_frame_argument_id.split('-')[1] : null, 'change_role')" style="padding: 10px 15px 10px 15px; color: #000000;">Zmień rolę</td> + <td id="assign-examples" @click="assign_examples()" style="padding: 10px 15px 10px 15px; color: #000000;">Podłącz przykłady</td> <!-- <td id="add-arg" @click="create_hyponym_or_hyperonym_relation(true)" style="padding: 10px 15px 10px 15px; color: #000000;">Podrama</td>--> <!-- <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="delete_hyponym_or_hyperonym_relation">Usuń powiązanie</td>--> <!-- <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="goToEdit">Edytuj</td>--> @@ -318,7 +466,7 @@ export default FreeLuEdit; </div> <div class="row"> <div class="col px-0 frame mb-3 active"> - <table class="table m-0 table-borderless border border-secondary text-dark"> + <table id="free-lus-frame" class="table m-0 table-borderless border border-secondary text-dark"> <tbody> <tr class="opinion-row"> <th scope="row" class="py-2 px-1 text-secondary" style="width: 3em;">Opinia</th>