Skip to content

Commit

Permalink
Merge pull request #368 from divio/feature/update-notification
Browse files Browse the repository at this point in the history
Added working draft of update notification template code
  • Loading branch information
vxsx authored Sep 15, 2016
2 parents d6aad17 + 3f42c14 commit 074817a
Show file tree
Hide file tree
Showing 16 changed files with 282 additions and 7 deletions.
10 changes: 10 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ Look at the source of ``templates/admin/base_site.html`` and override the templa
For example, you can add your own CSS in ``templates/admin/inc/extrastyle.html``.


Settings
========

* ``CMS_ENABLE_UPDATE_CHECK = True``
Set to ``False`` to disable the update notification.
* ``CMS_UPDATE_CHECK_TYPE = ('minor')``
Set to ``('patch')`` to get only patch notifications.
(minor = 3.x.x, patch = 3.4.x)


Compiling CSS
=============

Expand Down
18 changes: 18 additions & 0 deletions djangocms_admin_style/sass/components/_cms-update.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.cms-update-message {
position: relative;
margin-bottom: 30px;
padding: 10px 20px 10px 10px;
border: 1px solid $color-primary;
border-radius: 4px;
background-color: rgba($color-primary, 0.1);

.close {
position: absolute;
top: 0;
right: 0;
line-height: 20px;
text-align: center;
width: 20px;
height: 20px;
}
}
8 changes: 8 additions & 0 deletions djangocms_admin_style/sass/components/_tables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -374,3 +374,11 @@
}
}
}

.change-list table.navigator-table {
tbody {
td {
vertical-align: middle !important;
}
}
}
1 change: 1 addition & 0 deletions djangocms_admin_style/sass/djangocms-admin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
@import "components/footer";
@import "components/shortcuts";
@import "components/drag-and-drop";
@import "components/cms-update";

//##############################################################################
// IMPORT MOBILE
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var initDragAndDropSupportForTreeBeard = require('./modules/drag-touch-support')
var initUIFixes = require('./modules/ui-fixes');
var initRelatedWidgetWrappers = require('./modules/related-widget-wrapper');
var initToolbarDropdown = require('./modules/toolbar-dropdown');
var initUpdateNotification = require('./modules/update-notification');

// this attaches to global jQuery because
// we need to touch punch the things like sortedm2m
Expand All @@ -18,4 +19,5 @@ $(function () {
initUIFixes();
initRelatedWidgetWrappers();
initToolbarDropdown();
initUpdateNotification();
});

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ function init() {
var menuItem = document.getElementsByClassName('menu-item')[0];
var html = document.getElementsByTagName('html')[0];

if (!submenu || !menuItem) {
return;
}

menuItem.addEventListener('click', function (event) {
var evt = event || window.event;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
var $ = require('jquery');
var Cookies = require('js-cookie');
var RELEASES_URL = 'https://releases.django-cms.org/';
var MAIN_COOKIE_EXPIRATION = 365; // ~1 year
var REQUEST_COOKIE_EXPIRATION = 14; // check only every two weeks

/**
* @function getLatestVersionData
* @private
* @param {Object} data additional data to send as get params
* @returns {$.Deferred}
*/
function getLatestVersionData(data) {
return $.ajax({
url: RELEASES_URL,
data: data
});
}

/**
* @function compareVersion
* @param {String} a
* @param {String} b
* @returns {Number}
*/
function compareVersion(a, b) {
var i;
var cmp;
var len;
var re = /(\.0)+[^\.]*$/;

a = (a + '').replace(re, '').split('.'); // eslint-disable-line no-param-reassign
b = (b + '').replace(re, '').split('.'); // eslint-disable-line no-param-reassign
len = Math.min(a.length, b.length);
for (i = 0; i < len; i++) {
cmp = parseInt(a[i], 10) - parseInt(b[i], 10);

if (cmp !== 0) {
return cmp;
}
}

return a.length - b.length;
}

/**
* is first version greater than second version?
*
* @function greaterThanVersion
* @param {String} a
* @param {String} b
* @returns {Boolean} true if a > b or a === b but a is a dev/rc version
*/
function greaterThanVersion(a, b) {
var cmp = compareVersion(a, b);

if (cmp > 0) {
return true;
} else if (cmp === 0) {
if (b.match(/[^\.\d]+/)) {
return true;
}
return false;
}

return false;
}

/**
* @function injectMessage
* @param {Object} versionObject
* @param {String} versionObject.version
* @param {String} versionObject.url
* @param {String} checkType patch or minor/major
*/
function injectMessage(versionObject, checkType) {
var messageTmpl = $($('#cms-update-notification').html());

messageTmpl.find('.js-latest-version').text(versionObject.version);
messageTmpl.find('.js-release-notes-link').attr('href', versionObject.url);
messageTmpl.find('.close').on('click', function (e) {
e.preventDefault();

Cookies.set(
'cms_upgrade_notification_closed',
JSON.stringify({
version: versionObject.version,
type: checkType
}),
{
expires: MAIN_COOKIE_EXPIRATION
}
);

Cookies.set(
'cms_upgrade_notification_closed_recently',
true,
{
expires: REQUEST_COOKIE_EXPIRATION
}
);

messageTmpl.slideUp('fast', function () {
messageTmpl.remove();
});
});

messageTmpl.prependTo('#content').slideDown('fast');
}

/**
* @function shouldShowMessage
* @private
* @param {Object} versionObj
* @param {String} versionObj.version
* @param {String} currentVersion
* @param {String} checkType
* @returns {Boolean}
*/
function shouldShowMessage(versionObj, currentVersion, checkType) {
var cookie = Cookies.get('cms_upgrade_notification_closed');

if (cookie) {
cookie = JSON.parse(cookie);
}

if (cookie && cookie.type === checkType && cookie.version === versionObj.version) {
return false;
}

return greaterThanVersion(versionObj.version, currentVersion);
}

/**
* @function init
* @public
*/
function init() {
var metaVersion = $('meta[name="djangocms_version"]');

if (!metaVersion.length || Cookies.get('cms_upgrade_notification_closed_recently')) {
return;
}

var currentVersion = metaVersion.attr('content');
var checkType = $('meta[name="djangocms_version_check_type"]').attr('content');

getLatestVersionData({
version: currentVersion,
type: checkType
}).done(function (response) {
if (typeof response === 'string') {
try {
// eslint-disable-next-line
response = JSON.parse(response);
} catch (e) { }
}

var versionObj = response.latest;

if (checkType === 'patch') {
response.patches.forEach(function (patch) {
if (patch.version.match(new RegExp('^' + currentVersion.replace(/\.[^\.]+$/, '')))) {
versionObj = patch;
}
});
}

if (shouldShowMessage(versionObj, currentVersion, checkType)) {
injectMessage(versionObj, checkType);
}
});
}

module.exports = init;
3 changes: 2 additions & 1 deletion djangocms_admin_style/templates/admin/base_site.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{% extends "admin/base.html" %}
{% load i18n staticfiles %}
{% load i18n staticfiles admin_style_tags %}

{% block extrastyle %}{% include 'admin/inc/extrastyle.html' %}{% endblock %}

{% block extrahead %}
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="stylesheet" type="text/css" href="{% static 'djangocms_admin_style/css/djangocms-admin.css' %}" />
{% if request.user.is_superuser %}{% render_update_notification %}{% endif %}
<script src="{% static 'djangocms_admin_style/js/dist/bundle.adminstyle.min.js' %}"></script>
{% include 'admin/inc/extrahead.html' %}{% endblock %}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% load i18n %}
<meta name="djangocms_version" content="{{ cms_version }}">
<meta name="djangocms_version_check_type" content="{{ cms_version_check_type }}">
<script type="text/template" id="cms-update-notification">
<div class="cms-update-message" hidden>
{% autoescape off %}
{% blocktrans with version='<strong>'|add:cms_version|add:'</strong>' latest='<strong class="js-latest-version"></strong>' release_link_before='<a class="js-release-notes-link" target="_blank" href="">' release_link_after='</a>' %}
There is a django CMS upgrade available. You are using: {{ version }}, new version is: {{ latest }}.
{{ release_link_before }}Read the release notes.{{ release_link_after }}
{% endblocktrans %}
{% endautoescape %}
<a href="#" class="close">&times;</a>
</div>
</script>
37 changes: 37 additions & 0 deletions djangocms_admin_style/templatetags/admin_style_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@
from __future__ import unicode_literals

from django import template
from django.conf import settings
from django.contrib.sites.shortcuts import get_current_site
from django.template.loader import render_to_string


# We follow the Semantic versioning convention
# minor - Refers to the minor release track (3.x.1)
# patch - Refers to the patch release track (3.4.x)
VALID_VERSION_CHECK_TYPES = ('minor', 'patch')

register = template.Library()

Expand All @@ -13,3 +21,32 @@ def current_site_name(context):
request = context.get('request')
site = get_current_site(request)
return site.name


@register.simple_tag(takes_context=True)
def render_update_notification(context):
try:
import cms
except ImportError:
check_type = None
notifications_enabled = False
else:
check_type = getattr(settings, 'CMS_UPDATE_CHECK_TYPE', 'patch')
notifications_enabled = getattr(settings, 'CMS_ENABLE_UPDATE_CHECK', True)

request = context.get('request')

try:
index_page = request.resolver_match.url_name == 'index'
except AttributeError:
notifications_enabled = False
else:
notifications_enabled = index_page and notifications_enabled

if notifications_enabled and check_type in VALID_VERSION_CHECK_TYPES:
context = {
'cms_version': cms.__version__,
'cms_version_check_type': check_type,
}
return render_to_string('admin/inc/cms_upgrade_notification.html', context)
return ''
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ var PROJECT_PATTERNS = {
PROJECT_PATH.js + '/**/*.js',
PROJECT_PATH.tests + '/**/*.js',
'!' + PROJECT_PATH.js + '/**/jquery.*.js',
'!' + PROJECT_PATH.js + '/libs/**/*.js',
'!' + PROJECT_PATH.js + '/dist/**/*.js',
'gulpfile.js'
]
Expand Down
1 change: 1 addition & 0 deletions testserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def noop_gettext(s):
'content': 0,
'permissions': 0,
},
CMS_ENABLE_UPDATE_CHECK=False,
# required for integration tests
LOGIN_URL='/admin/login/?user-login=test',
CMS_LANGUAGES={
Expand Down
3 changes: 2 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ module.exports = function (opts) {
resolve: {
extensions: ['', '.js'],
alias: {
jquery: PROJECT_PATH.js + '/libs/jquery.min.js'
'jquery': PROJECT_PATH.js + '/libs/jquery.min.js',
'js-cookie': PROJECT_PATH.js + '/libs/js.cookie-2.1.2.min.js'
}
},
module: {
Expand Down

0 comments on commit 074817a

Please sign in to comment.