Rafał Pitoń 10 лет назад
Родитель
Сommit
d02b0f4d09

+ 1 - 1
misago/__init__.py

@@ -1 +1 @@
-__version__ = "0.6.0dev"
+__version__ = "0.5.99"

+ 1 - 0
misago/admin/urls.py

@@ -7,6 +7,7 @@ urlpatterns = patterns('misago.admin.views',
     # any request with path that falls below this one is assumed to be directed
     # at Misago Admin and will be checked by Misago Admin Middleware
     url(r'^$', 'index.admin_index', name='index'),
+    url(r'^resolve-version/$', 'index.check_version', name='check_version'),
     url(r'^logout/$', 'auth.logout', name='logout'),
 )
 

+ 61 - 0
misago/admin/views/index.py

@@ -1,9 +1,23 @@
+import json
+
+import requests
+from requests.exceptions import RequestException
+
+from django.http import Http404, JsonResponse
+from django.utils.translation import ugettext as _
+
+from misago import __version__
+
+from misago.core.cache import cache
 from misago.threads.models import Thread, Post
 from misago.users.models import User, ACTIVATION_REQUIRED_NONE
 
 from misago.admin.views import render
 
 
+VERSION_CHECK_CACHE_KEY = "misago_version_check"
+
+
 def admin_index(request):
     inactive_users = {'requires_activation__gt': ACTIVATION_REQUIRED_NONE}
     db_stats = {
@@ -15,4 +29,51 @@ def admin_index(request):
 
     return render(request, 'misago/admin/index.html', {
         'db_stats': db_stats,
+        'version_check': cache.get(VERSION_CHECK_CACHE_KEY)
     })
+
+
+def check_version(request):
+    if request.method != "POST":
+        raise Http404()
+    version = cache.get(VERSION_CHECK_CACHE_KEY, 'nada')
+    if version == 'nada':
+        try:
+            api_url = 'https://api.github.com/repos/rafalp/Misago/releases'
+            r = requests.get(api_url)
+
+            if r.status_code != requests.codes.ok:
+                r.raise_for_status()
+            latest_version = json.loads(r.content)[0]['tag_name']
+
+            latest = [int(v) for v in latest_version.split(".")]
+            current = [int(v) for v in __version__.split(".")]
+
+            for i in xrange(3):
+                if latest[i] > current[i]:
+                    message = _("Outdated: %(current)s < %(latest)s")
+                    formats = {
+                        'latest': latest_version,
+                        'current': __version__
+                    }
+
+                    version = {
+                        'is_error': True,
+                        'message': message % formats
+                    }
+                    break
+            else:
+                formats = {'current': __version__}
+                version = {
+                    'is_error': False,
+                    'message': _("Up to date! (%(current)s)") % formats,
+                }
+
+            cache.set(VERSION_CHECK_CACHE_KEY, version, 180)
+        except (RequestException, IndexError, KeyError, ValueError):
+            message = _("Failed to connect to GitHub API. Try again later.")
+            version = {
+                'is_error': True,
+                'message': message
+            }
+    return JsonResponse(version)

+ 71 - 0
misago/templates/misago/admin/index.html

@@ -18,9 +18,49 @@
 <div class="container">
   <div class="row">
     <div class="col-md-8">
+
+
+
     </div>
     <div class="col-md-4">
 
+      <table class="table version-check">
+        <thead>
+          <tr>
+            <th colspan="2">
+              <h4>
+                <span class="fa fa-github"></span>
+                {% trans "Misago version" %}
+              </h4>
+            </th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr>
+            <td class="text-center">
+              {% if version_check %}
+              <p class="lead text-{% if version_check.is_error %}error{% else %}success{% endif %}">
+                {% if version_check.is_error %}
+                <span class="fa fa-times fa-lg fa-fw"></span>
+                {% else %}
+                <span class="fa fa-check fa-lg fa-fw"></span>
+                {% endif %}
+                {{ version_check.message }}
+              </p>
+              {% else %}
+              <form method="POST">
+                {% csrf_token %}
+                <button type="submit" class="btn btn-default">
+                  <span class="fa fa-question-circle fa-fw"></span>
+                  <span class="name">{% trans "Check version" %}</span>
+                </button>
+              </form>
+              {% endif %}
+            </td>
+          </tr>
+        </tbody>
+      </table>
+
       <table class="table">
         <thead>
           <tr>
@@ -60,3 +100,34 @@
   </div>
 </div>
 {% endblock content %}
+
+
+{% block javascripts %}
+<script type="text/javascript">
+  $(function () {
+    var $version_check = $('.version-check');
+    var $outcome = $version_check.find('td');
+
+    $version_check.find('form').submit(function() {
+      var $form = $(this);
+      var $button = $(this).find("button");
+      $button.attr("disabled", "disabled");
+      $button.find('.fa').attr("class", "fa fa-refresh fa-fw fa-spin");
+      $button.find('.name').text("{% trans "Checking..." %}");
+
+      $.post("{% url 'misago:admin:check_version' %}", $form.serialize(), function(data) {
+        if (data.is_error) {
+          var $message = $('<p class="lead text-danger"><span class="fa fa-times fa-lg fa-fw"></span></p>');
+        } else {
+          var $message = $('<p class="lead text-success"><span class="fa fa-check fa-lg fa-fw"></span></p>');
+        }
+        $message.append(" " + data.message);
+        $form.fadeOut();
+        $outcome.html($message);
+      });
+
+      return false;
+    });
+  });
+</script>
+{% endblock javascripts %}

+ 59 - 57
misago/templates/misago/register/form.html

@@ -159,69 +159,71 @@
 {% block javascripts %}
 {{ block.super }}
 <script type="text/javascript">
-  // API-based validation
-  var csrf_token = $('input[name="csrfmiddlewaretoken"]').val()
-
-  $('.has-api-validation').each(function() {
-    var $control = $(this);
-    var $input = $control.find('input');
-    var $icon = $(this).find('.fa');
-    var $control_message = $(this).find('.control-message');
-
-    var api_url = $(this).data('validation-api');
-    var api_value = $(this).data('validation-value');
-
-    function validate() {
-      var data = {csrfmiddlewaretoken: csrf_token};
-      data[api_value] = $.trim($input.val());
-      $.post(api_url, data, function(data, textStatus, jqXHR) {
-        $control_message.find('strong').text(data.message);
-
-        if (data.has_error) {
-          $control.attr('class', 'form-group has-api-validation has-feedback has-error');
-          $icon.attr('class', 'fa fa-times form-control-feedback');
-          $control_message.attr('class', 'control-errors fade in')
-        } else {
-          $control.attr('class', 'form-group has-api-validation has-feedback has-success');
-          $icon.attr('class', 'fa fa-check form-control-feedback');
-          $control_message.attr('class', 'control-success fade in')
-        }
-      });
-    }
-    {% if form.is_bound %}
-    validate();
-    {% endif %}
-    $input.keyup(validate);
-  });
+  $(function () {
+    // API-based validation
+    var csrf_token = $('input[name="csrfmiddlewaretoken"]').val()
+
+    $('.has-api-validation').each(function() {
+      var $control = $(this);
+      var $input = $control.find('input');
+      var $icon = $(this).find('.fa');
+      var $control_message = $(this).find('.control-message');
+
+      var api_url = $(this).data('validation-api');
+      var api_value = $(this).data('validation-value');
+
+      function validate() {
+        var data = {csrfmiddlewaretoken: csrf_token};
+        data[api_value] = $.trim($input.val());
+        $.post(api_url, data, function(data, textStatus, jqXHR) {
+          $control_message.find('strong').text(data.message);
+
+          if (data.has_error) {
+            $control.attr('class', 'form-group has-api-validation has-feedback has-error');
+            $icon.attr('class', 'fa fa-times form-control-feedback');
+            $control_message.attr('class', 'control-errors fade in')
+          } else {
+            $control.attr('class', 'form-group has-api-validation has-feedback has-success');
+            $icon.attr('class', 'fa fa-check form-control-feedback');
+            $control_message.attr('class', 'control-success fade in')
+          }
+        });
+      }
+      {% if form.is_bound %}
+      validate();
+      {% endif %}
+      $input.keyup(validate);
+    });
 
-  // Password strength
-  var zxcvbn_src = "{% static "misago/js/zxcvbn.js" %}";
-  var labels = ["{% trans "Very weak" %}", "{% trans "Weak" %}", "{% trans "Medium" %}", "{% trans "Good" %}", "{% trans "Strong" %}"];
-  var label_styles = ["text-danger", "text-warning", "text-warning", "text-info", "text-success"];
-  var bar_styles = ["progress-bar-danger", "progress-bar-warning", "progress-bar-warning", "progress-bar-info", "progress-bar-success"];
+    // Password strength
+    var zxcvbn_src = "{% static "misago/js/zxcvbn.js" %}";
+    var labels = ["{% trans "Very weak" %}", "{% trans "Weak" %}", "{% trans "Medium" %}", "{% trans "Good" %}", "{% trans "Strong" %}"];
+    var label_styles = ["text-danger", "text-warning", "text-warning", "text-info", "text-success"];
+    var bar_styles = ["progress-bar-danger", "progress-bar-warning", "progress-bar-warning", "progress-bar-info", "progress-bar-success"];
 
-  function zxcvbn_load_hook() {
-    $(function() {
-      var $bar = $('#password-bar');
-      var $label = $('#password-strength');
+    function zxcvbn_load_hook() {
+      $(function() {
+        var $bar = $('#password-bar');
+        var $label = $('#password-strength');
 
-      function gradePassStrength() {
-        var username = $('#id_username').val();
-        var email = $('#id_email').val();
-        var password = $('#id_password').val();
+        function gradePassStrength() {
+          var username = $('#id_username').val();
+          var email = $('#id_email').val();
+          var password = $('#id_password').val();
 
-        var power = zxcvbn(password, [username, email]).score;
+          var power = zxcvbn(password, [username, email]).score;
 
-        $label.text(labels[power]);
-        $label.attr('class', label_styles[power]);
-        $bar.css('width', ((power + 1) * 20) + '%');
-        $bar.attr('class', "progress-bar " + bar_styles[power]);
-      }
+          $label.text(labels[power]);
+          $label.attr('class', label_styles[power]);
+          $bar.css('width', ((power + 1) * 20) + '%');
+          $bar.attr('class', "progress-bar " + bar_styles[power]);
+        }
 
-      gradePassStrength();
-      $('#id_password').keyup(gradePassStrength);
-    });
-  }
+        gradePassStrength();
+        $('#id_password').keyup(gradePassStrength);
+      });
+    }
+  });
 </script>
 <script type="text/javascript" src="{% static "misago/js/zxcvbn-async.js" %}"></script>
 {% endblock javascripts %}