Compare commits

..

76 Commits

Author SHA1 Message Date
Fabio Caccamo 875269e314 Updated version 2017-05-04 17:58:40 +02:00
Fabio Caccamo 775f1cf42b Added related modal support (related objects popup displayed in modal window) 2017-05-04 17:58:19 +02:00
Fabio Caccamo cc0474940f Moved responsive css to extrahead block 2017-05-04 17:55:28 +02:00
Fabio Caccamo 97896e3690 Added more comments to custom css 2017-05-04 17:51:46 +02:00
Fabio Caccamo 6a723e5515 Fixed inlines help text and error text margin-left 2017-05-04 17:43:09 +02:00
Fabio Caccamo fdf3b418f9 Removed theme active check in templates 2017-05-04 17:42:11 +02:00
Fabio Caccamo 49538ed582 Updated README.md [ci skip] 2017-04-14 13:16:25 +02:00
Fabio Caccamo c784a083f3 Updated version 2017-04-14 13:13:30 +02:00
Fabio Caccamo d1c912e875 Added django 1.11 support 2017-04-14 13:13:12 +02:00
Fabio Caccamo e9e950dda3 Fix error message margin left 2017-04-04 18:09:17 +02:00
Fabio Caccamo 3c4ea399e2 Updated version 2017-03-29 18:57:11 +02:00
Fabio Caccamo a28fe1c5e0 Improved Theme.get_active_theme method 2017-03-29 18:57:01 +02:00
Fabio Caccamo c07a846374 Updated README requirements and added badges 2017-03-29 16:32:52 +02:00
Fabio Caccamo f0126fb407 Updated version 2017-03-29 16:24:22 +02:00
Fabio Caccamo 869ae626da Added tox and travis 2017-03-29 16:22:34 +02:00
Fabio Caccamo a6bdb2b36d Updated setup.py 2017-03-29 16:22:09 +02:00
Fabio Caccamo aa18e19625 Added tests 2017-03-29 16:21:41 +02:00
Fabio Caccamo a35f8d0fb7 Dropped django < 1.7 support 2017-03-29 16:21:02 +02:00
Fabio Caccamo d29515c4ae Code refactoring 2017-03-29 16:20:07 +02:00
Fabio Caccamo 00f60c222d Fixed README syntax 2017-03-21 17:12:11 +01:00
Fabio Caccamo ff2d05e44c Fixed changelist filter header style 2017-02-16 11:30:44 +01:00
Fabio Caccamo 6e5cbf3a2c Fixed tools button focus color 2017-02-16 11:29:56 +01:00
Fabio Caccamo 55b365b2e4 Updated version 2017-02-09 16:25:25 +01:00
Fabio Caccamo 3203b437df Added horizontal scroll to long inlines to prevent full page scroll 2017-02-09 16:08:50 +01:00
Fabio Caccamo 202b5fa4aa Changed inlines delete buttons alignement 2017-02-09 16:07:52 +01:00
Fabio Caccamo 9fdc3a0268 Fixed help text alignement in wide inlines 2017-02-09 16:04:40 +01:00
Fabio Caccamo ded2fee89c Fixed issue #13 - Datetime widget broken in long inlines 2017-02-09 15:08:58 +01:00
Fabio Caccamo beec7242c6 Removed old code and added comment to previous fix 2017-02-09 15:08:37 +01:00
Fabio Caccamo 7a6a29b110 Fixed issue #12 - Inlines bad delete buttons alignement 2017-02-09 14:44:26 +01:00
Fabio Caccamo 1f3bb6514c Fixed issue #10 - Related widget broken in long tabular inline 2017-02-09 13:03:00 +01:00
Fabio Caccamo b416b46c5a Updated dynamic css indentation 2017-02-09 12:51:49 +01:00
Fabio Caccamo 59f1831cbd Fixed issue #11 - Inline border bottom should not be rounded 2017-02-09 12:50:36 +01:00
Fabio Caccamo 20050e2964 Removed duplicated code 2017-02-09 12:40:49 +01:00
Fabio Caccamo fd292ed1bf Fixed help text alignement in wide inlines 2017-02-07 16:06:05 +01:00
Fabio Caccamo fac0f690df Fixed breadcrumbs link focus color 2017-02-07 15:59:17 +01:00
Fabio Caccamo d18aadd93d Updated dependencies 2017-02-07 15:58:45 +01:00
Fabio Caccamo 9350575898 Updated setup.py 2016-11-08 12:18:35 +01:00
Fabio Caccamo 4789ee1dab Updated README.md 2016-11-08 12:18:19 +01:00
Fabio Caccamo a924c6cf5e Updated version 2016-11-08 12:17:53 +01:00
Fabio Caccamo 42b6e01f1f Added responsive support 2016-11-08 12:17:24 +01:00
Fabio Caccamo d7fa681c56 Fixed login padding 2016-11-08 12:15:42 +01:00
Fabio Caccamo 18e1425156 Updated version 2016-09-10 18:49:31 +02:00
Fabio Caccamo 1f39ceb0ad Fixed missing admin title #7 2016-09-10 18:49:20 +02:00
Fabio Caccamo 48cb73a604 Updated version 2016-09-04 18:44:07 +02:00
Fabio Caccamo c5bbbbc855 Updated README 2016-09-04 18:43:55 +02:00
Fabio Caccamo 793a019460 Fixed buttons color on focus and removed outline. 2016-09-04 18:43:29 +02:00
Fabio Caccamo 674178ecbe Updated README 2016-08-05 10:37:36 +02:00
Fabio Caccamo 07a51c1678 Updated version 2016-08-05 10:37:24 +02:00
Fabio Caccamo a58605a385 Renamed var 2016-08-05 10:36:59 +02:00
Fabio Caccamo e1d2c81ebe Merge pull request #6 from cereigido/master
Adding filename to File for Django 1.10 compatibility
2016-08-05 10:17:22 +02:00
Paulo Cereigido e5e55bdfcd adding filename to File from Django 1.10 compatibility 2016-08-05 01:29:53 -03:00
Fabio Caccamo f6ce51c839 Updated README.md 2016-07-12 18:55:01 +02:00
Fabio Caccamo b4b19650f1 Updated version 2016-06-29 16:05:34 +02:00
Fabio Caccamo 3d4f249487 Improved backward compatibility with South 2016-06-29 16:05:13 +02:00
Fabio Caccamo 7c236c6641 Updated version and dependencies version 2016-04-13 17:25:54 +02:00
Fabio Caccamo 91b3809d61 Improved sorl-thumbnail AdminImageMixin widget layout 2016-04-12 18:03:50 +02:00
Fabio Caccamo f918551971 Fixed login logo overflow 2016-04-11 17:53:50 +02:00
Fabio Caccamo 149c95311f Updated README.md 2016-04-11 12:56:09 +02:00
Fabio Caccamo 858f077bd4 Updated README.md 2016-03-01 12:05:06 +01:00
Fabio Caccamo e46daa8f99 Updated README 2016-02-24 10:14:26 +01:00
Fabio Caccamo e3320b2034 Updated LICENSE 2016-02-24 10:12:32 +01:00
Fabio Caccamo 8991863fb1 Updated README 2016-02-24 10:11:54 +01:00
Fabio Caccamo 54f120c9ba Updated version 2016-02-24 10:04:49 +01:00
Fabio Caccamo 816c05bebd Cleaned whitespace 2016-02-24 10:04:35 +01:00
Fabio Caccamo 710370e903 Fixed Django 1.9 support 2016-02-24 10:03:19 +01:00
Fabio Caccamo 10476e5675 Updated version 2016-02-15 16:21:27 +01:00
Fabio Caccamo bb5867460f Added django-flat-theme dependency 2016-02-15 16:21:16 +01:00
Fabio Caccamo 0ed341bdfd Cleaned white-space 2016-02-15 16:20:53 +01:00
Fabio Caccamo dd8a556d79 Fixed list filter selected link color 2016-02-15 16:20:35 +01:00
Fabio Caccamo f1c37feacb Improved fieldsets alignment and links colors 2016-02-15 16:01:28 +01:00
Fabio Caccamo 6b05143bcc Updated README.md 2015-12-03 11:53:47 +01:00
Fabio Caccamo 9f22ce4b70 Updated package description 2015-12-03 11:46:43 +01:00
Fabio Caccamo 12078589aa Updated version 2015-12-03 11:45:37 +01:00
Fabio Caccamo 98d7153b24 Added admin-interface and flat-theme body classes 2015-12-03 11:44:34 +01:00
Fabio Caccamo d702b0a328 Updated README.md 2015-11-26 11:25:07 +01:00
Fabio Caccamo 8bc899f107 Updated README.md 2015-11-26 11:24:44 +01:00
22 changed files with 3066 additions and 307 deletions
+22
View File
@@ -0,0 +1,22 @@
language: python
python: 3.5
env:
- TOX_ENV=py27-17
- TOX_ENV=py27-18
- TOX_ENV=py27-19
- TOX_ENV=py27-110
- TOX_ENV=py34-17
- TOX_ENV=py34-18
- TOX_ENV=py34-19
- TOX_ENV=py34-110
- TOX_ENV=py35-18
- TOX_ENV=py35-19
- TOX_ENV=py35-110
#- TOX_ENV=py36-18
#- TOX_ENV=py36-19
#- TOX_ENV=py36-110
install:
- pip install tox
script:
- tox -e $TOX_ENV
sudo: false
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2015 Fabio Caccamo - fabio.caccamo@gmail.com Copyright (c) 2016 Fabio Caccamo - fabio.caccamo@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+26 -38
View File
@@ -1,66 +1,54 @@
#django-admin-interface [![Build Status](https://travis-ci.org/fabiocaccamo/django-admin-interface.svg?branch=master)](https://travis-ci.org/fabiocaccamo/django-admin-interface)
django-admin-interface is a modern **flat admin interface customizable by the admin itself**. [![codecov](https://codecov.io/gh/fabiocaccamo/django-admin-interface/branch/master/graph/badge.svg)](https://codecov.io/gh/fabiocaccamo/django-admin-interface)
[![PyPI version](https://badge.fury.io/py/django-admin-interface.svg)](https://badge.fury.io/py/django-admin-interface)
[![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)
# django-admin-interface
django-admin-interface is a modern **responsive flat admin interface customizable by the admin itself**.
You can use the builtin **django-theme** or create your own and **customize** **title, logo and colors**. You can use the builtin **django-theme** or create your own and **customize** **title, logo and colors**.
##Requirements ## Requirements
- Python 2.6, Python 2.7 - Python 2.7, 3.4, 3.5, 3.6
- Django 1.6.5 through Django 1.8.4 - Django 1.7, 1.8, 1.9, 1.10, 1.11
##Installation ## Installation
- Run `pip install django-admin-interface` - Run `pip install django-admin-interface`
- Add `admin_interface`, `flat` and `colorfield` to `settings.INSTALLED_APPS` **before** `django.contrib.admin` - Add `admin_interface`, `flat_responsive`, `flat` and `colorfield` to `settings.INSTALLED_APPS` **before** `django.contrib.admin`
```python ```python
INSTALLED_APPS = ( INSTALLED_APPS = (
#... #...
'flat', 'admin_interface',
'flat_responsive',
'flat', #if django version < 1.9
'colorfield', 'colorfield',
'admin_interface',
#... #...
'django.contrib.admin', 'django.contrib.admin',
#... #...
) )
``` ```
- Run ``python manage.py migrate admin_interface`` - Run ``python manage.py migrate`` *(add ``--fake-initial`` if you are upgrading from 0.1.0 version)*
- Run ``python manage.py collectstatic`` - Run ``python manage.py collectstatic``
- Restart your application server - Restart your application server
##Screenshots ## Screenshots
######Admin login ###### Admin login
![django-admin-interface_login](https://cloud.githubusercontent.com/assets/1035294/11240233/55c8d4ba-8df1-11e5-9568-00fdc987ede8.gif) ![django-admin-interface_login](https://cloud.githubusercontent.com/assets/1035294/11240233/55c8d4ba-8df1-11e5-9568-00fdc987ede8.gif)
--- ---
######Admin dashboard ###### Admin dashboard
![django-admin-interface_dashboard](https://cloud.githubusercontent.com/assets/1035294/11240239/627c0362-8df1-11e5-81fa-216366a5d8da.gif) ![django-admin-interface_dashboard](https://cloud.githubusercontent.com/assets/1035294/11240239/627c0362-8df1-11e5-81fa-216366a5d8da.gif)
--- ---
######Admin themes management ###### Admin themes management
![django-admin-interface_themes_management](https://cloud.githubusercontent.com/assets/1035294/11240245/6cd1c342-8df1-11e5-928b-f22217474d3d.gif) ![django-admin-interface_themes_management](https://cloud.githubusercontent.com/assets/1035294/11240245/6cd1c342-8df1-11e5-928b-f22217474d3d.gif)
--- ---
######Admin theme customization ###### Admin theme customization
![django-admin-interface_theme_customization](https://cloud.githubusercontent.com/assets/1035294/11240250/7350d942-8df1-11e5-9b28-f2f54c333cdc.gif) ![django-admin-interface_theme_customization](https://cloud.githubusercontent.com/assets/1035294/11240250/7350d942-8df1-11e5-9b28-f2f54c333cdc.gif)
####Thanks #### Thanks
- [django-flat-theme](https://github.com/elky/django-flat-theme/) - [django-flat-theme](https://github.com/elky/django-flat-theme/)
- [django-flat-responsive](https://github.com/elky/django-flat-responsive)
- [django-colorfield](https://github.com/jaredly/django-colorfield/) - [django-colorfield](https://github.com/jaredly/django-colorfield/)
##License ## License
The MIT License (MIT) Released under [MIT License](LICENSE).
Copyright (c) 2015 Fabio Caccamo - fabio.caccamo@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+9 -5
View File
@@ -6,10 +6,10 @@ from admin_interface.models import Theme
class ThemeAdmin(admin.ModelAdmin): class ThemeAdmin(admin.ModelAdmin):
list_display = ('name', 'active', ) list_display = ('name', 'active', )
list_editable = ('active', ) list_editable = ('active', )
fieldsets = ( fieldsets = (
(None, { (None, {
'classes': ('wide', ), 'classes': ('wide', ),
@@ -43,13 +43,17 @@ class ThemeAdmin(admin.ModelAdmin):
'classes': ('wide', ), 'classes': ('wide', ),
'fields': ('css_delete_button_background_color', 'css_delete_button_background_hover_color', 'css_delete_button_text_color', ) 'fields': ('css_delete_button_background_color', 'css_delete_button_background_hover_color', 'css_delete_button_text_color', )
}), }),
('Extras', { ('Related Modal', {
'classes': ('wide', ),
'fields': ('related_modal_active', 'related_modal_background_color', 'related_modal_background_opacity', 'related_modal_rounded_corners', )
}),
('List Filter', {
'classes': ('wide', ), 'classes': ('wide', ),
'fields': ('list_filter_dropdown', ) 'fields': ('list_filter_dropdown', )
}), }),
) )
save_on_top = True save_on_top = True
admin.site.register(Theme, ThemeAdmin) admin.site.register(Theme, ThemeAdmin)
+5 -7
View File
@@ -3,16 +3,14 @@
from django.apps import AppConfig from django.apps import AppConfig
from django.db.models.signals import post_migrate from django.db.models.signals import post_migrate
from admin_interface.models import Theme
class AdminInterfaceConfig(AppConfig): class AdminInterfaceConfig(AppConfig):
name = 'admin_interface' name = 'admin_interface'
verbose_name = 'Admin Interface' verbose_name = 'Admin Interface'
def ready(self): def ready(self):
from admin_interface.models import Theme
post_migrate.connect(Theme.post_migrate_handler, sender = self) post_migrate.connect(Theme.post_migrate_handler, sender = self)
+1 -1
View File
@@ -1 +1 @@
[{"fields": {"css_save_button_text_color": "#FFFFFF", "css_module_link_hover_color": "#C9F0DD", "css_delete_button_text_color": "#FFFFFF", "list_filter_dropdown": false, "css_save_button_background_hover_color": "#0C3C26", "css_module_rounded_corners": true, "logo": "", "css_module_background_color": "#44B78B", "title": "Django administration", "css_header_link_color": "#FFFFFF", "css_delete_button_background_hover_color": "#A41515", "css": "", "css_module_link_color": "#FFFFFF", "css_module_text_color": "#FFFFFF", "css_generic_link_hover_color": "#156641", "css_save_button_background_color": "#0C4B33", "logo_visible": true, "active": false, "css_header_background_color": "#0C4B33", "name": "Django", "css_generic_link_color": "#0C3C26", "css_delete_button_background_color": "#BA2121", "css_header_text_color": "#44B78B", "css_header_link_hover_color": "#C9F0DD", "css_header_title_color": "#F5DD5D", "title_visible": true}, "model": "admin_interface.theme", "pk": 1}] [{"model": "admin_interface.theme", "pk": 1, "fields": {"name": "Django", "active": true, "title": "Django administration", "title_visible": true, "logo": "", "logo_visible": true, "css_header_background_color": "#0C4B33", "css_header_title_color": "#F5DD5D", "css_header_text_color": "#44B78B", "css_header_link_color": "#FFFFFF", "css_header_link_hover_color": "#C9F0DD", "css_module_background_color": "#44B78B", "css_module_text_color": "#FFFFFF", "css_module_link_color": "#FFFFFF", "css_module_link_hover_color": "#C9F0DD", "css_module_rounded_corners": true, "css_generic_link_color": "#0C3C26", "css_generic_link_hover_color": "#156641", "css_save_button_background_color": "#0C4B33", "css_save_button_background_hover_color": "#0C3C26", "css_save_button_text_color": "#FFFFFF", "css_delete_button_background_color": "#BA2121", "css_delete_button_background_hover_color": "#A41515", "css_delete_button_text_color": "#FFFFFF", "css": "", "related_modal_active": true, "related_modal_background_color": "#000000", "related_modal_background_opacity": 0.2, "related_modal_rounded_corners": true, "list_filter_dropdown": false}}]
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import colorfield.fields
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='theme',
name='list_filter_dropdown',
field=models.BooleanField(default=False, verbose_name=b'use dropdown'),
),
migrations.AddField(
model_name='theme',
name='related_modal_active',
field=models.BooleanField(default=True, verbose_name=b'active'),
),
migrations.AddField(
model_name='theme',
name='related_modal_background_color',
field=colorfield.fields.ColorField(blank=True, default=b'#000000', help_text=b'#000000', max_length=10, verbose_name=b'background color'),
),
migrations.AddField(
model_name='theme',
name='related_modal_background_opacity',
field=models.FloatField(choices=[(0.1, b'10%'), (0.2, b'20%'), (0.3, b'30%'), (0.4, b'40%'), (0.5, b'50%'), (0.6, b'60%'), (0.7, b'70%'), (0.8, b'80%'), (0.9, b'90%')], default=0.2, help_text=b'20%', verbose_name=b'background opacity'),
),
migrations.AddField(
model_name='theme',
name='related_modal_rounded_corners',
field=models.BooleanField(default=True, verbose_name=b'rounded corners'),
),
]
+78 -53
View File
@@ -10,101 +10,126 @@ import os
class Theme(models.Model): class Theme(models.Model):
@staticmethod @staticmethod
def post_migrate_handler(sender, **kwargs): def post_migrate_handler(sender, **kwargs):
Theme.get_or_create_default_theme() Theme.get_active_theme()
@staticmethod @staticmethod
def post_delete_handler(instance, **kwargs): def post_delete_handler(instance, **kwargs):
Theme.get_or_create_default_theme() Theme.get_active_theme()
@staticmethod @staticmethod
def post_save_handler(instance, created, **kwargs): def post_save_handler(instance, created, **kwargs):
instance.set_active(instance.active) Theme.get_active_theme()
Theme.get_or_create_default_theme()
@staticmethod @staticmethod
def get_or_create_default_theme(): def get_active_theme():
obj_active = (True if len(list(Theme.objects.filter(active = True))) == 0 else False) objs_active_qs = Theme.objects.filter( active = True )
obj, obj_created = Theme.objects.get_or_create(pk = '1', defaults = { 'active':obj_active })
#get or create default theme and enforce default logo if deleted
if not obj.logo: default_obj_active = (objs_active_qs.count() == 0)
obj.set_default_logo() default_obj, default_obj_created = Theme.objects.get_or_create(pk = '1', defaults = { 'active':default_obj_active })
if not obj_created and obj_active: if not default_obj_created and default_obj_active:
obj.set_active(True) default_obj.set_active()
return (obj, obj_created, ) if not default_obj.logo:
default_obj.set_default_logo()
obj = objs_active_qs.last()
objs_active_count = objs_active_qs.count()
if objs_active_count > 1:
obj.set_active()
return obj
name = models.CharField( max_length = 50, default = 'Django' ) name = models.CharField( max_length = 50, default = 'Django' )
active = models.BooleanField( default = True ) active = models.BooleanField( default = True )
title = models.CharField( max_length = 50, default = 'Django administration', blank = True ) title = models.CharField( max_length = 50, default = 'Django administration', blank = True )
title_visible = models.BooleanField( default = True, verbose_name = 'visible' ) title_visible = models.BooleanField( default = True, verbose_name = 'visible' )
logo = models.FileField( upload_to = 'admin-interface/logo/', blank = True ) logo = models.FileField( upload_to = 'admin-interface/logo/', blank = True )
logo_visible = models.BooleanField( default = True, verbose_name = 'visible' ) logo_visible = models.BooleanField( default = True, verbose_name = 'visible' )
css_header_background_color = ColorField( blank = True, default = '#0C4B33', help_text = '#0C4B33', verbose_name = 'background color' ) css_header_background_color = ColorField( blank = True, default = '#0C4B33', help_text = '#0C4B33', verbose_name = 'background color' )
css_header_title_color = ColorField( blank = True, default = '#F5DD5D', help_text = '#F5DD5D', verbose_name = 'title color' ) css_header_title_color = ColorField( blank = True, default = '#F5DD5D', help_text = '#F5DD5D', verbose_name = 'title color' )
css_header_text_color = ColorField( blank = True, default = '#44B78B', help_text = '#44B78B', verbose_name = 'text color' ) css_header_text_color = ColorField( blank = True, default = '#44B78B', help_text = '#44B78B', verbose_name = 'text color' )
css_header_link_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'link color' ) css_header_link_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'link color' )
css_header_link_hover_color = ColorField( blank = True, default = '#C9F0DD', help_text = '#C9F0DD', verbose_name = 'link hover color' ) css_header_link_hover_color = ColorField( blank = True, default = '#C9F0DD', help_text = '#C9F0DD', verbose_name = 'link hover color' )
css_module_background_color = ColorField( blank = True, default = '#44B78B', help_text = '#44B78B', verbose_name = 'background color' ) css_module_background_color = ColorField( blank = True, default = '#44B78B', help_text = '#44B78B', verbose_name = 'background color' )
css_module_text_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'text color' ) css_module_text_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'text color' )
css_module_link_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'link color' ) css_module_link_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'link color' )
css_module_link_hover_color = ColorField( blank = True, default = '#C9F0DD', help_text = '#C9F0DD', verbose_name = 'link hover color' ) css_module_link_hover_color = ColorField( blank = True, default = '#C9F0DD', help_text = '#C9F0DD', verbose_name = 'link hover color' )
css_module_rounded_corners = models.BooleanField( default = True, verbose_name = 'rounded corners' ) css_module_rounded_corners = models.BooleanField( default = True, verbose_name = 'rounded corners' )
css_generic_link_color = ColorField( blank = True, default = '#0C3C26', help_text = '#0C3C26', verbose_name = 'link color' ) css_generic_link_color = ColorField( blank = True, default = '#0C3C26', help_text = '#0C3C26', verbose_name = 'link color' )
css_generic_link_hover_color = ColorField( blank = True, default = '#156641', help_text = '#156641', verbose_name = 'link hover color' ) css_generic_link_hover_color = ColorField( blank = True, default = '#156641', help_text = '#156641', verbose_name = 'link hover color' )
css_save_button_background_color = ColorField( blank = True, default = '#0C4B33', help_text = '#0C4B33', verbose_name = 'background color' ) css_save_button_background_color = ColorField( blank = True, default = '#0C4B33', help_text = '#0C4B33', verbose_name = 'background color' )
css_save_button_background_hover_color = ColorField( blank = True, default = '#0C3C26', help_text = '#0C3C26', verbose_name = 'background hover color' ) css_save_button_background_hover_color = ColorField( blank = True, default = '#0C3C26', help_text = '#0C3C26', verbose_name = 'background hover color' )
css_save_button_text_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'text color' ) css_save_button_text_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'text color' )
css_delete_button_background_color = ColorField( blank = True, default = '#BA2121', help_text = '#BA2121', verbose_name = 'background color' ) css_delete_button_background_color = ColorField( blank = True, default = '#BA2121', help_text = '#BA2121', verbose_name = 'background color' )
css_delete_button_background_hover_color = ColorField( blank = True, default = '#A41515', help_text = '#A41515', verbose_name = 'background hover color' ) css_delete_button_background_hover_color = ColorField( blank = True, default = '#A41515', help_text = '#A41515', verbose_name = 'background hover color' )
css_delete_button_text_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'text color' ) css_delete_button_text_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'text color' )
css = models.TextField( blank = True ) css = models.TextField( blank = True )
list_filter_dropdown = models.BooleanField( default = False ) related_modal_active = models.BooleanField( default = True, verbose_name = 'active' )
related_modal_background_color = ColorField( blank = True, default = '#000000', help_text = '#000000', verbose_name = 'background color' )
related_modal_background_opacity_choices = (
def set_active(self, value): (0.1, '10%', ),
(0.2, '20%', ),
if value: (0.3, '30%', ),
Theme.objects.exclude(pk = self.pk).update(active = False) (0.4, '40%', ),
Theme.objects.filter(pk = self.pk).update(active = True) (0.5, '50%', ),
else: (0.6, '60%', ),
Theme.objects.filter(pk = self.pk).update(active = False) (0.7, '70%', ),
(0.8, '80%', ),
(0.9, '90%', ),
)
related_modal_background_opacity = models.FloatField( choices = related_modal_background_opacity_choices, default = 0.2, help_text = '20%', verbose_name = 'background opacity' )
related_modal_rounded_corners = models.BooleanField( default = True, verbose_name = 'rounded corners' )
list_filter_dropdown = models.BooleanField( default = False, verbose_name = 'use dropdown' )
def set_active(self):
Theme.objects.exclude( pk = self.pk ).update( active = False )
if not self.active:
self.active = True
self.save()
def set_default_logo(self): def set_default_logo(self):
logo_path = os.path.normpath(os.path.dirname(__file__) + '/data/logo-django.svg') logo_filename = 'logo-django.svg'
logo_path = os.path.normpath(os.path.dirname(__file__) + '/data/' + logo_filename)
logo_file = open(logo_path) logo_file = open(logo_path)
self.logo = File(logo_file) self.logo = File(logo_file, logo_filename)
self.save() self.save()
logo_file.close() logo_file.close()
class Meta: class Meta:
app_label = 'admin_interface' app_label = 'admin_interface'
verbose_name = 'Theme' verbose_name = 'Theme'
verbose_name_plural = 'Themes' verbose_name_plural = 'Themes'
def __unicode__(self): def __unicode__(self):
return unicode(u'%s' % (self.name, )) return unicode(u'%s' % (self.name, ))
post_delete.connect(Theme.post_delete_handler, sender = Theme) post_delete.connect(Theme.post_delete_handler, sender = Theme)
post_save.connect(Theme.post_save_handler, sender = Theme) post_save.connect(Theme.post_save_handler, sender = Theme)
@@ -0,0 +1,35 @@
/*global opener */
(function() {
'use strict';
var windowRef = window;
var windowName = windowRef.name;
var widgetName = windowName.replace(/^(change|add|delete|lookup)_/, '');
//var windowNames = windowName.split('____');
//var widgetName = windowNames[(windowNames.length - 1)];
//widgetName = widgetName.replace(/^(change|add|delete|lookup)_/, '');
//console.log('dismiss modal and update widget with id: "' + widgetName + '"');
var modalRef = {};
var openerRef = windowRef.opener;
if(!openerRef){
openerRef = windowRef.parent;
modalRef = {
name: openerRef.id_to_windowname(widgetName),
close: function(){
openerRef.dismissRelatedObjectModal();
}
};
}
var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
switch(initData.action){
case 'change':
openerRef.dismissChangeRelatedObjectPopup(modalRef, initData.value, initData.obj, initData.new_value);
break;
case 'delete':
openerRef.dismissDeleteRelatedObjectPopup(modalRef, initData.value);
break;
default:
openerRef.dismissAddRelatedObjectPopup(modalRef, initData.value, initData.obj);
break;
}
})();
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,351 @@
/* Magnific Popup CSS */
.mfp-bg {
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1042;
overflow: hidden;
position: fixed;
background: #0b0b0b;
opacity: 0.8; }
.mfp-wrap {
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1043;
position: fixed;
outline: none !important;
-webkit-backface-visibility: hidden; }
.mfp-container {
text-align: center;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
padding: 0 8px;
box-sizing: border-box; }
.mfp-container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle; }
.mfp-align-top .mfp-container:before {
display: none; }
.mfp-content {
position: relative;
display: inline-block;
vertical-align: middle;
margin: 0 auto;
text-align: left;
z-index: 1045; }
.mfp-inline-holder .mfp-content,
.mfp-ajax-holder .mfp-content {
width: 100%;
cursor: auto; }
.mfp-ajax-cur {
cursor: progress; }
.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
cursor: -moz-zoom-out;
cursor: -webkit-zoom-out;
cursor: zoom-out; }
.mfp-zoom {
cursor: pointer;
cursor: -webkit-zoom-in;
cursor: -moz-zoom-in;
cursor: zoom-in; }
.mfp-auto-cursor .mfp-content {
cursor: auto; }
.mfp-close,
.mfp-arrow,
.mfp-preloader,
.mfp-counter {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none; }
.mfp-loading.mfp-figure {
display: none; }
.mfp-hide {
display: none !important; }
.mfp-preloader {
color: #CCC;
position: absolute;
top: 50%;
width: auto;
text-align: center;
margin-top: -0.8em;
left: 8px;
right: 8px;
z-index: 1044; }
.mfp-preloader a {
color: #CCC; }
.mfp-preloader a:hover {
color: #FFF; }
.mfp-s-ready .mfp-preloader {
display: none; }
.mfp-s-error .mfp-content {
display: none; }
button.mfp-close,
button.mfp-arrow {
overflow: visible;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
display: block;
outline: none;
padding: 0;
z-index: 1046;
box-shadow: none;
touch-action: manipulation; }
button::-moz-focus-inner {
padding: 0;
border: 0; }
.mfp-close {
width: 44px;
height: 44px;
line-height: 44px;
position: absolute;
right: 0;
top: 0;
text-decoration: none;
text-align: center;
opacity: 0.65;
padding: 0 0 18px 10px;
color: #FFF;
font-style: normal;
font-size: 28px;
font-family: Arial, Baskerville, monospace; }
.mfp-close:hover,
.mfp-close:focus {
opacity: 1; }
.mfp-close:active {
top: 1px; }
.mfp-close-btn-in .mfp-close {
color: #333; }
.mfp-image-holder .mfp-close,
.mfp-iframe-holder .mfp-close {
color: #FFF;
right: -6px;
text-align: right;
padding-right: 6px;
width: 100%; }
.mfp-counter {
position: absolute;
top: 0;
right: 0;
color: #CCC;
font-size: 12px;
line-height: 18px;
white-space: nowrap; }
.mfp-arrow {
position: absolute;
opacity: 0.65;
margin: 0;
top: 50%;
margin-top: -55px;
padding: 0;
width: 90px;
height: 110px;
-webkit-tap-highlight-color: transparent; }
.mfp-arrow:active {
margin-top: -54px; }
.mfp-arrow:hover,
.mfp-arrow:focus {
opacity: 1; }
.mfp-arrow:before,
.mfp-arrow:after {
content: '';
display: block;
width: 0;
height: 0;
position: absolute;
left: 0;
top: 0;
margin-top: 35px;
margin-left: 35px;
border: medium inset transparent; }
.mfp-arrow:after {
border-top-width: 13px;
border-bottom-width: 13px;
top: 8px; }
.mfp-arrow:before {
border-top-width: 21px;
border-bottom-width: 21px;
opacity: 0.7; }
.mfp-arrow-left {
left: 0; }
.mfp-arrow-left:after {
border-right: 17px solid #FFF;
margin-left: 31px; }
.mfp-arrow-left:before {
margin-left: 25px;
border-right: 27px solid #3F3F3F; }
.mfp-arrow-right {
right: 0; }
.mfp-arrow-right:after {
border-left: 17px solid #FFF;
margin-left: 39px; }
.mfp-arrow-right:before {
border-left: 27px solid #3F3F3F; }
.mfp-iframe-holder {
padding-top: 40px;
padding-bottom: 40px; }
.mfp-iframe-holder .mfp-content {
line-height: 0;
width: 100%;
max-width: 900px; }
.mfp-iframe-holder .mfp-close {
top: -40px; }
.mfp-iframe-scaler {
width: 100%;
height: 0;
overflow: hidden;
padding-top: 56.25%; }
.mfp-iframe-scaler iframe {
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
background: #000; }
/* Main image in popup */
img.mfp-img {
width: auto;
max-width: 100%;
height: auto;
display: block;
line-height: 0;
box-sizing: border-box;
padding: 40px 0 40px;
margin: 0 auto; }
/* The shadow behind the image */
.mfp-figure {
line-height: 0; }
.mfp-figure:after {
content: '';
position: absolute;
left: 0;
top: 40px;
bottom: 40px;
display: block;
right: 0;
width: auto;
height: auto;
z-index: -1;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
background: #444; }
.mfp-figure small {
color: #BDBDBD;
display: block;
font-size: 12px;
line-height: 14px; }
.mfp-figure figure {
margin: 0; }
.mfp-bottom-bar {
margin-top: -36px;
position: absolute;
top: 100%;
left: 0;
width: 100%;
cursor: auto; }
.mfp-title {
text-align: left;
line-height: 18px;
color: #F3F3F3;
word-wrap: break-word;
padding-right: 36px; }
.mfp-image-holder .mfp-content {
max-width: 100%; }
.mfp-gallery .mfp-image-holder .mfp-figure {
cursor: pointer; }
@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) {
/**
* Remove all paddings around the image on small screen
*/
.mfp-img-mobile .mfp-image-holder {
padding-left: 0;
padding-right: 0; }
.mfp-img-mobile img.mfp-img {
padding: 0; }
.mfp-img-mobile .mfp-figure:after {
top: 0;
bottom: 0; }
.mfp-img-mobile .mfp-figure small {
display: inline;
margin-left: 5px; }
.mfp-img-mobile .mfp-bottom-bar {
background: rgba(0, 0, 0, 0.6);
bottom: 0;
margin: 0;
top: auto;
padding: 3px 5px;
position: fixed;
box-sizing: border-box; }
.mfp-img-mobile .mfp-bottom-bar:empty {
padding: 0; }
.mfp-img-mobile .mfp-counter {
right: 5px;
top: 3px; }
.mfp-img-mobile .mfp-close {
top: 0;
right: 0;
width: 35px;
height: 35px;
line-height: 35px;
background: rgba(0, 0, 0, 0.6);
position: fixed;
text-align: center;
padding: 0; } }
@media all and (max-width: 900px) {
.mfp-arrow {
-webkit-transform: scale(0.75);
transform: scale(0.75); }
.mfp-arrow-left {
-webkit-transform-origin: 0;
transform-origin: 0; }
.mfp-arrow-right {
-webkit-transform-origin: 100%;
transform-origin: 100%; }
.mfp-container {
padding-left: 6px;
padding-right: 6px; } }
@@ -0,0 +1,69 @@
if(typeof django !== 'undefined' && typeof django.jQuery !== 'undefined' )
{
(function($) {
$(document).ready(function(){
// create the function that will close the modal
function dismissRelatedObjectModal()
{
// close the popup
$.magnificPopup.close();
}
// assign the function to a global variable
window.dismissRelatedObjectModal = dismissRelatedObjectModal;
// listen click events on related links
// (:link prevents to listen click event if href is not defined)
$('a.related-widget-wrapper-link:link').click(function(e){
e.preventDefault();
// remove focus from clicked link
$(this).blur();
// use the clicked link id as iframe name
// it will be available as window.name in the loaded iframe
var iframeName = $(this).attr('id');
//var iframeName = String(window.name + '____' + $(this).attr('id'));
//console.log('open modal with name: "' + iframeName + '"');
// browsers stop loading nested iframes having the same src url
// create a random parameter and append it to the src url to prevent it
var iframeSrcRandom = String(Math.round(Math.random() * 999999));
var iframeSrc = $(this).attr('href') + '&_modal=' + iframeSrcRandom;
// build the iframe html
//var iframeHTML = '<iframe id="related-modal" name="' + iframeName + '" src="' + iframeSrc + '"></iframe>';
var iframeHTML = '<iframe id="related-modal-iframe" name="' + iframeName + '" src="' + iframeSrc + '"></iframe>';
// create the iframe jquery element
var iframeEl = $(iframeHTML);
// the modal css class
var iframeInternalModalClass = 'related-modal';
// if the current window is inside an iframe, it means that it is already in a modal,
// append an additional css class to the modal to offer more customization
if( window.top != window.self )
{
iframeInternalModalClass += ' related-modal__nested';
}
// open the popup using magnific popup
$.magnificPopup.open({
mainClass: iframeInternalModalClass,
items: {
src: iframeEl,
type: 'inline'
}
});
return false;
});
});
})(django.jQuery);
}
+348 -173
View File
@@ -1,419 +1,532 @@
{% extends "admin/base.html" %} {% extends "admin/base.html" %}
{% load i18n staticfiles admin_interface_tags %} {% load i18n staticfiles admin_interface_tags %}
{% block title %}
{% get_admin_interface_theme as theme %}
{% if theme.title %}{% trans theme.title %}{% else %}{% trans 'Django administration' %}{% endif %}
{% endblock %}
{% block extrastyle %} {% block extrastyle %}
{% get_admin_interface_theme as theme %} {% get_admin_interface_theme as theme %}
<style type="text/css"> <style type="text/css">
{% if theme.active %} #header {
height:auto;
#header { min-height:40px;
height:auto;
min-height:40px;
background:{{ theme.css_header_background_color }}; background:{{ theme.css_header_background_color }};
color:{{ theme.css_header_text_color }}; color:{{ theme.css_header_text_color }};
} }
#header #user-tools a { #header #user-tools a {
color:{{ theme.css_header_link_color }}; color:{{ theme.css_header_link_color }};
} }
#header #user-tools a:hover, #header #user-tools a:hover,
#header #user-tools a:active { #header #user-tools a:active {
color:{{ theme.css_header_link_hover_color }}; color:{{ theme.css_header_link_hover_color }};
border-bottom-color:rgba(255, 255, 255, 0.5); border-bottom-color:rgba(255, 255, 255, 0.5);
} }
#branding h1 img.logo { #branding h1 img.logo {
max-height:100px; max-height:100px;
margin-top:10px; margin-top:10px;
margin-bottom:10px; margin-bottom:10px;
margin-right:15px; margin-right:15px;
} }
#branding h1 { #branding h1 {
color:{{ theme.css_header_title_color }}; color:{{ theme.css_header_title_color }};
} }
#branding h1 img+span { #branding h1 img+span {
white-space:nowrap; white-space:nowrap;
} }
.module h2, .module h2,
.module caption, .module caption,
.module.filtered h2 { .module.filtered h2 {
background:{{ theme.css_module_background_color }}; background:{{ theme.css_module_background_color }};
color:{{ theme.css_module_text_color }}; color:{{ theme.css_module_text_color }};
} }
.module a.section:link, .module a.section:link,
.module a.section:visited { .module a.section:visited {
color:{{ theme.css_module_link_color }}; color:{{ theme.css_module_link_color }};
} }
.module a.section:active, .module a.section:active,
.module a.section:hover { .module a.section:hover {
color:{{ theme.css_module_link_hover_color }}; color:{{ theme.css_module_link_hover_color }};
} }
div.breadcrumbs { div.breadcrumbs {
background:{{ theme.css_module_background_color }}; background:{{ theme.css_module_background_color }};
color:{{ theme.css_module_text_color }}; color:{{ theme.css_module_text_color }};
} }
div.breadcrumbs a { div.breadcrumbs a {
color:{{ theme.css_module_link_color }}; color:{{ theme.css_module_link_color }};
} }
div.breadcrumbs a:hover, div.breadcrumbs a:active,
div.breadcrumbs a:active, div.breadcrumbs a:focus,
fieldset a.collapse-toggle:hover { div.breadcrumbs a:hover {
color:{{ theme.css_module_link_hover_color }} !important; color:{{ theme.css_module_link_hover_color }} !important;
} }
fieldset.collapsed a.collapse-toggle { fieldset.collapse {
color:{{ theme.css_module_background_color }} !important; border: 1px solid transparent;
} }
.inline-group h2, fieldset.collapse.collapsed a.collapse-toggle {
color:{{ theme.css_generic_link_color }} !important;
font-weight: bold;
text-transform: lowercase;
}
fieldset.collapse.collapsed a.collapse-toggle:hover,
fieldset.collapse.collapsed a.collapse-toggle:active {
color:{{ theme.css_generic_link_hover_color }} !important;
}
fieldset.collapse a.collapse-toggle {
color:{{ theme.css_module_link_color }} !important;
font-weight: bold;
text-transform: lowercase;
}
fieldset.collapse a.collapse-toggle:hover,
fieldset.collapse a.collapse-toggle:active {
color:{{ theme.css_module_link_hover_color }} !important;
}
.inline-group h2 { .inline-group h2 {
background:{{ theme.css_module_background_color }}; background:{{ theme.css_module_background_color }};
color:{{ theme.css_module_text_color }}; color:{{ theme.css_module_text_color }};
} }
.selector-chosen h2 { .selector-chosen h2 {
background:{{ theme.css_module_background_color }} !important; background:{{ theme.css_module_background_color }} !important;
color:{{ theme.css_module_text_color }} !important; color:{{ theme.css_module_text_color }} !important;
} }
a:link, a:visited { a:link, a:visited {
color:{{ theme.css_generic_link_color }}; color:{{ theme.css_generic_link_color }};
} }
a:hover { a:hover {
color:{{ theme.css_generic_link_hover_color }}; color:{{ theme.css_generic_link_hover_color }};
} }
.button, input[type=submit], input[type=button], .submit-row input, a.button { .button, input[type=submit], input[type=button], .submit-row input, a.button {
background:{{ theme.css_save_button_background_color }}; background:{{ theme.css_save_button_background_color }};
color:{{ theme.css_save_button_text_color }}; color:{{ theme.css_save_button_text_color }};
} }
.button:active, input[type=submit]:active, input[type=button]:active, .button:active, input[type=submit]:active, input[type=button]:active,
.button:focus, input[type=submit]:focus, input[type=button]:focus,
.button:hover, input[type=submit]:hover, input[type=button]:hover { .button:hover, input[type=submit]:hover, input[type=button]:hover {
background:{{ theme.css_save_button_background_hover_color }}; background:{{ theme.css_save_button_background_hover_color }};
color:{{ theme.css_save_button_text_color }}; color:{{ theme.css_save_button_text_color }};
outline: none;
} }
.button.default, input[type=submit].default, .submit-row input.default { .button.default, input[type=submit].default, .submit-row input.default {
background:{{ theme.css_save_button_background_color }}; background:{{ theme.css_save_button_background_color }};
color:{{ theme.css_save_button_text_color }}; color:{{ theme.css_save_button_text_color }};
outline: none;
} }
.button.default:active, input[type=submit].default:active, .button.default:active, input[type=submit].default:active,
.button.default:focus, input[type=submit].default:focus,
.button.default:hover, input[type=submit].default:hover { .button.default:hover, input[type=submit].default:hover {
background:{{ theme.css_save_button_background_hover_color }}; background:{{ theme.css_save_button_background_hover_color }};
color:{{ theme.css_save_button_text_color }}; color:{{ theme.css_save_button_text_color }};
outline: none;
} }
.submit-row a.deletelink:link, .submit-row a.deletelink:link,
.submit-row a.deletelink:visited { .submit-row a.deletelink:visited {
background:{{ theme.css_delete_button_background_color }}; background:{{ theme.css_delete_button_background_color }};
color:{{ theme.css_delete_button_text_color }}; color:{{ theme.css_delete_button_text_color }};
} }
.submit-row a.deletelink:hover { .submit-row a.deletelink:hover {
background:{{ theme.css_delete_button_background_hover_color }} !important; background:{{ theme.css_delete_button_background_hover_color }} !important;
color:{{ theme.css_delete_button_text_color }}; color:{{ theme.css_delete_button_text_color }};
} }
/* /*
#changelist table tbody tr.selected { #changelist table tbody tr.selected {
background-color:#FFFFCC; background-color:#FFFFCC;
} }
*/ */
#changelist .paginator { #changelist .paginator {
margin-top:-1px !important; /* merge 2 borders into 1 */ margin-top:-1px !important; /* merge 2 borders into 1 */
line-height:42px; line-height:42px;
} }
.paginator a, .paginator a,
.paginator a:link, .paginator a:link,
.paginator a:visited, .paginator a:visited,
.paginator .this-page { .paginator .this-page {
padding:7px 12px !important; padding:7px 12px !important;
{% if theme.css_module_rounded_corners %}border-radius:4px;{% endif %} {% if theme.css_module_rounded_corners %}border-radius:4px;{% endif %}
} }
.paginator a, .paginator a,
.paginator a:link, .paginator a:link,
.paginator a:visited { .paginator a:visited {
background-color:#ffffff !important; background-color:#ffffff !important;
color:{{ theme.css_generic_link_color }} !important; color:{{ theme.css_generic_link_color }} !important;
} }
.paginator a:hover, .paginator a:hover,
.paginator a:active { .paginator a:active {
background-color:#f8f8f8 !important; background-color:#f8f8f8 !important;
color:{{ theme.css_generic_link_hover_color }} !important; color:{{ theme.css_generic_link_hover_color }} !important;
} }
.paginator .this-page { .paginator .this-page {
background-color:{{ theme.css_module_background_color }} !important; background-color:{{ theme.css_module_background_color }} !important;
color:{{ theme.css_module_link_color }} !important; color:{{ theme.css_module_link_color }} !important;
} }
.paginator a, .paginator a,
.paginator .this-page { .paginator .this-page {
margin-left:0px; margin-left:0px;
} }
.paginator .this-page, .paginator .this-page,
.paginator a.end { .paginator a.end {
margin-right:25px; margin-right:25px;
} }
.paginator .this-page + a:not(.showall) { .paginator .this-page + a:not(.showall) {
margin-left:-25px !important; margin-left:-25px !important;
} }
body .paginator a.showall, body .paginator a.showall,
body .paginator a.showall:link, body .paginator a.showall:link,
body .paginator a.showall:visited { body .paginator a.showall:visited {
margin-left:20px; margin-left:20px;
color:{{ theme.css_generic_link_color }} !important; color:{{ theme.css_generic_link_color }} !important;
} }
body .paginator a.showall:hover, body .paginator a.showall:hover,
body .paginator a.showall:active { body .paginator a.showall:active {
color:{{ theme.css_generic_link_hover_color }} !important; color:{{ theme.css_generic_link_hover_color }} !important;
} }
/* OTHER FIXES */ /* OTHER FIXES */
/* reduced width */ /* reduced width */
.login #container { .login #container {
width:320px !important; width:320px !important;
min-width:320px !important; min-width:320px !important;
} }
.login #content {
padding:10px 30px 10px 30px !important;
}
/* same lateral padding as in logged view */ /* same lateral padding as in logged view */
.login #header { .login #header {
padding:10px 25px !important; padding:15px 30px !important;
} }
.login #branding h1 {
margin-right:0;
}
.login #branding h1 img.logo {
max-width:100%;
margin-right:0;
}
/* login button right aligned */ /* login button right aligned */
.login #header #branding h1 img+span { .login #header #branding h1 img+span {
display:block; display:block;
} }
/* login button right aligned */ /* login button right aligned */
.login .submit-row { .login .submit-row {
padding-left:0 !important; padding-left:0 !important;
text-align:right !important; text-align:right !important;
} }
/* top-right buttons color on hover -> just a lighten grey */ /* top-right buttons color on hover -> just a lighten grey */
.object-tools a:hover, .object-tools a:focus,
.object-tools a:hover,
.object-tools li:focus a,
.object-tools li:hover a { .object-tools li:hover a {
background-color:#AAAAAA; background-color:#AAAAAA;
} }
/* fix help text icon on newline */ /* fix help text icon on newline */
.inline-group thead th { .inline-group thead th {
white-space:nowrap; white-space:nowrap;
} }
.inline-group thead th img { .inline-group thead th img {
vertical-align: -2px; vertical-align: -2px;
margin-left: 5px; margin-left: 5px;
} }
form .form-row p.file-upload > a { form .form-row p.file-upload > a {
margin-right:10px; margin-right:10px;
} }
form .form-row p.file-upload .clearable-file-input { form .form-row p.file-upload .clearable-file-input {
display:inline-block; display:inline-block;
} }
form .wide p.help { form .wide p.help {
padding-left:10px !important; padding-left:10px !important;
} }
form .aligned.wide p.help,
form .aligned.wide ul.error-list,
form .aligned.wide ul.errorlist {
margin-left: 200px;
}
form .aligned.wide div.help {
margin-left: 210px;
}
textarea.tinymce ~ p.help { textarea.tinymce ~ p.help {
margin-top:5px !important; margin-top:5px !important;
} }
.aligned p.file-upload { .aligned p.file-upload {
display:table; display:table;
} }
/* fix lateral padding to align text with field labels */ /* begin fix issue #13 - Datetime widget broken in long inlines */
.module h2, p.datetime {
.dashboard .module caption, white-space:nowrap;
.inline-group h2,
.module.filtered h2,
.inline-group h2 {
padding:8px 10px;
{% if theme.css_module_rounded_corners %}border-radius:4px;{% endif %}
} }
/* end fix */
/* begin fix lateral padding to align text with field labels */
.module h2,
.dashboard .module caption,
.module.filtered h2,
.inline-group h2 {
padding-left:10px;
padding-right:10px;
}
/* end fix */
/* begin fix issue #11 - Inline border bottom should not be rounded */
.module h2,
.dashboard .module caption,
.module.filtered h2 {
{% if theme.css_module_rounded_corners %}
border-radius:4px;
{% endif %}
}
.inline-group h2 {
{% if theme.css_module_rounded_corners %}
border-bottom-left-radius:0;
border-bottom-right-radius:0;
{% endif %}
}
/* end fix */
.module.filtered h2 { .module.filtered h2 {
border-bottom-left-radius:0; border-bottom-left-radius:0;
border-bottom-right-radius:0; border-bottom-right-radius:0;
} }
.module.filtered #changelist-filter { .module.filtered #changelist-filter {
border-bottom-left-radius:4px; border-bottom-left-radius:4px;
border-bottom-right-radius:4px; border-bottom-right-radius:4px;
} }
.module.filtered #changelist-filter h2 {
font-size: 11px;
padding: 10px 15px;
}
.module.filtered #changelist-filter select { .module.filtered #changelist-filter select {
background-color:#ffffff; background-color:#ffffff;
} }
#content-related { .module.filtered #changelist-filter li.selected a,
{% if theme.css_module_rounded_corners %}border-radius:4px;{% endif %} .module.filtered #changelist-filter li.selected a:hover {
color: {{ theme.css_generic_link_color }};
} }
#content-related {
{% if theme.css_module_rounded_corners %}
border-radius:4px;
{% endif %}
}
/* selector chooseall / clearall color on hover -> just a lighten grey */ /* selector chooseall / clearall color on hover -> just a lighten grey */
a.selector-chooseall:hover, a.selector-clearall:hover { a.selector-chooseall:hover, a.selector-clearall:hover {
color:#888888 !important; color:#888888 !important;
} }
.inline-group {
overflow-x:auto;
}
/* begin fix issue #10 - Related widget broken in long tabular inline */
.inline-group .tabular .related-widget-wrapper {
white-space:nowrap;
}
/* end fix */
.inline-related h3 { .inline-related h3 {
padding:6px 10px !important; padding:6px 10px !important;
} }
/*
.inline-group .tabular thead th:last-child:not([class]):not([style]) {
text-align:center;
}
*/
/*.inline-group .tabular tr.has_original td.original, */
.inline-group .tabular tr td.delete {
vertical-align:middle !important;
text-align:center !important;
}
.inline-group .tabular tr td.delete a.inline-deletelink {
float:none;
display:inline-block;
}
/* improve django-modeltranslation support - https://github.com/deschler/django-modeltranslation/pull/313/commits */
/* begin fix issue #12 - Inlines bad delete buttons alignement */
.inline-group .tabular thead th:last-child:not([class]):not([style]) {
text-align:right;
}
.inline-group .tabular tr td.delete {
text-align:right;
padding-right:15px;
}
.inline-group .tabular tr td.delete a.inline-deletelink {
margin-top:2px;
overflow:hidden;
text-indent:9999px;
}
/* end fix */
/*
django-modeltranslation support
https://github.com/deschler/django-modeltranslation/pull/313/commits
*/
#content h1 select { #content h1 select {
text-transform:uppercase; text-transform:uppercase;
margin-left:15px; margin-left:15px;
} }
.ui-tabs .ui-tabs-nav { .ui-tabs .ui-tabs-nav {
padding:10px 0 0 10px !important; padding:10px 0 0 10px !important;
} }
.ui-tabs .ui-tabs-nav li { .ui-tabs .ui-tabs-nav li {
margin-left:-1px !important; margin-left:-1px !important;
} }
.ui-tabs .ui-tabs-nav li a { .ui-tabs .ui-tabs-nav li a {
outline:none; outline:none;
background-color:#f8f8f8 !important; background-color:#f8f8f8 !important;
border:1px solid #eeeeee !important; border:1px solid #eeeeee !important;
border-bottom:none !important; border-bottom:none !important;
text-transform:uppercase; text-transform:uppercase;
padding:7px 14px 8px 14px !important; padding:7px 14px 8px 14px !important;
margin-top:1px !important; margin-top:1px !important;
} }
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a { .ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
padding:8px 14px 8px 14px !important; padding:8px 14px 8px 14px !important;
margin-top:0px !important; margin-top:0px !important;
margin-bottom:-1px !important; margin-bottom:-1px !important;
background-color:#FFFFFF !important; background-color:#FFFFFF !important;
color:{{ theme.css_module_background_color }} !important; color:{{ theme.css_module_background_color }} !important;
border-bottom:1px solid #FFFFFF !important; border-bottom:1px solid #FFFFFF !important;
} }
.inline-group .tabular .ui-tabs .ui-tabs-panel { .inline-group .tabular .ui-tabs .ui-tabs-panel {
padding:8px !important; padding:8px !important;
} }
#changelist .row1:not(.selected):hover, #changelist .row1:not(.selected):hover,
#changelist .row2:not(.selected):hover { #changelist .row2:not(.selected):hover {
background:#f9f9f9; background:#f9f9f9;
} }
.row2 { .row2 {
background:#fcfcfc; background:#fcfcfc;
} }
.row2 .ui-tabs .ui-tabs-nav li a { .row2 .ui-tabs .ui-tabs-nav li a {
background-color:#f5f5f5 !important; background-color:#f5f5f5 !important;
border:1px solid #ebebeb !important; border:1px solid #ebebeb !important;
} }
.row2 .ui-tabs .ui-tabs-nav li.ui-tabs-active a, .row2 .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
.row2 .ui-tabs .ui-tabs-nav li.ui-tabs-selected a { .row2 .ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
background-color:#fcfcfc !important; background-color:#fcfcfc !important;
border-bottom:1px solid #fcfcfc !important; border-bottom:1px solid #fcfcfc !important;
} }
/*
list-filter-dropdown
*/
.list-filter-dropdown { .list-filter-dropdown {
margin-top:10px; margin-top:10px;
margin-bottom:20px; margin-bottom:20px;
} }
.list-filter-dropdown select { .list-filter-dropdown select {
width:90%; width:90%;
margin-right:5%; margin-right:5%;
} }
/* ckeditor + light theme - https://github.com/Ikimea/ckeditor-light-theme */ /*
sorl-thumbnail - improved AdminImageMixin widget layout
https://github.com/mariocesar/sorl-thumbnail
*/
a.thumbnail + input[type="checkbox"] {
margin:10px 0;
}
/*
ckeditor + light theme
https://github.com/Ikimea/ckeditor-light-theme
*/
.cke_inner, .cke_wysiwyg_frame { .cke_inner, .cke_wysiwyg_frame {
border-top-left-radius: 4px !important; border-top-left-radius: 4px !important;
border-top-right-radius: 4px !important; border-top-right-radius: 4px !important;
border-bottom-left-radius: 4px !important; border-bottom-left-radius: 4px !important;
border-bottom-right-radius: 4px !important; border-bottom-right-radius: 4px !important;
} }
.cke_top { .cke_top {
background: #f6f6f6 !important; background: #f6f6f6 !important;
border-top: none; border-top: none;
border-top-left-radius: 4px !important; border-top-left-radius: 4px !important;
border-top-right-radius: 4px !important; border-top-right-radius: 4px !important;
-moz-box-shadow: none !important; -moz-box-shadow: none !important;
-webkit-box-shadow: none !important; -webkit-box-shadow: none !important;
box-shadow: none !important; box-shadow: none !important;
} }
.cke_bottom { .cke_bottom {
background: #f6f6f6 !important; background: #f6f6f6 !important;
border-top: 1px solid #efefef !important; border-top: 1px solid #efefef !important;
border-bottom-left-radius: 4px !important; border-bottom-left-radius: 4px !important;
border-bottom-right-radius: 4px !important; border-bottom-right-radius: 4px !important;
} }
.cke_source { .cke_source {
padding: 13px 15px !important; padding: 13px 15px !important;
box-sizing: border-box !important; box-sizing: border-box !important;
} }
a.cke_button_on { a.cke_button_on {
-moz-box-shadow: none !important; -moz-box-shadow: none !important;
-webkit-box-shadow: none !important; -webkit-box-shadow: none !important;
@@ -421,44 +534,106 @@
background-color: rgba(0,0,0,0.1) !important; background-color: rgba(0,0,0,0.1) !important;
border-radius: 4px !important; border-radius: 4px !important;
} }
.cke_resizer { .cke_resizer {
border-color: transparent #999 transparent transparent !important; border-color: transparent #999 transparent transparent !important;
} }
/*
related modal + magnific popup customization
https://github.com/dimsemenov/Magnific-Popup
*/
.related-modal.mfp-bg {
background-color:{{ theme.related_modal_background_color }} !important;
opacity: {{ theme.related_modal_background_opacity }} !important;
}
.related-modal .mfp-content {
height: 100% !important;
overflow: hidden;
{% if theme.related_modal_rounded_corners %}
border-radius: 4px;
{% endif %}
-webkit-box-shadow: 0px 5px 30px 0px rgba(0,0,0,0.2);
-moz-box-shadow: 0px 5px 30px 0px rgba(0,0,0,0.2);
box-shadow: 0px 5px 30px 0px rgba(0,0,0,0.2);
}
.related-modal .mfp-container {
padding: 90px 90px 90px 90px !important;
}
.related-modal__nested .mfp-container {
padding: 30px 60px 30px 60px !important;
}
@media (max-width:640px){
.related-modal .mfp-container {
padding: 60px 15px 60px 15px !important;
}
.related-modal__nested .mfp-container {
padding: 30px 30px 30px 30px !important;
}
}
.related-modal #related-modal-iframe {
width: 100%;
height: 100%;
background-color: #FFFFFF;
background-repeat: no-repeat;
background-position: center center;
background-size: 30px 30px;
background-image: url("data:image/svg+xml;utf8,<?xml version='1.0' encoding='utf-8'?><svg width='30px' height='30px' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid' class='uil-ring-alt'><rect x='0' y='0' width='100' height='100' fill='none' class='bk'></rect><circle cx='50' cy='50' r='40' stroke='#eeeeee' fill='none' stroke-width='6' stroke-linecap='round'></circle><circle cx='50' cy='50' r='40' stroke='#aaaaaa' fill='none' stroke-width='6' stroke-linecap='round'><animate attributeName='stroke-dashoffset' dur='2s' repeatCount='indefinite' from='0' to='500'></animate><animate attributeName='stroke-dasharray' dur='2s' repeatCount='indefinite' values='150 100;1 250;150 100'></animate></circle></svg>");
border: none;
margin: 0 auto;
padding: 0;
display: block;
}
{% if theme.css %} {% if theme.css %}
{{ theme.css|safe }} {{ theme.css|safe }}
{% endif %} {% endif %}
{% else %}
#branding h1 img.logo {
display:none;
}
{% endif %}
</style> </style>
{% endblock %} {% endblock %}
{% block extrahead %} {% block extrahead %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/responsive.css" %}" />
{% get_admin_interface_theme as theme %}
{% if theme.related_modal_active %}
<link rel="stylesheet" type="text/css" href="{% static "admin_interface/magnific-popup/magnific-popup.css" %}" />
{% endif %}
{% endblock %} {% endblock %}
{% block branding %} {% block branding %}
{% get_admin_interface_theme as theme %} {% get_admin_interface_theme as theme %}
<h1 id="site-name"> <h1 id="site-name">
{% if theme.active %} {% if theme.logo_visible and theme.logo %}
{% if theme.logo_visible and theme.logo %} <img class="logo" src="{{ theme.logo.url }}" width="{{ theme.logo.width }}" height="{{ theme.logo.height }}" />
<img class="logo" src="{{ theme.logo.url }}" width="{{ theme.logo.width }}" height="{{ theme.logo.height }}" /> {% endif %}
{% endif %} {% if theme.title_visible %}
{% if theme.title_visible %} <span>{% if theme.title %}{% trans theme.title %}{% else %}{% trans 'Django administration' %}{% endif %}</span>
<span>{% if theme.title %}{% trans theme.title %}{% else %}{% trans 'Django administration' %}{% endif %}</span>
{% endif %}
{% else %}
{% trans 'Django administration' %}
{% endif %} {% endif %}
</h1> </h1>
{% endblock %} {% endblock %}
{% block bodyclass %}admin-interface flat-theme{% endblock %}
{% block blockbots %}
{{ block.super }}
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
{% endblock %}
{% block sidebar %} {% block sidebar %}
{% endblock %} {% endblock %}
{% block footer %}
{{ block.super }}
{% get_admin_interface_theme as theme %}
{% if theme.related_modal_active %}
<script type="text/javascript" src="{% static "admin_interface/magnific-popup/jquery.magnific-popup.js" %}"></script>
<script type="text/javascript" src="{% static "admin_interface/related-modal/related-modal.js" %}"></script>
{% endif %}
{% endblock %}
+4 -8
View File
@@ -5,15 +5,11 @@
{% if theme.list_filter_dropdown %} {% if theme.list_filter_dropdown %}
{% include "admin_interface/dropdown_filter.html" %} {% include "admin_interface/dropdown_filter.html" %}
{% else %} {% else %}
{% comment %} {# Use the default list filter template -> https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/filter.html #}
Use the default list filter template -> https://github.com/django/django/blob/master/django/contrib/admin/templates/admin/filter.html
{% endcomment %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3> <h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
<ul> <ul>
{% for choice in choices %} {% for choice in choices %}
@@ -10,16 +10,6 @@ register = template.Library()
@register.assignment_tag(takes_context = True) @register.assignment_tag(takes_context = True)
def get_admin_interface_theme(context): def get_admin_interface_theme(context):
obj_qs = Theme.objects.filter(active = True)[:1] return Theme.get_active_theme()
obj_ls = list(obj_qs)
obj = None
if len(obj_ls):
obj = obj_ls[0]
else:
obj = Theme.get_or_create_default_theme()
return obj
+1 -1
View File
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
__version__ = '0.1.1' __version__ = '0.4.0'
Executable
+21
View File
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
import os
import sys
import django
from django.conf import settings
from django.test.utils import get_runner
def runtests():
os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings'
django.setup()
TestRunner = get_runner(settings)
test_runner = TestRunner()
failures = test_runner.run_tests(['tests'])
sys.exit(bool(failures))
if __name__ == '__main__':
runtests()
+31 -7
View File
@@ -1,24 +1,48 @@
#!/usr/bin/env python #!/usr/bin/env python
from setuptools import find_packages, setup from setuptools import find_packages, setup
exec(open('admin_interface/version.py').read()) exec(open('admin_interface/version.py').read())
setup( setup(
name='django-admin-interface', name='django-admin-interface',
packages=find_packages(), packages=find_packages(exclude=['contrib', 'docs', 'tests*']),
include_package_data=True, include_package_data=True,
license='MIT License',
version=__version__, version=__version__,
description='django-admin-interface is a modern admin interface customizable by the admin itself.', description='django-admin-interface is a modern responsive flat admin interface customizable by the admin itself.',
author='Fabio Caccamo', author='Fabio Caccamo',
author_email='fabio.caccamo@gmail.com', author_email='fabio.caccamo@gmail.com',
url='https://github.com/fabiocaccamo/django-admin-interface', url='https://github.com/fabiocaccamo/django-admin-interface',
download_url='https://github.com/fabiocaccamo/django-admin-interface/archive/%s.tar.gz' % __version__, download_url='https://github.com/fabiocaccamo/django-admin-interface/archive/%s.tar.gz' % __version__,
keywords=['django', 'admin', 'interface', 'ui', 'flat', 'theme', 'custom'], keywords=['django', 'admin', 'interface', 'responsive', 'flat', 'theme', 'custom', 'ui'],
requires=['django(>=1.7)'],
install_requires=[ install_requires=[
'django-colorfield==0.1.10' 'django-colorfield==0.1.12',
'django-flat-theme==1.1.4',
'django-flat-responsive==1.3.0'
], ],
classifiers=[] classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 1.7',
'Framework :: Django :: 1.8',
'Framework :: Django :: 1.9',
'Framework :: Django :: 1.10',
'Framework :: Django :: 1.11',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Software Development :: Build Tools',
],
license='MIT',
test_suite='runtests.runtests'
) )
View File
+54
View File
@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
import django
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = 'django-admin-interface'
ALLOWED_HOSTS = ['*']
INSTALLED_APPS = [
'admin_interface',
'flat_responsive',
'flat', #if django version < 1.9
'colorfield',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
]
MIDDLEWARE_CLASSES = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
]
TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
]
},
},]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
MEDIA_ROOT = os.path.join(BASE_DIR, 'admin_interface/public/media/')
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'admin_interface/public/static/')
STATIC_URL = '/static/'
+83
View File
@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
from django.conf import settings
from django.test import TestCase
from django.template import Context, Template
import os
import shutil
from admin_interface.models import Theme
class AdminInterfaceTestCase(TestCase):
def setUp(self):
pass
def tearDown(self):
shutil.rmtree(settings.MEDIA_ROOT, ignore_errors=True)
pass
def __render_template(self, string, context=None):
context = context or {}
context = Context(context)
return Template(string).render(context)
def __test_active_theme(self):
theme = Theme.get_active_theme()
print( theme )
self.assertTrue(theme != None)
self.assertTrue(theme.active)
self.assertEqual(Theme.objects.filter( active = True ).count(), 1);
def test_default_theme_created_if_no_themes(self):
Theme.objects.all().delete()
self.__test_active_theme()
def test_default_theme_created_if_all_themes_deleted(self):
Theme.objects.all().delete()
self.__test_active_theme()
def test_default_theme_activated_on_save_if_no_active_themes(self):
Theme.objects.all().delete()
theme = Theme.get_active_theme()
theme.active = False
theme.save()
self.__test_active_theme()
def test_default_theme_activated_after_update_if_no_active_themes(self):
Theme.objects.all().delete()
Theme.objects.all().update( active = False )
self.__test_active_theme()
def test_default_theme_activated_on_active_theme_deleted(self):
Theme.objects.all().delete()
theme_1 = Theme.objects.create( name = 'Custom 1', active = True )
theme_2 = Theme.objects.create( name = 'Custom 2', active = True )
theme_3 = Theme.objects.create( name = 'Custom 3', active = True )
Theme.objects.filter( pk = Theme.get_active_theme().pk ).delete()
self.assertEqual( Theme.get_active_theme().pk, 1 )
def test_last_theme_activated_on_multiple_themes_created(self):
Theme.objects.all().delete()
theme_1 = Theme.objects.create( name = 'Custom 1', active = True )
theme_2 = Theme.objects.create( name = 'Custom 2', active = True )
theme_3 = Theme.objects.create( name = 'Custom 3', active = True )
self.assertEqual( Theme.get_active_theme().pk, theme_3.pk )
self.__test_active_theme()
def test_templatetags(self):
Theme.objects.all().delete()
rendered = self.__render_template('{% load admin_interface_tags %}{% get_admin_interface_theme as theme %}{{ theme.name }}')
self.assertEqual(rendered, 'Django')
+20
View File
@@ -0,0 +1,20 @@
[tox]
envlist =
py27-{17,18,19,110,111},
py34-{17,18,19,110,111},
py35-{18,19,110,111},
py36-{18,19,110,111},
[testenv]
passenv = CI TRAVIS TRAVIS_*
deps =
17: Django >= 1.7, < 1.8
18: Django >= 1.8, < 1.9
19: Django >= 1.9, < 1.10
110: Django >= 1.10, < 1.11
111: Django >= 1.11, < 1.12
coverage
codecov
commands =
coverage run --append --source=admin_interface setup.py test
coverage report -m
codecov