From 0dc1674a57aa4a80c2f2c88d82e8f462c1d330d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lo=C3=AFs=20Poujade?= <lois.poujade@tetras-libre.fr>
Date: Fri, 22 Apr 2022 17:46:00 +0200
Subject: [PATCH] Filter in mosaic using labels

closes tuleap 241
---
 capsule-prototype/css/mosaic.css      |  6 +++-
 capsule-prototype/index.html          |  2 +-
 capsule-prototype/js/online-script.js | 44 +++++++++++++++++++++++++--
 3 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/capsule-prototype/css/mosaic.css b/capsule-prototype/css/mosaic.css
index 8ad8ce8..4df12ee 100644
--- a/capsule-prototype/css/mosaic.css
+++ b/capsule-prototype/css/mosaic.css
@@ -26,7 +26,7 @@
 	flex-wrap: wrap;
 }
 
-.mosaic_filter_item {
+.mosaic_filter_item, .mosaic_label_filter {
 	width: var(--filter-width);
 	height: var(--filter-height);
 	margin: var(--base-spacing);
@@ -39,6 +39,10 @@
 	align-items: center;
 }
 
+.mosaic_label_filter_enabled {
+  background-color: rgba(255, 255, 255, .5);
+}
+
 .mosaic_category {
 	padding: var(--base-spacing);
 	margin: var(--base-spacing);
diff --git a/capsule-prototype/index.html b/capsule-prototype/index.html
index fc51a2d..a366e79 100644
--- a/capsule-prototype/index.html
+++ b/capsule-prototype/index.html
@@ -189,7 +189,7 @@
           <!-- templates -->
           <div id='popupLabelsInput' class='popupInput flex-col'>
             <input type='text' id='new_annotation_label' />
-            <input class='annotation_labels_template' type='checkbox' name='annotation_labels' id='' value='' style='display: none;' />
+            <input class='annotation_labels_template' type='checkbox' id='' value='' style='display: none;' />
             <label class='annotation_labels_template' for='' style='display: none;'></label>
           </div>
 				</td>
diff --git a/capsule-prototype/js/online-script.js b/capsule-prototype/js/online-script.js
index bfbbc4e..9cff9ad 100644
--- a/capsule-prototype/js/online-script.js
+++ b/capsule-prototype/js/online-script.js
@@ -156,13 +156,14 @@ function setEditionControls() {
   $('#new_annotation_label').keypress(function(event) {
     var keycode = (event.keyCode ? event.keyCode : event.which);
     if (keycode != 13) {
-      return
+      return;
     }
     var label = $('#new_annotation_label').val();
     var input = $('input.annotation_labels_template').first().clone();
     var html_label = $('label.annotation_labels_template').first().clone();
     var id = 'annotation_label_' + Math.floor((Math.random()*1000));
 
+    input.attr('name', 'annotation_labels');
     input.attr('checked', 'true');
     input.attr('id', id);
     input.attr('value', label);
@@ -816,7 +817,10 @@ function closeInputs() {
 				var keyDoc = $(this).parent().attr("keydoc");
         var newLabels = '';
         $('[name="annotation_labels"]:checked')
-          .toArray().forEach(e => newLabels += e.value + ';');
+          .toArray().forEach(e => {
+            newLabels += e.value + ';';
+            e.checked = false;
+          })
         console.log('new labels: ', newLabels);
         setMetaFromDom(keyDoc, "Rekall->Labels", newLabels);
 
@@ -916,6 +920,7 @@ function openMosaic() {
         let div=$('<div/>').addClass('mosaic_item').on('click', function() {tagOrDoc.openPopupEdit();});
         div.append($('<img/>').attr('src', url).attr('onerror', "this.src='../shared/css/images/img-document.png';"));
         div.append($('<span/>').addClass('caption').text(name));
+        div.attr('data-rekall-labels', tagOrDoc.getMetadata('Rekall->Labels'));
         return div;
     }
     function getFilterElement(text, color, callback, css_class) {
@@ -946,6 +951,7 @@ function openMosaic() {
         'mosaic_filter_item_all'
     ));
     container.append(filterdiv);
+    var labels = new Set();
     // TODO is there a better way to iterate over tags or documents ?
     for ( let [k, v] of  Object.entries(rekall.sortings.colors.categories)) {
         let categoryName = rekall.sortings.colors.getCategoryName(k)
@@ -967,9 +973,43 @@ function openMosaic() {
 
         for (let i in v.tags){
             grid.append(getMosaicItem(v.tags[i]));
+            var current_labels = v.tags[i].getMetadata('Rekall->Labels');
+            if (current_labels && current_labels != '') {
+              current_labels.split(';').forEach(l => {if (l != '') labels.add(l)});
+            }
         }
         container.append(category);
     }
+    labels.forEach(l => {
+      var button = $('<p/>').html(l);
+      button.my_state = undefined;
+      button.addClass('mosaic_label_filter');
+      button.click(ev => {
+        if (typeof(ev.target.my_state) === 'undefined') ev.target.my_state = true;
+        else ev.target.my_state = !ev.target.my_state;
+        if (ev.target.my_state) $(ev.target).addClass('mosaic_label_filter_enabled');
+        else $(ev.target).removeClass('mosaic_label_filter_enabled');
+        var labels = new Set();
+        $('.mosaic_label_filter').toArray().forEach(f => {
+          if (f.my_state == true)
+            labels.add(f.innerHTML);
+        });
+        if (!labels.size) {
+          $('.mosaic_label_filter').toArray().forEach(f => {
+            f.my_state = undefined;
+            $(f).removeClass('mosaic_label_filter_enabled');
+            labels.add(f.innerHTML);
+          });
+        }
+        $('.mosaic_item').toArray().forEach(t => {
+          if (Array.from(labels).map(l => t.dataset.rekallLabels.indexOf(l) != -1).includes(true))
+            $(t).show();
+          else
+            $(t).hide();
+        });
+      })
+      filterdiv.append(button);
+    });
 }
 
 function getTagGradientColor(tag) {
-- 
GitLab