Compare commits
66 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c4ea399e2 | |||
| a28fe1c5e0 | |||
| c07a846374 | |||
| f0126fb407 | |||
| 869ae626da | |||
| a6bdb2b36d | |||
| aa18e19625 | |||
| a35f8d0fb7 | |||
| d29515c4ae | |||
| 00f60c222d | |||
| ff2d05e44c | |||
| 6e5cbf3a2c | |||
| 55b365b2e4 | |||
| 3203b437df | |||
| 202b5fa4aa | |||
| 9fdc3a0268 | |||
| ded2fee89c | |||
| beec7242c6 | |||
| 7a6a29b110 | |||
| 1f3bb6514c | |||
| b416b46c5a | |||
| 59f1831cbd | |||
| 20050e2964 | |||
| fd292ed1bf | |||
| fac0f690df | |||
| d18aadd93d | |||
| 9350575898 | |||
| 4789ee1dab | |||
| a924c6cf5e | |||
| 42b6e01f1f | |||
| d7fa681c56 | |||
| 18e1425156 | |||
| 1f39ceb0ad | |||
| 48cb73a604 | |||
| c5bbbbc855 | |||
| 793a019460 | |||
| 674178ecbe | |||
| 07a51c1678 | |||
| a58605a385 | |||
| e1d2c81ebe | |||
| e5e55bdfcd | |||
| f6ce51c839 | |||
| b4b19650f1 | |||
| 3d4f249487 | |||
| 7c236c6641 | |||
| 91b3809d61 | |||
| f918551971 | |||
| 149c95311f | |||
| 858f077bd4 | |||
| e46daa8f99 | |||
| e3320b2034 | |||
| 8991863fb1 | |||
| 54f120c9ba | |||
| 816c05bebd | |||
| 710370e903 | |||
| 10476e5675 | |||
| bb5867460f | |||
| 0ed341bdfd | |||
| dd8a556d79 | |||
| f1c37feacb | |||
| 6b05143bcc | |||
| 9f22ce4b70 | |||
| 12078589aa | |||
| 98d7153b24 | |||
| d702b0a328 | |||
| 8bc899f107 |
+22
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -1,66 +1,54 @@
|
|||||||
#django-admin-interface
|
[](https://travis-ci.org/fabiocaccamo/django-admin-interface)
|
||||||
django-admin-interface is a modern **flat admin interface customizable by the admin itself**.
|
[](https://codecov.io/gh/fabiocaccamo/django-admin-interface)
|
||||||
|
[](https://badge.fury.io/py/django-admin-interface)
|
||||||
|
[](https://img.shields.io/pypi/pyversions/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
|
||||||
|
|
||||||
##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
|
||||||

|

|
||||||
---
|
---
|
||||||
######Admin dashboard
|
###### Admin dashboard
|
||||||

|

|
||||||
---
|
---
|
||||||
######Admin themes management
|
###### Admin themes management
|
||||||

|

|
||||||
---
|
---
|
||||||
######Admin theme customization
|
###### Admin theme customization
|
||||||

|

|
||||||
|
|
||||||
####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.
|
|
||||||
|
|||||||
@@ -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', ),
|
||||||
@@ -48,8 +48,8 @@ class ThemeAdmin(admin.ModelAdmin):
|
|||||||
'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)
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+61
-52
@@ -10,101 +10,110 @@ 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 )
|
list_filter_dropdown = models.BooleanField( default = False )
|
||||||
|
|
||||||
|
def set_active(self):
|
||||||
def set_active(self, value):
|
|
||||||
|
Theme.objects.exclude( pk = self.pk ).update( active = False )
|
||||||
if value:
|
|
||||||
Theme.objects.exclude(pk = self.pk).update(active = False)
|
if not self.active:
|
||||||
Theme.objects.filter(pk = self.pk).update(active = True)
|
self.active = True
|
||||||
else:
|
self.save()
|
||||||
Theme.objects.filter(pk = self.pk).update(active = False)
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
|||||||
@@ -1,419 +1,521 @@
|
|||||||
{% 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 %}
|
{% if theme.active %}
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
height:auto;
|
height:auto;
|
||||||
min-height:40px;
|
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 {
|
||||||
|
margin-left: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* begin fix issue #12 - Inlines bad delete buttons alignement */
|
||||||
.inline-group .tabular thead th:last-child:not([class]):not([style]) {
|
.inline-group .tabular thead th:last-child:not([class]):not([style]) {
|
||||||
text-align:center;
|
text-align:right;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/*.inline-group .tabular tr.has_original td.original, */
|
|
||||||
.inline-group .tabular tr td.delete {
|
.inline-group .tabular tr td.delete {
|
||||||
vertical-align:middle !important;
|
text-align:right;
|
||||||
text-align:center !important;
|
padding-right:15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inline-group .tabular tr td.delete a.inline-deletelink {
|
.inline-group .tabular tr td.delete a.inline-deletelink {
|
||||||
float:none;
|
margin-top:2px;
|
||||||
display:inline-block;
|
overflow:hidden;
|
||||||
|
text-indent:9999px;
|
||||||
}
|
}
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
/* improve django-modeltranslation support - https://github.com/deschler/django-modeltranslation/pull/313/commits */
|
/* improve 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 {
|
||||||
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%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* sorl-thumbnail - improved AdminImageMixin widget layout */
|
||||||
|
|
||||||
|
a.thumbnail + input[type="checkbox"] {
|
||||||
|
margin:10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ckeditor + light theme - https://github.com/Ikimea/ckeditor-light-theme */
|
/* 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,21 +523,21 @@
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
{% if theme.css %}
|
{% if theme.css %}
|
||||||
{{ theme.css|safe }}
|
{{ theme.css|safe }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
#branding h1 img.logo {
|
#branding h1 img.logo {
|
||||||
display:none;
|
display:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -460,5 +562,13 @@
|
|||||||
</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">
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static "admin/css/responsive.css" %}" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block sidebar %}
|
{% block sidebar %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -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,4 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
__version__ = '0.1.1'
|
__version__ = '0.3.1'
|
||||||
|
|
||||||
|
|||||||
Executable
+21
@@ -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()
|
||||||
|
|
||||||
@@ -1,24 +1,47 @@
|
|||||||
#!/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',
|
||||||
|
'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'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# -*- 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': {},
|
||||||
|
},]
|
||||||
|
|
||||||
|
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/'
|
||||||
|
|
||||||
@@ -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')
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
[tox]
|
||||||
|
envlist =
|
||||||
|
py27-{17,18,19,110},
|
||||||
|
py34-{17,18,19,110},
|
||||||
|
py35-{18,19,110},
|
||||||
|
py36-{18,19,110},
|
||||||
|
[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
|
||||||
|
coverage
|
||||||
|
codecov
|
||||||
|
commands =
|
||||||
|
coverage run --append --source=admin_interface setup.py test
|
||||||
|
coverage report -m
|
||||||
|
codecov
|
||||||
Reference in New Issue
Block a user