Skip to content

Commit 074817a

Browse files
authored
Merge pull request #368 from divio/feature/update-notification
Added working draft of update notification template code
2 parents d6aad17 + 3f42c14 commit 074817a

File tree

16 files changed

+282
-7
lines changed

16 files changed

+282
-7
lines changed

README.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ Look at the source of ``templates/admin/base_site.html`` and override the templa
2727
For example, you can add your own CSS in ``templates/admin/inc/extrastyle.html``.
2828

2929

30+
Settings
31+
========
32+
33+
* ``CMS_ENABLE_UPDATE_CHECK = True``
34+
Set to ``False`` to disable the update notification.
35+
* ``CMS_UPDATE_CHECK_TYPE = ('minor')``
36+
Set to ``('patch')`` to get only patch notifications.
37+
(minor = 3.x.x, patch = 3.4.x)
38+
39+
3040
Compiling CSS
3141
=============
3242

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.cms-update-message {
2+
position: relative;
3+
margin-bottom: 30px;
4+
padding: 10px 20px 10px 10px;
5+
border: 1px solid $color-primary;
6+
border-radius: 4px;
7+
background-color: rgba($color-primary, 0.1);
8+
9+
.close {
10+
position: absolute;
11+
top: 0;
12+
right: 0;
13+
line-height: 20px;
14+
text-align: center;
15+
width: 20px;
16+
height: 20px;
17+
}
18+
}

djangocms_admin_style/sass/components/_tables.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,3 +374,11 @@
374374
}
375375
}
376376
}
377+
378+
.change-list table.navigator-table {
379+
tbody {
380+
td {
381+
vertical-align: middle !important;
382+
}
383+
}
384+
}

djangocms_admin_style/sass/djangocms-admin.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
@import "components/footer";
3131
@import "components/shortcuts";
3232
@import "components/drag-and-drop";
33+
@import "components/cms-update";
3334

3435
//##############################################################################
3536
// IMPORT MOBILE

djangocms_admin_style/static/djangocms_admin_style/css/djangocms-admin.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

djangocms_admin_style/static/djangocms_admin_style/js/base-admin.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ var initDragAndDropSupportForTreeBeard = require('./modules/drag-touch-support')
44
var initUIFixes = require('./modules/ui-fixes');
55
var initRelatedWidgetWrappers = require('./modules/related-widget-wrapper');
66
var initToolbarDropdown = require('./modules/toolbar-dropdown');
7+
var initUpdateNotification = require('./modules/update-notification');
78

89
// this attaches to global jQuery because
910
// we need to touch punch the things like sortedm2m
@@ -18,4 +19,5 @@ $(function () {
1819
initUIFixes();
1920
initRelatedWidgetWrappers();
2021
initToolbarDropdown();
22+
initUpdateNotification();
2123
});

djangocms_admin_style/static/djangocms_admin_style/js/dist/bundle.adminstyle.min.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

djangocms_admin_style/static/djangocms_admin_style/js/libs/js.cookie-2.1.2.min.js

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

djangocms_admin_style/static/djangocms_admin_style/js/modules/toolbar-dropdown.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ function init() {
3232
var menuItem = document.getElementsByClassName('menu-item')[0];
3333
var html = document.getElementsByTagName('html')[0];
3434

35+
if (!submenu || !menuItem) {
36+
return;
37+
}
38+
3539
menuItem.addEventListener('click', function (event) {
3640
var evt = event || window.event;
3741

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
var $ = require('jquery');
2+
var Cookies = require('js-cookie');
3+
var RELEASES_URL = 'https://releases.django-cms.org/';
4+
var MAIN_COOKIE_EXPIRATION = 365; // ~1 year
5+
var REQUEST_COOKIE_EXPIRATION = 14; // check only every two weeks
6+
7+
/**
8+
* @function getLatestVersionData
9+
* @private
10+
* @param {Object} data additional data to send as get params
11+
* @returns {$.Deferred}
12+
*/
13+
function getLatestVersionData(data) {
14+
return $.ajax({
15+
url: RELEASES_URL,
16+
data: data
17+
});
18+
}
19+
20+
/**
21+
* @function compareVersion
22+
* @param {String} a
23+
* @param {String} b
24+
* @returns {Number}
25+
*/
26+
function compareVersion(a, b) {
27+
var i;
28+
var cmp;
29+
var len;
30+
var re = /(\.0)+[^\.]*$/;
31+
32+
a = (a + '').replace(re, '').split('.'); // eslint-disable-line no-param-reassign
33+
b = (b + '').replace(re, '').split('.'); // eslint-disable-line no-param-reassign
34+
len = Math.min(a.length, b.length);
35+
for (i = 0; i < len; i++) {
36+
cmp = parseInt(a[i], 10) - parseInt(b[i], 10);
37+
38+
if (cmp !== 0) {
39+
return cmp;
40+
}
41+
}
42+
43+
return a.length - b.length;
44+
}
45+
46+
/**
47+
* is first version greater than second version?
48+
*
49+
* @function greaterThanVersion
50+
* @param {String} a
51+
* @param {String} b
52+
* @returns {Boolean} true if a > b or a === b but a is a dev/rc version
53+
*/
54+
function greaterThanVersion(a, b) {
55+
var cmp = compareVersion(a, b);
56+
57+
if (cmp > 0) {
58+
return true;
59+
} else if (cmp === 0) {
60+
if (b.match(/[^\.\d]+/)) {
61+
return true;
62+
}
63+
return false;
64+
}
65+
66+
return false;
67+
}
68+
69+
/**
70+
* @function injectMessage
71+
* @param {Object} versionObject
72+
* @param {String} versionObject.version
73+
* @param {String} versionObject.url
74+
* @param {String} checkType patch or minor/major
75+
*/
76+
function injectMessage(versionObject, checkType) {
77+
var messageTmpl = $($('#cms-update-notification').html());
78+
79+
messageTmpl.find('.js-latest-version').text(versionObject.version);
80+
messageTmpl.find('.js-release-notes-link').attr('href', versionObject.url);
81+
messageTmpl.find('.close').on('click', function (e) {
82+
e.preventDefault();
83+
84+
Cookies.set(
85+
'cms_upgrade_notification_closed',
86+
JSON.stringify({
87+
version: versionObject.version,
88+
type: checkType
89+
}),
90+
{
91+
expires: MAIN_COOKIE_EXPIRATION
92+
}
93+
);
94+
95+
Cookies.set(
96+
'cms_upgrade_notification_closed_recently',
97+
true,
98+
{
99+
expires: REQUEST_COOKIE_EXPIRATION
100+
}
101+
);
102+
103+
messageTmpl.slideUp('fast', function () {
104+
messageTmpl.remove();
105+
});
106+
});
107+
108+
messageTmpl.prependTo('#content').slideDown('fast');
109+
}
110+
111+
/**
112+
* @function shouldShowMessage
113+
* @private
114+
* @param {Object} versionObj
115+
* @param {String} versionObj.version
116+
* @param {String} currentVersion
117+
* @param {String} checkType
118+
* @returns {Boolean}
119+
*/
120+
function shouldShowMessage(versionObj, currentVersion, checkType) {
121+
var cookie = Cookies.get('cms_upgrade_notification_closed');
122+
123+
if (cookie) {
124+
cookie = JSON.parse(cookie);
125+
}
126+
127+
if (cookie && cookie.type === checkType && cookie.version === versionObj.version) {
128+
return false;
129+
}
130+
131+
return greaterThanVersion(versionObj.version, currentVersion);
132+
}
133+
134+
/**
135+
* @function init
136+
* @public
137+
*/
138+
function init() {
139+
var metaVersion = $('meta[name="djangocms_version"]');
140+
141+
if (!metaVersion.length || Cookies.get('cms_upgrade_notification_closed_recently')) {
142+
return;
143+
}
144+
145+
var currentVersion = metaVersion.attr('content');
146+
var checkType = $('meta[name="djangocms_version_check_type"]').attr('content');
147+
148+
getLatestVersionData({
149+
version: currentVersion,
150+
type: checkType
151+
}).done(function (response) {
152+
if (typeof response === 'string') {
153+
try {
154+
// eslint-disable-next-line
155+
response = JSON.parse(response);
156+
} catch (e) { }
157+
}
158+
159+
var versionObj = response.latest;
160+
161+
if (checkType === 'patch') {
162+
response.patches.forEach(function (patch) {
163+
if (patch.version.match(new RegExp('^' + currentVersion.replace(/\.[^\.]+$/, '')))) {
164+
versionObj = patch;
165+
}
166+
});
167+
}
168+
169+
if (shouldShowMessage(versionObj, currentVersion, checkType)) {
170+
injectMessage(versionObj, checkType);
171+
}
172+
});
173+
}
174+
175+
module.exports = init;

0 commit comments

Comments
 (0)