From 1956fbd0ea213f95451afbc41d7a4ba75c8ea30c Mon Sep 17 00:00:00 2001
From: dcz <dcz@ipipan.waw.pl>
Date: Wed, 13 Jul 2022 19:24:31 +0200
Subject: [PATCH] Third attempt for Vue implementation of entries.js frame
 visualization.

---
 .../entries/js/components/InfoTooltip.js      |   8 +-
 .../js/components/LexicalUnitDisplay.js       |  64 +++++--
 .../entries/js/components/LexicalUnitEdit.js  | 180 ++++++++++++------
 .../frame-components/ExamplesComponent.js     |  52 +++--
 .../frame-components/MeaningComponent.js      |  49 +++++
 .../SemanticsSchemataComponent.js             |  38 +++-
 .../frame-components/SlowalFrameComponent.js  |  48 +++--
 7 files changed, 337 insertions(+), 102 deletions(-)
 create mode 100644 entries/static/entries/js/components/frame-components/MeaningComponent.js

diff --git a/entries/static/entries/js/components/InfoTooltip.js b/entries/static/entries/js/components/InfoTooltip.js
index aab7df5..3fa1e9a 100644
--- a/entries/static/entries/js/components/InfoTooltip.js
+++ b/entries/static/entries/js/components/InfoTooltip.js
@@ -1,5 +1,8 @@
 export default {
-  props: { text: String },
+  props: {
+    text: String,
+    visibleText: String
+  },
   data () {
     return {
       iconUrl: window.STATIC_URL + 'common/img/info.svg'
@@ -21,7 +24,8 @@ export default {
       :title="quotedText"
       ref="tooltip"
     >
-      <img :src="iconUrl" alt="info" width="14" height="14" />
+      <img v-if="!visibleText" :src="iconUrl" alt="info" width="14" height="14" />
+      <span v-else>{{visibleText}}</span>
     </span>
   `
 }
diff --git a/entries/static/entries/js/components/LexicalUnitDisplay.js b/entries/static/entries/js/components/LexicalUnitDisplay.js
index 5dc8249..1c42ac2 100644
--- a/entries/static/entries/js/components/LexicalUnitDisplay.js
+++ b/entries/static/entries/js/components/LexicalUnitDisplay.js
@@ -11,12 +11,19 @@ export default {
     lexicalUnitId: Number
   },
   data() {
-    return { frame: null, unifiedFrame: undefined, gettext: window.gettext, hasPermission: window.has_permission,
+    return {
+      frame: null,
+      unifiedFrame: undefined,
+      gettext: window.gettext,
+      hasPermission: window.has_permission,
       subentries: null,
       alternations: null,
       realisation_phrases: null,
       realisation_descriptions: null,
       examples: null,
+      selectedFrameArguments: null,
+      selectedLus: null,
+      selectedSchemas: null
     }
   },
   emits: ['refresh', 'refreshEntriesList'],
@@ -77,6 +84,13 @@ export default {
     setup_notes () {
       setup_notes($('#lexical-unit-notes'), $('#lexical-unit-notes-template'), this.lexicalUnitId, 'meanings.LexicalUnit', this.setup_notes);
     },
+    frameSelectionChanged (selectedFrameArguments, selectedLus) {
+      this.selectedLus = selectedLus;
+      this.selectedFrameArguments = selectedFrameArguments;
+    },
+    schemataSelected(schemas) {
+      this.selectedSchemas = schemas;
+    },
     setup () {
       $('#lexical-unit-notes').html('');
       get_entry(this.entryId, false, this.lexicalUnitId).then(entry => {
@@ -113,9 +127,12 @@ export default {
       <div id="main-frames-pane" class="row">
         <div class="col h-100 pl-3 pr-1 pt-0 pb-2 overflow-auto" id="semantics-frames-pane">
             <spinner />
-      
+<!--            <div id="semantics-frames"></div>-->
             <div id="vue-semantics-frames" v-if="frame">
-             <slowal-frame-component :frame="frame" :key="frame"/>
+               <slowal-frame-component 
+                  :frame="frame" :key="frame"
+                  @frame-selection-changed="frameSelectionChanged"
+               />
             </div>
       
             <div class="text-center mb-3">
@@ -156,21 +173,40 @@ export default {
             <div id="lexical-unit-notes"></div>
           </div>
         <div class="col h-100 px-1 pt-0 pb-0 overflow-auto" id="semantics-schemata-pane">
-  <!--      <semantics-schemata-component -->
-  <!--        :subentries="subentries"-->
-  <!--        :key="subentries"-->
-  <!--        :frame="frame"-->
-  <!--        :alternations="alternations"-->
-  <!--        :realisation_phrases="realisation_phrases"-->
-  <!--        :realisation_descriptions="realisation_descriptions"-->
-  <!--      />-->
-          <div id="semantics-schemata"></div>
+          <semantics-schemata-component 
+            :subentries="subentries"
+            :key="subentries"
+            :frame="frame"
+            :alternations="alternations"
+            :realisation_phrases="realisation_phrases"
+            :realisation_descriptions="realisation_descriptions"
+            @schemata-selected="schemataSelected"
+          />
+<!--          <div id="semantics-schemata"></div>-->
         </div>
       </div>
       <div id="vue-examples" class="row overflow-auto">
-        <div class="col w-100 pr-4">
-          <examples-component
+<!--        <div class="col w-100 p-0 tab-pane overflow-auto" id="examples">-->
+<!--            <table id="semantics-examples" class="table table-sm table-hover">-->
+<!--                <thead>-->
+<!--                    <tr>-->
+<!--                        <th scope="col">{{ gettext("Przykład") }}<i id="examples-argument"></i><i id="examples-lu"></i><i id="examples-schema"></i></th>-->
+<!--                        <th scope="col">{{ gettext("Źródło") }}</th>-->
+<!--                        <th scope="col">{{ gettext("Opinia") }}</th>-->
+<!--                    </tr>-->
+<!--                </thead>-->
+<!--                <tbody id="semantics-examples-list">-->
+<!--                </tbody>-->
+<!--            </table>-->
+<!--            <p class="mx-1 my-1" id="semantics-no-examples">{{ gettext("Brak przykładów") }}</p>-->
+<!--        </div>-->
+        <div class="col w-100 pr-4 overflow-auto">
+          <examples-component v-if="examples"
               :examples="examples" 
+              :frame="frame"
+              :frame_arguments="selectedFrameArguments"
+              :lus="selectedLus"
+              :schemas="selectedSchemas"
               :key="examples"
           />
         </div>
diff --git a/entries/static/entries/js/components/LexicalUnitEdit.js b/entries/static/entries/js/components/LexicalUnitEdit.js
index 26033a5..7b7406d 100644
--- a/entries/static/entries/js/components/LexicalUnitEdit.js
+++ b/entries/static/entries/js/components/LexicalUnitEdit.js
@@ -1,6 +1,9 @@
 import InfoTooltip from "./InfoTooltip.js";
 import Spinner from "./Spinner.js";
 import UnificationSwitchableList from "./UnificationSwitchableList.js";
+import ExamplesComponent from "./frame-components/ExamplesComponent.js";
+import SlowalFrameComponent from "./frame-components/SlowalFrameComponent.js";
+import SemanticsSchemataComponent from "./frame-components/SemanticsSchemataComponent.js";
 
 let LexicalUnitEdit = {};
 
@@ -89,10 +92,18 @@ Object.assign(LexicalUnitEdit, {
       internalForceRefresh: this.forceRefresh,
       statusButtonTitle: '',
       active_slowal_frame: null,
-      showVerifiedFrames: false
+      showVerifiedFrames: false,
+      subentries: null,
+      alternations: null,
+      realisation_phrases: null,
+      realisation_descriptions: null,
+      examples: null,
+      selectedFrameArguments: null,
+      selectedLus: null,
+      selectedSchemas: null
     }
   },
-  components: {InfoTooltip, Spinner, FramePreview},
+  components: {InfoTooltip, Spinner, FramePreview, SlowalFrameComponent, ExamplesComponent, SemanticsSchemataComponent},
   emits: ['goToDisplay', 'refresh', 'swapFrames', 'refreshEntriesList'],
   watch: {
     forceRefresh(newVal, oldVal) {
@@ -144,6 +155,13 @@ Object.assign(LexicalUnitEdit, {
             curr_realisation_phrases = response.realisation_phrases;
             curr_realisation_descriptions = response.realisation_descriptions;
             curr_examples = response.examples;
+
+            this.subentries = response.subentries;
+            this.alternations = response.alternations;
+            this.realisation_phrases = response.realisation_phrases;
+            this.realisation_descriptions = response.realisation_descriptions;
+            this.examples = response.examples;
+
             curr_examples_by_id = Object();
             for (var i in curr_examples) {
               curr_examples_by_id[curr_examples[i].id] = curr_examples[i];
@@ -708,10 +726,23 @@ Object.assign(LexicalUnitEdit, {
       const isSuperLeksykograf = this.isSuperLeksykograf();
       this.statusButtonTitle = isSuperLeksykograf ? 'Sprawdź' : 'Gotowe';
     },
-    slowalFrameSelected(frameId) {
-      const frame = this.frames.find(f => {
-            return f.id == frameId;
-          });
+    slowalFrameSelected(frame) {
+      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.selectedLus = [];
+      this.selectedFrameArguments = [];
+      this.selectedSchemas = [];
       if (this.active_slowal_frame === frame) {
         this.active_slowal_frame = null;
         if(!this.readOnly) {
@@ -820,7 +851,14 @@ Object.assign(LexicalUnitEdit, {
     },
     getArgumentCSS(argument) {
       return (argument.role ? argument.role.str + ' ' : '') + (argument == this.active_unified_frame_argument ? 'active' : '');
-    }
+    },
+    insideFrameSelectionChanged (selectedFrameArguments, selectedLus) {
+      this.selectedLus = selectedLus;
+      this.selectedFrameArguments = selectedFrameArguments;
+    },
+    schemataSelected(schemas) {
+      this.selectedSchemas = schemas;
+    },
   },
   mounted() {
     this.changeStatusButtonTitleToDefault();
@@ -841,33 +879,39 @@ Object.assign(LexicalUnitEdit, {
         gutterSize: 4,
         minSize: 10,
       });
+    } else {
+      Split(['#semantics-unified-frame-pane-preview', '#semantics-slowal-frames-pane-preview', '#examples-preview'], {
+        sizes: [40, 40, 20],
+        direction: 'vertical',
+        gutterSize: 4,
+        minSize: 10,
+      });
     }
+
     if(this.unifiedFrameId) {
       this.loadFrame();
     }
   },
   template: `
     <div class="col h-100 px-0 pt-0 pb-0 overflow-auto" id="semantics-frames-pane">
-    
-      <div id="semantics-unified-frame-pane" class="col w-100 p-0 overflow-auto">
-    
-      <table v-if="!readOnly" 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;">Zmień nazwę</td>
-          <td id="add-arg" @click="addArgument" style="padding: 10px 15px 10px 15px; color: #000000;">Dodaj argum.</td>
-          <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="addSelectivePreference">Dodaj prefer.</td>
-          <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="changeUnifiedFrameStatusToReady">Gotowe</td>
-          <td id="duplicates" @click="duplicate" style="padding: 10px 15px 10px 15px; color: #000000;">Duplikuj</td>
-        </tr>
-        <tr style="background-color: white;">
-          <td id="change-role" @click="changeRole" style="padding: 10px 15px 10px 15px; color: #000000;">Zmień rolę</td>
-          <td id="remove-arg" @click="removeArgument" style="padding: 10px 15px 10px 15px; color: #000000;">Usuń argum.</td>
-          <td id="change-windows" style="padding: 10px 15px 10px 15px; color: #000000;" @click="removeSelectionalPreference">Usuń prefer.</td>
-          <td id="change-windows" style="padding: 10px 15px 10px 15px; color: #000000;" @click="swapUnifiedFrames">Zamień okna</td>
-        </tr>
-      </table>
-      <spinner />
-      <div align="center">
+      <div :id="'semantics-unified-frame-pane' + (readOnly ? '-preview' : '')" class="col w-100 p-0 overflow-auto">
+        <table v-if="!readOnly" 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;">Zmień nazwę</td>
+            <td id="add-arg" @click="addArgument" style="padding: 10px 15px 10px 15px; color: #000000;">Dodaj argum.</td>
+            <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="addSelectivePreference">Dodaj prefer.</td>
+            <td style="padding: 10px 15px 10px 15px; color: #000000;" @click="changeUnifiedFrameStatusToReady">Gotowe</td>
+            <td id="duplicates" @click="duplicate" style="padding: 10px 15px 10px 15px; color: #000000;">Duplikuj</td>
+          </tr>
+          <tr style="background-color: white;">
+            <td id="change-role" @click="changeRole" style="padding: 10px 15px 10px 15px; color: #000000;">Zmień rolę</td>
+            <td id="remove-arg" @click="removeArgument" style="padding: 10px 15px 10px 15px; color: #000000;">Usuń argum.</td>
+            <td id="change-windows" style="padding: 10px 15px 10px 15px; color: #000000;" @click="removeSelectionalPreference">Usuń prefer.</td>
+            <td id="change-windows" style="padding: 10px 15px 10px 15px; color: #000000;" @click="swapUnifiedFrames">Zamień okna</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="lexical-unit" 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">
@@ -879,10 +923,10 @@ Object.assign(LexicalUnitEdit, {
               <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)"
-              >
+                  @click="unifiedFrameArgumentSelected(argument)"
+                  @mouseover="unifiedFrameArgumentHovered(argument)"
+                  @mouseleave="unifiedFrameArgumentHovered(null)"
+                >
                 {{ argument.role_type }}
                 
                 <div
@@ -957,7 +1001,7 @@ Object.assign(LexicalUnitEdit, {
           </div>
       </div>
       </div>
-      <div id="semantics-slowal-frames-pane" class="col w-100 p-0 overflow-auto">
+      <div :id="'semantics-slowal-frames-pane' + (readOnly ? '-preview' : '')" class="col w-100 p-0 overflow-auto">
         <table v-if="!readOnly && unified_frame.id" class="table-button-menu sticky-top" cellspacing="1">
           <tr style="background-color: white;">
             <td id="wrong-frame" style="padding: 10px 15px 10px 15px; color: #000000;" @click="change_slowal_frame_status('B')">Błędna</td>
@@ -982,18 +1026,28 @@ Object.assign(LexicalUnitEdit, {
           </tr>
         </table>
         <div id="semantics-frames">
-          <div v-for="frame in frames"
-             :key="frame.id">
+          <div v-for="frame in frames">
             <table class="table m-0 table-borderless border border-secondary text-dark"
              v-if="(!isFrameVerified(frame) || showVerifiedFrames) && isFrameVisible(frame.status)"
             >
               <tbody>
               <tr>
                 <th scope="row">
-                  <div 
-                    v-html="slowal_frame_html(frame)" 
-                    :class="isSelectedFrame(frame) ? 'active-frame' : ''"
-                  ></div>
+                <div
+                  @mouseenter="frame.hover=true"
+                  @mouseleave="frame.hover=false"
+                  @click="slowalFrameSelected(frame)"
+                  :class="frame === active_slowal_frame ? 'active-frame' : frame.hover ? 'bg-highlight' : ''" 
+                >
+<!--                  <div -->
+<!--                    v-html="slowal_frame_html(frame)" -->
+<!--                    :class="isSelectedFrame(frame) ? 'active-frame' : ''"-->
+<!--                  >-->
+                  <slowal-frame-component 
+                      :frame="frame" :key="frame"
+                      @frame-selection-changed="insideFrameSelectionChanged"
+                   />
+                </div>
                 </th>
                   <th scope="row">
                     <div v-if="!readOnly">
@@ -1017,23 +1071,31 @@ Object.assign(LexicalUnitEdit, {
             </table>
             </div>
           </div>
-        </div>
-      <div v-if="!readOnly" class="col w-100 p-0 tab-pane overflow-auto" id="examples">
-            <table id="semantics-examples" class="table table-sm table-hover">
-                <thead>
-                    <tr>
-                        <th scope="col">{{ gettext("Przykład") }}<i id="examples-argument"></i><i id="examples-lu"></i><i id="examples-schema"></i></th>
-                        <th scope="col">{{ gettext("Źródło") }}</th>
-                        <th scope="col">{{ gettext("Opinia") }}</th>
-                    </tr>
-                </thead>
-                <tbody id="semantics-examples-list">
-                </tbody>
-            </table>
-            <p class="mx-1 my-1" id="semantics-no-examples">{{ gettext("Brak przykładów") }}</p>
+      </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"
+              :lus="selectedLus"
+              :schemas="selectedSchemas"
+              :key="examples"
+          />
+<!--            <table id="semantics-examples" class="table table-sm table-hover">-->
+<!--                <thead>-->
+<!--                    <tr>-->
+<!--                        <th scope="col">{{ gettext("Przykład") }}<i id="examples-argument"></i><i id="examples-lu"></i><i id="examples-schema"></i></th>-->
+<!--                        <th scope="col">{{ gettext("Źródło") }}</th>-->
+<!--                        <th scope="col">{{ gettext("Opinia") }}</th>-->
+<!--                    </tr>-->
+<!--                </thead>-->
+<!--                <tbody id="semantics-examples-list">-->
+<!--                </tbody>-->
+<!--            </table>-->
+<!--            <p class="mx-1 my-1" id="semantics-no-examples">{{ gettext("Brak przykładów") }}</p>-->
         </div>
     </div>
-    <div v-if="!readOnly" class="col h-100 px-1 pt-0 pb-0 overflow-auto" id="semantics-schemata-pane">
+    <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"
@@ -1044,7 +1106,17 @@ Object.assign(LexicalUnitEdit, {
           {{ tab.label }}
         </li>
       </ul>
-      <div :class="right_pane_tab !== 'schemata' && 'd-none'" id="semantics-schemata"></div>
+      <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"
+                @schemata-selected="schemataSelected"
+              />
+      </div>
       <div v-if="right_pane_tab === 'frame_preview'">
         <frame-preview 
             :key="currentPreviewedUnifiedFrameId" 
diff --git a/entries/static/entries/js/components/frame-components/ExamplesComponent.js b/entries/static/entries/js/components/frame-components/ExamplesComponent.js
index 1a8f93f..2a74545 100644
--- a/entries/static/entries/js/components/frame-components/ExamplesComponent.js
+++ b/entries/static/entries/js/components/frame-components/ExamplesComponent.js
@@ -1,23 +1,57 @@
+import InfoTooltip from "../InfoTooltip.js";
 
 export default {
     props: {
         examples: Object,
+        frame: Object,
+        frame_arguments: Object,
+        schemas: Object,
+        lus: Object,
     },
+    components: {InfoTooltip},
     data() {
         return {
             img_prefix: String
         }
     },
     methods: {
+        getExamples () {
+            let ret = this.examples;
+            if(this.schemas && this.schemas.length > 0) {
+                // ograniczone do schematu
+                ret = ret.filter(e => this.schemas.every(a => e.schema_ids.includes(parseInt(a.id))));
+            }
+            if(this.frame_arguments && this.frame_arguments.length > 0) {
+                // ograniczone do argumentu ramy
+                ret = ret.filter(e => this.frame_arguments.every(a => e.argument_ids.includes(a.id)));
+            }
+            if(this.frame) {
+                ret = ret.filter(e => e.frame_ids.includes(this.frame.id));
+            }
+            if(this.lus && this.lus.length > 0) {
+                ret = ret.filter(e => this.lus.every(lu => e.lu_ids.includes(lu.id)));
+            }
+            return ret;
+        },
+        getSchemaStr(schema) {
+            return schema.positions.map(e => e.phrases.map(p => p.str).join(",")).join('|');
+        }
     },
     mounted () {
         this.img_prefix = window.STATIC_URL;
     },
     template: `
-    <table id="semantics-examples" class="table table-sm table-hover" style="">
+    <table id="semantics-examples" v-if="getExamples().length > 0" class="table table-sm table-hover" style="">
         <thead>
         <tr>
-            <th scope="col">Przykład<i id="examples-argument"></i><i id="examples-lu"></i><i id="examples-schema"></i>
+            <th scope="col">Przykład
+                <i v-if="frame_arguments" v-for="frame_argument in frame_arguments">
+                    <span class="example-role"> {{' '}}
+                        <span :class="frame_argument.role">{{frame_argument.role}}</span>
+                    </span>
+                </i>
+                <i v-if="lus" v-for="lu in lus">{{' ' + lu.str}}</i>
+                <i v-if="schemas" v-for="schema in schemas">{{' '+getSchemaStr(schema)}}</i>
             </th>
             <th scope="col">Źródło</th>
             <th scope="col">Opinia</th>
@@ -25,14 +59,10 @@ export default {
         </thead>
         <tbody id="semantics-examples-list">
         
-            <tr v-for="example in examples" class="example" data-example_id="345858">
-                <td class="py-1">{{example.sentence}}
-                        <span v-if="example.note" data-toggle="tooltip"
-                          data-placement="bottom"
-                          data-html="true" title=""
-                          :data-original-title="'Komentarz: <i>'+ example.note +'</i>'"><img
-                        :src="img_prefix + '/common/img/info.svg'" alt="info" width="14"
-                        height="14"></span>
+            <tr v-for="example in getExamples()" class="example">
+                <td class="py-1">
+                    {{example.sentence}}
+                    <info-tooltip v-if="example.note" :text="example.note" />
                 </td>
                 <td class="py-1">{{example.source}}</td>
                 <td class="py-1">{{example.opinion}}</td>
@@ -40,7 +70,7 @@ export default {
         
         </tbody>
     </table>
-    <p class="mx-1 my-1" id="semantics-no-examples" style="display: none;">Brak przykładów</p>
+    <p v-else class="mx-1 my-1" id="semantics-no-examples" style="display: none;">Brak przykładów</p>
   `
 }
 
diff --git a/entries/static/entries/js/components/frame-components/MeaningComponent.js b/entries/static/entries/js/components/frame-components/MeaningComponent.js
new file mode 100644
index 0000000..31eda2c
--- /dev/null
+++ b/entries/static/entries/js/components/frame-components/MeaningComponent.js
@@ -0,0 +1,49 @@
+import InfoTooltip from "../InfoTooltip.js";
+
+export default {
+  props: {
+    lexicalUnits: Object,
+  },
+  emits: ['meaningLuSelected'],
+  data () {
+    return {
+      iconUrl: window.STATIC_URL + 'common/img/ext-link.svg'
+    }
+  },
+  components: {InfoTooltip},
+  methods: {
+    getTooltipStr (lu) {
+      var tooltip = [];
+      if (lu.definition) {
+        tooltip.push(lu.definition);
+      }
+      if (lu.gloss) {
+        tooltip.push(lu.gloss);
+      }
+      if (!lu.url) {
+        tooltip.push(gettext('nowa jednostka spoza <i>Słowosieci</i>'));
+      }
+      return tooltip.length > 0 ? '<i>' + tooltip.join('; ') + '</i>' : null;
+    },
+    select(lexicalUnit) {
+      lexicalUnit.selected = !lexicalUnit.selected;
+      this.$emit('meaningLuSelected', this.lexicalUnits.filter(lexicalUnit => lexicalUnit.selected));
+    }
+  },
+  template: `
+    <p class="mb-1">
+        <template v-for="lexicalUnit in lexicalUnits">
+            <span
+                @mouseenter="lexicalUnit.hover=true"
+                @mouseleave="lexicalUnit.hover=false"
+                @click.stop="select(lexicalUnit)"
+                :class="lexicalUnit.selected ? 'entry-meaning active' : lexicalUnit.hover ? 'entry-meaning active' : ''" 
+                class="lexical-unit entry-meaning" style="padding-left: 4px; padding-right: 4px;">{{lexicalUnit.str}}</span> 
+            <info-tooltip v-if="getTooltipStr(lexicalUnit)" :text="getTooltipStr(lexicalUnit)"/>
+            <a v-if="lexicalUnit.url" class="lu-plwn" style="padding-left: 4px;" :href="lexicalUnit.url" target="_blank">
+                <img :src="iconUrl" alt="external link" height="14">
+            </a>
+        </template>
+    </p>
+  `
+}
diff --git a/entries/static/entries/js/components/frame-components/SemanticsSchemataComponent.js b/entries/static/entries/js/components/frame-components/SemanticsSchemataComponent.js
index d8f74f3..f5e17ce 100644
--- a/entries/static/entries/js/components/frame-components/SemanticsSchemataComponent.js
+++ b/entries/static/entries/js/components/frame-components/SemanticsSchemataComponent.js
@@ -1,3 +1,4 @@
+import InfoTooltip from "../InfoTooltip.js";
 
 export default {
     props: {
@@ -7,6 +8,8 @@ export default {
         realisation_phrases: Object,
         realisation_descriptions: Object,
     },
+    components: {InfoTooltip},
+    emits: ['schemataSelected'],
     data() {
         return {
             img_prefix: String
@@ -86,17 +89,36 @@ export default {
                 }
             }
             return phrases;
+        },
+        selectSchema(schema) {
+            schema.selected = !schema.selected;
+            const selected = [];
+            this.subentries.forEach(subentry => {
+                subentry.schemata.forEach(s => {
+                    if(s.selected) {
+                        selected.push(s);
+                    }
+                });
+            });
+            this.$emit('schemataSelected', selected);
         }
-
     },
     mounted () {
         this.img_prefix = window.STATIC_URL;
     },
     template: `
     <div>
-      <div class="subentry" v-for="subentry in subentries">
+      <template v-for="subentry in subentries">
+        <div class="subentry">
           <div class="mb-1 sticky-top"><h5 class="bg-dark text-light p-1">{{subentry.str}}</h5></div>
-          <div class="schema mb-3" v-for="schema in subentry.schemata">
+          <template v-for="schema in subentry.schemata">
+            <div class="schema mb-3" 
+                v-if="alternations[this.frame.id][schema.id]"
+                @mouseenter="schema.hover=true"
+                @mouseleave="schema.hover=false"
+                @click="selectSchema(schema)"
+                :class="(schema.selected ? 'active' : schema.hover ? 'bg-highlight' : '')"
+            >
               <table class="table m-0 table-borderless border border-secondary text-dark">
                   <tbody>
                       <tr class="opinion-row">
@@ -112,9 +134,8 @@ export default {
                           
                           <td class="position py-2 px-1 border-top border-left border-secondary"
                             v-for="position in schema.positions">
-                            <div v-for="f in getFunctions(position)" class="phrase px-1 py-2 " data-alternation="0" data-phrase_id="42-2-1"><span data-toggle="tooltip"
-                                                                                                              data-placement="bottom"
-                                                                                                              :title="f.tooltip">{{f.str}}</span>
+                            <div v-for="f in getFunctions(position)" class="phrase px-1 py-2 " data-alternation="0" data-phrase_id="42-2-1">
+                                <info-tooltip :text="f.tooltip" :visibleText="f.str"/>
                             </div>
                           </td>
                           
@@ -129,8 +150,7 @@ export default {
                               <div v-for="phrase in position.phrases" class="phrase px-1 py-2"
                                       :class="getRoleCss(schema, position)" 
                                       data-alternation="0" data-phrase_id="45-8-7">
-                                      <span data-toggle="tooltip" data-placement="bottom" 
-                                      :title="phrase.desc">{{phrase.str}}</span>
+                                      <info-tooltip :text="phrase.desc" :visibleText="phrase.str"/>
                               </div>
                               <div v-for="phrase in getPositionPhrases(schema, position)" class="realisation-phrase px-1 py-2"><i>{{phrase}}</i></div>
                           </td>
@@ -138,7 +158,9 @@ export default {
                   </tbody>
               </table>
           </div>
+          </template>
       </div>
+      </template>
   </div>
   `
 }
diff --git a/entries/static/entries/js/components/frame-components/SlowalFrameComponent.js b/entries/static/entries/js/components/frame-components/SlowalFrameComponent.js
index ffd804c..301cda8 100644
--- a/entries/static/entries/js/components/frame-components/SlowalFrameComponent.js
+++ b/entries/static/entries/js/components/frame-components/SlowalFrameComponent.js
@@ -1,11 +1,16 @@
+import InfoTooltip from "../InfoTooltip.js";
+import MeaningComponent from "./MeaningComponent.js";
 
 export default {
     props: {
         frame: Object,
     },
+    components: {InfoTooltip, MeaningComponent},
+    emits: ['frameSelectionChanged'],
     data() {
         return {
-            img_prefix: String
+            img_prefix: String,
+            selectedLus: null
         }
     },
     methods: {
@@ -18,6 +23,18 @@ export default {
         },
         getArguments() {
             return this.frame.arguments;
+        },
+        triggerSelectedEvent() {
+            const selectedLus = this.frame.lexical_units.filter(lu => lu.selected);
+            const selectedArguments = this.frame.arguments.filter(argument => argument.selected)
+            this.$emit('frameSelectionChanged', selectedArguments, selectedLus);
+        },
+        meaningLuSelected(selectedLus) {
+            this.triggerSelectedEvent();
+        },
+        selectArgument(argument) {
+            argument.selected = !argument.selected;
+            this.triggerSelectedEvent();
         }
     },
     mounted () {
@@ -25,7 +42,12 @@ export default {
     },
     template: `
         <div class="frame mb-3 active" data-frame_id="52">
-            <div class="frame mt-3" id="lexical-unit" v-html="getTitleHTML()"></div>
+            <div class="frame mt-3" id="lexical-unit">
+                <meaning-component
+                    :lexicalUnits="frame.lexical_units"
+                    @meaning-lu-selected="meaningLuSelected"
+                ></meaning-component>
+            </div>
             <table class="table m-0 table-borderless border border-secondary text-dark">
                 <tbody>
                     <tr class="opinion-row" v-html="getOpinionHTML()">
@@ -33,8 +55,13 @@ export default {
                     <tr>
                         <th scope="row" class="py-2 px-1 text-secondary">Rola</th>
                         <template v-for="argument in frame.arguments">
-                            <td class="argument py-2 px-1 border-top border-left border-secondary" :class="argument.role" data-argument_id="52-129"
-                                data-role="initiator">{{argument.str}}
+                            <td class="argument py-2 px-1 border-top border-left border-secondary" 
+                                @mouseenter="argument.hover=true"
+                                @mouseleave="argument.hover=false"
+                                @click.stop="selectArgument(argument)"
+                                :class="argument.role + ' ' + (argument.selected ? 'active' : argument.hover ? 'bg-highlight' : '')" 
+                            >
+                                {{argument.str}}
                             </td>
                         </template>
                     </tr>
@@ -42,21 +69,16 @@ export default {
                         <th scope="row" class="py-0 px-1 text-secondary">Preferencje selekcyjne</th>
                         <template v-for="argument in getArguments()">
                         
-                        <td class="preferences py-0 px-0 border-top border-left border-secondary" data-argument_id="104513-142252" data-role="condition">
-                       
+                        <td class="preferences py-0 px-0 border-top border-left border-secondary"
+                            :class="argument.selected ? 'active' : argument.hover ? 'bg-highlight' : ''" 
+                        >
                             <template v-if="argument.preferences.length > 0" v-for='preference in argument.preferences'>
                                 <div
                                   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 v-if="preference.info" data-toggle="tooltip"
-                                      data-placement="bottom"
-                                      data-html="true" 
-                                      :title="'definicja: <i>'+ preference.info +'</i>'"><img
-                                    :src="img_prefix + '/common/img/info.svg'" alt="info" width="14"
-                                    height="14">
-                                  </span>
+                                  <info-tooltip v-if="preference.info" :text="'definicja: <i>'+ preference.info +'</i>'" />
                                 </div>
                                 <div v-else class="preference py-2 px-1">{{ preference.str }}</div>
                             </template>
-- 
GitLab