diff --git a/entries/static/entries/css/entries.css b/entries/static/entries/css/entries.css index 4094eedbc7dc89dd7e7eb3fb2ba23599de5d1d64..3cd0c90d22453b0348b4d7a51ac015491b3df867 100644 --- a/entries/static/entries/css/entries.css +++ b/entries/static/entries/css/entries.css @@ -192,7 +192,7 @@ legend { text-decoration: underline; } -.lu-cursor-pointer { +.cursor-pointer { cursor: pointer; } @@ -276,3 +276,13 @@ legend { accent-color: green; pointer-events: none; } + +.hierarchy_not_exists { + background-color: rgba(138, 11, 17, 0.14) !important; +} + +.table-primary, +.table-primary>td, +.table-primary>th { + background-color:#bfbfbf !important; +} diff --git a/entries/static/entries/js/entries.js b/entries/static/entries/js/entries.js index 67bca83ef75bcaa1b37bfb17518da4c36100e354..f4370f3dd0a900ea48a8e4b8d571cbc6d2064a07 100644 --- a/entries/static/entries/js/entries.js +++ b/entries/static/entries/js/entries.js @@ -1004,6 +1004,9 @@ function setup_datatable(options) { { $(this).removeClass('tr-hover'); }); + if (options.setup_hierarchy_marking === true && data.hierarchy_exists !== true) { + $(row).addClass('hierarchy_not_exists'); + } }, initComplete: function(settings, json) { // display the first entry once it’s loaded diff --git a/entries/static/entries/js/unification_entries_list.js b/entries/static/entries/js/unification_entries_list.js index c7fc045651eea108ffcc3be1efd3da7e47c96f62..3ad96409b519ef14d3f9f99ca0f5146dc58cb965 100644 --- a/entries/static/entries/js/unification_entries_list.js +++ b/entries/static/entries/js/unification_entries_list.js @@ -84,7 +84,7 @@ function setup_lexical_units_table(drilldown, lexical_units, can_see_assignees, }); } -function show_notes_form($container, pk, model, refreshFunction, title, body) { +function show_notes_form($container, pk, model, refreshFunction, type, title, body) { $('.note-form', $container).html($('#note-form-template > div', $container).clone()); $('.hide-note-form', $container).click(function () { $('.note-form', $container).html(''); @@ -92,7 +92,7 @@ function show_notes_form($container, pk, model, refreshFunction, title, body) { $('.add-note', $container).click(function () { $.ajax({ type: 'post', - url: $('#note-form-template').data('url').replace('MODEL', model).replace('PK', pk), + url: $('#note-form-template').data('url').replace('MODEL', model).replace('PK', pk).replace('TYPE', type), dataType: 'json', data: { title: $('.note-form input[name=title]').val(), @@ -117,18 +117,18 @@ function show_notes_form($container, pk, model, refreshFunction, title, body) { } } -function setup_notes($container, $template, pk, model, refreshFunction, title, body) { +function setup_notes($container, $template, pk, model, refreshFunction, type, title, body) { $container.html($template.children().clone()); $('.show-note-form', $container).click(function () { - show_notes_form($container, pk, model, refreshFunction, title, body); + show_notes_form($container, pk, model, refreshFunction, type, title, body); return false }); if(title || body) { - show_notes_form($container, pk, model, refreshFunction, title, body); + show_notes_form($container, pk, model, refreshFunction, type, title, body); } $.ajax({ type: 'get', - url: $('.notes-table').data('url').replace('MODEL', model).replace('PK', pk), + url: $('.notes-table').data('url').replace('MODEL', model).replace('PK', pk).replace('TYPE', type), success: function (data) { data.notes.map(function (note) { $('.notes-table tbody', $container).append( diff --git a/entries/static/entries/js/unification_frames_list.js b/entries/static/entries/js/unification_frames_list.js index 58bb40db4fed866a8f7fbcaeca5d06809510cbaf..458283519b34df00aa6a6fc79aa6d9219d88a492 100644 --- a/entries/static/entries/js/unification_frames_list.js +++ b/entries/static/entries/js/unification_frames_list.js @@ -21,6 +21,7 @@ function setup_frames_list(options) { ], hidden_columns: can_see_assignees ? [3] : [2,3], selectEntryId: options.selectEntryId, + setup_hierarchy_marking: true }); datatable.on('click', 'tr.entry', function () { const data = datatable.row(this).data(); diff --git a/entries/templates/entries_base.html b/entries/templates/entries_base.html index 974596005e1913bef44ffe68019dfdf96c013854..2d460c0374f13f21861affed86dd5eaf52d36cdf 100644 --- a/entries/templates/entries_base.html +++ b/entries/templates/entries_base.html @@ -30,7 +30,10 @@ {% block additional-nav-items %} {% if request.user.is_authenticated %} <li class="nav-item"><a href="{% url 'entries:unification' %}" class="nav-link">{% trans "Unifikacja" %}</a></li> - <li class="nav-item"><a href="{% url 'entries:hierarchy' %}" class="nav-link">{% trans "Hierarchia" %}</a></li> + <li class="nav-item"><a + onclick='window.location.replace(window.currUnifiedFrameId ? "/pl/entries/hierarchy/?unified_frame_id="+window.currUnifiedFrameId : "/pl/entries/hierarchy")' + class="nav-link cursor-pointer">{% trans "Hierarchia" %}</a></li> + {% endif %} <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" href="#" id="nav-filters" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> diff --git a/entries/templates/hierarchy.html b/entries/templates/hierarchy.html index 6c757149c1cb09c826fc901e5f7438f400eecc27..61a407d1fde4b143dca2d57d635671e05122d362 100644 --- a/entries/templates/hierarchy.html +++ b/entries/templates/hierarchy.html @@ -14,7 +14,7 @@ <script src="{% static 'entries/js/unification_entries_for_frames_list.js' %}"></script> <script src="{% static 'entries/js/jquery-impromptu.min.js' %}"></script> <script> - window.initialUnifiedFrameId = {{ unified_frame_id|default:'null' }}; + window.currUnifiedFrameId = {{ unified_frame_id|default:'null' }}; </script> {% endblock %} diff --git a/entries/views.py b/entries/views.py index 1bd5081164e0066c14816afa5d673c4f02fa344c..686d92503c6e64aac482b5ecef552af57026d622 100644 --- a/entries/views.py +++ b/entries/views.py @@ -86,14 +86,20 @@ def unification(request): }, ) + @login_required def hierarchy(request): + + unified_frame_id = None + if "unified_frame_id" in request.GET: + unified_frame_id = request.GET.get("unified_frame_id") + return render( request, 'hierarchy.html', { 'is_vue_app': True, - 'unified_frame_id': request.GET.get("unified_frame_id"), + 'unified_frame_id': unified_frame_id, 'entries_form': EntryForm(), 'frames_form': FrameFormFactory.get_form(as_subform=False), 'schemata_form': SchemaFormFactory.get_form(as_subform=False), diff --git a/frontend/src/components/unification/Unification/LexicalUnitEdit.vue b/frontend/src/components/unification/Unification/LexicalUnitEdit.vue index 2afeec26e2c2c669cd69d707fc941d1dce4c22ed..a2ea35f7644d1f648b8e4925702d054a5bfb4947 100644 --- a/frontend/src/components/unification/Unification/LexicalUnitEdit.vue +++ b/frontend/src/components/unification/Unification/LexicalUnitEdit.vue @@ -115,16 +115,16 @@ Object.assign(LexicalUnitEdit, { } }, setup_notes_unified_frame() { - setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.unified_frame.id, 'unifier.UnifiedFrame', this.setup_notes_unified_frame); + setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.unified_frame.id, 'unifier.UnifiedFrame', this.setup_notes_unified_frame, 'unified_frame'); }, setup_notes_slowal_frame() { if (this.active_slowal_frame) { - setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.active_slowal_frame.id, 'semantics.Frame', this.setup_notes_slowal_frame); + setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.active_slowal_frame.id, 'semantics.Frame', this.setup_notes_slowal_frame, 'semantics_frame'); } }, setup_notes_slowal_frame_with_title_and_body(title, body) { this.right_pane_tab = 'notes'; - setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.active_slowal_frame.id, 'semantics.Frame', this.setup_notes_slowal_frame, title, body); + setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.active_slowal_frame.id, 'semantics.Frame', this.setup_notes_slowal_frame, 'semantics_frame', title, body); }, unifiedFrameArgumentSelected(argument) { if (this.active_unified_frame_argument === argument) { diff --git a/frontend/src/components/unification/Unification/Unification.vue b/frontend/src/components/unification/Unification/Unification.vue index 926824132d8e764fd7a0e554ff4c370be9639133..2ab9367c8e2c156700fab153afe6597a750375fa 100644 --- a/frontend/src/components/unification/Unification/Unification.vue +++ b/frontend/src/components/unification/Unification/Unification.vue @@ -22,6 +22,7 @@ export default { this.unifiedFrameId = unifiedFrameId; this.entryId = entryId; this.lexicalUnitId = lexicalUnitId; + window.currUnifiedFrameId = unifiedFrameId; }, refreshEntriesList() { this.unificationEntriesListRefreshKey++; diff --git a/frontend/src/components/unification/hierarchy/Hierarchy.vue b/frontend/src/components/unification/hierarchy/Hierarchy.vue index 82876fe016c46921e13a09d44b1badf259188107..af652e5970f5e7ad212c847c65304efcc8445880 100644 --- a/frontend/src/components/unification/hierarchy/Hierarchy.vue +++ b/frontend/src/components/unification/hierarchy/Hierarchy.vue @@ -28,15 +28,13 @@ export default { } }, setup() { - const lexicalUnit = new URL(location.href).searchParams.get('lexical_unit_id'); - const entryId = new URL(location.href).searchParams.get('entry_id'); + const unified_frame_id = new URL(location.href).searchParams.get('unified_frame_id'); return { - initialLexicalUnitId: parseInt(lexicalUnit), - initialEntryId: parseInt(entryId), + initial_unified_frame_id: parseInt(unified_frame_id), }; }, mounted () { - this.unifiedFrameSelected(window.initialUnifiedFrameId); + this.unifiedFrameSelected(window.currUnifiedFrameId); $('#entries-list').length && Split(['#entries-list', '#entry-display'], { sizes: [20, 80], gutterSize: 4, @@ -56,6 +54,7 @@ export default { <div id="entries-list-div" class="col p-0 h-100 w-100 overflow-hidden"> <unification-frames-list :unificationEntriesListRefreshKey="unificationEntriesListRefreshKey" + :initialUnifiedFrameId="initial_unified_frame_id" @unified-frame-selected="unifiedFrameSelected" /> <!-- <unification-switchable-list--> diff --git a/frontend/src/components/unification/hierarchy/HierarchyEdit.vue b/frontend/src/components/unification/hierarchy/HierarchyEdit.vue index 79f174b87a15c08428776411a04a01850eb37f91..80b326ac5b1497f84aeb8d5db2c2b20d00e15838 100644 --- a/frontend/src/components/unification/hierarchy/HierarchyEdit.vue +++ b/frontend/src/components/unification/hierarchy/HierarchyEdit.vue @@ -6,12 +6,12 @@ import SlowalFrameComponent from "../shared/frame-components/SlowalFrameComponen import SemanticsSchemataComponent from "../shared/frame-components/SemanticsSchemataComponent.vue"; import MeaningComponent from "../shared/frame-components/MeaningComponent.vue"; import SelectionalPreference from "../Unification/SelectionalPreference.js"; -import UnificationFramePreview from "../Unification/UnificationFramePreview.vue"; import { slowal_frames2selecional_preferencies } from "../shared/utils.js"; import HierarchyPreview from "./HierarchyPreview.vue"; +import HierarchyElement from "./HierarchyElement.vue"; let HierarchyEdit = { - components: {HierarchyPreview} + components: {HierarchyElement, HierarchyPreview} }; Object.assign(HierarchyEdit, { @@ -57,9 +57,11 @@ Object.assign(HierarchyEdit, { selectedSchemas: null, selectedExamples: null, hidden_frames: [], + hierarchy_hyponyms: null, + hierarchy_hyperonyms: null, } }, - components: {InfoTooltip, Spinner, HierarchyPreview, SlowalFrameComponent, ExamplesComponent, SemanticsSchemataComponent, MeaningComponent}, + components: {HierarchyElement, InfoTooltip, Spinner, HierarchyPreview, SlowalFrameComponent, ExamplesComponent, SemanticsSchemataComponent, MeaningComponent}, emits: ['goToDisplay', 'refresh', 'swapFrames', 'refreshEntriesList', 'clearUnifiedFrameView'], watch: { forceRefresh(newVal, oldVal) { @@ -69,9 +71,19 @@ Object.assign(HierarchyEdit, { computed: { selectionalPreference() { return new SelectionalPreference(); - } + }, }, methods: { + createHierarchyTree() { + return { + 'unified_frame': this.unified_frame, + 'hyponyms': this.hierarchy_hyponyms, + 'hypyronyms': this.hierarchy_hyperonyms + }; + }, + goToEdit (unifiedFrameId, entryId, lexicalUnitId) { + window.location = `/${lang}/entries/unification?unified_frame_id=${this.unified_frame.id}`; + }, hasWhiteSpace(s) { return /\s/g.test(s); }, @@ -104,7 +116,6 @@ Object.assign(HierarchyEdit, { window.update_last_visited(response.last_visited); window.clear_info(); - this.changeStatusButtonTitleToDefault(); if (!this.active_slowal_frame) { this.setup_notes_unified_frame(); } @@ -113,22 +124,40 @@ Object.assign(HierarchyEdit, { show_error(errorType + ' (' + errorMessage + ')'); } }); - + this.loadHierarchy(); } catch (error) { console.log(error); } }, - setup_notes_unified_frame() { - setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.unified_frame.id, 'unifier.UnifiedFrame', this.setup_notes_unified_frame); - }, - setup_notes_slowal_frame() { - if (this.active_slowal_frame) { - setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.active_slowal_frame.id, 'semantics.Frame', this.setup_notes_slowal_frame); - } + loadHierarchy() { + $.ajax({ + type: 'post', + url: '/' + lang + '/unifier/get_hierarchy_hyponyms/'+this.unifiedFrameId+"/", + dataType: 'json', + timeout: 60000, + success: function (response) { + this.hierarchy_hyponyms = response.hyponyms; + }.bind(this), + error: function (request, errorType, errorMessage) { + show_error(errorType + ' (' + errorMessage + ')'); + } + }); + + $.ajax({ + type: 'post', + url: '/' + lang + '/unifier/get_hierarchy_hyperonyms/'+this.unifiedFrameId+"/", + dataType: 'json', + timeout: 60000, + success: function (response) { + this.hierarchy_hyperonyms = response.hyperonyms; + }.bind(this), + error: function (request, errorType, errorMessage) { + show_error(errorType + ' (' + errorMessage + ')'); + } + }); }, - setup_notes_slowal_frame_with_title_and_body(title, body) { - this.right_pane_tab = 'notes'; - setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.active_slowal_frame.id, 'semantics.Frame', this.setup_notes_slowal_frame, title, body); + setup_notes_unified_frame() { + setup_notes($('#notes-component'), $('#lexical-unit-notes-template'), this.unified_frame.id, 'unifier.UnifiedFrame', this.setup_notes_unified_frame, 'hierarchy_frame'); }, unifiedFrameArgumentSelected(argument) { if (this.active_unified_frame_argument === argument) { @@ -154,274 +183,59 @@ Object.assign(HierarchyEdit, { show_info(gettext('Kliknij, aby wybrać kolumnÄ™ do edycji.')); } }, - addSelectivePreference() { - if (!this.active_unified_frame_argument) { - alert(gettext("Zaznacz argument, do którego chcesz dodać preferencjÄ™.")); + create_hyponym_or_hyperonym_relation(isHyperonym) { + if (this.currentPreviewedUnifiedFrameId === -1) { + alert(gettext("Wybierz w oknie podglÄ…du ram ramÄ™, która bÄ™dzie " + (isHyperonym ? "hiperonimem" : "hiponimem") + " ramy z okna głównego.")); } else { - this.selectionalPreference.addSelectivePreference(this.unified_frame, this.active_unified_frame_argument.id, this.frames, function () { - this.loadFrame(); - }.bind(this)); - // window.addSelectivePreference(this.unified_frame, this.active_unified_frame_argument.id, this.frames, function () { - // this.loadFrame(); - // }.bind(this)); - } - }, - removeSelectionalPreference() { - if (!this.active_unified_frame_argument) { - alert(gettext("Zaznacz argument, do którego chcesz dodać preferencjÄ™.")); - } else { - const existingPreferencies = function () { - return this.active_unified_frame_argument.preferences.map(preference => { - return `<label><input type="checkbox" name="preference" value="${preference.id}" /> ${preference.str}</label><br />`; - }).join(""); - }.bind(this); - - const remove_preference_popup = { - state0: { - title: 'Wybierz preferencje do usuniÄ™cia', - html: existingPreferencies, - buttons: {Anuluj: 0, UsuÅ„: 1}, - focus: -1, - submit: function (e, v, m, f) { - if (v == 0) { - e.preventDefault(); - $.prompt.close(); - } - if (v === 1) { - e.preventDefault(); - let preference_ids = normalizeFormData(f.preference); - const data = { - 'unified_frame_id': this.unified_frame.id, - 'argument_id': this.active_unified_frame_argument.id, - 'preference_ids': JSON.stringify(preference_ids) - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/remove_selectional_preference/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Wybrane preferencje zostaÅ‚u usuniÄ™te.'); - this.loadFrame(); - $.prompt.close(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - $.prompt.close(); - } - }); - } - }.bind(this) - } - } - $.prompt(remove_preference_popup); - } - }, - changeTitle() { - let title = this.unified_frame.title != null ? this.unified_frame.title : ''; - const change_title_popup = { - state0: { - title: 'Zmiana nazwy ramy', - html: '<input type="text" size="32" value="' + title + '" name="title" />', - buttons: {Anuluj: 0, Zapisz: 1}, - focus: -1, - submit: function (e, v, m, f) { - if (v == 0) { - $.prompt.close(); - } - if (v === 1) { - e.preventDefault(); - const title = f.title; - - if (this.hasWhiteSpace(title)) { - alert(gettext("Nazwa zunifikowanej ramy nie może zawierać biaÅ‚ych znaków.")); - } else { - const data = {'unified_frame_id': this.unified_frame.id, 'unified_frame_title': title}; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/save_unified_frame_title/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('TytuÅ‚ ramy zosaÅ‚ zapisany'); - $.prompt.close(); - this.loadFrame(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - $.prompt.close(); - } - }); - } + const data = isHyperonym ? {'hyponym_id': this.currentPreviewedUnifiedFrameId, 'hyperonym_id': this.unified_frame.id} : + {'hyponym_id': this.unified_frame.id, 'hyperonym_id': this.currentPreviewedUnifiedFrameId};; + $.ajax({ + type: 'post', + url: '/' + lang + '/unifier/hierarchy_assign/', + dataType: 'json', + data: data, + timeout: 60000, + success: function (response) { + if(response.succ === 'true') { + show_info('Relacja hierarchii zostaÅ‚a ustanowiona.'); + this.loadHierarchy(); + this.$emit('refreshEntriesList'); + } else if(response.exists === 'true') { + alert(gettext("Wybrana relacja hierarchii już wystÄ™puje.")); } - }.bind(this) - } + }.bind(this), + error: function (request, errorType, errorMessage) { + show_error(errorType + ' (' + errorMessage + ')'); + } + }); } - $.prompt(change_title_popup); }, - changeRole() { - if (!this.active_unified_frame_argument) { - alert(gettext("Zaznacz argument, dla którego chcesz wybrać rolÄ™.")); + delete_hyponym_or_hyperonym_relation() { + if (this.currentPreviewedUnifiedFrameId === -1) { + alert(gettext("Wybierz w oknie podglÄ…du ram ramÄ™, dla której powiÄ…zanie ma zostać usuniÄ™te.")); } else { - const existingSelect = function () { - let selected_unified_frame_argument = this.unified_frame_arguments.find(o => o.id === this.active_unified_frame_argument.id); - if (!selected_unified_frame_argument.proposed_roles) { - return gettext('Brak ról do wyboru.') - } - return selected_unified_frame_argument.proposed_roles.map(role => { - return `<label><input type="radio" name="roles" value="${role.id}" /> ${role.str}</label><br />`; - }).join(""); - }.bind(this); - - const newSelect = function () { - let rolesHTML = roles.map(role => { - return `<label><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(""); - const roleTypeHTML = ['role', 'modifier'].map(type => { - return `<label><input type="radio" name="role_type" value="${type}" /> ${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>'; - }.bind(this); - - let change_role_popup = { - state0: { - title: 'Wybór roli', - html: 'Wybierz lub dodaj rolÄ™', - buttons: {Wybierz: 0, Dodaj: 1, Koniec: -1}, - focus: -1, - submit: function (e, v, m, f) { - if (v == -1) { - e.preventDefault(); - - this.loadFrame(); - - $.prompt.close(); - } - if (v === 0) { - e.preventDefault(); - $.prompt.goToState('state1'); - } - if (v == 1) { - e.preventDefault(); - $.prompt.goToState('state2'); - } - }.bind(this) - }, - state1: { - title: 'Wybierz rolÄ™', - html: existingSelect(), - 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(); - normalizeFormData(f.roles).map(role_id => { - const data = { - 'unified_frame_id': this.unified_frame.id, - 'complement_id': this.active_unified_frame_argument.id, - 'role_id': role_id - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/save_selected_role/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Wybrana rola zosaÅ‚a zapisana'); - $.prompt.goToState('state0'); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - $.prompt.close(); - } - }); - }); - } - }.bind(this) - }, - state2: { - title: 'Dodaj rolÄ™', - html: newSelect(), - 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(); - - 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 data = { - 'unified_frame_id': this.unified_frame.id, - 'complement_id': this.active_unified_frame_argument.id, - 'role_type': role_type, - 'role_id': role_id, - 'attribute_id': attribute_id - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/save_new_role/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Nowa rola zosaÅ‚a zapisana'); - $.prompt.goToState('state0'); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - $.prompt.close(); - } - }); - } else { - alert(gettext("Musisz wybrać typ oraz rolÄ™.")); - } - } - }.bind(this) + const data = {'rel1_id': this.currentPreviewedUnifiedFrameId, 'rel2_id': this.unified_frame.id}; + $.ajax({ + type: 'post', + url: '/' + lang + '/unifier/hierarchy_unassign/', + dataType: 'json', + data: data, + timeout: 60000, + success: function (response) { + if(response.succ === true) { + show_info('Relacja hierarchii zostaÅ‚a usuniÄ™ta.'); + this.loadHierarchy(); + this.$emit('refreshEntriesList'); + } else { + alert(gettext("Wybrana relacja hierarchii nie wystÄ™puje.")); + } + }.bind(this), + error: function (request, errorType, errorMessage) { + show_error(errorType + ' (' + errorMessage + ')'); } - }; - $.prompt(change_role_popup); + }); } }, - addArgument() { - const data = {'unified_frame_id': this.unified_frame.id}; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/add_argument/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Nowy argument zosaÅ‚ dodany'); - this.loadFrame(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - $.prompt.close(); - } - }); - }, getSlowalFrameArgumentsBy(unified_frame_argument) { const slowalFrameArgumentIds = []; for (let i in this.unified_frame.slowal_frame_mapping) { @@ -439,163 +253,6 @@ Object.assign(HierarchyEdit, { } return slowalFrameArgumentIds; }, - removeArgument() { - if (!this.active_unified_frame_argument) { - alert(gettext("Zaznacz argument, który chcesz usunąć.")); - } else { - let hasSlowalFrameArgumentMapping = false; - for (let i in this.unified_frame.slowal_frame_mapping) { - const slowal_frame_mapping = this.unified_frame.slowal_frame_mapping[i]; - for (let j in slowal_frame_mapping.slowal_frame_argument_mapping) { - const slowal_frame_argument_mapping = slowal_frame_mapping.slowal_frame_argument_mapping[j]; - if (slowal_frame_argument_mapping.unified_frame_agrument_id == this.active_unified_frame_argument.id) { - hasSlowalFrameArgumentMapping = true; - break; - } - } - } - if (hasSlowalFrameArgumentMapping) { - alert(gettext("Zaznaczony argument nie może zostać usuniÄ™ty - podpiÄ™te ramy posiadajÄ… do niego dowiÄ…zania.")); - } else { - const data = { - 'unified_frame_id': this.unified_frame.id, - 'complement_id': this.active_unified_frame_argument.id - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/remove_argument/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Wybrany argument zosaÅ‚ usuniÄ™ty'); - this.loadFrame(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - $.prompt.close(); - } - }); - } - } - }, - duplicate() { - let title = this.unified_frame.title != null ? this.unified_frame.title : ''; - const duplicate_popup = { - state0: { - title: 'Podaj nazwÄ™ zduplikowanej ramy', - html: '<input type="text" size="32" value="KOPIA_' + title + '" name="title" />', - buttons: {Anuluj: 0, Zapisz: 1}, - focus: -1, - submit: function (e, v, m, f) { - if (v == 0) { - e.preventDefault(); - $.prompt.close(); - } - if (v === 1) { - e.preventDefault(); - const title = f.title; - - if (this.hasWhiteSpace(title)) { - alert(gettext("Nazwa zunifikowanej ramy nie może zawierać biaÅ‚ych znaków.")); - } else { - const data = { - 'unified_frame_id': this.unified_frame.id, - 'target_unified_frame_title': title - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/duplicate_unified_frame/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Zunifikowana rama zostaÅ‚a zduplikowana.'); - this.currentPreviewedUnifiedFrameId = response.unified_frame_id; - $.prompt.close(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - $.prompt.close(); - } - }); - } - } - }.bind(this) - } - } - $.prompt(duplicate_popup); - }, - changeUnifiedFrameStatusToReadyOrVerified() { - if (this.isSuperLeksykograf()) - this.changeUnifiedFrameStatusToReadyOrVerifiedByPath('change_unified_frame_status_to_verified_by_superleksykograf'); - else - this.changeUnifiedFrameStatusToReadyOrVerifiedByPath('change_unified_frame_status_to_ready') - }, - changeUnifiedFrameStatusToReadyOrVerifiedByPath(url_path) { - let foundNotVerifiedFrame = this.frames.find(frame => frame.status !== 'G' && frame.status !== 'S'); - if (foundNotVerifiedFrame) { - alert(gettext("Wszystkie podpiÄ™te ramy powinny być zweryfikowane.")); - } else { - let roleDict = {}; - let hasPreferenceSelected = true; - for (let i in this.unified_frame_arguments) { - const argument = this.unified_frame_arguments[i]; - if (argument.role) { - roleDict[argument.role.str] = argument.role; - } - if (!argument.preferences || argument.preferences.length == 0) { - hasPreferenceSelected = false; - } - } - if (Object.keys(roleDict).length === this.unified_frame_arguments.length && hasPreferenceSelected) { - //all roles are set, and are uniq - //TODO: aktywne preferencje w argumencie nie znajdujÄ… siÄ™ w relacji hipo-/hiperonimii. - const data = {'unified_frame_id': this.unified_frame.id}; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/' + url_path + '/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Status ramy zostaÅ‚ zmieniony'); - this.loadFrame(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - } - }); - } else { - alert(gettext("Role dla wszystkich argumentów powinny być ustawione oraz unikalne. Preferencje selekcyjne dla wszystkich argumentów powinny być ustawione.")); - } - } - }, - change_slowal2unified_frame_argument_mapping(slowal_frame) { - if (slowal_frame === this.active_slowal_frame && this.selectedFrameArguments && this.selectedFrameArguments.length == 2) { - const data = { - 'unified_frame_id': this.unified_frame.id, - 'slowal_frame_id': slowal_frame.id, - 'slowal_frame_selected_arguments': JSON.stringify(this.selectedFrameArguments.map(arg => arg.argument_id)) - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/change_slowal2unified_fram_argument_mapping/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Argumenty w ramie zostaÅ‚y zmienione'); - this.loadFrame(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - } - }); - } else { - alert(gettext("Zamiany pozycji argumentu w ramie wymaga zaznaczenia dokÅ‚adnie 2 argumentów.")); - } - }, isSuperLeksykograf() { return has_permission("users.view_assignment"); }, @@ -610,68 +267,9 @@ Object.assign(HierarchyEdit, { alert(gettext("Wybierz ramÄ™, dla której chcesz zmienić status.")); } }, - change_slowal_frame_status(status) { - this.select_slowal_frame_req(() => { - let frame = this.active_slowal_frame; - - if (status === 'B') { - this.setup_notes_slowal_frame_with_title_and_body("Niedopasowana jednostka (identyfikator jednostki)", "Do zatwierdzenia uznanie ramy Walentego jednostek (lista jednostek)" + - "za niedopasowana do zunifikowanej ramy (identyfikator) przez (Leksykograf)."); - } else if (status === 'Z') { - this.setup_notes_slowal_frame_with_title_and_body("BÅ‚Ä™dna jednostka (identyfikator jednostki)", "Do zatwierdzenia uznanie ramy Walentego jednostek (lista jednostek)" + - "za niedopasowana do zunifikowanej ramy (identyfikator) przez (Leksykograf)."); - } - - const data = { - 'unified_frame_id': this.unified_frame.id, - 'slowal_frame_id': frame.id, - 'status': status - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/change_slowal_frame_status/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Status ramy zostaÅ‚ zmieniony'); - this.$emit('refreshEntriesList'); - this.loadFrame(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - } - }); - }); - }, - slowal_frame_ready_rollback(status) { - this.select_slowal_frame_req(() => { - let frame = this.active_slowal_frame; - const isSuperLeksykograf = this.isSuperLeksykograf(); - let status = null; - if (!isSuperLeksykograf && frame.status === 'G') { - //przywracamy O - status = 'O'; - } else if (!isSuperLeksykograf && frame.status === 'O') { - //ustawiany na Gotowe - status = 'G'; - } else if (isSuperLeksykograf && frame.status === 'S') { - //ustawiany Sprawdzone - status = 'G'; - } else { - status = 'S'; - } - - this.change_slowal_frame_status(status); - }); - }, isFrameVisible(status) { return (status != 'B' && status != 'C') || this.isSuperLeksykograf(); }, - changeStatusButtonTitleToDefault() { - const isSuperLeksykograf = this.isSuperLeksykograf(); - this.statusButtonTitle = isSuperLeksykograf ? 'Sprawdź' : 'Gotowe'; - }, deselectSlowalFrameSelectedElements() { this.subentries.forEach(subentry => { subentry.schemata.forEach(s => { @@ -698,18 +296,8 @@ Object.assign(HierarchyEdit, { this.deselectSlowalFrameSelectedElements(); if (this.active_slowal_frame === frame) { this.active_slowal_frame = null; - if (!this.readOnly) { - this.setup_notes_unified_frame(); - this.changeStatusButtonTitleToDefault(); - } } else { this.active_slowal_frame = frame; - if (!this.readOnly) { - this.setup_notes_slowal_frame() - if (this.isFrameVerified(frame)) { - this.statusButtonTitle = 'Przywróć'; - } - } } }, isSelectedFrame(frame) { @@ -719,135 +307,21 @@ Object.assign(HierarchyEdit, { return false; } }, - extract_frames_to_new_frame() { - - const existingSelect = function () { - return this.frames.map(frame => { - return `<label><input type="checkbox" name="frames" value="${frame.id}" /> ${lexical_units2dom(frame.lexical_units)}</label><br />`; - }).join(""); - }.bind(this); - - const extract_frames_to_new_frame_popup = { - state0: { - title: 'Podaj nazwÄ™ zduplikowanej ramy', - html: existingSelect, - buttons: {Anuluj: 0, Wydziel: 1}, - focus: -1, - submit: function (e, v, m, f) { - if (v == 0) { - e.preventDefault(); - $.prompt.close(); - } - if (v === 1) { - e.preventDefault(); - let frame_ids = normalizeFormData(f.frames); - const data = { - 'unified_frame_id': this.unified_frame.id, 'slowal_frame_ids': JSON.stringify(frame_ids), - 'target_unified_frame_id': '' - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/extract_frames_to_new_frame/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Ramy zostaÅ‚y wydzielone do nowej ramy zunifikowanej.'); - this.loadFrame(); - let newUnifiedFrameId = response.unified_frame_id; - this.currentPreviewedUnifiedFrameId = newUnifiedFrameId; - $.prompt.close(); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - $.prompt.close(); - } - }); - } - }.bind(this) - } - } - $.prompt(extract_frames_to_new_frame_popup); - }, - extract_frame_to_preview_frame() { - if (this.currentPreviewedUnifiedFrameId !== -1 && this.currentPreviewedUnifiedFrameId !== this.unified_frame.id) { - let target_unified_frame_id = this.currentPreviewedUnifiedFrameId; - const data = { - 'unified_frame_id': this.unified_frame.id, 'slowal_frame_ids': JSON.stringify([this.active_slowal_frame.id]), - 'target_unified_frame_id': target_unified_frame_id - }; - $.ajax({ - type: 'post', - url: '/' + lang + '/unifier/extract_frames_to_new_frame/', - dataType: 'json', - data: data, - timeout: 60000, - success: function (response) { - show_info('Zaznaczona rama zostaÅ‚a przeniosiona.'); - this.active_slowal_frame = null; - this.loadFrame(); - this.internalForceRefresh += 1; - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - } - }); - } - }, changePreviewedUnifiedFrameId(unifiedFrameId) { this.currentPreviewedUnifiedFrameId = unifiedFrameId; }, - swapUnifiedFrames() { - if (this.currentPreviewedUnifiedFrameId !== -1 && this.unified_frame.id !== this.currentPreviewedUnifiedFrameId) { - this.$emit("swapFrames", this.currentPreviewedUnifiedFrameId); - } - }, - changeShowVerifiedFrames(val) { - this.showVerifiedFrames = val; - this.hidden_frames = []; - }, getArgumentCSS(argument) { return (argument.role ? argument.role.str + ' ' : '') + (argument == this.active_unified_frame_argument ? 'active' : ''); }, - meaningLuSelected(selectedLus) { - this.selectedLus = selectedLus; - }, - insideFrameSelectionChanged(selectedFrameArguments) { - this.selectedFrameArguments = selectedFrameArguments; - }, schemataSelected(schemas) { this.selectedSchemas = schemas; }, exampleSelected(selectedExamples) { this.selectedExamples = selectedExamples; }, - deleteUnifiedFrames() { - if (!confirm(gettext("Czy na pewno chcesz zunifikowanÄ… ramÄ™?"))) return false; - $.ajax({ - type: 'post', - url: '/' + lang + `/unifier/delete_unified_frame/${this.unified_frame.id}/`, - dataType: 'json', - timeout: 60000, - success: function (response) { - show_info('Zunifikowana rama zostaÅ‚a usuniÄ™ta.'); - this.$emit('refreshEntriesList'); - this.$emit("swapFrames", null); - }.bind(this), - error: function (request, errorType, errorMessage) { - show_error(errorType + ' (' + errorMessage + ')'); - } - }); - }, isReadOnlyForSuperLeksykograf() { return (this.isSuperLeksykograf() && this.unified_frame.status === 'O') && this.unified_frame.assignee_username !== window.USER_USERNAME; }, - hideFrame(frame) { - this.hidden_frames.push(frame); - }, - getSlowalReadyFrameCnt() { - const readyFrames = this.frames.filter(frame => frame.status == 'G'); - return readyFrames.length; - }, frames2lexical_units(frames) { const lexical_units = [] for (let i in frames) { @@ -890,6 +364,12 @@ Object.assign(HierarchyEdit, { slowal_frame.arguments = new_slowal_frame_arguments; } } + }, + createFrameHierarchyRepresentationHTML(unified_frame) { + + }, + createHierarchyHTML() { + this.unified_frame } }, mounted() { @@ -898,7 +378,6 @@ Object.assign(HierarchyEdit, { this.loadFrame(); } - this.changeStatusButtonTitleToDefault(); if(!this.readOnly) { Split(['#semantics-frames-pane', '#semantics-schemata-pane'], { sizes: [40, 60], @@ -936,10 +415,10 @@ export default HierarchyEdit; <div :id="'semantics-unified-frame-pane' + (readOnly ? '-preview' : '')" class="col w-100 p-0 overflow-auto"> <table v-if="!readOnly && !isReadOnlyForSuperLeksykograf()" class="table-button-menu sticky-top" cellspacing="1"> <tr style="background-color: white;"> - <td id="change-title" @click="changeTitle" style="padding: 10px 15px 10px 15px; color: #000000;">Nadrama</td> - <td id="add-arg" @click="addArgument" style="padding: 10px 15px 10px 15px; color: #000000;">Podrama</td> - <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="addSelectivePreference">UsiÅ„ powiÄ…zanie</td> - <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="changeUnifiedFrameStatusToReadyOrVerified">Edytuj</td> + <td id="change-title" @click="create_hyponym_or_hyperonym_relation(false)" style="padding: 10px 15px 10px 15px; color: #000000;">Nadrama</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">UsiÅ„ powiÄ…zanie</td> + <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="goToEdit">Edytuj</td> </tr> </table> @@ -1019,7 +498,7 @@ export default HierarchyEdit; v-for='lexical_unit in lexical_units' > <template v-if="isFrameVisible(lexical_unit.frame)"> - <td class="lu-cursor-pointer argument py-2 px-1 border-top border-left border-secondary" + <td class="cursor-pointer argument py-2 px-1 border-top border-left border-secondary" @mouseenter="lexical_unit.frame.hover=true" @mouseleave="lexical_unit.frame.hover=false" :class="lexical_unit.frame === active_slowal_frame ? 'active-lu' : lexical_unit.frame.hover ? 'lu-underline' : ''" @@ -1078,17 +557,10 @@ export default HierarchyEdit; :hierarchyEditComponent="HierarchyEdit" :initialUnifiedFrameId="currentPreviewedUnifiedFrameId" @change-frame="changePreviewedUnifiedFrameId" - @change-preview-to-edit="swapUnifiedFrames" :forceRefresh="internalForceRefresh" /> </div> - <div v-if="right_pane_tab === 'hierarchy'" class="overflow-hidden" style="height: calc(100% - 43px)"> - <hierarchy-preview - :key="currentPreviewedUnifiedFrameId" - :hierarchyEditComponent="HierarchyEdit" - :initialUnifiedFrameId="currentPreviewedUnifiedFrameId" - @change-frame="changePreviewedUnifiedFrameId" - @change-preview-to-edit="swapUnifiedFrames" - :forceRefresh="internalForceRefresh" /> + <div v-if="right_pane_tab === 'hierarchy'" class="overflow-hidden center" style="height: calc(100% - 43px); width: calc(80%)"> + <hierarchy-element :node="createHierarchyTree()" :spacing_elem_type="'none'"/> </div> <div :class="right_pane_tab !== 'notes' && 'd-none'" id="notes-component"></div> </div> diff --git a/frontend/src/components/unification/hierarchy/HierarchyElement.vue b/frontend/src/components/unification/hierarchy/HierarchyElement.vue new file mode 100644 index 0000000000000000000000000000000000000000..4f19b8d3c2e90a8017d23d80f31b6d3ae99fd907 --- /dev/null +++ b/frontend/src/components/unification/hierarchy/HierarchyElement.vue @@ -0,0 +1,184 @@ +<script> + +export default { + name: 'HierarchyElement', + props: { + node: { + type: Object, + required: true + }, + spacing: { + type: Number, + default: 0 + }, + spacing_elem_type: String + }, + data() { + return { + showHyponyms: false, + showHypyronyms: false + } + }, + computed: { + nodeMargin() { + return { + 'margin-left': `${this.spacing}px` + } + }, + hasHyponyms() { + const {hyponyms} = this.node + return hyponyms && hyponyms.length > 0 + }, + hasHypyronyms() { + const {hypyronyms} = this.node + return hypyronyms && hypyronyms.length > 0 + }, + toggleChildrenIcon() { + return this.showHypyronyms ? 'fas fa-angle-down' : 'fas fa-angle-right' + }, + getSpacingElem() { + if(this.spacing_elem_type === "std") { + return "├→"; + } else if(this.spacing_elem_type === "top_corner") { + return "┌→"; + } else if(this.spacing_elem_type === "down_corner") { + return "└→"; + } else { + return ""; + } + }, + }, + methods: { + loadChildren (children) { + for (let i in children) { + const hypyronym = children[i]; + if (hypyronym.hasChildrenLoaded !== true) { + $.ajax({ + type: 'post', + url: '/' + lang + '/unifier/get_hierarchy_hyperonyms/' + hypyronym.unified_frame_id + "/", + dataType: 'json', + timeout: 60000, + success: function (response) { + hypyronym.hypyronyms = response.hyperonyms; + }.bind(this), + error: function (request, errorType, errorMessage) { + show_error(errorType + ' (' + errorMessage + ')'); + } + }); + $.ajax({ + type: 'post', + url: '/' + lang + '/unifier/get_hierarchy_hyponyms/' + hypyronym.unified_frame_id + "/", + dataType: 'json', + timeout: 60000, + success: function (response) { + hypyronym.hyponyms = response.hyponyms; + }.bind(this), + error: function (request, errorType, errorMessage) { + show_error(errorType + ' (' + errorMessage + ')'); + } + }); + } + } + }, toggleHypyronyms() { + this.loadChildren(this.node.hypyronyms); + this.showHypyronyms = !this.showHypyronyms + }, + toggleHyponyms() { + this.loadChildren(this.node.hyponyms); + this.showHyponyms = !this.showHyponyms + } + } +} + +</script> + + +<template> + <div :style="nodeMargin"> + <div v-if="hasHypyronyms" v-show="showHypyronyms"> + <hierarchy-element + v-for="(child, index) in node.hypyronyms" + :key="child.id" + :node="child" + :spacing_elem_type='index === 0 ? "top_corner" : "std"' + :spacing="spacing + 10" + /> + </div> + <div show class="d-flex justify-content-between mb-1"> + <div class="row"> + <div class="col" v-html="getSpacingElem"/> + <div class="col"> + + <div align="left" style="display: table;"> + <div class="unifiedFrame mt-3" id="hierarchy-unified-frame-title" v-html="node.unified_frame.title"></div> + <table id="hierarchy-unified-frame" class="m-0 table-borderless border border-secondary text-dark frame active"> + <tbody> + <tr> + <template v-for="argument in node.unified_frame.arguments"> + <td + class="argument py-2 px-1 border-top border-left border-secondary role-column" + :class="argument.role ? argument.role.str + ' ' : ''" + > + {{ argument.role_type }} + + <div + v-if="argument.role" + > + [{{ argument.role.str }}] + </div> + <div v-else> + <ul class="ul-role"> + <li v-for="proposed_role in argument.proposed_roles"> + {{ proposed_role.str }} + </li> + </ul> + </div> + </td> + </template> + </tr> + <tr> + <td hidden class="preferences py-0 px-0 border-top border-left border-secondary role-column align-top" + v-for='argument in node.unified_frame.arguments' + :key='argument.id' + > + <ul class="ul-preference" v-if="argument.preferences.length > 0"> + <li v-for='preference in argument.preferences'> + <div + v-if="preference.url != null" + class="preference py-2 px-1 preference-bold" + > + <a class="synset-plwn" v-bind:href="preference.url" target="_blank">{{ preference.str }}</a> + </div> + <div v-else class="preference py-2 px-1 preference-bold">{{ preference.str }}</div> + </li> + </ul> + </td> + </tr> + </tbody> + </table> + </div> + {{ node.label }} + </div> + <div class="col"><span + v-if="hasHyponyms" + :class="toggleChildrenIcon" + @click="toggleHyponyms" + @keypress="toggleHyponyms">V</span></div> + <div class="col"><span + v-if="hasHypyronyms" + :class="toggleChildrenIcon" + @click="toggleHypyronyms" + @keypress="toggleHypyronyms">A</span></div> + </div> + </div> + <div v-if="hasHyponyms" v-show="showHyponyms"> + <hierarchy-element + v-for="(child, index) in node.hyponyms" + :key="child.id" + :node="child" + :spacing_elem_type='index === node.hyponyms.length - 1 ? "down_corner" : "std"' + :spacing="spacing + 10" + /> + </div> + </div> +</template> diff --git a/unifier/models.py b/unifier/models.py index 53c7013bef1d90444374060dadb82e5affb3a5b0..35973cf6ed4c0c5233bc1279c6668b16678609ea 100644 --- a/unifier/models.py +++ b/unifier/models.py @@ -36,6 +36,8 @@ class UnifiedFrame(models.Model): fin_statement = models.ForeignKey(FinStatement, on_delete=models.PROTECT, blank=True, default=None, null=True, related_name='unified_frame') + hasHierarchyElems = models.BooleanField(default=False) + def sorted_arguments(self): # TODO: zaimplementowac wlasciwe sortowanie return UnifiedFrameArgument.objects.filter(unified_frame=self) @@ -79,7 +81,6 @@ class UnifiedFrame(models.Model): argument_mapping.unified_agrument_id = new_unified_frame_arguments[i] argument_mapping.save() - self.update_sloval_frame_count() new_frame.update_sloval_frame_count() @@ -120,25 +121,26 @@ class UnifiedFrame(models.Model): class UnifiedFrameArgument(models.Model): role_type = models.ForeignKey(RoleType, on_delete=models.PROTECT, default=None, blank=True, null=True) - #rola - wybrana przez użytkownika + # rola - wybrana przez użytkownika role = models.ForeignKey(ArgumentRole, on_delete=models.PROTECT, default=None, blank=True, null=True) - #role zaproponowane przez system unifikacyjny + # role zaproponowane przez system unifikacyjny proposed_roles = models.ManyToManyField(ArgumentRole, related_name='proposed_roles') - #3 typy preferencji - wybrane przez użytkownika + # 3 typy preferencji - wybrane przez użytkownika predefined = models.ManyToManyField(PredefinedSelectionalPreference) synsets = models.ManyToManyField(Synset) relations = models.ManyToManyField('UnifiedRelationalSelectionalPreference') - #odwoÅ‚anie do ramy + # odwoÅ‚anie do ramy unified_frame = models.ForeignKey(UnifiedFrame, related_name='unified_arguments', default=None, blank=True, null=True, on_delete=models.PROTECT) - #do wyszukiwania + # do wyszukiwania preferences_count = models.PositiveIntegerField(null=False, default=0) def __str__(self): return str(self.role) + class UnifiedRelationalSelectionalPreference(models.Model): relation = models.ForeignKey(SelectionalPreferenceRelation, on_delete=models.PROTECT) to = models.ForeignKey(UnifiedFrameArgument,on_delete=models.PROTECT) @@ -152,11 +154,13 @@ class UnifiedFrame2SlowalFrameMapping(models.Model): unified_frame = models.ForeignKey(UnifiedFrame, related_name='unified_frame_2_slowal_frame', on_delete=models.PROTECT) slowal_frame = models.OneToOneField(Frame, related_name='slowal_frame_2_unified_frame', on_delete=models.PROTECT) + class UnifiedFrameArgumentSlowalFrameMapping(models.Model): unified_agrument = models.ForeignKey(UnifiedFrameArgument, related_name='unified_agrument_mapping', on_delete=models.PROTECT) slowal_agrument = models.ForeignKey(Argument, related_name='slowal_agrument_mapping', on_delete=models.PROTECT) unified_frame_mapping = models.ForeignKey(UnifiedFrame2SlowalFrameMapping, related_name='unified_frame_argument_mapping', on_delete=models.PROTECT) - - +class HierarchyModel(models.Model): + hyponym = models.ForeignKey(UnifiedFrame, related_name='hyponym_mapping', on_delete=models.PROTECT) + hyperonym = models.ForeignKey(UnifiedFrame, related_name='hyperonym_mapping', on_delete=models.PROTECT) diff --git a/unifier/urls.py b/unifier/urls.py index bf8476ecd3c83034373a9088331f86bc5b05d132..9ba2f659aa7d8c0e4246e9697b931c09cc842166 100644 --- a/unifier/urls.py +++ b/unifier/urls.py @@ -26,5 +26,9 @@ urlpatterns = [ path('delete_unified_frame/<int:unified_frame_id>/', views.delete_unified_frame, name='delete_unified_frame'), path('change_unified_frame_status_to_verified_by_superleksykograf/', views.change_unified_frame_status_to_verified_by_superleksykograf, name='change_unified_frame_status_to_verified_by_superleksykograf'), + path('hierarchy_assign/', views.hierarchy_assign, name='hierarchy_assign'), + path('hierarchy_unassign/', views.hierarchy_unassign, name='hierarchy_unassign'), + path('get_hierarchy_hyponyms/<int:unified_frame_id>/', views.get_hierarchy_hyponyms, name='get_hierarchy_hyponyms'), + path('get_hierarchy_hyperonyms/<int:unified_frame_id>/', views.get_hierarchy_hyperonyms, name='get_hierarchy_hyperonyms'), ] diff --git a/unifier/views.py b/unifier/views.py index 8a45397acd3776593414324ed6b6da572c7c29e6..67f713574cbd75f6ff31946d5d86d3884060c98d 100644 --- a/unifier/views.py +++ b/unifier/views.py @@ -18,12 +18,14 @@ from semantics.choices import FrameStatus from semantics.models import Frame, ArgumentRole, SemanticRole, RoleAttribute, RoleType from syntax.models import Schema from unifier.models import UnifiedFrameArgument, UnifiedRelationalSelectionalPreference, UnifiedFrame, \ - UnifiedFrame2SlowalFrameMapping, UnifiedFrameArgumentSlowalFrameMapping + UnifiedFrame2SlowalFrameMapping, UnifiedFrameArgumentSlowalFrameMapping, HierarchyModel from users.models import Assignment from . import choices from xml.etree.ElementTree import Element, SubElement, tostring import io from xml.sax import handler, make_parser +from django.db.models import Q + @ajax_required @transaction.atomic @@ -41,6 +43,7 @@ def save_synset_preference(request): return JsonResponse({}) + @ajax_required @transaction.atomic def save_predefined_preference(request): @@ -57,6 +60,7 @@ def save_predefined_preference(request): return JsonResponse({}) + @ajax_required @transaction.atomic def save_relational_selectional_preference(request): @@ -66,8 +70,10 @@ def save_relational_selectional_preference(request): complement_id_to = request.POST['complement_id_to'] relation_id = request.POST['relation_id'] - unifiedFrameArgument = UnifiedFrameArgument.objects.get(unified_frame_id=int(frame_id), id=int(complement_id_from)) - relationalSelectionalPreference = UnifiedRelationalSelectionalPreference(to_id=complement_id_to, relation_id=relation_id) + unifiedFrameArgument = UnifiedFrameArgument.objects.get(unified_frame_id=int(frame_id), + id=int(complement_id_from)) + relationalSelectionalPreference = UnifiedRelationalSelectionalPreference(to_id=complement_id_to, + relation_id=relation_id) relationalSelectionalPreference.save() unifiedFrameArgument.relations.add(relationalSelectionalPreference) unifiedFrameArgument.save() @@ -90,7 +96,7 @@ def get_unified_frames(request): forms = collect_forms(request.session['unified_frame_form'], errors_dict) unifiedFrames = get_filtered_objects(forms).filter() else: - unifiedFrames = UnifiedFrame.objects.all(); + unifiedFrames = UnifiedFrame.objects.all() if scroller_params['filter']: unifiedFrames = unifiedFrames.filter(title__startswith=scroller_params['filter']) @@ -113,45 +119,48 @@ def get_unified_frames(request): 'id': str(unifiedFrame.id), 'title': unifiedFrame.title, 'status': unifiedFrame.status, - 'assignee_username': assignment.user.username if (assignment := unifiedFrame.assignments.first()) else None, + 'assignee_username': assignment.user.username if ( + assignment := unifiedFrame.assignments.first()) else None, + 'hierarchy_exists': unifiedFrame.hasHierarchyElems, } resProcessed = [] for key, value in res.items(): - if (exclude_status == None or value['status'] != exclude_status) and \ - (restrict_to_user == None or value['assignee_username'] == restrict_to_user): + if (exclude_status is None or value['status'] != exclude_status) and \ + (restrict_to_user is None or value['assignee_username'] == restrict_to_user): resProcessed.append(value) ret = { - 'draw': scroller_params['draw'], - 'recordsTotal': len(resProcessed), - 'recordsFiltered': len(resProcessed), - 'data': resProcessed + 'draw': scroller_params['draw'], + 'recordsTotal': len(resProcessed), + 'recordsFiltered': len(resProcessed), + 'data': resProcessed } return JsonResponse(ret) return JsonResponse({}) - def unifiedFrame2dict(frame): return { - 'id' : frame.id, - 'title' : frame.title, - 'status' : str(frame.status), - 'assignee_username' : assignment.user.username if (assignment := frame.assignments.first()) else None, - 'arguments' : [ + 'id': frame.id, + 'title': frame.title, + 'status': str(frame.status), + 'assignee_username': assignment.user.username if (assignment := frame.assignments.first()) else None, + 'arguments': [ { - 'str' : str(a), - 'id' : a.id, - 'role' : { - 'str': '{}{}'.format(a.role.role.role.lower(), ' ' + a.role.attribute.attribute.lower() if a.role.attribute else '') if a.role is not None else None, + 'str': str(a), + 'id': a.id, + 'role': { + 'str': '{}{}'.format(a.role.role.role.lower(), + ' ' + a.role.attribute.attribute.lower() if a.role.attribute else '') if a.role is not None else None, 'id': str(a.role.id) } if a.role is not None else None, - 'role_type' : a.role_type.type.lower() if a.role_type is not None else '', - 'preferences' : get_prefs_list(a), + 'role_type': a.role_type.type.lower() if a.role_type is not None else '', + 'preferences': get_prefs_list(a), 'proposed_roles': [{ - 'str': '{}{}'.format(r.role.role.lower(), ' ' + r.attribute.attribute.lower() if r.attribute else ''), + 'str': '{}{}'.format(r.role.role.lower(), + ' ' + r.attribute.attribute.lower() if r.attribute else ''), 'id': str(r.id) } for r in a.proposed_roles.all()], } for a in sorted(frame.unified_arguments.all(), key=lambda x: x.id) @@ -171,6 +180,7 @@ def unifiedFrame2dict(frame): } + def get_examples(frames): examples = [] for frame in frames: @@ -186,41 +196,47 @@ def get_examples(frames): lu_ids.add(connection.lexical_unit.id) for hook in connection.schema_connections.all(): schema_ids.add(hook.schema.id); - phrases.add('{}-{}-{}-{}'.format(hook.schema.id, hook.position.id, hook.phrase_type.id, hook.alternation - 1)) + phrases.add('{}-{}-{}-{}'.format(hook.schema.id, hook.position.id, hook.phrase_type.id, + hook.alternation - 1)) phrases_syntax.add('{}-{}-{}'.format(hook.schema.id, hook.position.id, hook.phrase_type.id)) positions.add('{}-{}'.format(hook.schema.id, hook.position.id)) elem = { - 'id' : str(example.id), - 'sentence' : example.sentence, - 'source' : EXAMPLE_SOURCE()[example.source.key], - 'opinion' : EXAMPLE_OPINION()[example.opinion.key], - 'note' : example.note, - 'frame_ids' : sorted(frame_ids), - 'argument_ids' : sorted(argument_ids), - 'lu_ids' : sorted(lu_ids), - 'schema_ids' : sorted(schema_ids), - 'phrases' : sorted(phrases), - 'phrases_syntax' : sorted(phrases_syntax), - 'positions' : sorted(positions), + 'id': str(example.id), + 'sentence': example.sentence, + 'source': EXAMPLE_SOURCE()[example.source.key], + 'opinion': EXAMPLE_OPINION()[example.opinion.key], + 'note': example.note, + 'frame_ids': sorted(frame_ids), + 'argument_ids': sorted(argument_ids), + 'lu_ids': sorted(lu_ids), + 'schema_ids': sorted(schema_ids), + 'phrases': sorted(phrases), + 'phrases_syntax': sorted(phrases_syntax), + 'positions': sorted(positions), } if elem not in examples: examples.append(elem) return sorted(examples, key=lambda x: x['sentence']) -def get_unified_frame_json(unifiedFrame, request): - apply_filters = not simplejson.loads(request.POST['no_filters']) - local_schema_filter_form = get_local_schema_filter_form(apply_filters, request) - local_frame_filter_form = get_local_frame_filter_form(apply_filters, request) +def get_unified_frame_json(unifiedFrame, request): + local_schema_filter_form = None + local_frame_filter_form = None + if 'no_filters' in request.POST: + apply_filters = not simplejson.loads(request.POST['no_filters']) + local_schema_filter_form = get_local_schema_filter_form(apply_filters, request) + local_frame_filter_form = get_local_frame_filter_form(apply_filters, request) - slowal_frames_db = Frame.objects.filter(id__in=unifiedFrame.unified_frame_2_slowal_frame.values("slowal_frame_id")).distinct() + slowal_frames_db = Frame.objects.filter( + id__in=unifiedFrame.unified_frame_2_slowal_frame.values("slowal_frame_id")).distinct() if local_frame_filter_form: slowal_frames_db = get_filtered_objects(local_frame_filter_form, slowal_frames_db) slowal_frames = slowal_frames_db.all() - all_schema_objects = Schema.objects.filter(schema_hooks__argument_connections__argument__frame__in=slowal_frames).distinct() + all_schema_objects = Schema.objects.filter( + schema_hooks__argument_connections__argument__frame__in=slowal_frames).distinct() if local_schema_filter_form: all_schema_objects = get_filtered_objects(local_schema_filter_form, all_schema_objects) @@ -233,7 +249,8 @@ def get_unified_frame_json(unifiedFrame, request): alternations, realisation_phrases, realisation_descriptions = get_alternations(all_schema_objects, slowal_frames) examples = get_examples(slowal_frames) - all_schema_objects_dict = [schema2dict(schema, schema.subentries.all()[0].negativity, request.LANGUAGE_CODE) for schema in all_schema_objects] + all_schema_objects_dict = [schema2dict(schema, schema.subentries.all()[0].negativity, request.LANGUAGE_CODE) for + schema in all_schema_objects] subentries = [{ 'str': None, @@ -242,17 +259,21 @@ def get_unified_frame_json(unifiedFrame, request): unifiedFrame_dict = unifiedFrame2dict(unifiedFrame) - return { 'unified_frame_id': unifiedFrame.id, 'unified_frame': unifiedFrame_dict, 'subentries': subentries, 'frames' : slowal_frames_dict, 'alternations' : alternations, 'realisation_phrases' : realisation_phrases, 'realisation_descriptions' : realisation_descriptions, 'examples' : examples, 'last_visited' : request.session['last_visited'] } + return {'unified_frame_id': unifiedFrame.id, 'unified_frame': unifiedFrame_dict, 'subentries': subentries, + 'frames': slowal_frames_dict, 'alternations': alternations, 'realisation_phrases': realisation_phrases, + 'realisation_descriptions': realisation_descriptions, 'examples': examples, + 'last_visited': request.session['last_visited']} + @ajax_required @login_required def get_unified_frame(request): if request.method == 'POST': - #TODO (*) - #form = EntryForm(request.POST) + # TODO (*) + # form = EntryForm(request.POST) unified_frame_id = request.POST['unified_frame_id'] - #TODO (*) - if unified_frame_id.isdigit():# and form.is_valid(): + # TODO (*) + if unified_frame_id.isdigit(): # and form.is_valid(): unified_frame_id = int(unified_frame_id) request.session.modified = True unifiedFrame = UnifiedFrame.objects.get(id=unified_frame_id) @@ -260,6 +281,7 @@ def get_unified_frame(request): return JsonResponse({}) + @ajax_required @transaction.atomic def extract_frames_to_new_frame(request): @@ -273,10 +295,12 @@ def extract_frames_to_new_frame(request): new_unified_frame = None if target_unified_frame_id != '': new_unified_frame = UnifiedFrame.objects.get(id=target_unified_frame_id) - new_frame_fullfiled_and_saved = unified_frame.extract_frames_to(slowal_frames=slowal_frames, new_frame=new_unified_frame) + new_frame_fullfiled_and_saved = unified_frame.extract_frames_to(slowal_frames=slowal_frames, + new_frame=new_unified_frame) return JsonResponse(get_unified_frame_json(new_frame_fullfiled_and_saved, request)) return JsonResponse({}) + @ajax_required @transaction.atomic def remove_selectional_preference(request): @@ -314,6 +338,7 @@ def duplicate_unified_frame(request): return JsonResponse(get_unified_frame_json(new_frame, request)) return JsonResponse({}) + @ajax_required @transaction.atomic def change_slowal2unified_fram_argument_mapping(request): @@ -322,35 +347,38 @@ def change_slowal2unified_fram_argument_mapping(request): slowal_frame_id = request.POST['slowal_frame_id'] slowal_frame_selected_arguments = json.loads(request.POST['slowal_frame_selected_arguments']) - - unifiedFrame2SlowalFrameMapping = UnifiedFrame2SlowalFrameMapping.objects.get(unified_frame_id=unified_frame_id, slowal_frame=slowal_frame_id) + unifiedFrame2SlowalFrameMapping = UnifiedFrame2SlowalFrameMapping.objects.get(unified_frame_id=unified_frame_id, + slowal_frame=slowal_frame_id) arg1_id = int(slowal_frame_selected_arguments[0]) arg2_id = int(slowal_frame_selected_arguments[1]) - unifiedFrameArgumentMapping1 = UnifiedFrameArgumentSlowalFrameMapping.objects.get(unified_frame_mapping=unifiedFrame2SlowalFrameMapping, - slowal_agrument_id=arg1_id) if arg1_id >= 0 else None - unifiedFrameArgumentMapping2 = UnifiedFrameArgumentSlowalFrameMapping.objects.get(unified_frame_mapping=unifiedFrame2SlowalFrameMapping, - slowal_agrument_id=arg2_id) if arg2_id >= 0 else None + unifiedFrameArgumentMapping1 = UnifiedFrameArgumentSlowalFrameMapping.objects.get( + unified_frame_mapping=unifiedFrame2SlowalFrameMapping, + slowal_agrument_id=arg1_id) if arg1_id >= 0 else None + unifiedFrameArgumentMapping2 = UnifiedFrameArgumentSlowalFrameMapping.objects.get( + unified_frame_mapping=unifiedFrame2SlowalFrameMapping, + slowal_agrument_id=arg2_id) if arg2_id >= 0 else None if unifiedFrameArgumentMapping1 is not None and unifiedFrameArgumentMapping2 is not None: - #mamy oba argumenty, zamieniamy miescami + # mamy oba argumenty, zamieniamy miescami unifiedFrameArgumentMapping1.slowal_agrument_id = arg2_id unifiedFrameArgumentMapping2.slowal_agrument_id = arg1_id unifiedFrameArgumentMapping1.save() unifiedFrameArgumentMapping2.save() elif unifiedFrameArgumentMapping1 is not None and unifiedFrameArgumentMapping2 is None: - #mamy lewy argument, prawy jest Empty + # mamy lewy argument, prawy jest Empty unifiedFrameArgumentMapping1.unified_agrument_id = -arg2_id unifiedFrameArgumentMapping1.save() elif unifiedFrameArgumentMapping1 is None and unifiedFrameArgumentMapping2 is not None: - #mamy prawy argument, lewy jest Empty + # mamy prawy argument, lewy jest Empty unifiedFrameArgumentMapping2.unified_agrument_id = -arg1_id unifiedFrameArgumentMapping2.save() return JsonResponse({}) return JsonResponse({}) + @ajax_required @transaction.atomic def change_slowal_frame_status(request): @@ -365,6 +393,7 @@ def change_slowal_frame_status(request): return JsonResponse({}) return JsonResponse({}) + @ajax_required @transaction.atomic def save_unified_frame_title(request): @@ -379,6 +408,7 @@ def save_unified_frame_title(request): unifiedFrame.save() return JsonResponse({}) + @ajax_required @transaction.atomic def save_selected_role(request): @@ -387,11 +417,13 @@ def save_selected_role(request): complement_id = request.POST['complement_id'] role_id = request.POST['role_id'] - unifiedFrameArgument = UnifiedFrameArgument.objects.get(unified_frame_id=int(unified_frame_id), id=int(complement_id)) + unifiedFrameArgument = UnifiedFrameArgument.objects.get(unified_frame_id=int(unified_frame_id), + id=int(complement_id)) unifiedFrameArgument.role_id = role_id unifiedFrameArgument.save() return JsonResponse({}) + @ajax_required @transaction.atomic def save_new_role(request): @@ -404,7 +436,8 @@ def save_new_role(request): argumentRole = ArgumentRole.objects.filter(role_id=role_id, attribute_id=attribute_id).first() if argumentRole is None: - argumentRole = ArgumentRole(role=SemanticRole.objects.get(pk=role_id), attribute=RoleAttribute.objects.get(pk=attribute_id)) + argumentRole = ArgumentRole(role=SemanticRole.objects.get(pk=role_id), + attribute=RoleAttribute.objects.get(pk=attribute_id)) argumentRole.save() unifiedFrameArgument = UnifiedFrameArgument.objects.get(unified_frame_id=unified_frame_id, id=complement_id) @@ -413,6 +446,7 @@ def save_new_role(request): unifiedFrameArgument.save() return JsonResponse({}) + @ajax_required @transaction.atomic def add_argument(request): @@ -426,6 +460,7 @@ def add_argument(request): unifiedFrame.save() return JsonResponse({}) + @ajax_required @transaction.atomic def remove_argument(request): @@ -440,6 +475,7 @@ def remove_argument(request): unifiedFrame.save() return JsonResponse({}) + @ajax_required @transaction.atomic def change_unified_frame_status_to_ready(request): @@ -455,6 +491,7 @@ def change_unified_frame_status_to_ready(request): unifiedFrame.save() return JsonResponse({}) + @ajax_required @transaction.atomic def change_unified_frame_status_to_verified_by_superleksykograf(request): @@ -463,17 +500,18 @@ def change_unified_frame_status_to_verified_by_superleksykograf(request): unifiedFrame = UnifiedFrame.objects.get(pk=unified_frame_id) unifiedFrame.status = choices.UnifiedFrameStatus.VERIFIED - #save fin statement info for current active fin statement + # save fin statement info for current active fin statement fin_statements = FinStatement.objects.filter(is_active=True) if fin_statements.count() == 1: active_fin_statement = fin_statements[0] - unifiedFrame.fin_statement = active_fin_statement; + unifiedFrame.fin_statement = active_fin_statement unifiedFrame.save() return JsonResponse({}) + def create_unified_frame(lu_id): - response = requests.post('http://127.0.0.1:8000/en/unifier/build_unified_frame_xml/?lu_id='+str(lu_id)) + response = requests.post('http://127.0.0.1:8000/en/unifier/build_unified_frame_xml/?lu_id=' + str(lu_id)) parser = make_parser() parser.setFeature(handler.feature_external_ges, False) @@ -489,6 +527,7 @@ def create_unified_frame(lu_id): return unified_frame_id + @csrf_exempt def build_unified_frame_xml(request): if request.method == 'POST': @@ -519,12 +558,14 @@ def build_unified_frame_xml(request): for id, argument in enumerate(arguments): arguments_connectionElem = SubElement(arguments_connectionsElem, 'arguments_connection', - attrib={'unifier_argument_id': str(id), 'slowal_id': str(argument.id)}) + attrib={'unifier_argument_id': str(id), + 'slowal_id': str(argument.id)}) xml = tostring(matchingElem) return HttpResponse(xml) return HttpResponse() + @ajax_required @transaction.atomic def save_unified_frame_title(request): @@ -539,6 +580,7 @@ def save_unified_frame_title(request): unifiedFrame.save() return JsonResponse({}) + @ajax_required @transaction.atomic def frame_assign(request): @@ -572,24 +614,125 @@ def frame_assign(request): return JsonResponse(ret) return JsonResponse({}) + def removeUnifiedFrameMappingsAndAssigments(unified_frame_id): - #odpianie z ramy zunifikowanej + # odpianie z ramy zunifikowanej unifiedFrame2SlowalFrameMappings = UnifiedFrame2SlowalFrameMapping.objects.filter(unified_frame_id=unified_frame_id) for unifiedFrame2SlowalFrameMapping in unifiedFrame2SlowalFrameMappings: unifiedFrame2SlowalFrameMapping.slowal_frame.status = 'N' unifiedFrame2SlowalFrameMapping.slowal_frame.save() Assignment.delete(subject_id=unifiedFrame2SlowalFrameMapping.slowal_frame.id) - unifiedFrameArgumentSlowalFrameMappings = UnifiedFrameArgumentSlowalFrameMapping.objects.filter(unified_frame_mapping=unifiedFrame2SlowalFrameMapping) + unifiedFrameArgumentSlowalFrameMappings = UnifiedFrameArgumentSlowalFrameMapping.objects.filter( + unified_frame_mapping=unifiedFrame2SlowalFrameMapping) unifiedFrameArgumentSlowalFrameMappings.delete() unifiedFrame2SlowalFrameMapping.delete() Assignment.delete(subject_id=unified_frame_id) + @ajax(login_required=True, method='post') @transaction.atomic def delete_unified_frame(request, unified_frame_id): - removeUnifiedFrameMappingsAndAssigments(unified_frame_id) UnifiedFrameArgument.objects.filter(unified_frame_id=unified_frame_id).delete() UnifiedFrame.objects.get(id=unified_frame_id).delete() return {} + + +@ajax_required +@transaction.atomic +def hierarchy_assign(request): + if request.method == 'POST': + + hyponym_id = request.POST['hyponym_id'] + hyperonym_id = request.POST['hyperonym_id'] + + curr1 = HierarchyModel.objects.filter(hyponym_id=hyponym_id, hyperonym_id=hyperonym_id) + curr2 = HierarchyModel.objects.filter(hyponym_id=hyperonym_id, hyperonym_id=hyponym_id) + + if curr1 or curr2: + return JsonResponse({'exists': 'true'}) + + hierarchy = HierarchyModel() + hierarchy.hyponym_id = hyponym_id + hierarchy.hyperonym_id = hyperonym_id + hierarchy.save() + + setHierarchyExistsInfo(hyponym_id) + setHierarchyExistsInfo(hyperonym_id) + + return JsonResponse({'succ': 'true'}) + return JsonResponse({}) + + +def setHierarchyExistsInfo(unified_fram_id): + unified_frame = UnifiedFrame.objects.get(pk=unified_fram_id) + unified_frame.hasHierarchyElems = True + unified_frame.save() + + +@ajax_required +@transaction.atomic +def hierarchy_unassign(request): + if request.method == 'POST': + + rel1_id = request.POST['rel1_id'] + rel2_id = request.POST['rel2_id'] + + curr1 = HierarchyModel.objects.filter(hyponym_id=rel1_id, hyperonym_id=rel2_id) + + succ = False + + if curr1: + curr1.delete() + succ = True + else: + curr2 = HierarchyModel.objects.filter(hyponym_id=rel2_id, hyperonym_id=rel1_id) + if curr2: + curr2.delete() + succ = True + + # check if there is any heierarchy elements for unified frames from request + setNoHierarchyExistsInfo(rel1_id) + setNoHierarchyExistsInfo(rel2_id) + + return JsonResponse({'succ': succ}) + + +def setNoHierarchyExistsInfo(unified_frame_id): + rel_1_hierarchy_count = HierarchyModel.objects.filter(Q(hyponym_id=unified_frame_id) | Q(hyperonym_id=unified_frame_id)).count() + if rel_1_hierarchy_count == 0: + # set info of no hierarchy elems in unified frame -> used to color unified frame list component + unified_frame = UnifiedFrame.objects.get(pk=unified_frame_id) + unified_frame.hasHierarchyElems = False + unified_frame.save() + + +@ajax_required +@transaction.atomic +def get_hierarchy_hyponyms(request, unified_frame_id): + hyponyms = HierarchyModel.objects.filter(hyperonym_id=unified_frame_id) + + res = [] + for unifiedFrame in hyponyms: + res.append(get_unified_frame_json(unifiedFrame.hyponym, request)) + res = { + 'hyponyms': res + } + + return JsonResponse(res) + + +@ajax_required +@transaction.atomic +def get_hierarchy_hyperonyms(request, unified_frame_id): + hyperonyms = HierarchyModel.objects.filter(hyponym_id=unified_frame_id) + + res = [] + for unifiedFrame in hyperonyms: + res.append(get_unified_frame_json(unifiedFrame.hyperonym, request)) + res = { + 'hyperonyms': res + } + + return JsonResponse(res) diff --git a/users/models.py b/users/models.py index b6dde51edf2a228d23d74358f44f992ff1f294e0..2fe93d375d97f6a5814cfde766f4d70b01070b45 100644 --- a/users/models.py +++ b/users/models.py @@ -56,5 +56,6 @@ class Note(models.Model): title = models.CharField(max_length=100) note = models.TextField() created_at = models.DateTimeField(auto_now_add=True) + type = models.CharField(max_length=100, default=None, blank=True, null=True) objects = models.Manager.from_queryset(NoteQuerySet)() diff --git a/users/templates/notes.html b/users/templates/notes.html index 25240c81039341feb3862670dabf624427492a38..0b2ba2425daab3180a4691a00a5d030a903536bc 100644 --- a/users/templates/notes.html +++ b/users/templates/notes.html @@ -1,7 +1,7 @@ {% load i18n %} <div class="border p-2"> - <div id="note-form-template" class="d-none" data-url="{% url 'users:add_note' model='MODEL' pk='PK' %}"> + <div id="note-form-template" class="d-none" data-url="{% url 'users:add_note' model='MODEL' pk='PK' type='TYPE' %}"> <div class="mb-2 border-bottom pb-2"> <div class="clearfix"> <h6 class="float-left">{% trans 'Dodaj notatkÄ™' %}</h6> @@ -22,7 +22,7 @@ <h6 class="mt-4 d-inline">{% trans 'Notatki' %}</h6> <a href="#" class="show-note-form btn btn-xs btn-outline-dark ml-2">{% trans 'Dodaj' %}</a> </div> - <table class="table table-sm table-striped border notes-table mb-0" data-url="{% url 'users:get_notes' model='MODEL' pk='PK' %}"> + <table class="table table-sm table-striped border notes-table mb-0" data-url="{% url 'users:get_notes' model='MODEL' pk='PK' type='TYPE' %}"> <tbody></tbody> </table> </div> diff --git a/users/urls.py b/users/urls.py index 911aa58e603246bcdcf3466aed032d379c962b4a..acc4488818c137240a98a5a6b67361b4a601feed 100644 --- a/users/urls.py +++ b/users/urls.py @@ -54,7 +54,7 @@ urlpatterns = [ ), name='password_reset_confirm' ), - re_path(r'^notes/(?P<model>\w+.\w+)/(?P<pk>\w+)/$', views.get_notes, name='get_notes'), - re_path(r'^notes/(?P<model>\w+.\w+)/(?P<pk>\w+)/add/$', views.add_note, name='add_note'), + re_path(r'^notes/(?P<model>\w+.\w+)/(?P<pk>\w+)/(?P<type>\w+)/$', views.get_notes, name='get_notes'), + re_path(r'^notes/(?P<model>\w+.\w+)/(?P<pk>\w+)/(?P<type>\w+)/add/$', views.add_note, name='add_note'), path('notes/<int:pk>/delete/', views.delete_note, name='delete_note'), ] diff --git a/users/views.py b/users/views.py index 63b23cf22eec2fcafb56b1e2d3ff8e382f5b22a4..00789ac1522c2c28fe3bb9a9c2cb92d6a7d22f19 100644 --- a/users/views.py +++ b/users/views.py @@ -58,11 +58,13 @@ def user_edit(request, pk): @login_required -def get_notes(request, model, pk): +def get_notes(request, model, pk, type): model = apps.get_model(*model.split('.')) subject = get_object_or_404(model, pk=pk) ct = ContentType.objects.get_for_model(model) notes = Note.objects.filter(subject_ct=ct, subject_id=subject.pk).for_user(request.user).order_by('created_at') + if type: + notes = notes.filter(type=type) return JsonResponse({ "notes": [{ "pk": note.pk, @@ -70,16 +72,19 @@ def get_notes(request, model, pk): "created_at": note.created_at, "title": note.title, "note": note.note, + "type": note.type, } for note in notes], }) @require_http_methods(["POST"]) @login_required -def add_note(request, model, pk): +def add_note(request, model, pk, type): model = apps.get_model(*model.split('.')) subject = get_object_or_404(model, pk=pk) note = Note(author=request.user, subject=subject) + if type: + note.type = type form = NoteForm(instance=note, data=request.POST) if form.is_valid(): form.save() @@ -89,7 +94,8 @@ def add_note(request, model, pk): @require_http_methods(["DELETE"]) @login_required -def delete_note(request, pk): - note = get_object_or_404(Note.objects.for_user(request.user), pk=pk) +def delete_note(request, pk, type): + note = get_object_or_404(Note.objects.for_user(request.user), pk=pk, type=type) if type else \ + get_object_or_404(Note.objects.for_user(request.user), pk=pk) note.delete() return JsonResponse({})