From 49040430c1e78a76bc170d6aea49720b9b907954 Mon Sep 17 00:00:00 2001
From: Jorran de Wit <jorrandewit@outlook.com>
Date: Fri, 24 Mar 2017 18:17:23 +0100
Subject: [PATCH] Replace about page modal by custom script

The modal is replaced by a customized text block
 which does allow for hover and click action by
 the visitor to filter by specialization.
---
 .bootstraprc                                  |  4 +-
 scipost/static/scipost/about.js               | 53 +++++++++++---
 scipost/static/scipost/assets/css/_about.scss | 37 ++++++++--
 .../static/scipost/assets/css/_tooltip.scss   | 11 +++
 scipost/static/scipost/assets/css/style.scss  |  3 +-
 scipost/static/scipost/assets/js/tooltip.js   |  5 ++
 .../templates/scipost/_contributor_short.html |  8 +--
 scipost/templates/scipost/about.html          | 72 +++++++------------
 scipost/templatetags/scipost_extras.py        | 16 +++--
 scipost/views.py                              | 10 ++-
 webpack.config.js                             |  4 +-
 11 files changed, 146 insertions(+), 77 deletions(-)
 create mode 100644 scipost/static/scipost/assets/css/_tooltip.scss
 create mode 100644 scipost/static/scipost/assets/js/tooltip.js

diff --git a/.bootstraprc b/.bootstraprc
index 0fbcf0d56..2f2164a76 100644
--- a/.bootstraprc
+++ b/.bootstraprc
@@ -19,7 +19,6 @@
         "grid": true,
         "input-group": true,
         "list-group": true,
-        "modal": true,
         "mixins": true,
         "nav": true,
         "navbar": true,
@@ -27,12 +26,13 @@
         "reboot": true,
         "responsive-embed": true,
         "transitions": true,
+        "tooltip": true,
         "utilities": true,
     },
     "scripts": {
         "alert": true,
         "collapse": true,
-        "modal": true,
+        "tooltip": true,
         "util": true,
     }
 }
diff --git a/scipost/static/scipost/about.js b/scipost/static/scipost/about.js
index 556e798ef..748aaa14a 100644
--- a/scipost/static/scipost/about.js
+++ b/scipost/static/scipost/about.js
@@ -1,16 +1,51 @@
 
 $(function() {
-    $('.search-specialization').on('change keyup', function(event) {
+    // Toggle Specialization codes block
+    $('[data-toggle="toggle-show"]').on('click', function(){
+        var el = $($(this).attr('data-target'));
+        el.toggle();
+
+        // Reset active search after closing the box
+        if(!el.is(':visible')) {
+            $('.all-specializations .specialization')
+            .removeClass('active-search')
+            .trigger('search-specialization');
+        }
+    });
+
+    // Hover/Click class to Contributors on hovering specializations
+    $('.all-specializations .specialization')
+    .on('mouseover', function() {
+        var code = $(this).attr('data-specialization');
+        $('.single[data-specialization="'+code+'"]')
+        .parents('.contributor')
+        .addClass('hover-active');
+    })
+    .on('mouseleave', function() {
+        $('.contributor.hover-active').removeClass('hover-active');
+    })
+    .on('click', function() {
+        // Remove hover-class
+        $(this)
+        .toggleClass('active-search')
+        .trigger('search-specialization');
+    })
+    .on('search-specialization', function() {
+        // Reset: searching multiple specializations is not supported
+        $('.search-contributors.active-search').removeClass('active-search');
+        $('.contributor-col.active').removeClass('active');
+        $('.specialization.active-search').not(this).removeClass('active-search');
+
         var el = $(this);
-        var val = el.val().trim().toLowerCase(),
-            spec = el.attr('data-college');
-        if(val) {
-            $('[data-contributors="'+spec+'"]').addClass('searching');
-        } else {
-            $('[data-contributors="'+spec+'"]').removeClass('searching')
+        if( el.hasClass('active-search') ) {
+            // Add general 'click-active' class
+            $('.search-contributors').addClass('active-search');
 
+            // Add class to specialized Contributors
+            var code = el.attr('data-specialization');
+            $('.single[data-specialization="' + code + '"]')
+            .parents('.contributor-col')
+            .addClass('active');
         }
-        $('.contributor').removeClass('active');
-        $('[data-contributors="'+spec+'"] [data-specialization*="'+val+'"]').parents('.contributor').addClass('active');
     });
 });
diff --git a/scipost/static/scipost/assets/css/_about.scss b/scipost/static/scipost/assets/css/_about.scss
index 6fb2de17a..c7c0b58d2 100644
--- a/scipost/static/scipost/assets/css/_about.scss
+++ b/scipost/static/scipost/assets/css/_about.scss
@@ -1,9 +1,34 @@
-.search-contributors {
-    &.searching > .contributor {
-        display: none;
+.search-contributors.active-search .contributor-col {
+    display: none;
 
-        &.active {
-            display: block;
-        }
+    &.active {
+        display: block;
+    }
+}
+
+.contributor {
+    margin: 0.25rem 0;
+    padding: 0.05rem 0.75rem;
+    border-radius: 0.15rem;
+    -webkit-transition: all 0.05s ease-in-out;
+         -o-transition: all 0.05s ease-in-out;
+            transition: all 0.05s ease-in-out;
+
+    &.hover-active {
+        background-color: rgba(104, 132, 194, 0.3);
+    }
+}
+
+.all-specializations {
+    border: 1px solid $scipost-darkblue;
+    border-radius: 0.15rem;
+    padding: 1rem;
+}
+
+.specialization {
+    &.active-search,
+    &:hover {
+        cursor: pointer;
+        color: $scipost-lightblue;
     }
 }
diff --git a/scipost/static/scipost/assets/css/_tooltip.scss b/scipost/static/scipost/assets/css/_tooltip.scss
new file mode 100644
index 000000000..dd8445262
--- /dev/null
+++ b/scipost/static/scipost/assets/css/_tooltip.scss
@@ -0,0 +1,11 @@
+[data-toggle="tooltip"] {
+    cursor: pointer;
+
+    &:hover {
+        color: $scipost-lightblue;
+    }
+}
+
+.tooltip-inner {
+    border-radius: 0.15rem;
+}
diff --git a/scipost/static/scipost/assets/css/style.scss b/scipost/static/scipost/assets/css/style.scss
index a3ecac078..50ebdb189 100644
--- a/scipost/static/scipost/assets/css/style.scss
+++ b/scipost/static/scipost/assets/css/style.scss
@@ -24,9 +24,10 @@
 @import "grid";
 @import "labels";
 @import "messages";
-@import "modal";
+// @import "modal";
 @import "navbar";
 @import "page_header";
+@import "tooltip";
 @import "type";
 
 /**
diff --git a/scipost/static/scipost/assets/js/tooltip.js b/scipost/static/scipost/assets/js/tooltip.js
new file mode 100644
index 000000000..eaba2651c
--- /dev/null
+++ b/scipost/static/scipost/assets/js/tooltip.js
@@ -0,0 +1,5 @@
+require('bootstrap-loader');
+
+jQuery('[data-toggle="tooltip"]').tooltip({
+    animation: false,
+});
diff --git a/scipost/templates/scipost/_contributor_short.html b/scipost/templates/scipost/_contributor_short.html
index 46011d1f3..412c56712 100644
--- a/scipost/templates/scipost/_contributor_short.html
+++ b/scipost/templates/scipost/_contributor_short.html
@@ -2,7 +2,7 @@
 
 {% load static %}
 
-<h3 class="mb-0 pb-0 d-block">
+<h3 class="mb-0 py-0 d-block">
     {% if contributor.personalwebpage %}
         <a target="_blank" href="{{ contributor.personalwebpage }}">
     {% endif %}
@@ -16,7 +16,7 @@
     <span class="text-muted">({{contributor.affiliation}})</span>
 {% endif %}
 <div class="d-block">
-    {% if contributor.expertises %}
-        <div class="specialization d-inline" data-specialization="{{contributor.expertises_as_string}} {{expertise|lower}}" title="{{expertise}}">{{contributor.expertises|filter_main_specialization}}</div>
-    {% endif %}
+    {% for expertise in contributor.expertises %}
+        <div class="single d-inline" data-specialization="{{expertise|lower}}" data-toggle="tooltip" data-placement="bottom" title="{{expertise|get_specialization_display}}">{{expertise|get_specialization_code}}</div>
+    {% endfor %}
 </div>
diff --git a/scipost/templates/scipost/about.html b/scipost/templates/scipost/about.html
index 2fdece2a0..70a001a4b 100644
--- a/scipost/templates/scipost/about.html
+++ b/scipost/templates/scipost/about.html
@@ -144,34 +144,38 @@
     </div>
 </div>
 
-
 <hr>
-{% for college in object_list %}
 
-<div class="row">
-    <div class="col-12">
-        <div class="panel">
-          <h2 id="editorial_college_{{ college|lower }}">Editorial College ({{ college }})</h2>
+{% for college, codes in object_list %}
+
+    <div class="row">
+        <div class="col-12">
+            <div class="panel">
+              <h2 id="editorial_college_{{ college|lower }}">Editorial College ({{ college }})</h2>
+            </div>
         </div>
     </div>
-</div>
 
-<div class="row">
-    <div class="col-md-2">
-        <div class="input-group">
-            <input type="text" class="form-control search-specialization" data-college="{{ college|lower }}" placeholder="Search for specialization">
+    <div class="row">
+        <div class="col-12">
+            <a href="javascript:;" class="d-block mb-1" data-toggle="toggle-show" data-target="#specializations-{{college|lower}}">Show all specialization codes</a>
+            <div id="specializations-{{college|lower}}" class="all-specializations" style="border: 1px solid; display: none;">
+                {% for code in codes %}
+                    <div class="specialization" data-specialization="{{code.0|lower}}">{{code.0}} - {{code.1}}</div>
+                {% endfor %}
+            </div>
         </div>
-        <a class="mt-2 d-block" href="#" data-toggle="modal" data-target="#codes">All specialization codes</a>
     </div>
-</div>
 
-<div class="row search-contributors" data-contributors="{{ college|lower }}">
-    {% for fellowship in college.current_fellows|reorder_list_three %}
-        <div class="col-md-4 py-1 contributor">
-            {% include 'scipost/_contributor_short.html' with contributor=fellowship.contributor %}
-        </div>
-    {% endfor %}
-</div>
+    <div class="row search-contributors" data-contributors="{{ college|lower }}">
+        {% for fellowship in college.current_fellows|reorder_list_three %}
+            <div class="col-md-4 contributor-col">
+                <div class="contributor">
+                    {% include 'scipost/_contributor_short.html' with contributor=fellowship.contributor %}
+                </div>
+            </div>
+        {% endfor %}
+    </div>
 
 {% endfor %}
 
@@ -183,36 +187,10 @@
     </div>
 </div>
 
-<!-- Modal -->
-<div class="modal fade" id="codes" tabindex="-1" role="dialog" aria-labelledby="codes" aria-hidden="true">
-  <div class="modal-dialog" role="document">
-    <div class="modal-content">
-      <div class="modal-body">
-        {% for subject_content in subject_codes %}
-            {% for subject in subject_content %}
-                {% if forloop.first %}
-                    <h3>{{subject}}</h3>
-                {% else %}
-                    <div class="text-muted">
-                        {% for code in subject %}
-                        {{code.0}} - {{code.1}}<br>
-                        {% endfor %}
-                    </div>
-                {% endif %}
-            {% endfor %}
-        {% endfor %}
-      </div>
-      <div class="modal-footer">
-        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
-      </div>
-    </div>
-  </div>
-</div>
-
 {% endblock content %}
 
 {% block footer_script %}
 {{block.super}}
-    {% render_bundle 'modal' 'js' %}
+    {% render_bundle 'tooltip' 'js' %}
     <script src="{% static 'scipost/about.js' %}"></script>
 {% endblock %}
diff --git a/scipost/templatetags/scipost_extras.py b/scipost/templatetags/scipost_extras.py
index a343ba2e8..2a7074041 100644
--- a/scipost/templatetags/scipost_extras.py
+++ b/scipost/templatetags/scipost_extras.py
@@ -1,7 +1,8 @@
 from django import template
 from django.contrib.auth.models import Group
 
-from scipost.models import Contributor
+from ..constants import subject_areas_dict
+from ..models import Contributor
 
 register = template.Library()
 
@@ -35,6 +36,13 @@ def reorder_list_three(ul):
     return ul[::3] + ul[1::3] + ul[2::3]
 
 
-@register.filter(name='filter_main_specialization')
-def filter_main_specialization(codes):
-    return ', '.join([code.split(':')[1] for code in codes])
+@register.filter(name='get_specialization_code')
+def get_specialization_code(code):
+    # Get the specialization code without the main subject identifier
+    return code.split(':')[1]
+
+
+@register.filter(name='get_specialization_display')
+def get_specialization_display(code):
+    # Due to the ArrayField construction, one is not able to use get_FOO_display in the template
+    return subject_areas_dict[code]
diff --git a/scipost/views.py b/scipost/views.py
index f3aea56c0..d8b2ec289 100644
--- a/scipost/views.py
+++ b/scipost/views.py
@@ -26,7 +26,7 @@ from django.db.models import Prefetch
 
 from guardian.decorators import permission_required
 
-from .constants import SCIPOST_SUBJECT_AREAS
+from .constants import SCIPOST_SUBJECT_AREAS, subject_areas_raw_dict
 from .models import Contributor, CitationNotification, UnavailabilityPeriod,\
                     DraftInvitation, RegistrationInvitation,\
                     title_dict, SciPost_from_addresses_dict,\
@@ -1526,5 +1526,11 @@ class AboutView(ListView):
 
     def get_context_data(self, *args, **kwargs):
         context = super().get_context_data(*args, **kwargs)
-        context['subject_codes'] = SCIPOST_SUBJECT_AREAS
+        object_list = []
+        for college in context['object_list']:
+            object_list.append((
+                college,
+                subject_areas_raw_dict[str(college)],
+            ))
+        context['object_list'] = object_list
         return context
diff --git a/webpack.config.js b/webpack.config.js
index 810bdbac6..f9175f538 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -13,7 +13,7 @@ module.exports = {
             "./scipost/static/scipost/assets/css/style.scss"
         ],
         bootstrap: 'bootstrap-loader',
-        modal: "./scipost/static/scipost/assets/js/modal.js",
+        tooltip: "./scipost/static/scipost/assets/js/tooltip.js",
     },
     output: {
         path: path_bundles,
@@ -57,7 +57,7 @@ module.exports = {
             // Carousel: "exports-loader?Carousel!bootstrap/js/dist/carousel",
             Collapse: "exports-loader?Collapse!bootstrap/js/dist/collapse",
             // Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
-            Modal: "exports-loader?Modal!bootstrap/js/dist/modal",
+            // Modal: "exports-loader?Modal!bootstrap/js/dist/modal",
             // Popover: "exports-loader?Popover!bootstrap/js/dist/popover",
             // Scrollspy: "exports-loader?Scrollspy!bootstrap/js/dist/scrollspy",
             // Tab: "exports-loader?Tab!bootstrap/js/dist/tab",
-- 
GitLab