From 101c18f4b17e0f52f8b567f60ce1f16d4a257742 Mon Sep 17 00:00:00 2001
From: Jorran de Wit <jorrandewit@outlook.com>
Date: Mon, 23 Jan 2017 19:02:41 +0100
Subject: [PATCH] Make login response with custom filter

Login page is now responsive with the
 use of a template filter, such that all
 forms from now on may easily be printed
 using the same html frame. See `bootstrap`
 templatetag.
---
 scipost/static/scipost/SciPost.css            |  5 +-
 .../scipost/assets/config/preconfig.scss      |  5 +-
 scipost/static/scipost/assets/css/style.scss  |  6 +-
 scipost/templates/scipost/login.html          | 33 ++++----
 scipost/templates/tags/bootstrap/field.html   | 66 ++++++++++++++++
 scipost/templates/tags/bootstrap/form.html    | 16 ++++
 scipost/templates/tags/bootstrap/formset.html | 11 +++
 scipost/templatetags/bootstrap.py             | 78 +++++++++++++++++++
 scipost/templatetags/scipost_extras.py        |  1 -
 9 files changed, 199 insertions(+), 22 deletions(-)
 create mode 100644 scipost/templates/tags/bootstrap/field.html
 create mode 100644 scipost/templates/tags/bootstrap/form.html
 create mode 100644 scipost/templates/tags/bootstrap/formset.html
 create mode 100644 scipost/templatetags/bootstrap.py

diff --git a/scipost/static/scipost/SciPost.css b/scipost/static/scipost/SciPost.css
index 998ad47bd..825c43bfc 100644
--- a/scipost/static/scipost/SciPost.css
+++ b/scipost/static/scipost/SciPost.css
@@ -15,8 +15,8 @@ General style sheet for SciPost
 }
 
 [class*="col-"] {
-    float: left;
-    padding: 5px;
+    /*float: left;
+    padding: 5px;*/
 }
 /* For desktop: */
 .col-1 {width: 8.33%;}
@@ -602,7 +602,6 @@ input, textarea {
   border: 1px solid black; border-radius: 1px;
 }
 input[type='text'], input[type='URL'], textarea {
-  width: 80%;
   max-width: 800px;
   min-width: 200px;
 }
diff --git a/scipost/static/scipost/assets/config/preconfig.scss b/scipost/static/scipost/assets/config/preconfig.scss
index 5bc0d4064..de916d063 100644
--- a/scipost/static/scipost/assets/config/preconfig.scss
+++ b/scipost/static/scipost/assets/config/preconfig.scss
@@ -20,7 +20,10 @@ $font-family-base:       $font-family-sans-serif !default;
 $font-size-base: 0.8rem !default;
 
 
-// navbar
+// Navbar
 //
 $navbar-light-color: $scipost-darkblue !default;
 $navbar-light-hover-color: $scipost-darkblue !default;
+
+$input-border-radius: 0.15rem !default;
+$btn-border-radius: 0.15rem !default;
diff --git a/scipost/static/scipost/assets/css/style.scss b/scipost/static/scipost/assets/css/style.scss
index 478ca0337..2623dbf92 100644
--- a/scipost/static/scipost/assets/css/style.scss
+++ b/scipost/static/scipost/assets/css/style.scss
@@ -73,6 +73,10 @@ h1, h2, h3, h4, h5, h6 {
     .highlighted > .nav-link {
         background-color: rgba(255, 255, 255, 0.6);
     }
+
+    .nav-item {
+        margin-right: 0.5rem;
+    }
 }
 .navbar-brand {
     height: 38px;
@@ -81,6 +85,6 @@ h1, h2, h3, h4, h5, h6 {
     background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 43, 73, 1.0)");
 }
 .panel {
-    padding: 0.5rem;
+    padding: 0.75rem;
     background-color: #f4f4f4;
 }
diff --git a/scipost/templates/scipost/login.html b/scipost/templates/scipost/login.html
index fc67e14a2..f52e1cc6a 100644
--- a/scipost/templates/scipost/login.html
+++ b/scipost/templates/scipost/login.html
@@ -4,34 +4,35 @@
 
 {% block bodysup %}
 
-<section>
-  <div class="row">
-    <div class="col-6">
-      <h1>Log in to SciPost</h1>
+{% load bootstrap %}
+
+<div class="container">
+  <div class="row my-4">
+    <div class="col-md-6">
+      <h1 class="mb-md-2">Log in to SciPost</h1>
       <form action="{% url 'scipost:login' %}" method="post">
-	{% csrf_token %}
-	<table>
-	  <ul>
-	    {{ form.as_table }}
-	  </ul>
-	</table>
-	<input type="submit" value="Login" />
-	{% if next %}
-	<input type="hidden" name="next" value="{{ next }}"/>
-	{% endif %}
+    	{% csrf_token %}
+
+        {{ form|bootstrap }}
+
+    	<input class="btn btn-primary" type="submit" value="Login" />
+
+    	{% if next %}
+        	<input type="hidden" name="next" value="{{ next }}"/>
+    	{% endif %}
       </form>
       <br/>
       <a href="{% url 'scipost:reset_password' %}">Forgot your password?</a>
     </div>
 
 
-    <div class="col-6">
+    <div class="col-md-6">
       <h1>Not registered as a Contributor to SciPost?</h1>
       <p>If you are a professional scientist (PhD student and above), you can register by filling the
       <a href="{% url 'scipost:register' %}">registration form</a>.</p>
     </div>
 
   </div>
-</section>
+</div>
 
 {% endblock bodysup %}
diff --git a/scipost/templates/tags/bootstrap/field.html b/scipost/templates/tags/bootstrap/field.html
new file mode 100644
index 000000000..803a3e09b
--- /dev/null
+++ b/scipost/templates/tags/bootstrap/field.html
@@ -0,0 +1,66 @@
+{% load bootstrap %}
+
+<div class="form-group row{% if field.errors %} has-error{% endif %}">
+    {% if field|is_checkbox %}
+        <div class="{{ classes.single_value }}">
+            <div class="checkbox">
+                {% if field.auto_id %}
+                    <label {% if field.field.required and form.required_css_class %}class="{{ form.required_css_class }}"{% endif %}>
+                        {{ field }} <span>{{ field.label }}</span>
+                    </label>
+                {% endif %}
+                {% for error in field.errors %}
+                    <span class="help-block {{ form.error_css_class }}">{{ error }}</span>
+                {% endfor %}
+
+                {% if field.help_text %}
+                    <p class="help-block">
+                        {{ field.help_text|safe }}
+                    </p>
+                {% endif %}
+            </div>
+        </div>
+    {% elif field|is_radio %}
+        {% if field.auto_id %}
+            <label class="col-form-label {{ classes.label }}{% if field.field.required %} {{ form.required_css_class }}{% endif %}">{{ field.label }}</label>
+        {% endif %}
+        <div class="{{ classes.value }}">
+            {% for choice in field %}
+                <div class="radio">
+                    <label>
+                        {{ choice.tag }}
+                        {{ choice.choice_label }}
+                    </label>
+                </div>
+            {% endfor %}
+
+            {% for error in field.errors %}
+                <span class="help-block {{ form.error_css_class }}">{{ error }}</span>
+            {% endfor %}
+
+            {% if field.help_text %}
+            <p class="help-block">
+                {{ field.help_text|safe }}
+            </p>
+            {% endif %}
+        </div>
+    {% else %}
+        {% if field.auto_id %}
+            <label class="col-form-label {{ classes.label }}{% if field.field.required %} {{ form.required_css_class }}{% endif %}" for="{{ field.auto_id }}">{{ field.label }}</label>
+        {% endif %}
+
+        <div class="{{ classes.value }}{% if field|is_multiple_checkbox %} multiple-checkbox{% endif %}">
+            {{ field }}
+
+            {% for error in field.errors %}
+                <span class="help-block {{ form.error_css_class }}">{{ error }}</span>
+                {% endfor %}
+
+            {% if field.help_text %}
+                <p class="help-block">
+                    {{ field.help_text|safe }}
+                </p>
+            {% endif %}
+        </div>
+    {% endif %}
+</div>
diff --git a/scipost/templates/tags/bootstrap/form.html b/scipost/templates/tags/bootstrap/form.html
new file mode 100644
index 000000000..97a499eb7
--- /dev/null
+++ b/scipost/templates/tags/bootstrap/form.html
@@ -0,0 +1,16 @@
+{% if form.non_field_errors %}
+    <div class="alert alert-danger">
+        <a class="close" data-dismiss="alert">&times;</a>
+        {% for non_field_error in form.non_field_errors %}
+             {{ non_field_error }}
+        {% endfor %}
+    </div>
+{% endif %}
+
+{% for field in form.hidden_fields %}
+    {{ field }}
+{% endfor %}
+
+{% for field in form.visible_fields %}
+    {% include 'tags/bootstrap/field.html' %}
+{% endfor %}
diff --git a/scipost/templates/tags/bootstrap/formset.html b/scipost/templates/tags/bootstrap/formset.html
new file mode 100644
index 000000000..eb5722f81
--- /dev/null
+++ b/scipost/templates/tags/bootstrap/formset.html
@@ -0,0 +1,11 @@
+{{ formset.management_form }}
+
+{% for form in formset %}
+  {% if classes.label == 'sr-only' %}
+      <div class="form-inline">
+      {% include "tags/bootstrap/form.html" with form=form %}
+      </div>
+  {%else%}
+      {% include "tags/bootstrap/form.html" with form=form %}
+  {% endif %}
+{% endfor %}
diff --git a/scipost/templatetags/bootstrap.py b/scipost/templatetags/bootstrap.py
new file mode 100644
index 000000000..7e3817939
--- /dev/null
+++ b/scipost/templatetags/bootstrap.py
@@ -0,0 +1,78 @@
+from django import forms
+from django.template import Context
+from django.template.loader import get_template
+from django import template
+
+
+register = template.Library()
+
+# Custom filter originally created by tzangms
+#  and customized for use with Bootstrap 4.x
+#  https://github.com/tzangms/django-bootstrap-form
+
+
+@register.filter
+def bootstrap(element):
+    markup_classes = {'label': 'col-md-2', 'value': 'col-md-10', 'single_value': ''}
+    return render(element, markup_classes)
+
+
+@register.filter
+def bootstrap_inline(element):
+    markup_classes = {'label': 'sr-only', 'value': '', 'single_value': ''}
+    return render(element, markup_classes)
+
+
+@register.filter
+def add_input_classes(field):
+    if not is_checkbox(field) and not is_multiple_checkbox(field) \
+       and not is_radio(field) and not is_file(field):
+        field_classes = field.field.widget.attrs.get('class', '')
+        field_classes += ' form-control'
+        field.field.widget.attrs['class'] = field_classes
+
+
+def render(element, markup_classes):
+    element_type = element.__class__.__name__.lower()
+
+    if element_type == 'boundfield':
+        add_input_classes(element)
+        template = get_template("tags/bootstrap/field.html")
+        context = Context({'field': element, 'classes': markup_classes, 'form': element.form})
+    else:
+        has_management = getattr(element, 'management_form', None)
+        if has_management:
+            for form in element.forms:
+                for field in form.visible_fields():
+                    add_input_classes(field)
+
+            template = get_template("tags/bootstrap/formset.html")
+            context = Context({'formset': element, 'classes': markup_classes})
+        else:
+            for field in element.visible_fields():
+                add_input_classes(field)
+
+            template = get_template("tags/bootstrap/form.html")
+            context = Context({'form': element, 'classes': markup_classes})
+
+    return template.render(context)
+
+
+@register.filter
+def is_checkbox(field):
+    return isinstance(field.field.widget, forms.CheckboxInput)
+
+
+@register.filter
+def is_multiple_checkbox(field):
+    return isinstance(field.field.widget, forms.CheckboxSelectMultiple)
+
+
+@register.filter
+def is_radio(field):
+    return isinstance(field.field.widget, forms.RadioSelect)
+
+
+@register.filter
+def is_file(field):
+    return isinstance(field.field.widget, forms.FileInput)
diff --git a/scipost/templatetags/scipost_extras.py b/scipost/templatetags/scipost_extras.py
index 22bbea11f..3a34f87e7 100644
--- a/scipost/templatetags/scipost_extras.py
+++ b/scipost/templatetags/scipost_extras.py
@@ -2,7 +2,6 @@ from django import template
 from django.contrib.auth.models import Group
 
 from scipost.models import Contributor
-from journals.models import paper_nr_string
 
 register = template.Library()
 
-- 
GitLab