Compare commits

...

117 Commits

Author SHA1 Message Date
Fabio Caccamo cf76fd412e Updated version 2018-10-11 12:11:46 +02:00
Fabio Caccamo ab0afff087 Added automatic check of 3rd party installed apps according to django version. 2018-10-11 12:11:32 +02:00
Fabio Caccamo e3811e2609 Fixed delete modal not dismissed when clicking 'cancel' button. 2018-10-11 12:08:35 +02:00
Fabio Caccamo 47a3d66d5c Enforced django.jQuery usage in popup_response.js 2018-10-11 12:07:02 +02:00
Fabio Caccamo 2700b4ff12 Updated README [ci skip] 2018-10-10 15:51:06 +02:00
Fabio Caccamo 6a1897b95c Updated tests, tox and travis to support django 2.1 and python 3.7. 2018-10-10 15:48:43 +02:00
Fabio Caccamo e5768da21b Fixed tox and travis for django 2.1 testing. 2018-08-31 15:36:42 +02:00
Fabio Caccamo dc8efcbd6b Updated version. 2018-08-31 15:22:06 +02:00
Fabio Caccamo 01c4ad1f06 Added django 2.1 to tox and travis. 2018-08-31 15:21:54 +02:00
Fabio Caccamo 4a848948a0 Added modal to raw_id_fields #37 2018-08-31 15:21:30 +02:00
Fabio Caccamo a96a70400f Cleaned js code [ci skip] 2018-08-31 15:20:21 +02:00
Fabio Caccamo cc0d2a402b Update .gitattributes 2018-06-14 10:27:58 +02:00
Fabio Caccamo 415de9ca66 Update .gitattributes 2018-06-13 16:09:35 +02:00
Fabio Caccamo 7e57885988 Update .gitattributes 2018-06-13 16:04:18 +02:00
Fabio Caccamo 013dcedd37 Delete vendor.yml 2018-06-13 16:03:54 +02:00
Fabio Caccamo b011256370 Update vendor.yml 2018-06-13 15:59:07 +02:00
Fabio Caccamo 752ccbb603 Created vendor.yml 2018-06-13 12:39:14 +02:00
Fabio Caccamo 8612012783 Fixed README license link [ci skip] 2018-03-29 14:57:20 +02:00
Fabio Caccamo f78167b711 Fixed README license link [ci skip] 2018-03-29 14:55:47 +02:00
Fabio Caccamo ef9b7e6d1b Updated travis 2018-03-29 11:45:18 +02:00
Fabio Caccamo 748b95854e Updated tox 2018-03-29 11:38:04 +02:00
Fabio Caccamo 2f10c88375 AddAdded Django 1.11 to .travis 2018-03-07 10:22:20 +01:00
Fabio Caccamo 73c9a54d94 Updated version 2018-02-06 15:31:19 +01:00
Fabio Caccamo eff414b40c Removed old selector fixies 2018-02-06 15:31:09 +01:00
Fabio Caccamo ccbf76dc5a Improved jquery.ui.tabs compatibility 2018-02-06 15:30:29 +01:00
Fabio Caccamo 5b6e83751b Updated README [ci skip] 2018-02-05 12:37:02 +01:00
Fabio Caccamo 572294f646 Updated version 2018-02-05 12:24:54 +01:00
Fabio Caccamo 4e18d36c79 Added django-tabbed-admin style support 2018-02-05 12:24:42 +01:00
Fabio Caccamo ee9994231b Fixed selectors text overflow 2018-02-05 12:23:54 +01:00
Fabio Caccamo fb4cfdb772 Updated version 2018-02-01 14:52:56 +01:00
Fabio Caccamo 8535232598 Merge pull request #32 from founders4schools/django-20-simple-tag
Avoid deprecation warning about assignment_tag
2018-02-01 14:51:08 +01:00
Bruno Alla abbb666eae Avoid deprecation warning about assignment_tag
Even though the try/except is Django 2.0 compatible, it still
accesses the deprecated template tag, and therefore it emits a
warning in the console, whereas it's actually fixed.

I tried to swap the try and the catch, but it doesn't work:
`simple_tag` existed before 1.9 but in a non-compatible form.

I've changed the decorator name we use to match the new Django version,
it should make the codebase more future proof.
2018-02-01 13:35:54 +00:00
Fabio Caccamo d48fc882f1 Updated USWDS fixture [ci skip] 2018-01-31 16:38:08 +01:00
Fabio Caccamo f968bd9ffa Updated README [ci skip] 2018-01-31 16:37:36 +01:00
Fabio Caccamo c0592276de Updated README [ci skip] 2018-01-31 12:36:43 +01:00
Fabio Caccamo 451679d565 Updated version 2018-01-31 12:24:22 +01:00
Fabio Caccamo e579134152 Added enviroment display and customization 2018-01-31 12:24:08 +01:00
Fabio Caccamo 6e57cf558c Updated .gitignore [ci skip] 2018-01-31 12:12:01 +01:00
Fabio Caccamo d00428c30a Tested against django 2.0 2017-12-05 12:14:27 +01:00
Fabio Caccamo 9becccce39 Updated version 2017-11-23 12:10:32 +01:00
Fabio Caccamo 64a9e8371c Updated setup.py 2017-11-23 12:10:19 +01:00
Fabio Caccamo 8a85334f68 Changed related_modal_background_opacity field type from FloatField to CharField 2017-11-23 12:10:06 +01:00
Fabio Caccamo 41a5ba61c8 Fixed migrations pep8 compliance 2017-11-23 12:08:36 +01:00
Fabio Caccamo c780ccfbcf Added Requirements Status badge provided by https://requires.io/ [ci skip] 2017-10-18 15:52:42 +02:00
Fabio Caccamo 6091c886d7 Updated version 2017-10-04 12:10:24 +02:00
Fabio Caccamo d05009ce44 Fixed horizontal and vertical selector style in inlines 2017-10-04 12:09:48 +02:00
Fabio Caccamo ef1eefb084 Fixed ckeditor style in tabular inlines 2017-10-04 12:08:44 +02:00
Fabio Caccamo e57042b1b4 Fixed README.rst badges [ci skip] 2017-09-29 15:26:40 +02:00
Fabio Caccamo 0b0eff8653 Updated version 2017-09-29 15:11:32 +02:00
Fabio Caccamo f6cef18c6b Updated README.rst for pypi 2017-09-29 15:11:18 +02:00
Fabio Caccamo e8522fe3d7 Updated version 2017-09-29 12:25:29 +02:00
Fabio Caccamo fcb8a38e50 Generate long_description in rst (reStructured Text) format on the fly using pandoc. 2017-09-29 12:25:15 +02:00
Fabio Caccamo 6c3a645edd Replaced repeated strings with variables 2017-09-29 12:24:02 +02:00
Fabio Caccamo b9d0ac6dab Updated django-flat-responsive version range. 2017-09-29 12:22:16 +02:00
Fabio Caccamo 3f270b0b75 Removed README.rst 2017-09-29 12:19:43 +02:00
Fabio Caccamo 7bc15ba61e Removed unused context argument 2017-09-29 12:12:44 +02:00
Fabio Caccamo 37bb3ce0df Removed unused arguments and variables 2017-09-29 12:12:01 +02:00
Fabio Caccamo 66b0172195 Removed unused import 2017-09-29 12:11:40 +02:00
Fabio Caccamo ca2f5c549e Fixed inlines style 2017-09-29 12:11:02 +02:00
Fabio Caccamo 21b221f9e9 Removed unused templatetag 2017-09-27 14:58:42 +02:00
Fabio Caccamo 5fcbef3c5b Merge branch 'master' of https://github.com/fabiocaccamo/django-admin-interface 2017-09-27 14:50:41 +02:00
Fabio Caccamo bc9d200461 Added README.rst to MANIFEST.in 2017-09-27 14:47:42 +02:00
Fabio Caccamo 8c903d5f4c Updated version 2017-09-27 14:47:14 +02:00
Fabio Caccamo c253617346 Updated Python code to be PEP8 compliant 2017-09-27 14:47:03 +02:00
Fabio Caccamo ca2b405989 Updated README.rst 2017-09-27 14:37:18 +02:00
Fabio Caccamo 0fd8469d9a Updated version 2017-09-27 14:34:28 +02:00
Fabio Caccamo 5cce94eefc Added README.rst [ci skip] 2017-09-27 14:33:52 +02:00
Fabio Caccamo c4c6a2b0f2 Updated README.md [ci skip] 2017-09-11 11:48:57 +02:00
Fabio Caccamo 73a61080ae Added code-quality badge to README - [ci skip] 2017-09-04 17:19:12 +02:00
Fabio Caccamo 0164e5b791 Fixed fieldset collapse show/hide link style [ci skip] 2017-08-29 12:41:29 +02:00
Fabio Caccamo bb29c637ff Fixed tests error 2017-08-24 18:37:28 +02:00
Fabio Caccamo a8e9fffdac Increased coverage 2017-08-24 18:23:35 +02:00
Fabio Caccamo d81c7fcdd8 Updated version 2017-08-24 14:28:54 +02:00
Fabio Caccamo 4d07e9fec5 Added favicon support #28 2017-08-24 14:28:36 +02:00
Fabio Caccamo 3b982a84c3 Improved coverage 2017-08-24 14:27:34 +02:00
Fabio Caccamo 072fdcdc95 Fixed duplicated admin queries #19 2017-08-24 14:27:01 +02:00
Fabio Caccamo 07c38baa83 Updated version 2017-07-13 18:01:10 +02:00
Fabio Caccamo ed669a88be Fixed django 1.7 and django 1.9 compatibility 2017-07-13 18:00:56 +02:00
Fabio Caccamo 71ad991ba7 Fixed modals closing in older django versions. 2017-07-13 15:53:00 +02:00
Fabio Caccamo 05128a997e Added version parameter to prevent css/js caching. 2017-07-13 15:50:58 +02:00
Fabio Caccamo 92a816b9ae Updated README.md [ci skip] 2017-06-13 12:57:07 +02:00
Fabio Caccamo 4a9b6e5e5c Updated version 2017-06-13 11:45:28 +02:00
Fabio Caccamo 0e69ccdba6 Changed dependencies versions from strict to ranges 2017-06-13 11:45:17 +02:00
Fabio Caccamo 3f9dc0c58e Merge pull request #26 from 18F/uswds-theme
Add USWDS color scheme.
2017-06-13 10:38:12 +02:00
CM Lubinski cbd414485f Add USWDS color scheme.
As a first draft of a U.S. Web Design Standards theme, this selects uses
reasonable colors from its 508-compliant color pallet.
2017-06-12 17:48:42 -04:00
Fabio Caccamo ccb818043c Merge pull request #23 from 18F/bytes2unicode
Add migration to convert bytes to unicode.
2017-06-12 15:50:37 +02:00
Fabio Caccamo 07d4fd65ef Merge pull request #21 from 18F/future-safe
Specify a max_length on all ColorFields.
2017-06-12 15:49:44 +02:00
Fabio Caccamo 4dd7a9dd3d Merge pull request #20 from founders4schools/deprecation-warnings
Fix a Django deprecation warning
2017-06-12 11:42:05 +02:00
CM Lubinski 9ecaa3836c Add migration to convert bytes to unicode.
Python 2 and 3 treat strings differently; in 2 they are bytes and in 3 they
are unicode objects. The Theme fields' attributes were encoded as bytes in the
initial migration (0001) but should be unicode values, leading to a missing
migration whenever the code is ran on Python 3. This changeset "alters" all
the fields to set them to have unicode attributes rather than bytes.

For more context, we've more or less followed the steps outlined here:
https://docs.djangoproject.com/en/1.11/topics/migrations/#supporting-python-2-and-3
2017-06-09 11:41:15 -04:00
Bruno Alla 511ad909bf Run tests on Python 3.6 for Django 1.11+ 2017-06-09 16:27:13 +01:00
CM Lubinski 8fe6ffd3b2 Specify a max_length on all ColorFields.
Django-colorfield bumped up its default max_length from 10 to 18 characters in
bfe421b8. Though we've pinned the version of colorfields we're depending on,
we can make the future version upgrade easier now by locking our fields to
having a max length of 10 chars.
2017-06-09 11:26:46 -04:00
Bruno Alla d0f8d7514a Fix allow_failures 2017-06-09 15:56:05 +01:00
Bruno Alla 78d80bc129 Run tests against Django master 2017-06-09 15:49:54 +01:00
Bruno Alla 09bd082759 Fix the error on older versions of Django 2017-06-09 15:44:23 +01:00
Bruno Alla 70b4be757d Fix a Django deprecation warning
Replace deprecated assignment_tag:

`python/lib/python3.5/site-packages/admin_interface/templatetags/admin_interface_tags.py:11: RemovedInDjango20Warning: assignment_tag() is deprecated. Use simple_tag() instead`
2017-06-09 15:12:00 +01:00
Fabio Caccamo 486bfa9aba Updated version 2017-06-09 11:58:26 +02:00
Fabio Caccamo e19cd51803 Added per-request cache to get_admin_interface_theme template tag #19 2017-06-09 11:58:10 +02:00
Fabio Caccamo 2d8eeee425 Updated README [ci skip] 2017-05-24 12:46:42 +02:00
Fabio Caccamo ef35236c58 Updated version 2017-05-24 12:02:27 +02:00
Fabio Caccamo eb676d9841 Added 3 themes as fixtures (django, bootstrap, foundation) 2017-05-24 12:01:25 +02:00
Fabio Caccamo 2301eedc8b Added possibility to hide recent actions 2017-05-24 11:57:08 +02:00
Fabio Caccamo 2bc5c9f9ce Removed double space in field declaration 2017-05-24 11:56:16 +02:00
Fabio Caccamo 44bae8b515 Changed modeltranslation active tab font-weight to bold 2017-05-24 11:55:23 +02:00
Fabio Caccamo ed34055290 Renamed field css_header_title_color to title_color according to logo_color 2017-05-24 11:53:33 +02:00
Fabio Caccamo 8a9842c219 Added possibility to customize the default logo color 2017-05-24 11:44:46 +02:00
Fabio Caccamo b449a1140c Fixed related-modal preloader background image url urlencode 2017-05-24 11:31:36 +02:00
Fabio Caccamo 3b2e567387 Increased tests coverage 2017-05-23 12:31:14 +02:00
Fabio Caccamo f3c7695409 Merge branch 'master' of https://github.com/fabiocaccamo/django-admin-interface 2017-05-23 10:43:01 +02:00
Fabio Caccamo 15aefd48d3 Merge pull request #18 from founders4schools/bugfix/repr
Fix the representation of Theme model under Python 3
2017-05-23 10:24:10 +02:00
Bruno Alla f6c8e84b7b Fix representation of Theme models on Python 3 2017-05-22 18:21:51 +01:00
Bruno Alla 1865da3477 Write a test covering the representation of the model 2017-05-22 18:14:38 +01:00
Fabio Caccamo b25cf463eb Fixed theme switching bug 2017-05-22 18:56:22 +02:00
Fabio Caccamo 4ef14c248a Fixed filter horizontal css height 2017-05-22 18:56:00 +02:00
Fabio Caccamo 165a8e4572 Updated version 2017-05-19 12:59:19 +02:00
Fabio Caccamo a6df45a571 Improved responsive m2m selector, ckeditor and sorl-thumbnail widgets 2017-05-19 12:59:02 +02:00
Fabio Caccamo b24c6010d2 Updated version 2017-05-18 10:56:19 +02:00
Fabio Caccamo bb2dd77646 Fixed django-storages compatibility - #16 2017-05-18 10:56:06 +02:00
48 changed files with 2221 additions and 418 deletions
+2 -1
View File
@@ -1 +1,2 @@
admin_interface/static/ckeditor/* linguist-vendored
admin_interface/static/admin_interface/magnific-popup/* linguist-vendored=true
admin_interface/static/ckeditor/* linguist-vendored=true
+2
View File
@@ -55,3 +55,5 @@ docs/_build/
# PyBuilder
target/
screenshots
TODO.txt
+55 -15
View File
@@ -1,22 +1,62 @@
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
- TOX_ENV=py27-dj17
- TOX_ENV=py27-dj18
- TOX_ENV=py27-dj19
- TOX_ENV=py27-dj110
- TOX_ENV=py27-dj111
- TOX_ENV=py34-dj17
- TOX_ENV=py34-dj18
- TOX_ENV=py34-dj19
- TOX_ENV=py34-dj110
- TOX_ENV=py34-dj111
- TOX_ENV=py34-dj20
- TOX_ENV=py35-dj18
- TOX_ENV=py35-dj19
- TOX_ENV=py35-dj110
- TOX_ENV=py35-dj111
- TOX_ENV=py35-dj20
- TOX_ENV=py35-dj21
- TOX_ENV=py35-djmaster
# - TOX_ENV=py36-dj111
# - TOX_ENV=py36-dj20
# - TOX_ENV=py36-dj21
# - TOX_ENV=py36-djmaster
# - TOX_ENV=py37-dj20
# - TOX_ENV=py37-dj21
# - TOX_ENV=py37-djmaster
matrix:
include:
- python: "3.6"
env: TOX_ENV=py36-dj111
- python: "3.6"
env: TOX_ENV=py36-dj20
- python: "3.6"
env: TOX_ENV=py36-dj21
- python: "3.6"
env: TOX_ENV=py36-djmaster
- python: "3.7"
env: TOX_ENV=py37-dj20
dist: xenial
language: python
sudo: required
- python: "3.7"
env: TOX_ENV=py37-dj21
dist: xenial
language: python
sudo: required
- python: "3.7"
env: TOX_ENV=py37-djmaster
dist: xenial
language: python
sudo: required
allow_failures:
- env: TOX_ENV=py35-djmaster
- env: TOX_ENV=py36-djmaster
- env: TOX_ENV=py37-djmaster
install:
- pip install tox
script:
- tox -e $TOX_ENV
sudo: false
sudo: false
+48 -12
View File
@@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.org/fabiocaccamo/django-admin-interface.svg?branch=master)](https://travis-ci.org/fabiocaccamo/django-admin-interface)
[![codecov](https://codecov.io/gh/fabiocaccamo/django-admin-interface/branch/master/graph/badge.svg)](https://codecov.io/gh/fabiocaccamo/django-admin-interface)
[![Code Health](https://landscape.io/github/fabiocaccamo/django-admin-interface/master/landscape.svg?style=flat)](https://landscape.io/github/fabiocaccamo/django-admin-interface/master)
[![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)
@@ -7,17 +8,24 @@
# django-admin-interface
django-admin-interface is a modern **responsive flat admin interface customizable by the admin itself**.
![django-admin-interface-preview](https://user-images.githubusercontent.com/1035294/35631521-64b0cab8-06a4-11e8-8f57-c04fdfbb7e8b.gif)
## Features
- Beautiful default **django-theme**
- Themes management and customization *(you can **customize admin title, logo and colors**)*
- Responsive
- List filter dropdown *(optional)*
- **`NEW`** **Related modal** *(instead of the old popup window, optional)*
- Style optimizations for: `django-ckeditor`, `django-modeltranslation`, `sorl-thumbnail`
- `NEW` **Related modal** *(instead of the old popup window, optional)*
- `NEW` **Enviroment label** *(development, testing, staging, production)*
- Style optimizations for:
- `django-ckeditor`
- `django-modeltranslation`
- `django-tabbed-admin`
- `sorl-thumbnail`
## Requirements
- Python 2.7, 3.4, 3.5, 3.6
- Django 1.7, 1.8, 1.9, 1.10, 1.11
- Python 2.7, 3.4, 3.5, 3.6, 3.7
- Django 1.7, 1.8, 1.9, 1.10, 1.11, 2.0, 2.1
## Installation
- Run `pip install django-admin-interface`
@@ -26,8 +34,8 @@ django-admin-interface is a modern **responsive flat admin interface customizabl
INSTALLED_APPS = (
#...
'admin_interface',
'flat_responsive',
'flat', #if django version < 1.9
'flat_responsive', # only if django version < 2.0
'flat', # only if django version < 1.9
'colorfield',
#...
'django.contrib.admin',
@@ -40,10 +48,36 @@ INSTALLED_APPS = (
#### Upgrade
- Run `pip install django-admin-interface --upgrade`
- Run ``python manage.py migrate`` *(add ``--fake-initial`` if you are upgrading from 0.1.0 version)*
- Run ``python manage.py migrate`` *(add* ``--fake-initial`` *if you are upgrading from 0.1.0 version)*
- Run ``python manage.py collectstatic --clear``
- Restart your application server
## Optional themes
This package ships with optional themes as fixtures, they can be installed using the [loaddata admin command](https://docs.djangoproject.com/en/1.11/ref/django-admin/#django-admin-loaddata). Optional themes are activated on installation.
##### [Django](https://www.djangoproject.com/) theme (default):
Run ``python manage.py loaddata admin_interface_theme_django.json``
##### [Bootstrap](http://getbootstrap.com/) theme:
Run ``python manage.py loaddata admin_interface_theme_bootstrap.json``
##### [Foundation](http://foundation.zurb.com/) theme:
Run ``python manage.py loaddata admin_interface_theme_foundation.json``
##### [U.S. Web Design Standards](https://standards.usa.gov/) theme:
Run ``python manage.py loaddata admin_interface_theme_uswds.json``
### Add more themes
You can add a theme you've created through the admin to this repository by [sending us a PR](http://makeapullrequest.com/). Here are the steps to follow to add :
1. Export your exact theme as fixture using the `dumpdata` admin command:
``python manage.py dumpdata admin_interface.Theme --indent 4 -o admin_interface_theme_{{name}}.json --pks=N``
2. Copy the generated json file into the fixtures folder *(making sure its name starts with* `admin_interface_theme_` *to avoid clashes with fixtures that might be provided by other third party apps)*.
3. Remove the `"pk"` from the fixture and make sure the `active` field is set to `true` *(in this way a theme is automatically activated when installed)*.
4. Edit the section above to document your theme.
## Screenshots
###### Admin login
@@ -58,10 +92,12 @@ INSTALLED_APPS = (
###### Admin theme customization
![django-admin-interface_theme_customization](https://cloud.githubusercontent.com/assets/1035294/11240250/7350d942-8df1-11e5-9b28-f2f54c333cdc.gif)
#### Thanks
- [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/)
## FAQ
- #### I already have a custom `base_site.html`, how can I make it work?
You can use [django-apptemplates](https://github.com/bittner/django-apptemplates), then add `{% extends "admin_interface:admin/base_site.html" %}` to your `base_site.html`
---
## License
Released under [MIT License](LICENSE).
Released under [MIT License](LICENSE.txt).
+152
View File
@@ -0,0 +1,152 @@
|Build Status| |codecov| |Code Health| |PyPI version| |Py versions| |License|
django-admin-interface
======================
django-admin-interface is a modern **responsive flat admin interface
customizable by the admin itself**.
|django-admin-interface_preview|
---------------------------------
Features
--------
- Beautiful default **django-theme**
- Themes management and customization *(you can customize admin title, logo and colors)*
- Responsive
- List filter dropdown *(optional)*
- ``NEW`` **Related modal** (instead of the old popup window, optional)
- ``NEW`` **Enviroment label** (development, testing, staging, production)
- Style optimizations for:
- `django-ckeditor`
- `django-modeltranslation`
- `django-tabbed-admin`
- `sorl-thumbnail`
Requirements
------------
- Python 2.7, 3.4, 3.5, 3.6, 3.7
- Django 1.7, 1.8, 1.9, 1.10, 1.11, 2.0, 2.1
Installation
------------
- Run ``pip install django-admin-interface``
- Add ``admin_interface``, ``flat_responsive`` *(only if django version < 2.0)*, ``flat`` *(only if django version < 1.9)* and ``colorfield`` to ``settings.INSTALLED_APPS`` **before** ``django.contrib.admin``
- Run ``python manage.py migrate``
- Run ``python manage.py collectstatic``
- Restart your application server
Upgrade
^^^^^^^
- Run ``pip install django-admin-interface --upgrade``
- Run ``python manage.py migrate`` *(add* ``--fake-initial`` *if you are upgrading from 0.1.0 version)*
- Run ``python manage.py collectstatic --clear``
- Restart your application server
Optional themes
^^^^^^^^^^^^^^^
This package ships with optional themes as fixtures, they can be
installed using the ``loaddata`` admin command.
Optional themes are activated on installation.
**Django theme** (default):
Run ``python manage.py loaddata admin_interface_theme_django.json``
**Bootstrap theme**:
Run ``python manage.py loaddata admin_interface_theme_bootstrap.json``
**Foundation theme**:
Run ``python manage.py loaddata admin_interface_theme_foundation.json``
**U.S. Web Design Standards theme**:
Run ``python manage.py loaddata admin_interface_theme_uswds.json``
Add more themes
^^^^^^^^^^^^^^^
You can add a theme you've created through the admin to this repository
by **sending us a PR**. Here are the steps to follow to add:
1. Export your exact theme as fixture using the ``dumpdata`` admin command:
``python manage.py dumpdata admin_interface.Theme --indent 4 -o admin_interface_theme_{{name}}.json --pks=N``
2. Copy the generated json file into the fixtures folder *(making sure
its name starts with ``admin_interface_theme_`` to avoid clashes with
fixtures that might be provided by other third party apps)*.
3. Remove the ``pk`` from the fixture and make sure the ``active``
field is set to ``true`` *(in this way a theme is automatically
activated when installed)*.
4. Edit the section above to document your theme.
Screenshots
-----------
Admin login
|django-admin-interface_login|
-------------------------------
Admin dashboard
|django-admin-interface_dashboard|
-----------------------------------
Admin themes management
|django-admin-interface_themes_management|
--------------------------------------------
Admin theme customization
|django-admin-interface_theme_customization|
---------------------------------------------
FAQ
---
**I already have a custom** ``base_site.html`` **, how can I make it work?**
You can use ``django-apptemplates`, then add ``{% extends "admin_interface:admin/base_site.html" %}`` to your ``base_site.html``
License
-------
Released under **MIT License**.
.. |Build Status| image:: https://travis-ci.org/fabiocaccamo/django-admin-interface.svg?branch=master
.. |codecov| image:: https://codecov.io/gh/fabiocaccamo/django-admin-interface/branch/master/graph/badge.svg
.. |Code Health| image:: https://landscape.io/github/fabiocaccamo/django-admin-interface/master/landscape.svg?style=flat
.. |PyPI version| image:: https://badge.fury.io/py/django-admin-interface.svg
.. |Py versions| image:: https://img.shields.io/pypi/pyversions/django-admin-interface.svg
.. |License| image:: https://img.shields.io/pypi/l/django-admin-interface.svg
.. |django-admin-interface_preview| image:: https://user-images.githubusercontent.com/1035294/35631521-64b0cab8-06a4-11e8-8f57-c04fdfbb7e8b.gif
.. |django-admin-interface_login| image:: https://cloud.githubusercontent.com/assets/1035294/11240233/55c8d4ba-8df1-11e5-9568-00fdc987ede8.gif
.. |django-admin-interface_dashboard| image:: https://cloud.githubusercontent.com/assets/1035294/11240239/627c0362-8df1-11e5-81fa-216366a5d8da.gif
.. |django-admin-interface_themes_management| image:: https://cloud.githubusercontent.com/assets/1035294/11240245/6cd1c342-8df1-11e5-928b-f22217474d3d.gif
.. |django-admin-interface_theme_customization| image:: https://cloud.githubusercontent.com/assets/1035294/11240250/7350d942-8df1-11e5-9b28-f2f54c333cdc.gif
-3
View File
@@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from admin_interface.version import __version__
default_app_config = 'admin_interface.apps.AdminInterfaceConfig'
+58 -9
View File
@@ -15,45 +15,94 @@ class ThemeAdmin(admin.ModelAdmin):
'classes': ('wide', ),
'fields': ('name', 'active', )
}),
('Enviroment', {
'classes': ('wide', ),
'fields': (
'env',
'env_visible',
)
}),
('Logo', {
'classes': ('wide', ),
'fields': ('logo', 'logo_visible', )
'fields': (
'logo',
'logo_color',
'logo_visible',
)
}),
('Favicon', {
'classes': ('wide', ),
'fields': ('favicon', )
}),
('Title', {
'classes': ('wide', ),
'fields': ('title', 'title_visible', )
'fields': (
'title',
'title_color',
'title_visible',
)
}),
('Header', {
'classes': ('wide', ),
'fields': ('css_header_background_color', 'css_header_title_color', 'css_header_text_color', 'css_header_link_color', 'css_header_link_hover_color', )
'fields': (
'css_header_background_color',
'css_header_text_color',
'css_header_link_color',
'css_header_link_hover_color',
)
}),
('Breadcrumbs / Module headers', {
'classes': ('wide', ),
'fields': ('css_module_background_color', 'css_module_text_color', 'css_module_link_color', 'css_module_link_hover_color', 'css_module_rounded_corners', )
'fields': (
'css_module_background_color',
'css_module_text_color',
'css_module_link_color',
'css_module_link_hover_color',
'css_module_rounded_corners',
)
}),
('Generic Links', {
'classes': ('wide', ),
'fields': ('css_generic_link_color', 'css_generic_link_hover_color', )
'fields': (
'css_generic_link_color',
'css_generic_link_hover_color',
)
}),
('Save Buttons', {
'classes': ('wide', ),
'fields': ('css_save_button_background_color', 'css_save_button_background_hover_color', 'css_save_button_text_color', )
'fields': (
'css_save_button_background_color',
'css_save_button_background_hover_color',
'css_save_button_text_color',
)
}),
('Delete Buttons', {
'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',
)
}),
('Related Modal', {
'classes': ('wide', ),
'fields': ('related_modal_active', 'related_modal_background_color', 'related_modal_background_opacity', 'related_modal_rounded_corners', )
'fields': (
'related_modal_active',
'related_modal_background_color',
'related_modal_background_opacity',
'related_modal_rounded_corners',
)
}),
('List Filter', {
'classes': ('wide', ),
'fields': ('list_filter_dropdown', )
}),
('Recent Actions', {
'classes': ('wide', ),
'fields': ('recent_actions_visible', )
}),
)
save_on_top = True
admin.site.register(Theme, ThemeAdmin)
+4 -1
View File
@@ -11,6 +11,9 @@ class AdminInterfaceConfig(AppConfig):
def ready(self):
from admin_interface import settings
from admin_interface.models import Theme
post_migrate.connect(Theme.post_migrate_handler, sender = self)
settings.check_installed_apps()
post_migrate.connect(
Theme.post_migrate_handler, sender=self)
-11
View File
@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="104px" height="36px" viewBox="0 0 104 36" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<title>logo-django</title>
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="logo-django" sketch:type="MSArtboardGroup" transform="translate(-8.000000, -5.000000)" fill="#FFFFFF">
<path d="M20.2602817,5 L25.9509859,5 L25.9509859,31.0824248 C23.0360563,31.6338042 20.8901408,31.8507285 18.5684507,31.8507285 C11.6180282,31.8434735 8,28.7383366 8,22.7747325 C8,17.0287781 11.8377465,13.2997118 17.7847887,13.2997118 C18.7076056,13.2997118 19.4107042,13.3722617 20.2602817,13.5899115 L20.2602817,5 L20.2602817,5 Z M20.2602817,18.1242821 C19.5938028,17.9066323 19.044507,17.8340823 18.3414085,17.8340823 C15.4630986,17.8340823 13.8005634,19.5897906 13.8005634,22.6666331 C13.8005634,25.6622196 15.3898592,27.316358 18.3047887,27.316358 C18.9346479,27.316358 19.4473239,27.2808085 20.2602817,27.1719836 L20.2602817,18.1242821 L20.2602817,18.1242821 Z M34.9960563,13.6987364 L34.9960563,26.7577235 C34.9960563,31.2550936 34.6591549,33.417807 33.6704225,35.2823401 C32.7476056,37.0750489 31.531831,38.2053768 29.0197183,39.453961 L23.7391549,36.9654985 C26.2512676,35.7981701 27.4670423,34.7665101 28.2433803,33.1921767 C29.056338,31.5822938 29.3126761,29.7177606 29.3126761,24.8133855 L29.3126761,13.6987364 L34.9960563,13.6987364 Z M29.3126761,5.02901997 L35.0033803,5.02901997 L35.0033803,10.8112493 L29.3126761,10.8112493 L29.3126761,5.02901997 Z M38.4302535,14.9828702 C40.9430986,13.8148163 43.3453521,13.2997118 45.9673239,13.2997118 C48.8895775,13.2997118 50.8077183,14.0687411 51.6580282,15.5705246 C52.1340845,16.4121037 52.2878873,17.5076077 52.2878873,19.8509704 L52.2878873,31.2993491 C49.7398873,31.6620987 46.5239437,31.922553 44.1649014,31.922553 C39.3970141,31.922553 37.2584225,30.2756696 37.2584225,26.6198787 C37.2584225,22.6659076 40.1008451,20.8376494 47.079831,20.2565245 L47.079831,19.0159207 C47.079831,17.9929667 46.559831,17.6229621 45.124338,17.6229621 C43.0223662,17.6229621 40.6567324,18.2106165 38.4375775,19.3423954 L38.4302535,14.9828702 Z M47.336169,23.9420608 C43.571662,24.3048105 42.3485634,24.8931904 42.3485634,26.3579734 C42.3485634,27.4549284 43.051662,27.9693073 44.604338,27.9693073 C45.4539155,27.9693073 46.2302535,27.8967574 47.3354366,27.7153826 L47.3354366,23.9420608 L47.336169,23.9420608 Z M55.056338,14.5765906 C58.4180282,13.6987364 61.1857465,13.2997118 63.9908169,13.2997118 C66.9057465,13.2997118 69.0157746,13.9599162 70.2674366,15.2367949 C71.4458592,16.4411237 71.8208451,17.7615324 71.8208451,20.5764696 L71.8208451,31.6258237 L66.1294085,31.6258237 L66.1294085,20.8013744 C66.1294085,18.6393866 65.3896901,17.8340823 63.3616901,17.8340823 C62.5846197,17.8340823 61.8822535,17.9066323 60.7397183,18.2403619 L60.7397183,31.6265492 L55.056338,31.6265492 L55.056338,14.5765906 Z M74.0326761,34.7012152 C76.0240563,35.7241692 78.0169014,36.1964692 80.1261972,36.1964692 C83.8540845,36.1964692 85.4433803,34.6946857 85.4433803,31.1107193 L85.4433803,31.0018944 C84.3374648,31.5460188 83.223493,31.7716491 81.7513803,31.7716491 C76.764507,31.7716491 73.5932394,28.5141573 73.5932394,23.3558574 C73.5932394,16.9496987 78.2878873,13.3294573 86.5932394,13.3294573 C89.0321127,13.3294573 91.2878873,13.583382 94.0189859,14.1347615 L92.0708169,18.1975575 C90.5562254,17.9073578 91.9463099,18.1540275 90.804507,18.0452026 L90.804507,18.6328571 L90.8777465,21.0124947 L90.9136338,24.0886117 C90.9509859,24.8583664 90.9509859,25.6259447 90.988338,26.3956994 L90.988338,27.9330324 C90.988338,32.7648576 90.5774648,35.0291409 89.3616901,36.900929 C87.5892958,39.6425908 84.5212958,41 80.1620845,41 C77.943662,41 76.0240563,40.6727998 74.0326761,39.9030451 L74.0326761,34.7012152 L74.0326761,34.7012152 Z M85.3335211,17.8703573 L85.1504225,17.8703573 L84.7395493,17.8703573 C83.6336338,17.8340823 82.3380282,18.1242821 81.4510986,18.6756615 C80.0895775,19.4446908 79.3872113,20.8376494 79.3872113,22.8110074 C79.3872113,25.6252192 80.7934085,27.2365531 83.3055211,27.2365531 C84.0811268,27.2365531 84.7117183,27.0921787 85.4441127,26.8738034 L85.4441127,26.4667983 L85.4441127,24.9294653 C85.4441127,24.269261 85.4067606,23.5365067 85.4067606,22.7674775 L85.3708732,20.17019 L85.3335211,18.3056569 L85.3335211,17.8703573 Z M102.84507,13.2271619 C108.528451,13.2271619 112,16.7748534 112,22.5208077 C112,28.4118619 108.382704,32.1039278 102.617296,32.1039278 C96.9265915,32.1039278 93.4176901,28.5569618 93.4176901,22.8480079 C93.4272113,16.9199532 97.044507,13.2271619 102.84507,13.2271619 Z M102.727887,27.5623023 C104.910423,27.5623023 106.199437,25.7710445 106.199437,22.6586526 C106.199437,19.5825356 104.94631,17.7542774 102.765239,17.7542774 C100.509465,17.7542774 99.2189859,19.5462607 99.2189859,22.6586526 C99.2189859,25.7710445 100.516056,27.5623023 102.727887,27.5623023 L102.727887,27.5623023 Z M102.727887,27.5623023" id="Shape" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.2 KiB

@@ -0,0 +1,39 @@
[
{
"model": "admin_interface.theme",
"fields": {
"name": "Bootstrap",
"active": true,
"title": "Django administration",
"title_color": "#503873",
"title_visible": false,
"logo": "",
"logo_color": "#503873",
"logo_visible": true,
"css_header_background_color": "#FFFFFF",
"css_header_text_color": "#463265",
"css_header_link_color": "#463265",
"css_header_link_hover_color": "#7351A6",
"css_module_background_color": "#7351A6",
"css_module_text_color": "#FFFFFF",
"css_module_link_color": "#CDBFE3",
"css_module_link_hover_color": "#FFFFFF",
"css_module_rounded_corners": true,
"css_generic_link_color": "#463265",
"css_generic_link_hover_color": "#7351A6",
"css_save_button_background_color": "#5CB85C",
"css_save_button_background_hover_color": "#449D44",
"css_save_button_text_color": "#FFFFFF",
"css_delete_button_background_color": "#D9534F",
"css_delete_button_background_hover_color": "#C9302C",
"css_delete_button_text_color": "#FFFFFF",
"css": "",
"related_modal_active": true,
"related_modal_background_color": "#503873",
"related_modal_background_opacity": 0.2,
"related_modal_rounded_corners": true,
"list_filter_dropdown": false,
"recent_actions_visible": true
}
}
]
@@ -0,0 +1,39 @@
[
{
"model": "admin_interface.theme",
"fields": {
"name": "Django",
"active": true,
"title": "Django administration",
"title_color": "#F5DD5D",
"title_visible": true,
"logo": "",
"logo_color": "#FFFFFF",
"logo_visible": true,
"css_header_background_color": "#0C4B33",
"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,
"recent_actions_visible": true
}
}
]
@@ -0,0 +1,39 @@
[
{
"model": "admin_interface.theme",
"fields": {
"name": "Foundation",
"active": true,
"title": "Django administration",
"title_color": "#DDDDDD",
"title_visible": false,
"logo": "",
"logo_color": "#CCCCCC",
"logo_visible": true,
"css_header_background_color": "#2C3840",
"css_header_text_color": "#FFFFFF",
"css_header_link_color": "#FFFFFF",
"css_header_link_hover_color": "#DDDDDD",
"css_module_background_color": "#074E68",
"css_module_text_color": "#FFFFFF",
"css_module_link_color": "#FFFFFF",
"css_module_link_hover_color": "#DDDDDD",
"css_module_rounded_corners": true,
"css_generic_link_color": "#000000",
"css_generic_link_hover_color": "#074E68",
"css_save_button_background_color": "#2199E8",
"css_save_button_background_hover_color": "#1585CF",
"css_save_button_text_color": "#FFFFFF",
"css_delete_button_background_color": "#CC4B37",
"css_delete_button_background_hover_color": "#BF4634",
"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,
"recent_actions_visible": true
}
}
]
@@ -0,0 +1,39 @@
[
{
"model": "admin_interface.theme",
"fields": {
"name": "USWDS",
"active": true,
"title": "Django administration",
"title_color": "#FFFFFF",
"title_visible": false,
"logo": "",
"logo_color": "#FFFFFF",
"logo_visible": true,
"css_header_background_color": "#112E51",
"css_header_text_color": "#FFFFFF",
"css_header_link_color": "#FFFFFF",
"css_header_link_hover_color": "#E1F3F8",
"css_module_background_color": "#205493",
"css_module_text_color": "#FFFFFF",
"css_module_link_color": "#FFFFFF",
"css_module_link_hover_color": "#E1F3F8",
"css_module_rounded_corners": true,
"css_generic_link_color": "#205493",
"css_generic_link_hover_color": "#0071BC",
"css_save_button_background_color": "#205493",
"css_save_button_background_hover_color": "#112E51",
"css_save_button_text_color": "#FFFFFF",
"css_delete_button_background_color": "#CD2026",
"css_delete_button_background_hover_color": "#981B1E",
"css_delete_button_text_color": "#FFFFFF",
"css": "",
"related_modal_active": true,
"related_modal_background_color": "#000000",
"related_modal_background_opacity": 0.8,
"related_modal_rounded_corners": true,
"list_filter_dropdown": false,
"recent_actions_visible": true
}
}
]
+161 -27
View File
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import colorfield.fields
@@ -14,33 +16,165 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Theme',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(default=b'Django', max_length=50)),
('active', models.BooleanField(default=True)),
('title', models.CharField(default=b'Django administration', max_length=50, blank=True)),
('title_visible', models.BooleanField(default=True, verbose_name=b'visible')),
('logo', models.FileField(upload_to=b'admin-interface/logo/', blank=True)),
('logo_visible', models.BooleanField(default=True, verbose_name=b'visible')),
('css_header_background_color', colorfield.fields.ColorField(default=b'#0C4B33', help_text=b'#0C4B33', max_length=10, verbose_name=b'background color', blank=True)),
('css_header_title_color', colorfield.fields.ColorField(default=b'#F5DD5D', help_text=b'#F5DD5D', max_length=10, verbose_name=b'title color', blank=True)),
('css_header_text_color', colorfield.fields.ColorField(default=b'#44B78B', help_text=b'#44B78B', max_length=10, verbose_name=b'text color', blank=True)),
('css_header_link_color', colorfield.fields.ColorField(default=b'#FFFFFF', help_text=b'#FFFFFF', max_length=10, verbose_name=b'link color', blank=True)),
('css_header_link_hover_color', colorfield.fields.ColorField(default=b'#C9F0DD', help_text=b'#C9F0DD', max_length=10, verbose_name=b'link hover color', blank=True)),
('css_module_background_color', colorfield.fields.ColorField(default=b'#44B78B', help_text=b'#44B78B', max_length=10, verbose_name=b'background color', blank=True)),
('css_module_text_color', colorfield.fields.ColorField(default=b'#FFFFFF', help_text=b'#FFFFFF', max_length=10, verbose_name=b'text color', blank=True)),
('css_module_link_color', colorfield.fields.ColorField(default=b'#FFFFFF', help_text=b'#FFFFFF', max_length=10, verbose_name=b'link color', blank=True)),
('css_module_link_hover_color', colorfield.fields.ColorField(default=b'#C9F0DD', help_text=b'#C9F0DD', max_length=10, verbose_name=b'link hover color', blank=True)),
('css_module_rounded_corners', models.BooleanField(default=True, verbose_name=b'rounded corners')),
('css_generic_link_color', colorfield.fields.ColorField(default=b'#0C3C26', help_text=b'#0C3C26', max_length=10, verbose_name=b'link color', blank=True)),
('css_generic_link_hover_color', colorfield.fields.ColorField(default=b'#156641', help_text=b'#156641', max_length=10, verbose_name=b'link hover color', blank=True)),
('css_save_button_background_color', colorfield.fields.ColorField(default=b'#0C4B33', help_text=b'#0C4B33', max_length=10, verbose_name=b'background color', blank=True)),
('css_save_button_background_hover_color', colorfield.fields.ColorField(default=b'#0C3C26', help_text=b'#0C3C26', max_length=10, verbose_name=b'background hover color', blank=True)),
('css_save_button_text_color', colorfield.fields.ColorField(default=b'#FFFFFF', help_text=b'#FFFFFF', max_length=10, verbose_name=b'text color', blank=True)),
('css_delete_button_background_color', colorfield.fields.ColorField(default=b'#BA2121', help_text=b'#BA2121', max_length=10, verbose_name=b'background color', blank=True)),
('css_delete_button_background_hover_color', colorfield.fields.ColorField(default=b'#A41515', help_text=b'#A41515', max_length=10, verbose_name=b'background hover color', blank=True)),
('css_delete_button_text_color', colorfield.fields.ColorField(default=b'#FFFFFF', help_text=b'#FFFFFF', max_length=10, verbose_name=b'text color', blank=True)),
('css', models.TextField(blank=True)),
('list_filter_dropdown', models.BooleanField(default=False)),
('id',
models.AutoField(
verbose_name='ID',
serialize=False,
auto_created=True,
primary_key=True)),
('name',
models.CharField(
default=b'Django',
max_length=50)),
('active',
models.BooleanField(
default=True)),
('title',
models.CharField(
default=b'Django administration',
max_length=50,
blank=True)),
('title_visible',
models.BooleanField(
default=True,
verbose_name=b'visible')),
('logo',
models.FileField(
upload_to=b'admin-interface/logo/',
blank=True)),
('logo_visible',
models.BooleanField(
default=True,
verbose_name=b'visible')),
('css_header_background_color',
colorfield.fields.ColorField(
default=b'#0C4B33',
help_text=b'#0C4B33',
max_length=10,
verbose_name=b'background color',
blank=True)),
('css_header_title_color',
colorfield.fields.ColorField(
default=b'#F5DD5D',
help_text=b'#F5DD5D',
max_length=10,
verbose_name=b'title color',
blank=True)),
('css_header_text_color',
colorfield.fields.ColorField(
default=b'#44B78B',
help_text=b'#44B78B',
max_length=10,
verbose_name=b'text color',
blank=True)),
('css_header_link_color',
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
max_length=10,
verbose_name=b'link color',
blank=True)),
('css_header_link_hover_color',
colorfield.fields.ColorField(
default=b'#C9F0DD',
help_text=b'#C9F0DD',
max_length=10,
verbose_name=b'link hover color',
blank=True)),
('css_module_background_color',
colorfield.fields.ColorField(
default=b'#44B78B',
help_text=b'#44B78B',
max_length=10,
verbose_name=b'background color',
blank=True)),
('css_module_text_color',
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
max_length=10,
verbose_name=b'text color',
blank=True)),
('css_module_link_color',
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
max_length=10,
verbose_name=b'link color',
blank=True)),
('css_module_link_hover_color',
colorfield.fields.ColorField(
default=b'#C9F0DD',
help_text=b'#C9F0DD',
max_length=10,
verbose_name=b'link hover color',
blank=True)),
('css_module_rounded_corners',
models.BooleanField(
default=True,
verbose_name=b'rounded corners')),
('css_generic_link_color',
colorfield.fields.ColorField(
default=b'#0C3C26',
help_text=b'#0C3C26',
max_length=10,
verbose_name=b'link color',
blank=True)),
('css_generic_link_hover_color',
colorfield.fields.ColorField(
default=b'#156641',
help_text=b'#156641',
max_length=10,
verbose_name=b'link hover color',
blank=True)),
('css_save_button_background_color',
colorfield.fields.ColorField(
default=b'#0C4B33',
help_text=b'#0C4B33',
max_length=10,
verbose_name=b'background color',
blank=True)),
('css_save_button_background_hover_color',
colorfield.fields.ColorField(
default=b'#0C3C26',
help_text=b'#0C3C26',
max_length=10,
verbose_name=b'background hover color',
blank=True)),
('css_save_button_text_color',
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
max_length=10,
verbose_name=b'text color',
blank=True)),
('css_delete_button_background_color',
colorfield.fields.ColorField(
default=b'#BA2121',
help_text=b'#BA2121',
max_length=10,
verbose_name=b'background color',
blank=True)),
('css_delete_button_background_hover_color',
colorfield.fields.ColorField(
default=b'#A41515',
help_text=b'#A41515',
max_length=10,
verbose_name=b'background hover color',
blank=True)),
('css_delete_button_text_color',
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
max_length=10,
verbose_name=b'text color',
blank=True)),
('css',
models.TextField(
blank=True)),
('list_filter_dropdown',
models.BooleanField(
default=False)),
],
options={
'verbose_name': 'Theme',
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import colorfield.fields
@@ -15,26 +17,44 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='theme',
name='list_filter_dropdown',
field=models.BooleanField(default=False, verbose_name=b'use 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'),
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'),
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'),
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'),
field=models.BooleanField(
default=True,
verbose_name=b'rounded corners'),
),
]
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import colorfield.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0002_add_related_modal'),
]
operations = [
migrations.AddField(
model_name='theme',
name='logo_color',
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
max_length=10,
verbose_name='logo color'),
),
migrations.AlterField(
model_name='theme',
name='logo',
field=models.FileField(
blank=True,
help_text='(leave blank to use the default Django logo)',
upload_to='admin-interface/logo/'),
),
]
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0003_add_logo_color'),
]
operations = [
migrations.RenameField(
model_name='theme',
old_name='css_header_title_color',
new_name='title_color',
),
]
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0004_rename_title_color'),
]
operations = [
migrations.AddField(
model_name='theme',
name='recent_actions_visible',
field=models.BooleanField(
default=True,
verbose_name='visible'),
),
]
@@ -0,0 +1,266 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import colorfield.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0005_add_recent_actions_visible'),
]
operations = [
migrations.AlterField(
model_name='theme',
name='css_delete_button_background_color',
field=colorfield.fields.ColorField(
blank=True,
default='#BA2121',
help_text='#BA2121',
max_length=10,
verbose_name='background color'),
),
migrations.AlterField(
model_name='theme',
name='css_delete_button_background_hover_color',
field=colorfield.fields.ColorField(
blank=True,
default='#A41515',
help_text='#A41515',
max_length=10,
verbose_name='background hover color'),
),
migrations.AlterField(
model_name='theme',
name='css_delete_button_text_color',
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
max_length=10,
verbose_name='text color'),
),
migrations.AlterField(
model_name='theme',
name='css_generic_link_color',
field=colorfield.fields.ColorField(
blank=True,
default='#0C3C26',
help_text='#0C3C26',
max_length=10,
verbose_name='link color'),
),
migrations.AlterField(
model_name='theme',
name='css_generic_link_hover_color',
field=colorfield.fields.ColorField(
blank=True,
default='#156641',
help_text='#156641',
max_length=10,
verbose_name='link hover color'),
),
migrations.AlterField(
model_name='theme',
name='css_header_background_color',
field=colorfield.fields.ColorField(
blank=True,
default='#0C4B33',
help_text='#0C4B33',
max_length=10,
verbose_name='background color'),
),
migrations.AlterField(
model_name='theme',
name='css_header_link_color',
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
max_length=10,
verbose_name='link color'),
),
migrations.AlterField(
model_name='theme',
name='css_header_link_hover_color',
field=colorfield.fields.ColorField(
blank=True,
default='#C9F0DD',
help_text='#C9F0DD',
max_length=10,
verbose_name='link hover color'),
),
migrations.AlterField(
model_name='theme',
name='css_header_text_color',
field=colorfield.fields.ColorField(
blank=True,
default='#44B78B',
help_text='#44B78B',
max_length=10,
verbose_name='text color'),
),
migrations.AlterField(
model_name='theme',
name='css_module_background_color',
field=colorfield.fields.ColorField(
blank=True,
default='#44B78B',
help_text='#44B78B',
max_length=10,
verbose_name='background color'),
),
migrations.AlterField(
model_name='theme',
name='css_module_link_color',
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
max_length=10,
verbose_name='link color'),
),
migrations.AlterField(
model_name='theme',
name='css_module_link_hover_color',
field=colorfield.fields.ColorField(
blank=True,
default='#C9F0DD',
help_text='#C9F0DD',
max_length=10,
verbose_name='link hover color'),
),
migrations.AlterField(
model_name='theme',
name='css_module_rounded_corners',
field=models.BooleanField(
default=True,
verbose_name='rounded corners'),
),
migrations.AlterField(
model_name='theme',
name='css_module_text_color',
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
max_length=10,
verbose_name='text color'),
),
migrations.AlterField(
model_name='theme',
name='css_save_button_background_color',
field=colorfield.fields.ColorField(
blank=True,
default='#0C4B33',
help_text='#0C4B33',
max_length=10,
verbose_name='background color'),
),
migrations.AlterField(
model_name='theme',
name='css_save_button_background_hover_color',
field=colorfield.fields.ColorField(
blank=True,
default='#0C3C26',
help_text='#0C3C26',
max_length=10,
verbose_name='background hover color'),
),
migrations.AlterField(
model_name='theme',
name='css_save_button_text_color',
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
max_length=10,
verbose_name='text color'),
),
migrations.AlterField(
model_name='theme',
name='list_filter_dropdown',
field=models.BooleanField(
default=False,
verbose_name='use dropdown'),
),
migrations.AlterField(
model_name='theme',
name='logo_visible',
field=models.BooleanField(
default=True,
verbose_name='visible'),
),
migrations.AlterField(
model_name='theme',
name='name',
field=models.CharField(
default='Django',
max_length=50),
),
migrations.AlterField(
model_name='theme',
name='related_modal_active',
field=models.BooleanField(
default=True,
verbose_name='active'),
),
migrations.AlterField(
model_name='theme',
name='related_modal_background_color',
field=colorfield.fields.ColorField(
blank=True,
default='#000000',
help_text='#000000',
max_length=10,
verbose_name='background color'),
),
migrations.AlterField(
model_name='theme',
name='related_modal_background_opacity',
field=models.FloatField(
choices=[
(0.1, '10%'), (0.2, '20%'), (0.3, '30%'),
(0.4, '40%'), (0.5, '50%'), (0.6, '60%'),
(0.7, '70%'), (0.8, '80%'), (0.9, '90%')],
default=0.2,
help_text='20%',
verbose_name='background opacity'),
),
migrations.AlterField(
model_name='theme',
name='related_modal_rounded_corners',
field=models.BooleanField(
default=True,
verbose_name='rounded corners'),
),
migrations.AlterField(
model_name='theme',
name='title',
field=models.CharField(
blank=True,
default='Django administration',
max_length=50),
),
migrations.AlterField(
model_name='theme',
name='title_color',
field=colorfield.fields.ColorField(
blank=True,
default='#F5DD5D',
help_text='#F5DD5D',
max_length=10,
verbose_name='title color'),
),
migrations.AlterField(
model_name='theme',
name='title_visible',
field=models.BooleanField(
default=True,
verbose_name='visible'),
),
]
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0006_bytes_to_str'),
]
operations = [
migrations.AddField(
model_name='theme',
name='favicon',
field=models.FileField(
blank=True,
help_text='(.ico|.png|.gif - 16x16|32x32 px)',
upload_to='admin-interface/favicon/',
verbose_name='favicon'),
),
]
@@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0007_add_favicon'),
]
operations = [
migrations.AlterField(
model_name='theme',
name='related_modal_background_opacity',
field=models.CharField(
choices=[
('0.1', '10%'), ('0.2', '20%'), ('0.3', '30%'),
('0.4', '40%'), ('0.5', '50%'), ('0.6', '60%'),
('0.7', '70%'), ('0.8', '80%'), ('0.9', '90%')],
default='0.3',
help_text='20%',
max_length=5,
verbose_name='background opacity'),
),
]
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2018-01-31 11:00
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0008_change_related_modal_background_opacity_type'),
]
operations = [
migrations.AddField(
model_name='theme',
name='env',
field=models.CharField(choices=[('development', 'Development'), ('testing', 'Testing'), ('staging', 'Staging'), ('production', 'Production')], default='development', max_length=50, verbose_name='enviroment'),
),
migrations.AddField(
model_name='theme',
name='env_visible',
field=models.BooleanField(default=True, verbose_name='visible'),
),
]
+142 -90
View File
@@ -1,126 +1,180 @@
# -*- coding: utf-8 -*-
from django.core.files import File
from __future__ import unicode_literals
from django.db import models
from django.db.models.signals import post_delete, post_save
from django.utils.encoding import python_2_unicode_compatible, force_text
from colorfield.fields import ColorField
import os
@python_2_unicode_compatible
class Theme(models.Model):
@staticmethod
def post_migrate_handler(sender, **kwargs):
def post_migrate_handler(**kwargs):
Theme.get_active_theme()
@staticmethod
def post_delete_handler(instance, **kwargs):
def post_delete_handler(**kwargs):
Theme.get_active_theme()
@staticmethod
def post_save_handler(instance, created, **kwargs):
def post_save_handler(instance, **kwargs):
if instance.active:
Theme.objects.exclude(pk=instance.pk).update(active=False)
Theme.get_active_theme()
@staticmethod
def get_active_theme():
objs_active_qs = Theme.objects.filter( active = True )
objs_active_qs = Theme.objects.filter(active=True)
objs_active_ls = list(objs_active_qs)
objs_active_count = len(objs_active_ls)
#get or create default theme and enforce default logo if deleted
default_obj_active = (objs_active_qs.count() == 0)
default_obj, default_obj_created = Theme.objects.get_or_create(pk = '1', defaults = { 'active':default_obj_active })
if objs_active_count == 0:
default_obj, default_obj_created = Theme.objects.get_or_create(
pk='1', defaults={'active': True})
if not default_obj_created:
default_obj.set_active()
obj = default_obj
if not default_obj_created and default_obj_active:
default_obj.set_active()
elif objs_active_count == 1:
obj = objs_active_ls[0]
default_obj.set_default_logo()
obj = objs_active_qs.last()
objs_active_count = objs_active_qs.count()
if objs_active_count > 1:
elif objs_active_count > 1:
obj = objs_active_ls[-1]
obj.set_active()
return obj
name = models.CharField( max_length = 50, default = 'Django' )
active = models.BooleanField( default = True )
name = models.CharField(max_length=50, default='Django')
active = models.BooleanField(default=True)
title = models.CharField( max_length = 50, default = 'Django administration', blank = True )
title_visible = models.BooleanField( default = True, verbose_name = 'visible' )
title = models.CharField(
max_length=50, default='Django administration', blank=True)
title_color = ColorField(
blank=True, default='#F5DD5D', help_text='#F5DD5D',
max_length=10, verbose_name='title color')
title_visible = models.BooleanField(
default=True, verbose_name='visible')
logo = models.FileField( upload_to = 'admin-interface/logo/', blank = True )
logo_visible = models.BooleanField( default = True, verbose_name = 'visible' )
logo = models.FileField(
upload_to='admin-interface/logo/', blank=True,
help_text='(leave blank to use the default Django logo)')
logo_color = ColorField(
blank=True, default='#FFFFFF', help_text='#FFFFFF',
max_length=10, verbose_name='logo color')
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_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_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' )
favicon = models.FileField(
upload_to='admin-interface/favicon/', blank=True,
help_text='(.ico|.png|.gif - 16x16|32x32 px)', verbose_name='favicon')
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_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_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_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_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_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_text_color = ColorField( blank = True, default = '#FFFFFF', help_text = '#FFFFFF', verbose_name = 'text color' )
css = models.TextField( blank = True )
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 = (
(0.1, '10%', ),
(0.2, '20%', ),
(0.3, '30%', ),
(0.4, '40%', ),
(0.5, '50%', ),
(0.6, '60%', ),
(0.7, '70%', ),
(0.8, '80%', ),
(0.9, '90%', ),
env_choices = (
('development', 'Development', ),
('testing', 'Testing', ),
('staging', 'Staging', ),
('production', 'Production', ),
)
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' )
env = models.CharField(
max_length=50,
choices=env_choices,
default='development', verbose_name='enviroment')
env_visible = models.BooleanField(
default=True, verbose_name='visible')
list_filter_dropdown = models.BooleanField( default = False, verbose_name = 'use dropdown' )
css_header_background_color = ColorField(
blank=True, default='#0C4B33', help_text='#0C4B33',
max_length=10, verbose_name='background color')
css_header_text_color = ColorField(
blank=True, default='#44B78B', help_text='#44B78B',
max_length=10, verbose_name='text color')
css_header_link_color = ColorField(
blank=True, default='#FFFFFF', help_text='#FFFFFF',
max_length=10, verbose_name='link color')
css_header_link_hover_color = ColorField(
blank=True, default='#C9F0DD', help_text='#C9F0DD',
max_length=10, verbose_name='link hover color')
css_module_background_color = ColorField(
blank=True, default='#44B78B', help_text='#44B78B',
max_length=10, verbose_name='background color')
css_module_text_color = ColorField(
blank=True, default='#FFFFFF', help_text='#FFFFFF',
max_length=10, verbose_name='text color')
css_module_link_color = ColorField(
blank=True, default='#FFFFFF', help_text='#FFFFFF',
max_length=10, verbose_name='link color')
css_module_link_hover_color = ColorField(
blank=True, default='#C9F0DD', help_text='#C9F0DD',
max_length=10, verbose_name='link hover color')
css_module_rounded_corners = models.BooleanField(
default=True, verbose_name='rounded corners')
css_generic_link_color = ColorField(
blank=True, default='#0C3C26', help_text='#0C3C26',
max_length=10, verbose_name='link color')
css_generic_link_hover_color = ColorField(
blank=True, default='#156641', help_text='#156641',
max_length=10, verbose_name='link hover color')
css_save_button_background_color = ColorField(
blank=True, default='#0C4B33', help_text='#0C4B33',
max_length=10, verbose_name='background color')
css_save_button_background_hover_color = ColorField(
blank=True, default='#0C3C26', help_text='#0C3C26',
max_length=10, verbose_name='background hover color')
css_save_button_text_color = ColorField(
blank=True, default='#FFFFFF', help_text='#FFFFFF',
max_length=10, verbose_name='text color')
css_delete_button_background_color = ColorField(
blank=True, default='#BA2121', help_text='#BA2121',
max_length=10, verbose_name='background color')
css_delete_button_background_hover_color = ColorField(
blank=True, default='#A41515', help_text='#A41515',
max_length=10, verbose_name='background hover color')
css_delete_button_text_color = ColorField(
blank=True, default='#FFFFFF', help_text='#FFFFFF',
max_length=10, verbose_name='text color')
css = models.TextField(blank=True)
related_modal_active = models.BooleanField(
default=True, verbose_name='active')
related_modal_background_color = ColorField(
blank=True, default='#000000', help_text='#000000',
max_length=10, verbose_name='background color')
related_modal_background_opacity_choices = (
('0.1', '10%', ),
('0.2', '20%', ),
('0.3', '30%', ),
('0.4', '40%', ),
('0.5', '50%', ),
('0.6', '60%', ),
('0.7', '70%', ),
('0.8', '80%', ),
('0.9', '90%', ),
)
related_modal_background_opacity = models.CharField(
max_length=5,
choices=related_modal_background_opacity_choices,
default='0.3', 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')
recent_actions_visible = models.BooleanField(
default=True, verbose_name='visible')
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):
if self.logo and os.path.isfile(self.logo.path):
return
logo_filename = 'logo-django.svg'
logo_path = os.path.normpath(os.path.dirname(__file__) + '/data/' + logo_filename)
logo_file = open(logo_path)
self.logo = File(logo_file, logo_filename)
post_save.disconnect(Theme.post_save_handler, sender = Theme)
self.active = True
self.save()
post_save.connect(Theme.post_save_handler, sender = Theme)
logo_file.close()
class Meta:
@@ -129,11 +183,9 @@ class Theme(models.Model):
verbose_name = 'Theme'
verbose_name_plural = 'Themes'
def __unicode__(self):
return unicode(u'%s' % (self.name, ))
def __str__(self):
return force_text(self.name)
post_delete.connect(Theme.post_delete_handler, sender = Theme)
post_save.connect(Theme.post_save_handler, sender = Theme)
post_delete.connect(Theme.post_delete_handler, sender=Theme)
post_save.connect(Theme.post_save_handler, sender=Theme)
+38
View File
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
import django
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
def check_installed_apps():
dj_version = django.VERSION
installed_apps = settings.INSTALLED_APPS
if 'colorfield' not in installed_apps:
raise ImproperlyConfigured(
'\'colorfield\' needed, '
'add it to settings.INSTALLED_APPS.')
if dj_version < (1, 9):
if 'flat' not in installed_apps:
raise ImproperlyConfigured(
'\'flat\' needed before django 1.9, '
'add it to settings.INSTALLED_APPS.')
else:
if 'flat' in installed_apps:
raise ImproperlyConfigured(
'\'flat\' not needed since django 1.9, '
'remove it from settings.INSTALLED_APPS.')
if dj_version < (2, 0):
if 'flat_responsive' not in installed_apps:
raise ImproperlyConfigured(
'\'flat_responsive\' needed before django 2.0, '
'add it to settings.INSTALLED_APPS.')
else:
if 'flat_responsive' in installed_apps:
raise ImproperlyConfigured(
'\'flat_responsive\' not needed since django 2.0, '
'remove it from settings.INSTALLED_APPS.')
+16
View File
@@ -0,0 +1,16 @@
(function($) {
'use strict';
$(function() {
$('.cancel-link').click(function(e) {
e.preventDefault();
var parentWindow = window.parent;
if (parentWindow && typeof(parentWindow.dismissRelatedObjectModal) === 'function') {
parentWindow.dismissRelatedObjectModal();
} else {
// fallback to default behavior
history.back();
}
return false;
});
});
})(django.jQuery);
@@ -1,35 +1,52 @@
/*global opener */
(function() {
/* 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();
}
};
function getModalWindowData()
{
var windowRef = window;
var windowName = windowRef.name;
var widgetName = windowName.replace(/^(change|add|delete|lookup)_/, '');
var modalRef = {};
var openerRef = windowRef.opener;
if (!openerRef) {
openerRef = windowRef.parent;
modalRef = {
name: openerRef.id_to_windowname(widgetName),
close: function(){
openerRef.dismissRelatedObjectModal();
}
};
}
return { opener:openerRef, modal:modalRef };
}
var modalData = getModalWindowData();
var modalRef = modalData['modal'];
var openerRef = modalData['opener'];
var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
switch(initData.action){
// console.log(initData);
switch (initData.action) {
case 'change':
openerRef.dismissChangeRelatedObjectPopup(modalRef, initData.value, initData.obj, initData.new_value);
if (typeof(openerRef.dismissChangeRelatedObjectPopup) === 'function') {
openerRef.dismissChangeRelatedObjectPopup(modalRef, initData.value, initData.obj, initData.new_value);
}
break;
case 'delete':
openerRef.dismissDeleteRelatedObjectPopup(modalRef, initData.value);
if (typeof(openerRef.dismissDeleteRelatedObjectPopup) === 'function') {
openerRef.dismissDeleteRelatedObjectPopup(modalRef, initData.value);
}
break;
default:
openerRef.dismissAddRelatedObjectPopup(modalRef, initData.value, initData.obj);
if (typeof(openerRef.dismissAddRelatedObjectPopup) === 'function') {
openerRef.dismissAddRelatedObjectPopup(modalRef, initData.value, initData.obj);
}
else if (typeof(openerRef.dismissAddAnotherPopup) === 'function') {
// django 1.7 compatibility
openerRef.dismissAddAnotherPopup(modalRef, initData.value, initData.obj);
}
break;
}
})();
})(django.jQuery);
@@ -1,53 +1,104 @@
if(typeof django !== 'undefined' && typeof django.jQuery !== 'undefined' )
if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined')
{
(function($) {
$(document).ready(function(){
// create the function that will close the modal
function dismissRelatedObjectModal()
function dismissModal()
{
// close the popup
$.magnificPopup.close();
}
// assign the function to a global variable
// create the function that will close the modal
function dismissRelatedObjectModal()
{
dismissModal();
}
function dismissRelatedLookupModal(win, chosenId)
{
var windowRef = win;
var windowName = windowRef.name;
var widgetName = windowName.replace(/^(change|add|delete|lookup)_/, '');
var widgetEl = $('#' + widgetName);
var widgetVal = widgetEl.val();
if (widgetEl.hasClass('vManyToManyRawIdAdminField') && Boolean(widgetVal)) {
widgetEl.val(widgetVal + ', ' + chosenId);
} else {
widgetEl.val(chosenId);
}
dismissModal();
}
// assign functions to global variables
window.dismissRelatedObjectModal = dismissRelatedObjectModal;
window.dismissRelatedLookupPopup = dismissRelatedLookupModal;
// 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){
function presentRelatedObjectModal(e)
{
var linkEl = $(this);
var href = (linkEl.attr('href') || '');
if (href == '') {
return;
}
// open the popup as modal
e.preventDefault();
e.stopImmediatePropagation();
// remove focus from clicked link
$(this).blur();
linkEl.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 + '"');
var iframeName = linkEl.attr('id');
var iframeSrc = href;
// 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;
if (e.data.lookup !== true)
{
// browsers stop loading nested iframes having the same src url
// create a random parameter and append it to the src url to prevent it
// this workaround doesn't work with related lookup url
var iframeSrcRandom = String(Math.round(Math.random() * 999999));
if( iframeSrc.indexOf('?') === -1 ){
iframeSrc += '?_modal=' + iframeSrcRandom;
} else {
iframeSrc += '&_modal=' + iframeSrcRandom;
}
}
// fix for django 1.7
if (iframeSrc.indexOf('_popup=1') === -1) {
if (iframeSrc.indexOf('?') === -1) {
iframeSrc += '?_popup=1';
} else {
iframeSrc += '&_popup=1';
}
}
// 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);
if (e.data.lookup === true)
{
// set current window as iframe opener because
// the callback is called on the opener window
iframeEl.load(function(){
var iframeObj = $(this).get(0);
var iframeWindow = iframeObj.contentWindow;
iframeWindow.opener = window;
});
}
// 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 )
{
if (window.top != window.self) {
iframeInternalModalClass += ' related-modal__nested';
}
@@ -61,7 +112,20 @@ if(typeof django !== 'undefined' && typeof django.jQuery !== 'undefined' )
});
return false;
});
}
// listen click events on related links
// django 1.7 compatibility
$('a.add-another').removeAttr('onclick');
$('a.add-another').click({ lookup:false }, presentRelatedObjectModal);
// django 1.8 and above
$('a.related-widget-wrapper-link').click({ lookup:false }, presentRelatedObjectModal);
// raw_id_fields support
$('a.related-lookup').unbind('click');
$('a.related-lookup').click({ lookup:true }, presentRelatedObjectModal);
});
})(django.jQuery);
+28 -8
View File
@@ -8,14 +8,21 @@
{% block extrastyle %}
{% get_admin_interface_theme as theme %}
{% get_admin_interface_version as version %}
<style type="text/css">
/*
django-admin-interface {{ version }}
https://github.com/fabiocaccamo/django-admin-interface
*/
{% include "admin_interface/css/admin-interface.css" %}
{% include "admin_interface/css/admin-interface-fix.css" %}
{% include "admin_interface/css/list-filter-dropdown.css" %}
{% include "admin_interface/css/recent-actions.css" %}
{% include "admin_interface/css/related-modal.css" %}
{% include "admin_interface/css/jquery.ui.tabs.css" %}
{% include "admin_interface/css/modeltranslation.css" %}
{% include "admin_interface/css/sorl-thumbnail.css" %}
{% include "admin_interface/css/tabbed-admin.css" %}
{% include "admin_interface/css/ckeditor.css" %}
{% include "admin_interface/css/tinymce.css" %}
@@ -28,14 +35,18 @@
{% block blockbots %}
{{ block.super }}
{% get_admin_interface_theme as theme %}
{% get_admin_interface_version as version %}
{# https://github.com/elky/django-flat-responsive#important-note #}
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive.css' %}" />
{% get_admin_interface_theme as theme %}
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive.css' %}?v={{ version }}" />
{% if theme.favicon %}
<link rel="icon" type="image/x-icon" href="{{ theme.favicon.url }}?v={{ version }}" />
{% endif %}
{% if theme.related_modal_active %}
<link rel="stylesheet" type="text/css" href="{% static 'admin_interface/magnific-popup/magnific-popup.css' %}" />
<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>
<link rel="stylesheet" type="text/css" href="{% static 'admin_interface/magnific-popup/magnific-popup.css' %}?v={{ version }}" />
<script type="text/javascript" src="{% static 'admin_interface/magnific-popup/jquery.magnific-popup.js' %}?v={{ version }}"></script>
<script type="text/javascript" src="{% static 'admin_interface/related-modal/related-modal.js' %}?v={{ version }}"></script>
{% endif %}
{% endblock %}
@@ -44,11 +55,20 @@
{% block branding %}
{% get_admin_interface_theme as theme %}
<h1 id="site-name">
{% if theme.logo_visible and theme.logo %}
<img class="logo" style="display:none;" src="{{ theme.logo.url }}" {% if theme.logo.width %}width="{{ theme.logo.width }}"{% endif %} {% if theme.logo.height %}height="{{ theme.logo.height }}"{% endif %} />
{% if theme.logo_visible %}
{% if theme.logo %}
<img class="logo" style="display:none;" src="{{ theme.logo.url }}" {% if theme.logo.width %}width="{{ theme.logo.width }}"{% endif %} {% if theme.logo.height %}height="{{ theme.logo.height }}"{% endif %} />
{% else %}
<img class="logo default" style="display:none;" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" width="104" height="36" />
{% endif %}
{% endif %}
{% if theme.title_visible %}
<span>{% if theme.title %}{% trans theme.title %}{% else %}{% trans 'Django administration' %}{% endif %}</span>
{% endif %}
</h1>
{% endblock %}
{% block welcome-msg %}
{% get_admin_interface_theme as theme %}
{% if theme.env_visible %}<span class="enviroment-label {{ theme.env }}"></span> - {% endif %}{{ block.super }}<br>
{% endblock %}
@@ -0,0 +1,15 @@
{% load i18n static %}<!DOCTYPE html>
<html>
<head><title>{% trans 'Popup closing...' %}</title></head>
<body>
<script type="text/javascript"
id="django-admin-popup-response-constants"
src="{% static "admin/js/popup_response.js" %}"
{% if popup_response_data %}
data-popup-response="{{ popup_response_data }}"
{% else %}
data-popup-response='{"action":"{{ action|escape }}","value":"{{ value|escape }}","obj":"{{ obj|escape }}","new_value":"{{ new_value|escape }}"}'
{% endif %}>
</script>
</body>
</html>
@@ -45,6 +45,18 @@
text-align:right;
}
@media (max-width:767px){
.admin-interface.login .submit-row label {
display:none;
}
.admin-interface.login .submit-row {
float: left;
width: 100%;
margin-top: 20px;
margin-bottom: 30px;
}
}
.admin-interface #header {
height:auto;
min-height:40px;
@@ -55,7 +67,7 @@
margin-top:10px;
margin-bottom:10px;
margin-right:15px;
display:inline-block !important;
display:inline-block !important; /* override inline display:none; */
}
.admin-interface #branding h1 img.logo+span {
@@ -66,14 +78,13 @@
border: 1px solid transparent;
}
.admin-interface fieldset.collapse.collapsed a.collapse-toggle {
font-weight: bold;
text-transform: lowercase;
}
.admin-interface fieldset.collapse.collapsed a.collapse-toggle,
.admin-interface fieldset.collapse a.collapse-toggle {
font-weight: bold;
font-weight: normal;
text-transform: lowercase;
font-size: 12px;
text-decoration: underline;
padding: 0 1px;
}
/*
@@ -83,7 +94,7 @@
*/
.admin-interface #changelist .paginator {
margin-top:-1px !important; /* merge 2 borders into 1 */
margin-top:-1px; /* merge 2 borders into 1 */
line-height:42px;
}
@@ -91,7 +102,7 @@
.admin-interface .paginator a:link,
.admin-interface .paginator a:visited,
.admin-interface .paginator .this-page {
padding:7px 12px !important;
padding:7px 12px;
}
.admin-interface .paginator a,
@@ -105,7 +116,7 @@
}
.admin-interface .paginator .this-page + a:not(.showall) {
margin-left:-25px/* !important*/;
margin-left:-25px;
}
body.admin-interface .paginator a.showall,
@@ -147,9 +158,16 @@ body.admin-interface .paginator a.showall:visited {
}
@media (max-width:767px){
.admin-interface form .form-row p.file-upload {
width: 100%;
}
.admin-interface form .form-row p.file-upload > a {
margin-right:0px;
display: block;
white-space: pre-wrap;
word-break: break-word;
}
.admin-interface form .form-row p.file-upload .clearable-file-input {
@@ -163,31 +181,36 @@ body.admin-interface .paginator a.showall:visited {
width: auto;
padding: 0px;
}
}
/* HELPS / MESSAGES */
.admin-interface form .wide p.help {
padding-left:10px;
}
@media (max-width:767px){
.admin-interface form .wide p.help {
padding-left:0px;
/* fix inline horizontal scroll caused by checkbox-row */
.admin-interface form .form-row > div.checkbox-row {
width: 100%;
}
}
.admin-interface form .aligned.wide p.help,
.admin-interface form .aligned.wide ul.error-list,
.admin-interface form .aligned.wide ul.errorlist {
/* FIX WIDE FIELDSET HELPS / ERROR MESSAGES */
.admin-interface form .wide p.help,
.admin-interface form .wide div.help {
padding-left: 50px;
}
.admin-interface form .wide input + p.help,
.admin-interface form .wide input + div.help {
margin-left: 160px;
}
@media (max-width:767px){
.admin-interface form .form-row div.help {
display: block;
width: 100%;
}
}
.admin-interface form .wide ul.errorlist {
margin-left: 200px;
}
.admin-interface form .aligned.wide div.help {
margin-left: 210px;
}
/* LIST FILTER */
.admin-interface .module.filtered h2 {
border-bottom-left-radius:0;
@@ -220,15 +243,17 @@ body.admin-interface .paginator a.showall:visited {
}
/* end fix */
/* selector chooseall / clearall color on hover -> just a lighten grey */
.admin-interface a.selector-chooseall:hover,
.admin-interface a.selector-clearall:hover {
color:#888888/* !important*/;
}
.admin-interface .inline-group {
/* begin fix restrict tabular-inline horizontal-scroll to inline-group instead of whole page */
.admin-interface .inline-group[data-inline-type="tabular"] {
overflow-x:auto;
}
/* end fix */
/* begin fix stacked-inline margin-bottom in responsive small viewport */
.admin-interface .inline-group[data-inline-type="stacked"] .module {
margin-bottom:0px;
}
/* end fix */
/* begin fix issue #10 - Related widget broken in long tabular inline */
.admin-interface .inline-group .tabular .related-widget-wrapper {
@@ -237,7 +262,7 @@ body.admin-interface .paginator a.showall:visited {
/* end fix */
.admin-interface .inline-related h3 {
padding:6px 10px/* !important*/;
padding:6px 10px;
}
/* begin fix issue #12 - Inlines bad delete buttons alignement */
@@ -245,13 +270,22 @@ body.admin-interface .paginator a.showall:visited {
text-align:right;
}
.admin-interface .inline-group .tabular tr td {
vertical-align: top;
}
.admin-interface .inline-group .tabular tr td.delete {
text-align:right;
padding-right:15px;
vertical-align: top;
}
.admin-interface .inline-group .tabular tr td input[type="checkbox"] {
margin: 7px 0px;
}
.admin-interface .inline-group .tabular tr td.delete a.inline-deletelink {
margin-top:2px;
margin-top:4px;
overflow:hidden;
text-indent:9999px;
}
@@ -268,8 +302,34 @@ body.admin-interface .paginator a.showall:visited {
background-color:#AAAAAA;
}
/* selector chooseall / clearall color on hover -> just a lighten grey */
.admin-interface a.selector-chooseall:hover,
.admin-interface a.selector-clearall:hover {
color:#888888/* !important*/;
/* fix textarea horizontal scroll on Firefox */
@media (max-width: 767px){
.admin-interface .aligned .form-row textarea {
width: 100% !important;
flex: 0 1 auto;
}
.admin-interface .aligned .form-row input[type="file"] {
width: 100% !important;
}
}
/* improve responsive selector */
/* fix [stacked, not-stacked] equalize horizontal and vertical select padding for selector */
.admin-interface .selector .selector-available select,
.admin-interface .selector .selector-chosen select {
padding: 7px 10px;
display: block;
}
/* fix [stacked, not-stacked] select options text overflow */
.admin-interface .selector .selector-available select option,
.admin-interface .selector .selector-chosen select option {
overflow: hidden;
text-overflow: ellipsis;
}
/* fix [not-stacked] equalize selectors height by adding the height of the .selector-available filter-bar */
.admin-interface .selector:not(.stacked) .selector-chosen select {
height: calc(46px + 17.2em) !important;
}
File diff suppressed because one or more lines are too long
@@ -2,6 +2,14 @@
ckeditor + light theme
https://github.com/Ikimea/ckeditor-light-theme
*/
.admin-interface .cke {
border: none;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.admin-interface .cke_inner,
.admin-interface .cke_wysiwyg_frame {
border-top-left-radius: 4px;
@@ -10,24 +18,46 @@ https://github.com/Ikimea/ckeditor-light-theme
border-bottom-right-radius: 4px;
}
.admin-interface .cke_top {
background: #f6f6f6;
border-top: none;
.admin-interface .cke_inner {
border: 1px solid #CCCCCC;
}
.admin-interface .cke_chrome {
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.admin-interface .cke_top {
background: #f8f8f8;
border-top: none;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom: 1px solid #EEEEEE;
padding-left: 10px;
padding-right: 10px;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.admin-interface .cke_toolgroup {
background: none;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.admin-interface .cke_bottom {
background: #f6f6f6;
border-top: 1px solid #efefef;
background: #f8f8f8;
border-top: 1px solid #EEEEEE;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.admin-interface .cke_source {
@@ -35,14 +65,62 @@ https://github.com/Ikimea/ckeditor-light-theme
box-sizing: border-box;
}
.admin-interface a.cke_button_on {
.admin-interface a.cke_button,
.admin-interface a.cke_button:active,
.admin-interface a.cke_button:hover,
.admin-interface a.cke_button:focus {
box-shadow: none;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
background-color: rgba(0,0,0,0.1);
background-image: none;
border-radius: 4px;
border: none;
}
.admin-interface a.cke_button:active,
.admin-interface a.cke_button:hover,
.admin-interface a.cke_button:focus {
background-color: #E8E8E8 !important;
}
.admin-interface a.cke_button.cke_button_on {
background-color: #CCCCCC !important;
}
.admin-interface a.cke_button.cke_button_disabled {
background-color: transparent !important;
}
.admin-interface .cke_resizer {
border-color: transparent #999 transparent transparent;
border-color: transparent #666666 transparent transparent;
}
@media (max-width: 767px){
.admin-interface .django-ckeditor-widget,
.admin-interface .cke {
width: 100% !important;
}
.admin-interface .cke_top {
padding-left: 10px;
padding-right: 10px;
}
.admin-interface .cke_toolbar {
height: auto;
}
.admin-interface .cke_contents {
height: auto;
}
.admin-interface .tabular .django-ckeditor-widget,
.admin-interface .tabular .cke {
width: 400px !important;
}
.admin-interface .tabular .cke_contents {
height: 90px !important;
}
}
@@ -0,0 +1,144 @@
/*
* jQuery UI CSS Framework
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
* http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/base/jquery.ui.core.css
*/
/*
backward compatibility:
.ui-tabs-selected: jquery ui < 1.10
.ui-tabs-active classes jquery ui >= 1.10
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
.ui-state-disabled { cursor: default !important; }
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/base/jquery.ui.tabs.css */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-active, .ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.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-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide {
position: absolute;
display: none;
}
/* Custom tabs theme */
.admin-interface .ui-tabs {
padding: 0;
}
.admin-interface .ui-tabs,
.admin-interface .ui-tabs .ui-widget-header,
.admin-interface .ui-tabs .ui-widget-header .ui-state-default {
border: none;
background: transparent;
}
.admin-interface .ui-tabs .ui-tabs-nav {
padding: 10px 0 0 10px;
border-bottom: none;
}
.admin-interface .ui-tabs .ui-tabs-nav li {
margin: 0 0 0 -1px;
}
.admin-interface .ui-tabs .ui-tabs-nav li.required {
font-weight: bold;
}
.admin-interface .ui-tabs .ui-tabs-nav li a {
border: 1px solid #eeeeee;
background-color: #f8f8f8;
border-bottom: none;
color: #666666;
padding: 7px 14px 8px 14px;
margin-top: 1px;
-moz-border-radius-topright: 4px;
-webkit-border-top-right-radius: 4px;
-moz-border-radius-topleft: 4px;
-webkit-border-top-left-radius: 4px;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
font-size: 12px;
text-transform: uppercase;
outline: none;
}
.admin-interface .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
.admin-interface .ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
padding: 8px 14px 8px 14px;
margin-top: 0px;
margin-bottom: -1px;
font-weight: bold;
background-color: #FFFFFF;
color: {{ theme.css_module_background_color }};
border-bottom: 1px solid #FFFFFF;
}
.admin-interface .ui-tabs .ui-tabs-panel {
border: 1px solid #eeeeee;
border-radius: 4px;
padding: 10px;
margin-bottom: 30px;
overflow: hidden;
}
.admin-interface .inline-group .tabular .ui-tabs .ui-tabs-panel {
padding: 8px;
}
.admin-interface .inline-group .tabular .ui-tabs .ui-tabs-nav {
padding-left: 4px;
}
.admin-interface .inline-group .tabular tr td {
vertical-align: bottom;
}
.admin-interface .inline-group .tabular tr.has_original td.original,
.admin-interface .inline-group .tabular tr td.delete {
vertical-align: top;
}
.admin-interface .inline-group .tabular .datetime > input {
margin-right: 5px;
}
.admin-interface .inline-group .tabular .datetime br {
display: none;
}
.admin-interface #changelist .row1:not(.selected):hover,
.admin-interface #changelist .row2:not(.selected):hover {
background: #f9f9f9;
}
.admin-interface .row2 {
background: #fcfcfc;
}
.admin-interface .row2 .ui-tabs .ui-tabs-nav li a {
background-color: #f5f5f5;
border: 1px solid #ebebeb;
}
.admin-interface .row2 .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
.admin-interface .row2 .ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
background-color: #fcfcfc;
border-bottom: 1px solid #fcfcfc;
}
@@ -1,6 +1,7 @@
/*
list-filter-dropdown
*/
.admin-interface .list-filter-dropdown {
margin-top:10px;
margin-bottom:20px;
@@ -1,65 +1,17 @@
/*
django-modeltranslation support
https://github.com/deschler/django-modeltranslation/pull/313/commits
https://github.com/deschler/django-modeltranslation
*/
.admin-interface #content h1 select {
text-transform:uppercase;
margin-left:15px;
text-transform: uppercase;
margin-left: 15px;
min-width: 50px;
}
.admin-interface .ui-tabs .ui-tabs-nav {
padding:10px 0 0 10px/* !important*/;
.admin-interface .ui-tabs .ui-tabs-panel[id^=tab_id_] {
border: none;
border-top: 1px solid #eeeeee;
padding: 0;
margin-bottom: 0;
}
.admin-interface .ui-tabs .ui-tabs-nav li {
margin-left:-1px/* !important*/;
}
.admin-interface .ui-tabs .ui-tabs-nav li a {
outline:none;
background-color:#f8f8f8/* !important*/;
border:1px solid #eeeeee/* !important*/;
border-bottom:none/* !important*/;
text-transform:uppercase;
padding:7px 14px 8px 14px/* !important*/;
margin-top:1px/* !important*/;
}
.admin-interface .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
.admin-interface .ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
padding:8px 14px 8px 14px/* !important*/;
margin-top:0px/* !important*/;
margin-bottom:-1px/* !important*/;
background-color:#FFFFFF/* !important*/;
color:{{ theme.css_module_background_color }} !important;
border-bottom:1px solid #FFFFFF !important;
}
.admin-interface .inline-group .tabular .ui-tabs .ui-tabs-panel {
padding:8px/* !important*/;
}
.admin-interface #changelist .row1:not(.selected):hover,
.admin-interface #changelist .row2:not(.selected):hover {
background:#f9f9f9;
}
.admin-interface .row2 {
background:#fcfcfc;
}
.admin-interface .row2 .ui-tabs .ui-tabs-nav li a {
background-color:#f5f5f5/* !important*/;
border:1px solid #ebebeb/* !important*/;
}
.admin-interface .row2 .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
.admin-interface .row2 .ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
background-color:#fcfcfc/* !important*/;
border-bottom:1px solid #fcfcfc/* !important*/;
}
@@ -0,0 +1,9 @@
{% if not theme.recent_actions_visible %}
.admin-interface.dashboard #content {
max-width:600px;
margin-right:0;
}
.admin-interface.dashboard #content #recent-actions-module {
display:none;
}
{% endif %}
@@ -3,12 +3,12 @@ related modal + magnific popup customization
https://github.com/dimsemenov/Magnific-Popup
*/
.admin-interface .related-modal.mfp-bg {
background-color:{{ theme.related_modal_background_color }}/* !important*/;
opacity: {{ theme.related_modal_background_opacity }}/* !important*/;
background-color:{{ theme.related_modal_background_color }};
opacity: {{ theme.related_modal_background_opacity }};
}
.admin-interface .related-modal .mfp-content {
height: 100%/* !important*/;
height: 100%;
overflow: hidden;
{% if theme.related_modal_rounded_corners %}
border-radius: 4px;
@@ -19,19 +19,19 @@ https://github.com/dimsemenov/Magnific-Popup
}
.admin-interface .related-modal .mfp-container {
padding: 90px 90px 90px 90px/* !important*/;
padding: 90px 90px 90px 90px;
}
.admin-interface .related-modal__nested .mfp-container {
padding: 30px 60px 30px 60px/* !important*/;
padding: 30px 60px 30px 60px;
}
@media (max-width:640px){
.admin-interface .related-modal .mfp-container {
padding: 60px 15px 60px 15px/* !important*/;
padding: 60px 15px 60px 15px;
}
.admin-interface .related-modal__nested .mfp-container {
padding: 30px 30px 30px 30px/* !important*/;
padding: 30px 30px 30px 30px;
}
}
@@ -42,7 +42,7 @@ https://github.com/dimsemenov/Magnific-Popup
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>");
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='%23eeeeee' fill='none' stroke-width='6' stroke-linecap='round'></circle><circle cx='50' cy='50' r='40' stroke='%23aaaaaa' 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;
@@ -2,8 +2,25 @@
sorl-thumbnail - improved AdminImageMixin widget layout
https://github.com/mariocesar/sorl-thumbnail
*/
.admin-interface a.thumbnail + input[type="checkbox"] {
margin: 10px 0;
.admin-interface a.thumbnail + a {
font-weight: normal;
}
.admin-interface a.thumbnail + a + input[type="checkbox"] {
margin: 10px 0px 10px 18px;
}
@media (max-width: 767px){
.admin-interface a.thumbnail + a {
display: block;
margin-top: 3px;
white-space: pre-wrap;
word-break: break-word;
}
.admin-interface a.thumbnail + a + input[type="checkbox"] {
margin: 15px 0;
}
}
.admin-interface a.thumbnail ~ label {
@@ -21,6 +38,13 @@ https://github.com/mariocesar/sorl-thumbnail
margin-bottom: 5px;
}
@media (max-width: 767px){
.admin-interface.change-form div[style="float:left"] {
font-size: 12px;
width: 100%;
}
}
.admin-interface .aligned .form-row a.thumbnail ~ input[type="file"] {
margin-top: 0px;
}
@@ -29,9 +53,15 @@ https://github.com/mariocesar/sorl-thumbnail
.admin-interface .aligned .form-row a.thumbnail ~ input[type="file"] {
width: auto;
padding: 0px;
display: block;
margin-top: 3px;
}
.admin-interface div[style="float:left"] {
margin-bottom: 0px;
}
}
.admin-interface div[style="float:left"] + div.help {
margin-top: 0px !important;
}
}
@@ -0,0 +1,37 @@
/*
django-tabbed-admin support
https://github.com/omji/django-tabbed-admin
*/
/* Hide tabs until ready */
/*
.admin-interface #tabs ul {
display: none;
}
.admin-interface #tabs ul.ui-tabs-nav {
display: block;
}
*/
.admin-interface .ui-tabs .ui-tabs-panel[id^=tabs] .module.aligned:last-child {
margin-bottom: 0;
}
.admin-interface .ui-tabs .ui-tabs-panel[id^=tabs] .module.aligned:last-child .form-row:last-child {
border-bottom: none;
}
@media (max-width: 350px){
.admin-interface .ui-tabs .ui-tabs-panel[id^=tabs] .vTextField,
.admin-interface .inline-related .vTextField {
width: 17em;
}
}
@media (max-width: 767px){
/* fix horizontal overflow - responsive.css:563 */
.admin-interface .ui-tabs .ui-tabs-panel[id^=tabs] .aligned .form-row > div:not([class]) {
width: 100% !important;
}
}
@@ -1,3 +1,3 @@
.admin-interface textarea.tinymce ~ p.help {
margin-top:5px/* !important*/;
margin-top:5px !important;
}
@@ -1,4 +1,4 @@
{% load i18n admin_interface_tags %}
{% load i18n %}
<div class="list-filter-dropdown">
<h3>{% blocktrans with title as filter_title %} By {{ filter_title }} {% endblocktrans %}</h3>
@@ -1,15 +1,35 @@
# -*- coding: utf-8 -*-
from django import template
from django import template, VERSION
from admin_interface.models import Theme
from admin_interface.version import __version__
register = template.Library()
if VERSION < (1, 9):
simple_tag = register.assignment_tag
else:
simple_tag = register.simple_tag
@register.assignment_tag(takes_context = True)
@simple_tag(takes_context=True)
def get_admin_interface_theme(context):
theme = None
request = context.get('request', None)
return Theme.get_active_theme()
if request:
theme = getattr(request, 'admin_interface_theme', None)
if not theme:
theme = Theme.get_active_theme()
if request:
request.admin_interface_theme = theme
return theme
@simple_tag(takes_context=False)
def get_admin_interface_version():
return __version__
+1 -2
View File
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
__version__ = '0.4.2'
__version__ = '0.8.0'
+24 -7
View File
@@ -1,25 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from setuptools import find_packages, setup
import os
exec(open('admin_interface/version.py').read())
github_url = 'https://github.com/fabiocaccamo'
package_name = 'django-admin-interface'
package_path = os.path.abspath(os.path.dirname(__file__))
long_description_file_path = os.path.join(package_path, 'README.rst')
long_description = ''
try:
with open(long_description_file_path) as f:
long_description = f.read()
except IOError:
pass
setup(
name='django-admin-interface',
name=package_name,
packages=find_packages(exclude=['contrib', 'docs', 'tests*']),
include_package_data=True,
version=__version__,
description='django-admin-interface is a modern responsive flat admin interface customizable by the admin itself.',
long_description=long_description,
author='Fabio Caccamo',
author_email='fabio.caccamo@gmail.com',
url='https://github.com/fabiocaccamo/django-admin-interface',
download_url='https://github.com/fabiocaccamo/django-admin-interface/archive/%s.tar.gz' % __version__,
url='%s/%s' % (github_url, package_name, ),
download_url='%s/%s/archive/%s.tar.gz' % (github_url, package_name, __version__, ),
keywords=['django', 'admin', 'interface', 'responsive', 'flat', 'theme', 'custom', 'ui'],
requires=['django(>=1.7)'],
install_requires=[
'django-colorfield==0.1.12',
'django-flat-theme==1.1.4',
'django-flat-responsive==1.3.0'
'django-colorfield >= 0.1, < 1.0',
'django-flat-theme >= 1.0, < 2.0',
'django-flat-responsive >= 1.0, < 3.0',
],
classifiers=[
'Development Status :: 5 - Production/Stable',
@@ -30,6 +45,8 @@ setup(
'Framework :: Django :: 1.9',
'Framework :: Django :: 1.10',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Framework :: Django :: 2.1',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
@@ -40,9 +57,9 @@ setup(
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Topic :: Software Development :: Build Tools',
],
license='MIT',
test_suite='runtests.runtests'
)
+31 -8
View File
@@ -9,24 +9,46 @@ SECRET_KEY = 'django-admin-interface'
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'admin_interface',
'flat_responsive',
'flat', #if django version < 1.9
'colorfield',
]
if django.VERSION < (1, 9):
# ONLY if django version < 1.9
INSTALLED_APPS += [
'flat',
]
if django.VERSION < (2, 0):
# ONLY if django version < 2.0
INSTALLED_APPS += [
'flat_responsive',
]
INSTALLED_APPS += [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.messages',
'django.contrib.sessions',
]
MIDDLEWARE_CLASSES = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
]
if django.VERSION < (2, 0):
MIDDLEWARE_CLASSES = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware'
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
]
else:
MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
]
TEMPLATES = [{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
@@ -35,6 +57,7 @@ TEMPLATES = [{
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
]
},
},]
+92
View File
@@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
import django
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.test import override_settings, TestCase
from admin_interface.settings import check_installed_apps
class AdminInterfaceSettingsTestCase(TestCase):
DJANGO_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.messages',
'django.contrib.sessions',
]
def setUp(self):
pass
def tearDown(self):
pass
def __test_installed_apps(self):
dj_version = django.VERSION
installed_apps = settings.INSTALLED_APPS
if 'colorfield' not in installed_apps:
self.assertRaises(ImproperlyConfigured, check_installed_apps)
elif 'flat' not in installed_apps and dj_version < (1, 9):
self.assertRaises(ImproperlyConfigured, check_installed_apps)
elif 'flat' in installed_apps and dj_version >= (1, 9):
self.assertRaises(ImproperlyConfigured, check_installed_apps)
elif 'flat_responsive' not in installed_apps and dj_version < (2, 0):
self.assertRaises(ImproperlyConfigured, check_installed_apps)
elif 'flat_responsive' in installed_apps and dj_version >= (2, 0):
self.assertRaises(ImproperlyConfigured, check_installed_apps)
else:
check_installed_apps()
@override_settings(
INSTALLED_APPS = [
'admin_interface',
'colorfield',
'flat',
'flat_responsive',
] + DJANGO_APPS
)
def test_installed_apps_all(self):
self.__test_installed_apps()
@override_settings(
INSTALLED_APPS = [
'admin_interface',
# 'colorfield',
'flat',
'flat_responsive',
] + DJANGO_APPS
)
def test_installed_apps_no_colorfield(self):
self.__test_installed_apps()
@override_settings(
INSTALLED_APPS = [
'admin_interface',
'colorfield',
# 'flat',
'flat_responsive',
] + DJANGO_APPS
)
def test_installed_apps_no_flat(self):
self.__test_installed_apps()
@override_settings(
INSTALLED_APPS = [
'admin_interface',
'colorfield',
'flat',
# 'flat_responsive',
] + DJANGO_APPS
)
def test_installed_apps_no_flat_responsive(self):
self.__test_installed_apps()
+65 -34
View File
@@ -2,17 +2,21 @@
from django.conf import settings
from django.test import TestCase
from django.test.client import RequestFactory
from django.template import Context, Template
import os
import random
import shutil
from admin_interface.models import Theme
from admin_interface.templatetags import admin_interface_tags as templatetags
from admin_interface.version import __version__
class AdminInterfaceTestCase(TestCase):
def setUp(self):
self.request_factory = RequestFactory()
pass
def tearDown(self):
@@ -20,13 +24,9 @@ class AdminInterfaceTestCase(TestCase):
pass
def __render_template(self, string, context=None):
context = context or {}
context = Context(context)
return Template(string).render(context)
return Template(string).render(Context(context or {}))
def __test_active_theme(self):
theme = Theme.get_active_theme()
print( theme )
self.assertTrue(theme != None)
@@ -34,17 +34,14 @@ class AdminInterfaceTestCase(TestCase):
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
@@ -52,40 +49,28 @@ class AdminInterfaceTestCase(TestCase):
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):
def test_default_theme_activated_after_update_if_multiple_active_themes(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.update( active = False )
Theme.objects.update( active = True )
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_default_theme_logo_created_if_deleted(self):
Theme.objects.all().delete()
theme = Theme.get_active_theme()
theme.logo = ''
theme.save()
theme = Theme.get_active_theme()
self.assertNotEqual( theme.logo, None )
def test_default_theme_logo_not_created_if_not_deleted(self):
Theme.objects.all().delete()
theme = Theme.get_active_theme()
self.assertNotEqual( theme.logo, None )
logo_url = theme.logo.url
theme = Theme.get_active_theme()
self.assertEqual( theme.logo.url, logo_url )
self.__test_active_theme()
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 )
@@ -93,9 +78,55 @@ class AdminInterfaceTestCase(TestCase):
self.assertEqual( Theme.get_active_theme().pk, theme_3.pk )
self.__test_active_theme()
def test_templatetags(self):
def test_last_theme_activated_on_multiple_themes_activated(self):
Theme.objects.all().delete()
rendered = self.__render_template('{% load admin_interface_tags %}{% get_admin_interface_theme as theme %}{{ theme.name }}')
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_4 = Theme.objects.create( name = 'Custom 4', active = True )
theme_5 = Theme.objects.create( name = 'Custom 5', active = True )
themes = [ theme_1, theme_2, theme_3, theme_4, theme_5 ]
for i in range(5):
random.shuffle(themes)
for theme in themes:
theme.set_active()
self.assertEqual( Theme.get_active_theme().pk, theme.pk )
self.__test_active_theme()
def test_templatetags_get_theme(self):
Theme.objects.all().delete()
context = Context({})
theme = templatetags.get_admin_interface_theme(context)
self.assertEqual(theme.name, 'Django')
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_theme as theme %}'\
'{{ theme.name }}', context)
self.assertEqual(rendered, 'Django')
def test_templatetags_get_theme_with_request(self):
Theme.objects.all().delete()
context = Context({
'request': self.request_factory.get('/')
})
theme = templatetags.get_admin_interface_theme(context)
self.assertEqual(theme.name, 'Django')
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_theme as theme %}'\
'{{ theme.name }}', context)
self.assertEqual(rendered, 'Django')
def test_templatetags_get_version(self):
version = templatetags.get_admin_interface_version()
self.assertEqual(version, __version__)
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_version as version %}'\
'{{ version }}')
self.assertEqual(rendered, __version__)
def test_repr(self):
theme = Theme.get_active_theme()
self.assertEqual( '{0}'.format(theme), 'Django' )
+13 -9
View File
@@ -1,17 +1,21 @@
[tox]
envlist =
py27-{17,18,19,110,111},
py34-{17,18,19,110,111},
py35-{18,19,110,111},
py36-{18,19,110,111},
py27-{dj17,dj18,dj19,dj110,dj111},
py34-{dj17,dj18,dj19,dj110,dj111,dj20},
py35-{dj18,dj19,dj110,dj111,dj20,dj21,djmaster},
py36-{dj18,dj19,dj110,dj111,dj20,dj21,djmaster},
py37-{dj20,dj21,djmaster},
[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
dj17: Django >= 1.7, < 1.8
dj18: Django >= 1.8, < 1.9
dj19: Django >= 1.9, < 1.10
dj110: Django >= 1.10, < 1.11
dj111: Django >= 1.11, < 1.12
dj20: Django >= 2.0, < 2.1
dj21: Django >= 2.1, < 2.2
djmaster: https://github.com/django/django/archive/master.tar.gz
coverage
codecov
commands =