diff --git a/entries/form_fields/generic_fields.py b/entries/form_fields/generic_fields.py index 65255665852871189043de3020814cc79ea9d4b4..b982ebed322f70885c1f65395a6bfb5770844cf9 100644 --- a/entries/form_fields/generic_fields.py +++ b/entries/form_fields/generic_fields.py @@ -30,7 +30,6 @@ class CheckboxesLayoutField(object): else: return layout.Field(x, **kwargs) - class RadiosLayoutField(object): def layout(self, x, **kwargs): diff --git a/entries/static/entries/css/entries.css b/entries/static/entries/css/entries.css index 3142fbfd5121517051227ddd0bca1921431dd07b..4094eedbc7dc89dd7e7eb3fb2ba23599de5d1d64 100644 --- a/entries/static/entries/css/entries.css +++ b/entries/static/entries/css/entries.css @@ -184,6 +184,18 @@ legend { border-color: #564c4c; } +.active-lu { + font-weight: bold; +} + +.lu-underline { + text-decoration: underline; +} + +.lu-cursor-pointer { + cursor: pointer; +} + .sticky-bottom { position: sticky; bottom: 0; diff --git a/entries/templates/entries_base.html b/entries/templates/entries_base.html index 0d1501ea98f2367e7c6a45fe23b7feadb5b8352e..974596005e1913bef44ffe68019dfdf96c013854 100644 --- a/entries/templates/entries_base.html +++ b/entries/templates/entries_base.html @@ -30,6 +30,7 @@ {% 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> {% 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 new file mode 100644 index 0000000000000000000000000000000000000000..6c757149c1cb09c826fc901e5f7438f400eecc27 --- /dev/null +++ b/entries/templates/hierarchy.html @@ -0,0 +1,24 @@ +{% extends "entries_base.html" %} + +{% load i18n %} +{% load static %} + +{% block title %}{% trans "Hasła" %}{% endblock %} + +{% block scripts %} + {{ block.super }} + <link rel="stylesheet" type="text/css" href="{% static 'entries/css/unification_frames.css' %}"> + <link rel="stylesheet" type="text/css" href="{% static 'common/css/role_colours.css' %}"> + <script src="{% static 'entries/js/unification_entries_list.js' %}"></script> + <script src="{% static 'entries/js/unification_frames_list.js' %}"></script> + <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' }}; + </script> +{% endblock %} + +{% block modals %} + {{ block.super }} + <div id="lexical-unit-notes-template" class="d-none">{% include 'notes.html' %}</div> +{% endblock %} diff --git a/entries/urls.py b/entries/urls.py index 3b4bd7c465d4a2cee984aeb6ab0f2c60b310f969..7e244f59e82cf179f8c8cabb8b3329223a775474 100644 --- a/entries/urls.py +++ b/entries/urls.py @@ -18,6 +18,7 @@ urlpatterns = [ path('change_show_reals_desc/', views.change_show_reals_desc, name='change_show_reals_desc'), path('change_show_linked_entries/', views.change_show_linked_entries, name='change_show_linked_entries'), path('unification/', views.unification, name='unification'), + path('hierarchy/', views.hierarchy, name='hierarchy'), path('autocomplete/', autocompletes.autocomplete, name='autocomplete'), path('plWN_context_lookup/', ajax_plWN_context_lookup, name='plWN_context_lookup'), diff --git a/entries/views.py b/entries/views.py index a0c9f1cfc92d33896e3138f2914fd5aaec6f5e14..1bd5081164e0066c14816afa5d673c4f02fa344c 100644 --- a/entries/views.py +++ b/entries/views.py @@ -86,6 +86,20 @@ def unification(request): }, ) +@login_required +def hierarchy(request): + return render( + request, + 'hierarchy.html', + { + 'is_vue_app': True, + 'unified_frame_id': request.GET.get("unified_frame_id"), + 'entries_form': EntryForm(), + 'frames_form': FrameFormFactory.get_form(as_subform=False), + 'schemata_form': SchemaFormFactory.get_form(as_subform=False), + 'unified_frames_form': UnifiedFrameFormFactory.get_form(as_subform=False), + }, + ) FORM_TYPES = { 'entry' : EntryForm, diff --git a/frontend/src/components/unification/Unification/LexicalUnitEdit.vue b/frontend/src/components/unification/Unification/LexicalUnitEdit.vue index 32f59691f6f09b6885016ff7d9b39460e3085237..2afeec26e2c2c669cd69d707fc941d1dce4c22ed 100644 --- a/frontend/src/components/unification/Unification/LexicalUnitEdit.vue +++ b/frontend/src/components/unification/Unification/LexicalUnitEdit.vue @@ -959,7 +959,7 @@ export default LexicalUnitEdit; <tbody> <tr> <th scope="row" class="py-2 px-1 text-secondary role-header">Role</th> - + <template v-for="argument in unified_frame_arguments"> <td class="argument py-2 px-1 border-top border-left border-secondary role-column" @@ -1023,7 +1023,8 @@ export default LexicalUnitEdit; <tbody> <tr> <th scope="row" class="py-2 px-1 text-secondary">Jednostka leksykalna</th> - <th scope="row" class="py-2 px-1 text-secondary">Opinion</th> + <th scope="row" class="py-2 px-1 text-secondary">Opinia</th> + <th scope="row" class="py-2 px-1 text-secondary">Status</th> </tr> <tr class="preferences py-0 px-0 border-top border-left border-secondary" v-for='lexical_unit in lexical_units' diff --git a/frontend/src/components/unification/hierarchy/Hierarchy.vue b/frontend/src/components/unification/hierarchy/Hierarchy.vue new file mode 100644 index 0000000000000000000000000000000000000000..82876fe016c46921e13a09d44b1badf259188107 --- /dev/null +++ b/frontend/src/components/unification/hierarchy/Hierarchy.vue @@ -0,0 +1,80 @@ +<script> +import UnificationFramesList from "../Unification/UnificationFramesList.vue"; +import HierarchyRightPane from "./HierarchyRightPane.vue"; + +export default { + data () { + return { + entryId: null, + lexicalUnitId: null, + unifiedFrameId: null, + gettext: window.gettext, + unificationEntriesListRefreshKey: 1, + }; + }, + components: {HierarchyRightPane, UnificationFramesList}, + methods: { + lexicalUnitSelected (entryId, lexicalUnitId) { + this.entryId = entryId; + this.lexicalUnitId = lexicalUnitId; + }, + unifiedFrameSelected (unifiedFrameId, entryId, lexicalUnitId) { + this.unifiedFrameId = unifiedFrameId; + this.entryId = entryId; + this.lexicalUnitId = lexicalUnitId; + }, + refreshEntriesList() { + this.unificationEntriesListRefreshKey++; + } + }, + setup() { + const lexicalUnit = new URL(location.href).searchParams.get('lexical_unit_id'); + const entryId = new URL(location.href).searchParams.get('entry_id'); + return { + initialLexicalUnitId: parseInt(lexicalUnit), + initialEntryId: parseInt(entryId), + }; + }, + mounted () { + this.unifiedFrameSelected(window.initialUnifiedFrameId); + $('#entries-list').length && Split(['#entries-list', '#entry-display'], { + sizes: [20, 80], + gutterSize: 4, + minSize: 10, + elementStyle: (dimension, size, gutterSize) => { + return { + 'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)' + } + }, + }); + }, +}; +</script> + +<template> + <div id="entries-list" class="col h-100 w-100 pr-0 overflow-hidden"> + <div id="entries-list-div" class="col p-0 h-100 w-100 overflow-hidden"> + <unification-frames-list + :unificationEntriesListRefreshKey="unificationEntriesListRefreshKey" + @unified-frame-selected="unifiedFrameSelected" + /> +<!-- <unification-switchable-list--> +<!-- :unificationEntriesListRefreshKey="unificationEntriesListRefreshKey"--> +<!-- :initialLexicalUnitId="lexicalUnitId ? lexicalUnitId : initialLexicalUnitId"--> +<!-- :initialEntryId="entryId ? entryId : initialEntryId"--> +<!-- @lexical-unit-selected="lexicalUnitSelected"--> +<!-- @unified-frame-selected="unifiedFrameSelected"--> +<!-- />--> + </div> + </div> + <div id="entry-display" class="col h-100 p-0 overflow-hidden"> + <hierarchy-right-pane + ref="hierarchyRightPane" + :entryId="entryId" + :lexicalUnitId="lexicalUnitId" + :initialUnifiedFrameId="unifiedFrameId" + @refresh-entries-list="refreshEntriesList" + /> + </div> +</template> + diff --git a/frontend/src/components/unification/hierarchy/HierarchyEdit.vue b/frontend/src/components/unification/hierarchy/HierarchyEdit.vue new file mode 100644 index 0000000000000000000000000000000000000000..79f174b87a15c08428776411a04a01850eb37f91 --- /dev/null +++ b/frontend/src/components/unification/hierarchy/HierarchyEdit.vue @@ -0,0 +1,1095 @@ +<script> +import InfoTooltip from "../../shared/InfoTooltip.vue"; +import Spinner from "../../shared/Spinner.vue"; +import ExamplesComponent from "../shared/frame-components/ExamplesComponent.vue"; +import SlowalFrameComponent from "../shared/frame-components/SlowalFrameComponent.vue"; +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"; + +let HierarchyEdit = { + components: {HierarchyPreview} +}; + +Object.assign(HierarchyEdit, { + props: { + unifiedFrameId: Number, + previewedUnifiedFrameId: Number, + readOnly: Boolean, + initialRightPaneTab: String, + forceRefresh: Number, + }, + data() { + return { + gettext: window.gettext, + HierarchyEdit: HierarchyEdit, + unified_frame: {}, + unified_frame_title: '', + unified_frame_arguments: [], + active_unified_frame_argument: null, + slowal_frames2selecional_preferencies_mapping: {}, + lexical_units: [], + img_prefix: window.STATIC_URL, + frames: [], + right_pane_tabs: [ + {id: 'schemata', label: gettext('Schematy')}, + {id: 'frame_preview', label: gettext('Podgląd ram')}, + {id: 'hierarchy', label: gettext('Hierarchia')}, + {id: 'notes', label: gettext('Notatki')}, + ], + right_pane_tab: this.initialRightPaneTab || 'schemata', + currentPreviewedUnifiedFrameId: this.previewedUnifiedFrameId, + internalForceRefresh: this.forceRefresh, + statusButtonTitle: '', + active_slowal_frame: null, + showVerifiedFrames: false, + subentries: null, + alternations: null, + realisation_phrases: null, + realisation_descriptions: null, + examples: null, + selectedFrameArguments: null, + frame_arguments_or_type: false, + selectedLus: null, + selectedSchemas: null, + selectedExamples: null, + hidden_frames: [], + } + }, + components: {InfoTooltip, Spinner, HierarchyPreview, SlowalFrameComponent, ExamplesComponent, SemanticsSchemataComponent, MeaningComponent}, + emits: ['goToDisplay', 'refresh', 'swapFrames', 'refreshEntriesList', 'clearUnifiedFrameView'], + watch: { + forceRefresh(newVal, oldVal) { + this.loadFrame(); + } + }, + computed: { + selectionalPreference() { + return new SelectionalPreference(); + } + }, + methods: { + hasWhiteSpace(s) { + return /\s/g.test(s); + }, + async loadFrame() { + try { + const data = {'unified_frame_id': this.unifiedFrameId, 'no_filters' : false}; + $.ajax({ + type: 'post', + url: '/' + lang + '/unifier/get_unified_frame/', + dataType: 'json', + data: data, + timeout: 60000, + success: function (response) { + + this.img_prefix = window.STATIC_URL; + this.lexical_units = this.frames2lexical_units(response.frames); + this.unified_frame = response.unified_frame; + this.unified_frame_title = this.unified_frame.title; + this.unified_frame_arguments = this.unified_frame.arguments; + this.frames = response.frames; + this.slowal_frames2selecional_preferencies_mapping = slowal_frames2selecional_preferencies(this.unified_frame, response.frames); + + this.subentries = response.subentries; + this.alternations = response.alternations; + this.realisation_phrases = response.realisation_phrases; + this.realisation_descriptions = response.realisation_descriptions; + this.examples = response.examples; + + this.fulfill_slowal_frames_arguments_with_empty_elems(response.unified_frame, response.frames) + window.update_last_visited(response.last_visited); + window.clear_info(); + + this.changeStatusButtonTitleToDefault(); + if (!this.active_slowal_frame) { + this.setup_notes_unified_frame(); + } + }.bind(this), + error: function (request, errorType, errorMessage) { + show_error(errorType + ' (' + errorMessage + ')'); + } + }); + + } 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); + } + }, + 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); + }, + unifiedFrameArgumentSelected(argument) { + if (this.active_unified_frame_argument === argument) { + this.active_unified_frame_argument = null; + this.frame_arguments_or_type = false; + this.deselectSlowalFrameSelectedElements(); + } else { + this.active_slowal_frame = null; + this.active_unified_frame_argument = argument; + const slowalFrameArguments = this.getSlowalFrameArgumentsBy(argument); + this.frame_arguments_or_type = true; + this.deselectSlowalFrameSelectedElements(); + this.selectedFrameArguments = slowalFrameArguments; + } + this.unifiedFrameArgumentHovered(argument); + }, + unifiedFrameArgumentHovered(argument) { + clear_info(); + if (argument && this.active_unified_frame_argument === argument) { + show_info(gettext('Kliknij, aby cofnąć wybór kolumny do edycji.')); + } + if (argument && this.active_unified_frame_argument !== argument) { + 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ę.")); + } 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(); + } + }); + } + } + }.bind(this) + } + } + $.prompt(change_title_popup); + }, + changeRole() { + if (!this.active_unified_frame_argument) { + alert(gettext("Zaznacz argument, dla którego chcesz wybrać rolę.")); + } 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) + } + }; + $.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) { + const slowal_frame_mapping = this.unified_frame.slowal_frame_mapping[i]; + const slowalFrame = this.frames.find(frame => frame.id === slowal_frame_mapping.slowal_frame_id); + if(slowalFrame != null) { + 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 == unified_frame_argument.id) { + const slowalFrameArgument = slowalFrame.arguments.find(arg => arg.argument_id === slowal_frame_argument_mapping.slowal_frame_agrument_id); + slowalFrameArgumentIds.push(slowalFrameArgument); + } + } + } + } + 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"); + }, + isFrameVerified(frame) { + const isSuperLeksykograf = this.isSuperLeksykograf(); + return (!isSuperLeksykograf && frame.status === 'G') || (isSuperLeksykograf && frame.status === 'S') + }, + select_slowal_frame_req(to_invoke) { + if (this.active_slowal_frame) { + to_invoke(); + } else { + 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 => { + s.selected = false; + }); + }); + this.frames.forEach(frame => { + frame.lexical_units.forEach(lu => { + lu.selected = false; + }); + frame.arguments.forEach(argument => { + argument.selected = false; + }); + }); + this.examples.forEach(example => { + example.selected = false; + }); + this.selectedLus = []; + this.selectedFrameArguments = []; + this.selectedSchemas = []; + this.selectedExamples = []; + }, + slowalFrameSelected(frame) { + 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) { + if (this.active_slowal_frame) { + return frame.id === this.active_slowal_frame.id; + } else { + 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) { + const frame = frames[i]; + for (let j in frame.lexical_units) { + const lexical_unit = frame.lexical_units[j]; + lexical_unit.opinion = frame.opinion; + lexical_unit.opinion_key = frame.opinion_key; + lexical_unit.frame_status = frame.status; + lexical_unit.frame = frame; + lexical_units.push(lexical_unit); + } + } + return lexical_units; + }, + fulfill_slowal_frames_arguments_with_empty_elems(unified_frame, slowal_frames) { + for (let i in unified_frame.slowal_frame_mapping) { + const slowal_frame_mapping = unified_frame.slowal_frame_mapping[i]; + let slowal_frame = slowal_frames.find(o => o.id === slowal_frame_mapping.slowal_frame_id); + if(slowal_frame != null) { + let new_slowal_frame_arguments = []; + for (let j in unified_frame.arguments) { + const unified_frame_argument = unified_frame.arguments[j]; + let unified_frame_argument_mapping = slowal_frame_mapping.slowal_frame_argument_mapping.find(o => o.unified_frame_agrument_id === unified_frame_argument.id); + let slowal_frame_argument = null; + if (unified_frame_argument_mapping == null) { + slowal_frame_argument = { + 'str': 'Empty', + 'id': slowal_frame.id + '-_' + (unified_frame_argument.id), + 'role': 'Empty', + 'role_type': 'Empty', + 'preferences': [], + 'proposed_roles': [], + } + } else { + slowal_frame_argument = slowal_frame.arguments.find(o => o.argument_id === unified_frame_argument_mapping.slowal_frame_agrument_id); + } + new_slowal_frame_arguments.push(slowal_frame_argument) + } + slowal_frame.arguments = new_slowal_frame_arguments; + } + } + } + }, + mounted() { + + if(this.unifiedFrameId) { + this.loadFrame(); + } + + this.changeStatusButtonTitleToDefault(); + if(!this.readOnly) { + Split(['#semantics-frames-pane', '#semantics-schemata-pane'], { + sizes: [40, 60], + minSize: 10, + gutterSize: 4, + elementStyle: (dimension, size, gutterSize) => { + return { + 'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)' + } + }, + }); + Split(['#semantics-unified-frame-pane', '#examples'], { + sizes: [60, 40], + direction: 'vertical', + gutterSize: 4, + minSize: 10, + }); + } else { + Split(['#semantics-unified-frame-pane-preview', '#examples-preview'], { + sizes: [60, 40], + direction: 'vertical', + gutterSize: 4, + minSize: 10, + }); + } + } +}); + +export default HierarchyEdit; + +</script> + +<template> + <div class="col h-100 px-0 pt-0 pb-0 overflow-auto" id="semantics-frames-pane"> + <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> + </tr> + </table> + + <spinner /> + <div align="center"> + <div align="left" style="display: table;"> + <div class="unifiedFrame mt-3" v-bind:data-frame_id="unified_frame.id" id="unified-frame-title" v-html="unified_frame_title"></div> + <table v-if="unified_frame.id" id="unified-frame" class="m-0 table-borderless border border-secondary text-dark frame active"> + <tbody> + <tr> + <template v-for="argument in unified_frame_arguments"> + <td + class="argument py-2 px-1 border-top border-left border-secondary role-column" + :class="getArgumentCSS(argument)" + @click="unifiedFrameArgumentSelected(argument)" + @mouseover="unifiedFrameArgumentHovered(argument)" + @mouseleave="unifiedFrameArgumentHovered(null)" + > + {{ 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 class="preferences py-0 px-0 border-top border-left border-secondary role-column align-top" + v-for='argument in 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> + <ul class="ul-preference" v-if="unified_frame.status !== 'S'"> + <li v-for="preference in slowal_frames2selecional_preferencies_mapping[argument.id]"> + <span v-if="preference.url != null" class="preference py-2 px-1"> + <a class="synset-plwn" v-bind:href="preference.url" target="_blank">{{ preference.str }}</a> + </span> + <span v-else class="preference py-2 px-1">{{ preference.str }}</span> + <info-tooltip v-if="preference.info" :text="preference.info" /> + </li> + </ul> + </td> + </tr> + </tbody> + </table> + </div> + <div v-if="unified_frame.id" class="lu-table mt-3 mb-3"> + <table class="m-0 table-borderless border border-secondary text-dark"> + <tbody> + <tr> + <th scope="row" class="py-2 px-1 text-secondary">Jednostka leksykalna</th> + <th scope="row" class="py-2 px-1 text-secondary">Opinia</th> + <th scope="row" class="py-2 px-1 text-secondary">Status</th> + </tr> + <tr class="preferences py-0 px-0 border-top border-left border-secondary" + 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" + @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' : ''" + @click="slowalFrameSelected(lexical_unit.frame)">{{ lexical_unit.str }}</td> + <td class="argument py-2 px-1 border-top border-left border-secondary"> + <img v-bind:src="img_prefix + 'entries/img/' +lexical_unit.opinion_key + '.svg'" width="12" height="12" v-bind:alt="lexical_unit.opinion"> + {{ lexical_unit.opinion }} + </td> + <td class="argument py-2 px-1 border-top border-left border-secondary">[{{ lexical_unit.frame_status }}]</td> + </template> + </tr> + </tbody> + </table> + </div> + </div> + </div> + <div :id="'examples' + (readOnly ? '-preview' : '')" class="col w-100 p-0 tab-pane overflow-auto"> + <examples-component v-if="examples" + :examples="examples" + :frame="active_slowal_frame" + :frame_arguments="selectedFrameArguments" + :frame_arguments_or_type="frame_arguments_or_type" + :lus="selectedLus" + :schemas="selectedSchemas" + :key="examples" + @example-selected="exampleSelected" + /> + </div> + </div> + <div v-if="!readOnly" class="col h-100 px-1 pt-0 pb-0 overflow-auto" style="padding-left: 0px!important; padding-right: 0px!important;" id="semantics-schemata-pane"> + <ul class="nav nav-pills nav-justified p-1" id="entryTabs" role="tablist"> + <li + v-for="tab in right_pane_tabs" + class="btn btn-sm btn-outline-dark nav-link mx-1" + :class="right_pane_tab === tab.id && 'active'" + @click="right_pane_tab = tab.id" + > + {{ tab.label }} + </li> + </ul> + <div v-if="active_slowal_frame" :class="right_pane_tab !== 'schemata' && 'd-none'"> + <semantics-schemata-component + :subentries="subentries" + :key="subentries" + :frame="active_slowal_frame" + :alternations="alternations" + :realisation_phrases="realisation_phrases" + :realisation_descriptions="realisation_descriptions" + :selectedExamples="selectedExamples" + @schemata-selected="schemataSelected" + /> + </div> + <div v-if="right_pane_tab === 'frame_preview'" 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> + <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> + <div :class="right_pane_tab !== 'notes' && 'd-none'" id="notes-component"></div> + </div> +</template> diff --git a/frontend/src/components/unification/hierarchy/HierarchyPreview.vue b/frontend/src/components/unification/hierarchy/HierarchyPreview.vue new file mode 100644 index 0000000000000000000000000000000000000000..a88db178c963a0d44586121fed07c7997869ce33 --- /dev/null +++ b/frontend/src/components/unification/hierarchy/HierarchyPreview.vue @@ -0,0 +1,64 @@ +<script> +import UnificationFramesList from "../Unification/UnificationFramesList.vue"; + +export default { + props: { + initialUnifiedFrameId: Number, + initialLexicalUnitId: Number, + forceRefresh: Number, + hierarchyEditComponent: Object, + }, + data () { + return { + unifiedFrameId: this.initialUnifiedFrameId + }; + }, + components: {UnificationFramesList}, + emits: ['changeFrame', 'refreshEntriesList'], + methods: { + unifiedFrameSelected (unifiedFrameId) { + this.$emit('changeFrame', unifiedFrameId); + }, + refreshEntriesList() { + this.$emit('refreshEntriesList') + }, + }, + mounted () { + Split(['#frame-preview-left-pane', '#frame-preview-right-pane'], { + sizes: [60, 40], + minSize: 20, + gutterSize: 4, + elementStyle: (dimension, size, gutterSize) => { + return { + 'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)' + } + }, + }); + } +}; +</script> + +<template> + <div class="row h-100 overflow-hidden"> + <div :key="unifiedFrameId" class="col h-100 pr-0 pt-0 pb-0 overflow-auto" id="frame-preview-left-pane"> + <component v-bind:is="hierarchyEditComponent" + v-if="unifiedFrameId !== -1" + :readOnly="true" + :unifiedFrameId="unifiedFrameId" + :forceRefresh="forceRefresh" + @refresh-entries-list="refreshEntriesList" + /> + <div v-else class="h-100"> + Brak ramy do wyświetlenia + </div> + </div> + <div class="col h-100 pl-1 pt-0 pb-0 overflow-auto" id="frame-preview-right-pane"> +<!-- <unification-switchable-list--> +<!-- @unified-frame-selected="unifiedFrameSelected"--> +<!-- />--> + <unification-frames-list + @unified-frame-selected="unifiedFrameSelected" + /> + </div> + </div> +</template> diff --git a/frontend/src/components/unification/hierarchy/HierarchyRightPane.vue b/frontend/src/components/unification/hierarchy/HierarchyRightPane.vue new file mode 100644 index 0000000000000000000000000000000000000000..913bbf73ff32d8e620d7e127760f826e20c8b768 --- /dev/null +++ b/frontend/src/components/unification/hierarchy/HierarchyRightPane.vue @@ -0,0 +1,68 @@ +<script> +import HierarchyEdit from './HierarchyEdit.vue'; + +export default { + components: {HierarchyEdit}, + props: { + entryId: Number, + lexicalUnitId: Number, + initialUnifiedFrameId: Number, + }, + emits: ['refreshEntriesList'], + data() { + return this.getInitialData(); + }, + methods: { + getInitialData() { + return { + key: this.lexicalUnitId, + entryIdLocal: this.entryId, + unifiedFrameId: this.initialUnifiedFrameId, + previewedUnifiedFrameId: null + }; + }, + goToDisplay() { + this.unifiedFrameId = null; + }, + refresh() { + this.key = null; + setTimeout(() => { + this.key = this.lexicalUnitId; + }, 0); + }, + swapFrames(previewedUnifiedFrameId) { + this.previewedUnifiedFrameId = this.unifiedFrameId; + this.unifiedFrameId = previewedUnifiedFrameId; + this.refresh(); + }, + refreshEntriesList() { + this.$emit('refreshEntriesList'); + } + }, + watch: { + lexicalUnitId() { + Object.assign(this, this.getInitialData()); + }, + initialUnifiedFrameId() { + Object.assign(this, this.getInitialData()); + } + }, +}; +</script> + +<template> + <div v-if="key || unifiedFrameId" :key="(key, entryIdLocal, unifiedFrameId)" class="row h-100 m-0 p-0 overflow-auto" id="semantics-top-pane"> + <hierarchy-edit + ref="hierarchyEdit" + v-if="unifiedFrameId" + :key="unifiedFrameId" + :readOnly="false" + :unifiedFrameId="unifiedFrameId" + :previewedUnifiedFrameId="previewedUnifiedFrameId" + :initialRightPaneTab="previewedUnifiedFrameId && unifiedFrameId !== previewedUnifiedFrameId ? 'frame_preview' : 'schemata'" + @go-to-display="goToDisplay" + @swap-frames="swapFrames" + @refresh-entries-list="refreshEntriesList" + /> + </div> +</template> diff --git a/frontend/src/main.js b/frontend/src/main.js index ffa91dae0990e3332e895ffd92f3155c1780c048..d28df1bdbb8ca055338d77e06e127d4b9b85f453 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -5,12 +5,14 @@ import { createRouter, createWebHistory } from "vue-router"; import Entries from "./components/unification/Entries/Entries.vue"; import Unification from "./components/unification/Unification/Unification.vue"; +import Hierarchy from "./components/unification/hierarchy/Hierarchy.vue"; const router = createRouter({ history: createWebHistory(), routes: [ { path: '/:lang/entries/', component: Entries }, { path: '/:lang/entries/unification/', component: Unification }, + { path: '/:lang/entries/hierarchy/', component: Hierarchy }, { path: '/:pathMatch(.*)*', component: null, name: '404' }, ] }); diff --git a/unifier/views.py b/unifier/views.py index fe251b14feac78b203eb7146434edf710b42ec85..8a45397acd3776593414324ed6b6da572c7c29e6 100644 --- a/unifier/views.py +++ b/unifier/views.py @@ -92,6 +92,9 @@ def get_unified_frames(request): else: unifiedFrames = UnifiedFrame.objects.all(); + if scroller_params['filter']: + unifiedFrames = unifiedFrames.filter(title__startswith=scroller_params['filter']) + # TODO: zapytać, czy mamy zaciągać powiązane ramy zunifikowane poprzez Enrty (slowal_frame -> lexical_units -> entries -> related_entries) # linked_ids = set() # if request.session['show_linked_entries']: @@ -120,7 +123,7 @@ def get_unified_frames(request): resProcessed.append(value) ret = { - 'draw' : scroller_params['draw'], + 'draw': scroller_params['draw'], 'recordsTotal': len(resProcessed), 'recordsFiltered': len(resProcessed), 'data': resProcessed