diff --git a/entries/forms.py b/entries/forms.py index c30edf0c5d087d417b904ac626bff84412c2e21d..2384da9efe47129041330cc754d31075c07d7ec2 100644 --- a/entries/forms.py +++ b/entries/forms.py @@ -27,6 +27,7 @@ from semantics.models import ( ) from meanings.models import Synset +from unifier.models import UnifiedFrame from .form_fields.generic_fields import ( RangeFilter, @@ -601,6 +602,53 @@ class FrameFormFactory(FormFactory): raise KeyError(type(child_form)) + +class UnifiedFrameFormFactory(FormFactory): + + form_class_name = 'UnifiedFrameForm' + form_model = UnifiedFrame + form_formtype = 'unifiedframe' + form_header = _('Zunifikowana rama semantyczna') + + field_makers = ( + ( + 'opinion', + lambda: ModelMultipleChoiceFilter( + label=_('Opinia'), + queryset=FrameOpinion.objects.exclude(key='unk').filter(frame__isnull=False).distinct(), + key='key', + human_values=polish_strings.FRAME_OPINION(), + lookup='opinion', + ), None, + ), + ( + 'num_arguments', + lambda: RangeFilter( + label=_('Liczba argumentów'), + lookup='arguments_count', + ), None + ), + ( + 'name', + lambda: RegexFilter( + label=_('Nazwa'), + max_length=200, + lookup='title', + ), None, + ), + ( + None, None, + lambda n, cls: and_or_form_creator(_('UnifiedFrameArgument'), 'add-argument-{}'.format(n), data_add='argument'), + ), + ) + + @staticmethod + def get_child_form_prefix(child_form): + if child_form.model_class == Argument: + return 'arguments__in' + raise KeyError(type(child_form)) + + class ArgumentFormFactory(FormFactory): form_class_name = 'ArgumentForm' diff --git a/entries/static/entries/js/entries.js b/entries/static/entries/js/entries.js index a218b24fe6e98f44d5bd4bf553a3b3f16fb43b15..cc480ad453915afe7b0fd6e245dc5ffccb52d90d 100644 --- a/entries/static/entries/js/entries.js +++ b/entries/static/entries/js/entries.js @@ -1128,6 +1128,8 @@ $(document).ready(function() { initialize_frames_form(); initialize_schemata_form(); + + initialize_unified_frames_form(); //$('.local-filter').hide(); diff --git a/entries/static/entries/js/forms.js b/entries/static/entries/js/forms.js index b123492bd940332a30525ca435345a8861b087fb..cacca0d1477ba2309913bffaf41c7f5b5db97122 100644 --- a/entries/static/entries/js/forms.js +++ b/entries/static/entries/js/forms.js @@ -427,6 +427,7 @@ function initialize_main_form() { if (response.errors) { show_form_errors(main_form, response.errors); } else if (response.success) { + //ponizsza funkcja prowadzi do metody osadzonej w main.js, gdzie nastepuje odpowiednie odswiezenie komponentu z lista elementow Vue update_entries(); $('#entry-filters').modal('hide'); } @@ -476,6 +477,7 @@ function initialize_local_form(selector, url) { if (response.errors) { show_form_errors(form, response.errors); } else if (response.success) { + //ponizsza funkcja prowadzi do metody osadzonej w main.js, gdzie nastepuje odpowiednie odswiezenie komponentu z lista elementow Vue update_entries(); selector.modal('hide'); } @@ -494,6 +496,11 @@ function initialize_frames_form() { initialize_local_form($('#frame-filters'), '/' + lang + '/entries/send_frames_form/'); } +function initialize_unified_frames_form() { + initialize_local_form($('#unified-frame-filters'), '/' + lang + '/entries/send_unified_frames_form/'); +} + + function initialize_schemata_form() { initialize_local_form($('#schema-filters'), '/' + lang + '/entries/send_schemata_form/'); diff --git a/entries/templates/checkboxselectmultiple_with_tooltips.html b/entries/templates/checkboxselectmultiple_with_tooltips.html index b0cbaef385728f68dc73fa99153a4c99b9c62c7b..9ef9c8a11c109bc86ea3bb3e10aef759e2a1e879 100644 --- a/entries/templates/checkboxselectmultiple_with_tooltips.html +++ b/entries/templates/checkboxselectmultiple_with_tooltips.html @@ -9,7 +9,7 @@ <input type="checkbox" class="{%if use_custom_control%}custom-control-input{% else %}form-check-input{% endif %}{%if is_bound %} is-{% if field.errors %}in{%endif%}valid{% endif %}"{% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|default_if_none:""|stringformat:"s" %} checked="checked"{% endif %} name="{{ field.html_name }}" id="id_{{ field.html_name }}_{{ forloop.counter }}" value="{{ choice.0|unlocalize }}" {{ field.field.widget.attrs|flatatt }}> <label class="{%if use_custom_control%}custom-control-label{% else %}form-check-label{% endif %}" for="id_{{ field.html_name }}_{{ forloop.counter }}"> {% if choice.1.1 %} - {{ choice.1.0|unlocalize }} <span data-toggle="tooltip" data-placement="bottom" title="{{ choice.1.1 }}"><img src="{% static 'common/img/info.svg' %}" alt="info" width="14" height="14"/></span> + {{ choice.1.0|unlocalize }} <span data-toggle="tooltip" data-placement="bottom" title="{{ choice.1.1 }}"><img src="common/img/info.svg" alt="info" width="14" height="14"/></span> {% else %} {{ choice.1.0|unlocalize }} {% endif %} diff --git a/entries/templates/entries_base.html b/entries/templates/entries_base.html index b46559a6c66c07047c2d29e5564328bc95d7595a..546dee8aa39f437e471e430f9a4c9c89908933b9 100644 --- a/entries/templates/entries_base.html +++ b/entries/templates/entries_base.html @@ -42,6 +42,9 @@ <a href="#" class="dropdown-item font-weight-bold text-dark text-uppercase" id="filter-frames-button" data-toggle="modal" data-target="#frame-filters"> {% trans "Ramy" %} </a> + <a href="#" class="dropdown-item font-weight-bold text-dark text-uppercase" id="filter-unified-frames-button" data-toggle="modal" data-target="#unified-frame-filters"> + {% trans "Ramy zunifikowane" %} + </a> <a href="#" class="dropdown-item font-weight-bold text-dark text-uppercase" id="filter-schemata-button" data-toggle="modal" data-target="#schema-filters"> {% trans "Schematy" %} </a> @@ -115,6 +118,22 @@ </div> </div> +<div class="modal fade" id="unified-frame-filters" tabindex="-1" role="dialog" aria-labelledby="unified-frame-filtersLabel" aria-hidden="true"> + <div class="modal-dialog modal-xl" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="unified-frame-filtersLabel">{% trans "Filtrowanie zunifikowanych ram" %}</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body text-dark"> + {% crispy unified_frames_form %} + </div> + </div> + </div> +</div> + <div class="modal fade" id="schema-filters" tabindex="-1" role="dialog" aria-labelledby="schema-filtersLabel" aria-hidden="true"> <div class="modal-dialog modal-xl" role="document"> <div class="modal-content"> diff --git a/entries/templates/role_checkboxselectmultiple_inner.html b/entries/templates/role_checkboxselectmultiple_inner.html index 6310fe05320954dfef444387b26231e5f5ba0308..bc10a421c47d858eb8ca2fef3627a6b2c667f9cb 100644 --- a/entries/templates/role_checkboxselectmultiple_inner.html +++ b/entries/templates/role_checkboxselectmultiple_inner.html @@ -26,7 +26,7 @@ <input type="checkbox" class="{%if use_custom_control%}custom-control-input{% else %}form-check-input{% endif %}{%if is_bound %} is-{% if field.errors %}in{%endif%}valid{% endif %}"{% if choice.0 in field.value or choice.0|stringformat:"s" in field.value or choice.0|stringformat:"s" == field.value|default_if_none:""|stringformat:"s" %} checked="checked"{% endif %} name="{{ field.html_name }}" id="id_{{ field.html_name }}_{{ forloop.parentloop.parentloop.counter }}_{{ forloop.parentloop.counter }}_{{ forloop.counter }}" value="{{ choice.0|unlocalize }}" {{ field.field.widget.attrs|flatatt }}> <label class="{%if use_custom_control%}custom-control-label{% else %}form-check-label{% endif %} text-dark" for="id_{{ field.html_name }}_{{ forloop.parentloop.parentloop.counter }}_{{ forloop.parentloop.counter }}_{{ forloop.counter }}"> {% if choice.1.1 %} - {{ choice.1.0|unlocalize }} <span data-toggle="tooltip" data-placement="bottom" title="{{ choice.1.1 }}"><img src="{% static 'common/img/info.svg' %}" alt="info" width="14" height="14"/></span> + {{ choice.1.0|unlocalize }} <span data-toggle="tooltip" data-placement="bottom" title="{{ choice.1.1 }}"><img src="common/img/info.sv" alt="info" width="14" height="14"/></span> {% else %} {{ choice.1.0|unlocalize }} {% endif %} diff --git a/entries/urls.py b/entries/urls.py index d735f33755b5dde2f94cfe4ec78cb284fe9f9621..3b4bd7c465d4a2cee984aeb6ab0f2c60b310f969 100644 --- a/entries/urls.py +++ b/entries/urls.py @@ -10,6 +10,7 @@ urlpatterns = [ path('send_form/', views.send_form, name='send_form'), path('send_schemata_form/', views.send_schemata_form, name='send_schemata_form'), path('send_frames_form/', views.send_frames_form, name='send_frames_form'), + path('send_unified_frames_form/', views.send_unified_frames_form, name='send_unified_frames_form'), #path('filter_schemata/', views.filter_schemata, name='filter_schemata'), path('get_entries/', views.get_entries, name='get_entries'), path('get_entry/', views.get_entry, name='get_entry'), diff --git a/entries/views.py b/entries/views.py index 5430b0109f26927229d996ab1e9025de26be55b6..8cacf582e825e48cdd530fca364ce55804d69088 100644 --- a/entries/views.py +++ b/entries/views.py @@ -38,7 +38,7 @@ from .forms import ( ArgumentFormFactory, PredefinedPreferenceFormFactory, RelationalPreferenceFormFactory, - SynsetPreferenceFormFactory, + SynsetPreferenceFormFactory, UnifiedFrameFormFactory, ) from .polish_strings import STATUS, POS, SCHEMA_OPINION, FRAME_OPINION, EXAMPLE_SOURCE, EXAMPLE_OPINION, RELATION @@ -66,7 +66,8 @@ def entries(request): 'is_vue_app': True, 'entries_form' : EntryForm(), 'frames_form' : FrameFormFactory.get_form(as_subform=False), - 'schemata_form' : SchemaFormFactory.get_form(as_subform=False) + 'schemata_form' : SchemaFormFactory.get_form(as_subform=False), + 'unified_frames_form': UnifiedFrameFormFactory.get_form(as_subform=False), }) @@ -80,7 +81,8 @@ def unification(request): '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) + 'schemata_form': SchemaFormFactory.get_form(as_subform=False), + 'unified_frames_form': UnifiedFrameFormFactory.get_form(as_subform=False), }, ) @@ -95,6 +97,7 @@ FORM_FACTORY_TYPES = { 'phrase_lex' : LexFormFactory, 'lemma' : LemmaFormFactory, 'frame' : FrameFormFactory, + 'unifiedframe' : UnifiedFrameFormFactory, 'argument' : ArgumentFormFactory, 'predefined' : PredefinedPreferenceFormFactory, 'relational' : RelationalPreferenceFormFactory, @@ -334,6 +337,21 @@ def send_frames_form(request): return JsonResponse({}) +@ajax_required +def send_unified_frames_form(request): + if request.method == 'POST': + errors_dict = dict() + forms = collect_forms(request.POST['forms[]'], errors_dict) + eid = request.POST['entry'] + if errors_dict: + del request.session['unified_frame_form'] + return JsonResponse({ 'success' : 0, 'errors' : errors_dict }) + else: + request.session['unified_frame_form'] = request.POST['forms[]'] + return JsonResponse({ 'success' : 1 }) + return JsonResponse({}) + + def get_scroller_params(POST_data): order = (int(POST_data['order[0][column]']), POST_data['order[0][dir]']) return { @@ -371,6 +389,12 @@ def get_entries(request): if scroller_params['filter']: entries = entries.filter(name__startswith=scroller_params['filter']) filtered = entries.count() + + local_frame_form = None + if 'frame_form' in request.session: + errors_dict = dict() + local_frame_form = collect_forms(request.session['frame_form'], errors_dict) + assert(not errors_dict) linked_ids = set() if request.session['show_linked_entries']: @@ -402,28 +426,32 @@ def get_entries(request): .select_related('status', 'pos') .prefetch_related(Prefetch("assignments", to_attr="_assignments")) ) + if with_lexical_units: + frameQueryset = Frame.objects.select_related("slowal_frame_2_unified_frame").prefetch_related(Prefetch("assignments", to_attr="_assignments")); entries = entries.prefetch_related( Prefetch( "lexical_units", LexicalUnit.objects.prefetch_related( Prefetch( "frames", - Frame.objects - .select_related("slowal_frame_2_unified_frame") - .prefetch_related(Prefetch("assignments", to_attr="_assignments")), + queryset=get_filtered_objects(local_frame_form, frameQueryset) if local_frame_form is not None else frameQueryset, to_attr="_frames", ) ) ) ) + status_names = STATUS() POS_names = POS() def iter_lexical_units(e): for lu in e.lexical_units.all(): - lu._frame = lu._frames[0] if lu._frames else None - yield lu + lu._frame = lu._frames[0] if lu._frames and len(lu._frames) > 0 else None + if lu._frame is None: + continue + else: + yield lu result = { 'draw' : scroller_params['draw'], diff --git a/frontend/src/components/unification/Entries/EntriesList.vue b/frontend/src/components/unification/Entries/EntriesList.vue index 40e4b3c958d1c7b784ce0a355ff65b4cef0028f8..e72897d4d7d831d701ec58f85103f50c37eb55ce 100644 --- a/frontend/src/components/unification/Entries/EntriesList.vue +++ b/frontend/src/components/unification/Entries/EntriesList.vue @@ -24,7 +24,7 @@ } }, methods: { - reset_entry_list() { + reset_list() { this.$emit('lexicalUnitSelected', null, null); setup_entries_list({ table: this.$refs.table, diff --git a/frontend/src/components/unification/Unification/UnificationFramesList.vue b/frontend/src/components/unification/Unification/UnificationFramesList.vue index b4e1bb451827a7b55dc90d980e0de3a5fbff6034..933bae26bbab537a3d9f9f01273e44313805bc22 100644 --- a/frontend/src/components/unification/Unification/UnificationFramesList.vue +++ b/frontend/src/components/unification/Unification/UnificationFramesList.vue @@ -10,6 +10,18 @@ export default { canViewAssignment: has_permission("users.view_assignment") } }, + methods: { + reset_list() { + this.$emit('unifiedFrameSelected', null); + setup_frames_list({ + table: this.$refs.table, + unifiedFrameSelected: (unifiedFrameId) => { + this.$emit('unifiedFrameSelected', unifiedFrameId); + }, + selectEntryId: this.initialUnifiedFrameId, + }); + } + }, watch: { unificationEntriesListRefreshKey() { // TODO: reload data and click in selected row @@ -25,6 +37,7 @@ export default { }, emits: ['unifiedFrameSelected'], mounted() { + this.$.appContext.config.globalProperties.$entries_list = this; setup_frames_list({ table: this.$refs.table, unifiedFrameSelected: (unifiedFrameId) => { diff --git a/frontend/src/main.js b/frontend/src/main.js index 3e8ecc4816a2f0882e76a9cf2f5689022c5defd3..ffa91dae0990e3332e895ffd92f3155c1780c048 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -25,6 +25,6 @@ window.update_entries = function () { mounted = true; } if(app._context.config.globalProperties.$entries_list) { - app._context.config.globalProperties.$entries_list.reset_entry_list(); + app._context.config.globalProperties.$entries_list.reset_list(); } } diff --git a/unifier/views.py b/unifier/views.py index 036dc0043f898837f1a9f0280b81ca0970ad1f6f..8de7272c3e9a27e39c003a289204778d00a22e90 100644 --- a/unifier/views.py +++ b/unifier/views.py @@ -8,7 +8,8 @@ from django.views.decorators.csrf import csrf_exempt from common.decorators import ajax_required, ajax from entries.polish_strings import EXAMPLE_SOURCE, EXAMPLE_OPINION -from entries.views import get_scroller_params, get_alternations, get_prefs_list, schema2dict, frame2dict +from entries.views import get_scroller_params, get_alternations, get_prefs_list, schema2dict, frame2dict, collect_forms, \ + get_filtered_objects from importer.unification.UnificationPreprocessXML import UnificationPreprocessHandler from meanings.models import LexicalUnit from semantics.choices import FrameStatus @@ -72,8 +73,14 @@ def get_unified_frames(request): exclude_status = request.GET.get('exclude_status') restrict_to_user = request.GET.get('restrict_to_user') + errors_dict = dict() + forms = collect_forms(request.session['unified_frame_form'], errors_dict) + res = {} - unifiedFrames = UnifiedFrame.objects.all(); + # unifiedFrames = UnifiedFrame.objects.all(); + + unifiedFrames = get_filtered_objects(forms).filter() + for unifiedFrame in unifiedFrames: res[unifiedFrame.id] = { 'id': str(unifiedFrame.id),