Compare commits

...

5 Commits

Author SHA1 Message Date
Fabio Caccamo 1c2ac2a308 Updated version. [ci skip] 2019-02-21 18:05:09 +01:00
Fabio Caccamo 3133beb82f Enabled travis pip cache. 2019-02-21 17:30:13 +01:00
Fabio Caccamo 18d2281011 Splitted tests to multiple files. 2019-02-21 17:17:59 +01:00
Fabio Caccamo 7d9edddf82 Added env badge to favicon. 2019-02-21 17:16:48 +01:00
Fabio Caccamo 1c335f83e9 Added PyPi downloads badge to README. [ci skip] 2019-02-08 12:01:33 +01:00
14 changed files with 1027 additions and 66 deletions
+1
View File
@@ -1,4 +1,5 @@
language: python language: python
cache: pip
python: 3.5 python: 3.5
env: env:
- TOX_ENV=py27-dj17-sqlite - TOX_ENV=py27-dj17-sqlite
+1
View File
@@ -2,6 +2,7 @@
[![codecov](https://codecov.io/gh/fabiocaccamo/django-admin-interface/branch/master/graph/badge.svg)](https://codecov.io/gh/fabiocaccamo/django-admin-interface) [![codecov](https://codecov.io/gh/fabiocaccamo/django-admin-interface/branch/master/graph/badge.svg)](https://codecov.io/gh/fabiocaccamo/django-admin-interface)
[![Code Health](https://landscape.io/github/fabiocaccamo/django-admin-interface/master/landscape.svg?style=flat)](https://landscape.io/github/fabiocaccamo/django-admin-interface/master) [![Code Health](https://landscape.io/github/fabiocaccamo/django-admin-interface/master/landscape.svg?style=flat)](https://landscape.io/github/fabiocaccamo/django-admin-interface/master)
[![PyPI version](https://badge.fury.io/py/django-admin-interface.svg)](https://badge.fury.io/py/django-admin-interface) [![PyPI version](https://badge.fury.io/py/django-admin-interface.svg)](https://badge.fury.io/py/django-admin-interface)
[![PyPI downloads](https://img.shields.io/pypi/dm/django-admin-interface.svg)](https://img.shields.io/pypi/dm/django-admin-interface.svg)
[![Py versions](https://img.shields.io/pypi/pyversions/django-admin-interface.svg)](https://img.shields.io/pypi/pyversions/django-admin-interface.svg) [![Py versions](https://img.shields.io/pypi/pyversions/django-admin-interface.svg)](https://img.shields.io/pypi/pyversions/django-admin-interface.svg)
[![License](https://img.shields.io/pypi/l/django-admin-interface.svg)](https://img.shields.io/pypi/l/django-admin-interface.svg) [![License](https://img.shields.io/pypi/l/django-admin-interface.svg)](https://img.shields.io/pypi/l/django-admin-interface.svg)
+3 -1
View File
@@ -1,4 +1,4 @@
|Build Status| |codecov| |Code Health| |PyPI version| |Py versions| |License| |Build Status| |codecov| |Code Health| |PyPI version| |PyPI downloads| |Py versions| |License|
django-admin-interface django-admin-interface
====================== ======================
@@ -137,6 +137,8 @@ Released under **MIT License**.
.. |PyPI version| image:: https://badge.fury.io/py/django-admin-interface.svg .. |PyPI version| image:: https://badge.fury.io/py/django-admin-interface.svg
.. |PyPI downloads| image:: https://img.shields.io/pypi/dm/django-admin-interface.svg
.. |Py versions| image:: https://img.shields.io/pypi/pyversions/django-admin-interface.svg .. |Py versions| image:: https://img.shields.io/pypi/pyversions/django-admin-interface.svg
.. |License| image:: https://img.shields.io/pypi/l/django-admin-interface.svg .. |License| image:: https://img.shields.io/pypi/l/django-admin-interface.svg
+20 -5
View File
@@ -93,20 +93,35 @@ class Theme(models.Model):
help_text=_('(.ico|.png|.gif - 16x16|32x32 px)'), help_text=_('(.ico|.png|.gif - 16x16|32x32 px)'),
verbose_name=_('favicon')) verbose_name=_('favicon'))
envs = (
'development',
'testing',
'staging',
'production',
)
env_choices = ( env_choices = (
('development', _('Development'), ), (envs[0], _('Development'), ),
('testing', _('Testing'), ), (envs[1], _('Testing'), ),
('staging', _('Staging'), ), (envs[2], _('Staging'), ),
('production', _('Production'), ), (envs[3], _('Production'), ),
) )
env = models.CharField( env = models.CharField(
max_length=50, max_length=50,
choices=env_choices, choices=env_choices,
default='development', default=env_choices[0][0],
verbose_name=_('environment')) verbose_name=_('environment'))
env_visible = models.BooleanField( env_visible = models.BooleanField(
default=True, default=True,
verbose_name=_('visible')) verbose_name=_('visible'))
env_colors = {
envs[0]: '#e74c3c',
envs[1]: '#e67e22',
envs[2]: '#f1c40f',
envs[3]: '#2ecc71',
}
@property
def env_color(self):
return Theme.env_colors.get(self.env, '')
css_header_background_color = ColorField( css_header_background_color = ColorField(
blank=True, blank=True,
@@ -0,0 +1,913 @@
/**
* @license MIT or GPL-2.0
* @fileOverview Favico animations
* @author Miroslav Magda, http://blog.ejci.net
* @source: https://github.com/ejci/favico.js
* @version 0.3.10
*/
/**
* Create new favico instance
* @param {Object} Options
* @return {Object} Favico object
* @example
* var favico = new Favico({
* bgColor : '#d00',
* textColor : '#fff',
* fontFamily : 'sans-serif',
* fontStyle : 'bold',
* type : 'circle',
* position : 'down',
* animation : 'slide',
* elementId: false,
* element: null,
* dataUrl: function(url){},
* win: window
* });
*/
(function () {
var Favico = (function (opt) {
'use strict';
opt = (opt) ? opt : {};
var _def = {
bgColor: '#d00',
textColor: '#fff',
fontFamily: 'sans-serif', //Arial,Verdana,Times New Roman,serif,sans-serif,...
fontStyle: 'bold', //normal,italic,oblique,bold,bolder,lighter,100,200,300,400,500,600,700,800,900
type: 'circle',
position: 'down', // down, up, left, leftup (upleft)
animation: 'slide',
elementId: false,
element: null,
dataUrl: false,
win: window
};
var _opt, _orig, _h, _w, _canvas, _context, _img, _ready, _lastBadge, _running, _readyCb, _stop, _browser, _animTimeout, _drawTimeout, _doc;
_browser = {};
_browser.ff = typeof InstallTrigger != 'undefined';
_browser.chrome = !!window.chrome;
_browser.opera = !!window.opera || navigator.userAgent.indexOf('Opera') >= 0;
_browser.ie = /*@cc_on!@*/false;
_browser.safari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
_browser.supported = (_browser.chrome || _browser.ff || _browser.opera);
var _queue = [];
_readyCb = function () {
};
_ready = _stop = false;
/**
* Initialize favico
*/
var init = function () {
//merge initial options
_opt = merge(_def, opt);
_opt.bgColor = hexToRgb(_opt.bgColor);
_opt.textColor = hexToRgb(_opt.textColor);
_opt.position = _opt.position.toLowerCase();
_opt.animation = (animation.types['' + _opt.animation]) ? _opt.animation : _def.animation;
_doc = _opt.win.document;
var isUp = _opt.position.indexOf('up') > -1;
var isLeft = _opt.position.indexOf('left') > -1;
//transform the animations
if (isUp || isLeft) {
for (var a in animation.types) {
for (var i = 0; i < animation.types[a].length; i++) {
var step = animation.types[a][i];
if (isUp) {
if (step.y < 0.6) {
step.y = step.y - 0.4;
} else {
step.y = step.y - 2 * step.y + (1 - step.w);
}
}
if (isLeft) {
if (step.x < 0.6) {
step.x = step.x - 0.4;
} else {
step.x = step.x - 2 * step.x + (1 - step.h);
}
}
animation.types[a][i] = step;
}
}
}
_opt.type = (type['' + _opt.type]) ? _opt.type : _def.type;
_orig = link. getIcons();
//create temp canvas
_canvas = document.createElement('canvas');
//create temp image
_img = document.createElement('img');
var lastIcon = _orig[_orig.length - 1];
if (lastIcon.hasAttribute('href')) {
_img.setAttribute('crossOrigin', 'anonymous');
//get width/height
_img.onload = function () {
_h = (_img.height > 0) ? _img.height : 32;
_w = (_img.width > 0) ? _img.width : 32;
_canvas.height = _h;
_canvas.width = _w;
_context = _canvas.getContext('2d');
icon.ready();
};
_img.setAttribute('src', lastIcon.getAttribute('href'));
} else {
_h = 32;
_w = 32;
_img.height = _h;
_img.width = _w;
_canvas.height = _h;
_canvas.width = _w;
_context = _canvas.getContext('2d');
icon.ready();
}
};
/**
* Icon namespace
*/
var icon = {};
/**
* Icon is ready (reset icon) and start animation (if ther is any)
*/
icon.ready = function () {
_ready = true;
icon.reset();
_readyCb();
};
/**
* Reset icon to default state
*/
icon.reset = function () {
//reset
if (!_ready) {
return;
}
_queue = [];
_lastBadge = false;
_running = false;
_context.clearRect(0, 0, _w, _h);
_context.drawImage(_img, 0, 0, _w, _h);
//_stop=true;
link.setIcon(_canvas);
//webcam('stop');
//video('stop');
window.clearTimeout(_animTimeout);
window.clearTimeout(_drawTimeout);
};
/**
* Start animation
*/
icon.start = function () {
if (!_ready || _running) {
return;
}
var finished = function () {
_lastBadge = _queue[0];
_running = false;
if (_queue.length > 0) {
_queue.shift();
icon.start();
} else {
}
};
if (_queue.length > 0) {
_running = true;
var run = function () {
// apply options for this animation
['type', 'animation', 'bgColor', 'textColor', 'fontFamily', 'fontStyle'].forEach(function (a) {
if (a in _queue[0].options) {
_opt[a] = _queue[0].options[a];
}
});
animation.run(_queue[0].options, function () {
finished();
}, false);
};
if (_lastBadge) {
animation.run(_lastBadge.options, function () {
run();
}, true);
} else {
run();
}
}
};
/**
* Badge types
*/
var type = {};
var options = function (opt) {
opt.n = ((typeof opt.n) === 'number') ? Math.abs(opt.n | 0) : opt.n;
opt.x = _w * opt.x;
opt.y = _h * opt.y;
opt.w = _w * opt.w;
opt.h = _h * opt.h;
opt.len = ("" + opt.n).length;
return opt;
};
/**
* Generate circle
* @param {Object} opt Badge options
*/
type.circle = function (opt) {
opt = options(opt);
var more = false;
if (opt.len === 2) {
opt.x = opt.x - opt.w * 0.4;
opt.w = opt.w * 1.4;
more = true;
} else if (opt.len >= 3) {
opt.x = opt.x - opt.w * 0.65;
opt.w = opt.w * 1.65;
more = true;
}
// begin patch
// draw a smaller badge without text
opt.w = 14;
opt.h = 14;
opt.x = (_w - opt.w);
opt.y = (_h - opt.h);
// end patch
_context.clearRect(0, 0, _w, _h);
_context.drawImage(_img, 0, 0, _w, _h);
_context.beginPath();
_context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.85 : 1)) + "px " + _opt.fontFamily;
_context.textAlign = 'center';
if (more) {
_context.moveTo(opt.x + opt.w / 2, opt.y);
_context.lineTo(opt.x + opt.w - opt.h / 2, opt.y);
_context.quadraticCurveTo(opt.x + opt.w, opt.y, opt.x + opt.w, opt.y + opt.h / 2);
_context.lineTo(opt.x + opt.w, opt.y + opt.h - opt.h / 2);
_context.quadraticCurveTo(opt.x + opt.w, opt.y + opt.h, opt.x + opt.w - opt.h / 2, opt.y + opt.h);
_context.lineTo(opt.x + opt.h / 2, opt.y + opt.h);
_context.quadraticCurveTo(opt.x, opt.y + opt.h, opt.x, opt.y + opt.h - opt.h / 2);
_context.lineTo(opt.x, opt.y + opt.h / 2);
_context.quadraticCurveTo(opt.x, opt.y, opt.x + opt.h / 2, opt.y);
} else {
_context.arc(opt.x + opt.w / 2, opt.y + opt.h / 2, opt.h / 2, 0, 2 * Math.PI);
}
_context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
_context.fill();
_context.closePath();
_context.beginPath();
_context.stroke();
_context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
//_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
if ((typeof opt.n) === 'number' && opt.n > 999) {
_context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000)) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
} else {
_context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
}
_context.closePath();
};
/**
* Generate rectangle
* @param {Object} opt Badge options
*/
type.rectangle = function (opt) {
opt = options(opt);
var more = false;
if (opt.len === 2) {
opt.x = opt.x - opt.w * 0.4;
opt.w = opt.w * 1.4;
more = true;
} else if (opt.len >= 3) {
opt.x = opt.x - opt.w * 0.65;
opt.w = opt.w * 1.65;
more = true;
}
_context.clearRect(0, 0, _w, _h);
_context.drawImage(_img, 0, 0, _w, _h);
_context.beginPath();
_context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.9 : 1)) + "px " + _opt.fontFamily;
_context.textAlign = 'center';
_context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
_context.fillRect(opt.x, opt.y, opt.w, opt.h);
_context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
//_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
if ((typeof opt.n) === 'number' && opt.n > 999) {
_context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000)) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
} else {
_context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
}
_context.closePath();
};
/**
* Set badge
*/
var badge = function (number, opts) {
opts = ((typeof opts) === 'string' ? {
animation: opts
} : opts) || {};
_readyCb = function () {
try {
if (typeof (number) === 'number' ? (number > 0) : (number !== '')) {
var q = {
type: 'badge',
options: {
n: number
}
};
if ('animation' in opts && animation.types['' + opts.animation]) {
q.options.animation = '' + opts.animation;
}
if ('type' in opts && type['' + opts.type]) {
q.options.type = '' + opts.type;
}
['bgColor', 'textColor'].forEach(function (o) {
if (o in opts) {
q.options[o] = hexToRgb(opts[o]);
}
});
['fontStyle', 'fontFamily'].forEach(function (o) {
if (o in opts) {
q.options[o] = opts[o];
}
});
_queue.push(q);
if (_queue.length > 100) {
throw new Error('Too many badges requests in queue.');
}
icon.start();
} else {
icon.reset();
}
} catch (e) {
throw new Error('Error setting badge. Message: ' + e.message);
}
};
if (_ready) {
_readyCb();
}
};
/**
* Set image as icon
*/
var image = function (imageElement) {
_readyCb = function () {
try {
var w = imageElement.width;
var h = imageElement.height;
var newImg = document.createElement('img');
var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
newImg.setAttribute('crossOrigin', 'anonymous');
newImg.onload=function(){
_context.clearRect(0, 0, _w, _h);
_context.drawImage(newImg, 0, 0, _w, _h);
link.setIcon(_canvas);
};
newImg.setAttribute('src', imageElement.getAttribute('src'));
newImg.height = (h / ratio);
newImg.width = (w / ratio);
} catch (e) {
throw new Error('Error setting image. Message: ' + e.message);
}
};
if (_ready) {
_readyCb();
}
};
/**
* Set the icon from a source url. Won't work with badges.
*/
var rawImageSrc = function (url) {
_readyCb = function() {
link.setIconSrc(url);
};
if (_ready) {
_readyCb();
}
};
/**
* Set video as icon
*/
var video = function (videoElement) {
_readyCb = function () {
try {
if (videoElement === 'stop') {
_stop = true;
icon.reset();
_stop = false;
return;
}
//var w = videoElement.width;
//var h = videoElement.height;
//var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
videoElement.addEventListener('play', function () {
drawVideo(this);
}, false);
} catch (e) {
throw new Error('Error setting video. Message: ' + e.message);
}
};
if (_ready) {
_readyCb();
}
};
/**
* Set video as icon
*/
var webcam = function (action) {
//UR
if (!window.URL || !window.URL.createObjectURL) {
window.URL = window.URL || {};
window.URL.createObjectURL = function (obj) {
return obj;
};
}
if (_browser.supported) {
var newVideo = false;
navigator.getUserMedia = navigator.getUserMedia || navigator.oGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
_readyCb = function () {
try {
if (action === 'stop') {
_stop = true;
icon.reset();
_stop = false;
return;
}
newVideo = document.createElement('video');
newVideo.width = _w;
newVideo.height = _h;
navigator.getUserMedia({
video: true,
audio: false
}, function (stream) {
newVideo.src = URL.createObjectURL(stream);
newVideo.play();
drawVideo(newVideo);
}, function () {
});
} catch (e) {
throw new Error('Error setting webcam. Message: ' + e.message);
}
};
if (_ready) {
_readyCb();
}
}
};
var setOpt = function (key, value) {
var opts = key;
if (!(value == null && Object.prototype.toString.call(key) == '[object Object]')) {
opts = {};
opts[key] = value;
}
var keys = Object.keys(opts);
for (var i = 0; i < keys.length; i++) {
if (keys[i] == 'bgColor' || keys[i] == 'textColor') {
_opt[keys[i]] = hexToRgb(opts[keys[i]]);
} else {
_opt[keys[i]] = opts[keys[i]];
}
}
_queue.push(_lastBadge);
icon.start();
};
/**
* Draw video to context and repeat :)
*/
function drawVideo(video) {
if (video.paused || video.ended || _stop) {
return false;
}
//nasty hack for FF webcam (Thanks to Julian Ćwirko, kontakt@redsunmedia.pl)
try {
_context.clearRect(0, 0, _w, _h);
_context.drawImage(video, 0, 0, _w, _h);
} catch (e) {
}
_drawTimeout = setTimeout(function () {
drawVideo(video);
}, animation.duration);
link.setIcon(_canvas);
}
var link = {};
/**
* Get icons from HEAD tag or create a new <link> element
*/
link.getIcons = function () {
var elms = [];
//get link element
var getLinks = function () {
var icons = [];
var links = _doc.getElementsByTagName('head')[0].getElementsByTagName('link');
for (var i = 0; i < links.length; i++) {
if ((/(^|\s)icon(\s|$)/i).test(links[i].getAttribute('rel'))) {
icons.push(links[i]);
}
}
return icons;
};
if (_opt.element) {
elms = [_opt.element];
} else if (_opt.elementId) {
//if img element identified by elementId
elms = [_doc.getElementById(_opt.elementId)];
elms[0].setAttribute('href', elms[0].getAttribute('src'));
} else {
//if link element
elms = getLinks();
if (elms.length === 0) {
elms = [_doc.createElement('link')];
elms[0].setAttribute('rel', 'icon');
_doc.getElementsByTagName('head')[0].appendChild(elms[0]);
}
}
elms.forEach(function(item) {
item.setAttribute('type', 'image/png');
});
return elms;
};
link.setIcon = function (canvas) {
var url = canvas.toDataURL('image/png');
link.setIconSrc(url);
};
link.setIconSrc = function (url) {
if (_opt.dataUrl) {
//if using custom exporter
_opt.dataUrl(url);
}
if (_opt.element) {
_opt.element.setAttribute('href', url);
_opt.element.setAttribute('src', url);
} else if (_opt.elementId) {
//if is attached to element (image)
var elm = _doc.getElementById(_opt.elementId);
elm.setAttribute('href', url);
elm.setAttribute('src', url);
} else {
//if is attached to fav icon
if (_browser.ff || _browser.opera) {
//for FF we need to "recreate" element, atach to dom and remove old <link>
//var originalType = _orig.getAttribute('rel');
var old = _orig[_orig.length - 1];
var newIcon = _doc.createElement('link');
_orig = [newIcon];
//_orig.setAttribute('rel', originalType);
if (_browser.opera) {
newIcon.setAttribute('rel', 'icon');
}
newIcon.setAttribute('rel', 'icon');
newIcon.setAttribute('type', 'image/png');
_doc.getElementsByTagName('head')[0].appendChild(newIcon);
newIcon.setAttribute('href', url);
if (old.parentNode) {
old.parentNode.removeChild(old);
}
} else {
_orig.forEach(function(icon) {
icon.setAttribute('href', url);
});
}
}
};
//http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-5624139
//HEX to RGB convertor
function hexToRgb(hex) {
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : false;
}
/**
* Merge options
*/
function merge(def, opt) {
var mergedOpt = {};
var attrname;
for (attrname in def) {
mergedOpt[attrname] = def[attrname];
}
for (attrname in opt) {
mergedOpt[attrname] = opt[attrname];
}
return mergedOpt;
}
/**
* Cross-browser page visibility shim
* http://stackoverflow.com/questions/12536562/detect-whether-a-window-is-visible
*/
function isPageHidden() {
return _doc.hidden || _doc.msHidden || _doc.webkitHidden || _doc.mozHidden;
}
/**
* @namespace animation
*/
var animation = {};
/**
* Animation "frame" duration
*/
animation.duration = 40;
/**
* Animation types (none,fade,pop,slide)
*/
animation.types = {};
animation.types.fade = [{
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.0
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.1
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.2
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.3
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.4
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.5
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.6
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.7
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.8
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 0.9
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 1.0
}];
animation.types.none = [{
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 1
}];
animation.types.pop = [{
x: 1,
y: 1,
w: 0,
h: 0,
o: 1
}, {
x: 0.9,
y: 0.9,
w: 0.1,
h: 0.1,
o: 1
}, {
x: 0.8,
y: 0.8,
w: 0.2,
h: 0.2,
o: 1
}, {
x: 0.7,
y: 0.7,
w: 0.3,
h: 0.3,
o: 1
}, {
x: 0.6,
y: 0.6,
w: 0.4,
h: 0.4,
o: 1
}, {
x: 0.5,
y: 0.5,
w: 0.5,
h: 0.5,
o: 1
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 1
}];
animation.types.popFade = [{
x: 0.75,
y: 0.75,
w: 0,
h: 0,
o: 0
}, {
x: 0.65,
y: 0.65,
w: 0.1,
h: 0.1,
o: 0.2
}, {
x: 0.6,
y: 0.6,
w: 0.2,
h: 0.2,
o: 0.4
}, {
x: 0.55,
y: 0.55,
w: 0.3,
h: 0.3,
o: 0.6
}, {
x: 0.50,
y: 0.50,
w: 0.4,
h: 0.4,
o: 0.8
}, {
x: 0.45,
y: 0.45,
w: 0.5,
h: 0.5,
o: 0.9
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 1
}];
animation.types.slide = [{
x: 0.4,
y: 1,
w: 0.6,
h: 0.6,
o: 1
}, {
x: 0.4,
y: 0.9,
w: 0.6,
h: 0.6,
o: 1
}, {
x: 0.4,
y: 0.9,
w: 0.6,
h: 0.6,
o: 1
}, {
x: 0.4,
y: 0.8,
w: 0.6,
h: 0.6,
o: 1
}, {
x: 0.4,
y: 0.7,
w: 0.6,
h: 0.6,
o: 1
}, {
x: 0.4,
y: 0.6,
w: 0.6,
h: 0.6,
o: 1
}, {
x: 0.4,
y: 0.5,
w: 0.6,
h: 0.6,
o: 1
}, {
x: 0.4,
y: 0.4,
w: 0.6,
h: 0.6,
o: 1
}];
/**
* Run animation
* @param {Object} opt Animation options
* @param {Object} cb Callabak after all steps are done
* @param {Object} revert Reverse order? true|false
* @param {Object} step Optional step number (frame bumber)
*/
animation.run = function (opt, cb, revert, step) {
var animationType = animation.types[isPageHidden() ? 'none' : _opt.animation];
if (revert === true) {
step = (typeof step !== 'undefined') ? step : animationType.length - 1;
} else {
step = (typeof step !== 'undefined') ? step : 0;
}
cb = (cb) ? cb : function () {
};
if ((step < animationType.length) && (step >= 0)) {
type[_opt.type](merge(opt, animationType[step]));
_animTimeout = setTimeout(function () {
if (revert) {
step = step - 1;
} else {
step = step + 1;
}
animation.run(opt, cb, revert, step);
}, animation.duration);
link.setIcon(_canvas);
} else {
cb();
return;
}
};
//auto init
init();
return {
badge: badge,
video: video,
image: image,
rawImageSrc: rawImageSrc,
webcam: webcam,
setOpt: setOpt,
reset: icon.reset,
browser: {
supported: _browser.supported
}
};
});
// AMD / RequireJS
if (typeof define !== 'undefined' && define.amd) {
define([], function () {
return Favico;
});
}
// CommonJS
else if (typeof module !== 'undefined' && module.exports) {
module.exports = Favico;
}
// included directly via <script> tag
else {
this.Favico = Favico;
}
})();
File diff suppressed because one or more lines are too long
@@ -40,14 +40,8 @@ https://github.com/fabiocaccamo/django-admin-interface
{# https://github.com/elky/django-flat-responsive#important-note #} {# https://github.com/elky/django-flat-responsive#important-note #}
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"> <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive.css' %}?v={{ version }}" /> <link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive.css' %}?v={{ version }}" />
{% if theme.favicon %} {% include "admin_interface/favicon.html" %}
<link rel="icon" type="image/x-icon" href="{{ theme.favicon.url }}?v={{ version }}" /> {% include "admin_interface/related-modal.html" %}
{% endif %}
{% if theme.related_modal_active %}
<link rel="stylesheet" type="text/css" href="{% static 'admin_interface/magnific-popup/magnific-popup.css' %}?v={{ version }}" />
<script type="text/javascript" src="{% static 'admin_interface/magnific-popup/jquery.magnific-popup.js' %}?v={{ version }}"></script>
<script type="text/javascript" src="{% static 'admin_interface/related-modal/related-modal.js' %}?v={{ version }}"></script>
{% endif %}
{% endblock %} {% endblock %}
{% block bodyclass %}admin-interface flat-theme {% get_admin_interface_theme as theme %}{% if theme.name %}{{ theme.name|slugify }}-theme{% endif %}{% endblock %} {% block bodyclass %}admin-interface flat-theme {% get_admin_interface_theme as theme %}{% if theme.name %}{{ theme.name|slugify }}-theme{% endif %}{% endblock %}
@@ -20,19 +20,19 @@
} }
.admin-interface .enviroment-label.development::before { .admin-interface .enviroment-label.development::before {
background-color: #e74c3c; background-color: {{ theme.env_colors.development }};
} }
.admin-interface .enviroment-label.testing::before { .admin-interface .enviroment-label.testing::before {
background-color: #e67e22; background-color: {{ theme.env_colors.testing }};
} }
.admin-interface .enviroment-label.staging::before { .admin-interface .enviroment-label.staging::before {
background-color: #f1c40f; background-color: {{ theme.env_colors.staging }};
} }
.admin-interface .enviroment-label.production::before { .admin-interface .enviroment-label.production::before {
background-color: #2ecc71; background-color: {{ theme.env_colors.production }};
} }
.admin-interface .enviroment-label::after { .admin-interface .enviroment-label::after {
@@ -10,4 +10,3 @@
</select> </select>
</div> </div>
</div> </div>
@@ -0,0 +1,17 @@
{% load static %}
{% if theme.favicon %}
<link rel="icon" type="image/x-icon" href="{{ theme.favicon.url }}?v={{ version }}" />
{% if theme.env_visible %}
<script type="text/javascript" src="{% static 'admin_interface/favico/favico-0.3.10-patched.min.js' %}?v={{ version }}"></script>
<script type="text/javascript">
var favicon = new Favico({
type: 'circle',
bgColor: '{{ theme.env_color }}',
textColor: '#FFFFFF',
animation: 'none'
});
favicon.badge(' ');
</script>
{% endif %}
{% endif %}
@@ -0,0 +1,7 @@
{% load static %}
{% if theme.related_modal_active %}
<link rel="stylesheet" type="text/css" href="{% static 'admin_interface/magnific-popup/magnific-popup.css' %}?v={{ version }}" />
<script type="text/javascript" src="{% static 'admin_interface/magnific-popup/jquery.magnific-popup.js' %}?v={{ version }}"></script>
<script type="text/javascript" src="{% static 'admin_interface/related-modal/related-modal.js' %}?v={{ version }}"></script>
{% endif %}
+1 -1
View File
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
__version__ = '0.9.2' __version__ = '0.9.3'
+1 -44
View File
@@ -2,29 +2,20 @@
from django.conf import settings from django.conf import settings
from django.test import TestCase from django.test import TestCase
from django.test.client import RequestFactory
from django.template import Context, Template
import random import random
import shutil import shutil
from admin_interface.models import Theme from admin_interface.models import Theme
from admin_interface.templatetags import admin_interface_tags as templatetags
from admin_interface.version import __version__
class AdminInterfaceTestCase(TestCase): class AdminInterfaceModelsTestCase(TestCase):
def setUp(self): def setUp(self):
self.request_factory = RequestFactory()
pass pass
def tearDown(self): def tearDown(self):
shutil.rmtree(settings.MEDIA_ROOT, ignore_errors=True) shutil.rmtree(settings.MEDIA_ROOT, ignore_errors=True)
pass
def __render_template(self, string, context=None):
return Template(string).render(Context(context or {}))
def __test_active_theme(self): def __test_active_theme(self):
theme = Theme.get_active_theme() theme = Theme.get_active_theme()
@@ -93,40 +84,6 @@ class AdminInterfaceTestCase(TestCase):
self.assertEqual(Theme.get_active_theme().pk, theme.pk) self.assertEqual(Theme.get_active_theme().pk, theme.pk)
self.__test_active_theme() self.__test_active_theme()
def test_templatetags_get_theme(self):
Theme.objects.all().delete()
context = Context({})
theme = templatetags.get_admin_interface_theme(context)
self.assertEqual(theme.name, 'Django')
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_theme as theme %}'\
'{{ theme.name }}', context)
self.assertEqual(rendered, 'Django')
def test_templatetags_get_theme_with_request(self):
Theme.objects.all().delete()
context = Context({
'request': self.request_factory.get('/')
})
theme = templatetags.get_admin_interface_theme(context)
self.assertEqual(theme.name, 'Django')
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_theme as theme %}'\
'{{ theme.name }}', context)
self.assertEqual(rendered, 'Django')
def test_templatetags_get_version(self):
version = templatetags.get_admin_interface_version()
self.assertEqual(version, __version__)
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_version as version %}'\
'{{ version }}')
self.assertEqual(rendered, __version__)
def test_repr(self): def test_repr(self):
theme = Theme.get_active_theme() theme = Theme.get_active_theme()
self.assertEqual('{0}'.format(theme), 'Django') self.assertEqual('{0}'.format(theme), 'Django')
+54
View File
@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
from django.test import TestCase
from django.test.client import RequestFactory
from django.template import Context, Template
from admin_interface.models import Theme
from admin_interface.templatetags import admin_interface_tags as templatetags
from admin_interface.version import __version__
class AdminInterfaceTemplateTagsTestCase(TestCase):
def setUp(self):
self.request_factory = RequestFactory()
def tearDown(self):
pass
def __render_template(self, string, context=None):
return Template(string).render(Context(context or {}))
def test_get_theme(self):
Theme.objects.all().delete()
context = Context({})
theme = templatetags.get_admin_interface_theme(context)
self.assertEqual(theme.name, 'Django')
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_theme as theme %}'\
'{{ theme.name }}', context)
self.assertEqual(rendered, 'Django')
def test_get_theme_with_request(self):
Theme.objects.all().delete()
context = Context({
'request': self.request_factory.get('/')
})
theme = templatetags.get_admin_interface_theme(context)
self.assertEqual(theme.name, 'Django')
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_theme as theme %}'\
'{{ theme.name }}', context)
self.assertEqual(rendered, 'Django')
def test_get_version(self):
version = templatetags.get_admin_interface_version()
self.assertEqual(version, __version__)
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_version as version %}'\
'{{ version }}')
self.assertEqual(rendered, __version__)