From 24c70cad75f57acc2745b4abdfc7ad1573d638ea Mon Sep 17 00:00:00 2001
From: dcz <dcz@ipipan.waw.pl>
Date: Thu, 24 Aug 2023 12:36:17 +0200
Subject: [PATCH] SubAttribute in semsntic role #81

---
 entries/static/entries/js/entries.js            | 14 ++++++++++++++
 entries/urls.py                                 |  3 ++-
 entries/views.py                                | 17 ++++++++++++++++-
 .../unification/Unification/LexicalUnitEdit.vue | 14 ++++++++++----
 semantics/models.py                             | 16 ++++++++++++++++
 syntax/management/commands/import_tei.py        | 17 ++++++++++++-----
 unifier/views.py                                | 17 +++++++++++------
 .../commands/create_groups_and_permissions.py   |  2 +-
 8 files changed, 82 insertions(+), 18 deletions(-)

diff --git a/entries/static/entries/js/entries.js b/entries/static/entries/js/entries.js
index f4370f3..9046133 100644
--- a/entries/static/entries/js/entries.js
+++ b/entries/static/entries/js/entries.js
@@ -11,6 +11,7 @@ var curr_examples_by_id = null;
 
 var roles = []
 var role_attributes = []
+var role_sub_attributes = []
 
 function make_opinion_row(item, span, width) {
     const opinion_row = document.createElement('tr');
@@ -1112,6 +1113,17 @@ function getRoleAttributes() {
     });
 }
 
+function getRoleSubAttributes() {
+    $.ajax({
+        dataType: "json",
+        url: '/' + lang + '/entries/role_sub_attributes',
+        success: function(data){
+            role_sub_attributes = data.role_sub_attributes;
+        },
+        async: false
+    });
+}
+
 $(document).ready(function() {
     bind_last_visited();
     
@@ -1143,6 +1155,8 @@ $(document).ready(function() {
 
     getRoleAttributes();
 
+    getRoleSubAttributes();
+
     // $.getJSON('relations', function(data){
     //     memorizeRelations(data.relations);
     // });
diff --git a/entries/urls.py b/entries/urls.py
index 7e244f5..d440adb 100644
--- a/entries/urls.py
+++ b/entries/urls.py
@@ -2,7 +2,7 @@ from django.urls import path
 
 from . import autocompletes, views
 from .views import ajax_plWN_context_lookup, ajax_predefined_preferences, ajax_relations, ajax_synsets, ajax_roles, \
-    ajax_role_attributes
+    ajax_role_attributes, ajax_role_sub_attributes
 
 app_name = 'entries'
 
@@ -25,6 +25,7 @@ urlpatterns = [
     path('predefined_preferences/', ajax_predefined_preferences, name='predefined_preferences'),
     path('roles/', ajax_roles, name='roles'),
     path('role_attributes/', ajax_role_attributes, name='role_attributes'),
+    path('role_sub_attributes/', ajax_role_sub_attributes, name='role_sub_attributes'),
     path('relations/', ajax_relations, name='relations'),
     path('synsets/', ajax_synsets, name='synsets'),
 
diff --git a/entries/views.py b/entries/views.py
index eb3210f..9708d31 100644
--- a/entries/views.py
+++ b/entries/views.py
@@ -21,7 +21,7 @@ from connections.models import Entry, Subentry, ArgumentConnection, RealisationD
 from meanings.models import LexicalUnit
 from syntax.models import NaturalLanguageDescription, Schema
 from semantics.models import Frame, PredefinedSelectionalPreference, SelectivePreferenceRelations, SemanticRole, \
-    RoleAttribute
+    RoleAttribute, RoleSubAttribute
 
 from common.decorators import ajax_required, ajax
 from unifier.models import UnifiedFrame
@@ -1045,6 +1045,21 @@ def ajax_role_attributes(request):
 
     return context
 
+
+@ajax(method='get', encode_result=True)
+def ajax_role_sub_attributes(request):
+    role_sub_attributes = []
+    for roleSubAttribute in RoleSubAttribute.objects.order_by('priority'):
+        role_sub_attributes.append({"id": roleSubAttribute.id, "sub_attribute": roleSubAttribute.sub_attribute,
+                               "priority": roleSubAttribute.priority})
+
+    context = {
+        'role_sub_attributes': role_sub_attributes,
+    }
+
+    return context
+
+
 # @render('relations.json')
 @ajax(method='get', encode_result=True)
 def ajax_relations(request):
diff --git a/frontend/src/components/unification/Unification/LexicalUnitEdit.vue b/frontend/src/components/unification/Unification/LexicalUnitEdit.vue
index aafc7a2..5c172a4 100644
--- a/frontend/src/components/unification/Unification/LexicalUnitEdit.vue
+++ b/frontend/src/components/unification/Unification/LexicalUnitEdit.vue
@@ -280,13 +280,17 @@ Object.assign(LexicalUnitEdit, {
           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 => {
+          let subAttributesHTML = role_sub_attributes.map(subAttribute => {
+            return `<label><input type="radio" name="sub_attribute" value="${subAttribute.id}" /> ${subAttribute.sub_attribute}</label><br />`;
+          }).join("");
+          const roleTypeHTML = ['required', 'typical'].map(type => {
             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 class="column"><div class="role_select_header">Podatrybuty</div>' + subAttributesHTML + '</div>' +
               '</div>';
         }.bind(this);
 
@@ -370,12 +374,15 @@ Object.assign(LexicalUnitEdit, {
                 if (role_id != null && role_type != null) {
                   const attribute_id = normalizeFormData(f.attribute)[0];
 
+                  const sub_attribute_id = normalizeFormData(f.sub_attribute)[0];
+
                   const data = {
                     '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
+                    'attribute_id': attribute_id,
+                    'sub_attribute_id': sub_attribute_id
                   };
                   $.ajax({
                     type: 'post',
@@ -985,8 +992,7 @@ export default LexicalUnitEdit;
                     @mouseover="unifiedFrameArgumentHovered(argument)"
                     @mouseleave="unifiedFrameArgumentHovered(null)"
                 >
-                {{ argument.role_type }}
-                
+                <span style="font-size: 0.8rem;">{{ argument.role_type }}</span>
                 <div
                   v-if="argument.role"
                 >
diff --git a/semantics/models.py b/semantics/models.py
index e9ddba0..4dda269 100644
--- a/semantics/models.py
+++ b/semantics/models.py
@@ -58,6 +58,7 @@ class Argument(models.Model):
 class ArgumentRole(models.Model):
     role = models.ForeignKey('SemanticRole', on_delete=models.PROTECT)
     attribute = models.ForeignKey('RoleAttribute', null=True, on_delete=models.PROTECT)
+    sub_attribute = models.ForeignKey('RoleSubAttribute', null=True, on_delete=models.PROTECT)
 
     def __str__(self):
         if self.attribute is None:
@@ -90,6 +91,17 @@ class RoleAttribute(models.Model):
         return self.attribute
 
 
+class RoleSubAttribute(models.Model):
+    sub_attribute = models.CharField(max_length=20)
+    priority = models.PositiveIntegerField()
+
+    class Meta:
+        ordering = ['priority']
+
+    def __str__(self):
+        return self.sub_attribute
+
+
 class RoleType(models.Model):
     type = models.CharField(max_length=20)
 
@@ -105,6 +117,7 @@ class PredefinedSelectionalPreference(models.Model):
     def __str__(self):
         return self.name
 
+
 class RelationalSelectionalPreference(models.Model):
     relation = models.ForeignKey('SelectionalPreferenceRelation', on_delete=models.PROTECT)
     to = models.ForeignKey('Argument', on_delete=models.PROTECT)
@@ -112,6 +125,7 @@ class RelationalSelectionalPreference(models.Model):
     def __str__(self):
         return '%s -> %s' % (self.relation, self.to)
 
+
 class SelectivePreferenceRelations(models.Model):
     plwn_id = models.IntegerField(null=True)
     name = models.CharField(max_length=80)
@@ -120,10 +134,12 @@ class SelectivePreferenceRelations(models.Model):
     def __unicode__(self):
         return u'%s' % (self.name)
 
+
 class SynsetRelationalSelectivePreference(models.Model):
     relation = models.ForeignKey(SelectivePreferenceRelations, on_delete=models.PROTECT)
     to = models.ForeignKey(Synset, on_delete=models.PROTECT)
 
+
 class SelectivePreference(models.Model):
     generals = models.ManyToManyField(PredefinedSelectionalPreference)
     synsets = models.ManyToManyField(Synset)
diff --git a/syntax/management/commands/import_tei.py b/syntax/management/commands/import_tei.py
index 8917105..b6ac6c8 100644
--- a/syntax/management/commands/import_tei.py
+++ b/syntax/management/commands/import_tei.py
@@ -13,7 +13,7 @@ from examples.models import ExampleOpinion, ExampleSource
 from importer.WalentyPreprocessXML import WalentyPreprocessTeiHandler
 from importer.WalentyXML import WalentyTeiHandler
 from semantics.models import FrameOpinion, ArgumentRole, SemanticRole, RoleAttribute, \
-    SelectionalPreferenceRelation, RoleType
+    SelectionalPreferenceRelation, RoleType, RoleSubAttribute
 from shellvalier.environment import get_environment
 from shellvalier.settings import BASE_DIR
 from syntax.management.commands.add_predefined_preferences import create_predefined_preferences
@@ -188,7 +188,6 @@ def import_semantic_roles():
         (150, u'Time', u'242,236,54', None),
         (160, u'Duration', u'233,192,6', None),
         (170, u'Measure', u'238,72,154', None),
-        (180, u'Lemma', u'256,256,256', None),
         (190, u'Disponent', u'127,255,212', None),
         (200, u'Means', u'pre', None)
     ]
@@ -196,14 +195,19 @@ def import_semantic_roles():
     # Role_Source < Role_Foreground < Role_Background < Role_Goal
     # and Role can be inserted anywhere into that hierarchy
     attributes = [(1, u'Source', None, u'left'), (3, u'Foreground', None, u'top'), (5, u'Background', None, u'bottom'),
-                  (7, u'Goal', None, u'right'), (8, u'Source_Part', None, u'right'),
-                  (9, u'Source_Attrib', None, u'right')]
+                  (7, u'Goal', None, u'right'), (8, u'Source', None, u'right')]
+
+    sub_attributes = [(1, u'Part'), (2, u'Attrib')]
+
     for pri, role, color, gradient in roles:
         role = SemanticRole(role=role, color=color, priority=pri)
         role.save()
     for pri, role, color, gradient in attributes:
         role = RoleAttribute(attribute=role, gradient=gradient, priority=pri)
         role.save()
+    for pri, sub_attrib in sub_attributes:
+        sub_attrib_obj = RoleSubAttribute(sub_attribute=sub_attrib, priority=pri)
+        sub_attrib_obj.save()
 
     for role in SemanticRole.objects.all():
         r = ArgumentRole(role=role, attribute=None)
@@ -211,10 +215,13 @@ def import_semantic_roles():
         for attribute in RoleAttribute.objects.all():
             r = ArgumentRole(role=role, attribute=attribute)
             r.save()
+            for sub_attribute in RoleSubAttribute.objects.all():
+                r = ArgumentRole(role=role, attribute=attribute, sub_attribute=sub_attribute)
+                r.save()
 
 
 def import_semantic_role_types():
-    role_types = [(10, u'role'), (20, u'alternative'), (30, u'modifier')]
+    role_types = [(10, u'required'), (20, u'alternative'), (30, u'typical')]
     for pri, name in role_types:
         cont = RoleType(type=name)
         cont.save()
diff --git a/unifier/views.py b/unifier/views.py
index ce20416..1a4bb73 100644
--- a/unifier/views.py
+++ b/unifier/views.py
@@ -15,7 +15,7 @@ from financial_settlement.models import FinStatement
 from importer.unification.UnificationPreprocessXML import UnificationPreprocessHandler
 from meanings.models import LexicalUnit
 from semantics.choices import FrameStatus
-from semantics.models import Frame, ArgumentRole, SemanticRole, RoleAttribute, RoleType
+from semantics.models import Frame, ArgumentRole, SemanticRole, RoleAttribute, RoleType, RoleSubAttribute
 from syntax.models import Schema
 from unifier.models import UnifiedFrameArgument, UnifiedRelationalSelectionalPreference, UnifiedFrame, \
     UnifiedFrame2SlowalFrameMapping, UnifiedFrameArgumentSlowalFrameMapping, HierarchyModel
@@ -159,9 +159,11 @@ def unified_frame_2_dict(frame):
                 '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': '{}{}{}'.format(a.role.role.role.lower(),
+                                           ' ' + a.role.attribute.attribute.lower() if a.role.attribute else '',
+                                           ' (' + a.role.sub_attribute.sub_attribute.lower() + ')'
+                                           if a.role.sub_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 '',
@@ -448,11 +450,14 @@ def save_new_role(request):
         role_id = request.POST['role_id']
         role_type = request.POST['role_type']
         attribute_id = request.POST.get('attribute_id', None)
+        sub_attribute_id = request.POST.get('sub_attribute_id', None)
 
-        argument_role = ArgumentRole.objects.filter(role_id=role_id, attribute_id=attribute_id).first()
+        argument_role = ArgumentRole.objects.filter(role_id=role_id, attribute_id=attribute_id,
+                                                    sub_attribute_id=sub_attribute_id).first()
         if argument_role is None:
             argument_role = ArgumentRole(role=SemanticRole.objects.get(pk=role_id),
-                                         attribute=RoleAttribute.objects.get(pk=attribute_id))
+                                         attribute=RoleAttribute.objects.get(pk=attribute_id),
+                                         sub_attribute=RoleSubAttribute.objects.get(pk=sub_attribute_id))
             argument_role.save()
 
         unified_frame_argument = UnifiedFrameArgument.objects.get(unified_frame_id=unified_frame_id, id=complement_id)
diff --git a/users/management/commands/create_groups_and_permissions.py b/users/management/commands/create_groups_and_permissions.py
index 524fa2e..d7429b6 100644
--- a/users/management/commands/create_groups_and_permissions.py
+++ b/users/management/commands/create_groups_and_permissions.py
@@ -49,7 +49,7 @@ class Command(BaseCommand):
         super_lexicographs, __ = Group.objects.get_or_create(name=settings.SUPER_LEXICOGRAPHS_GROUP_NAME)
         super_lexicographs.permissions.add(
             self._get_permission(Assignment, 'view_assignment'),
-            self._get_permission(Note, 'view_all_notes'),
+            # self._get_permission(Note, 'view_all_notes'),
             self._get_permission(Frame, 'manage_invalid_lexical_units'),
         )
 
-- 
GitLab