Compare commits

...
56 Commits
Author SHA1 Message Date
davide_borgonovo 4244b0b3ae Aggiornata versione 2022-04-28 18:34:52 +02:00
davide_borgonovo 7baffaf490 Ora più utenti possono avere lo stesso tema e li setto con una Inline 2022-04-28 18:34:28 +02:00
davide_borgonovo b8a160f746 Aggiornata versione 2022-03-15 17:59:01 +01:00
davide_borgonovo 5e3e3a1480 Revert "Converted dynamic inline CSS to external static CSS using CSS variables. #157 #93"
This reverts commit 8fe7178a13.
2022-03-15 17:56:03 +01:00
davide_borgonovo 7d649185cb Forkino per aggiungere modalità demo con un tema selezionato e per rendere il tema associabile ad un utente 2022-03-14 23:58:22 +01:00
Fabio Caccamo 3ff4f05e51 Update test-package.yml
Revert "Update test-package.yml"

This reverts commit d5cb8ff3fd09d43e3b2d333693b9fd97619a2b7f.

Update test-package.yml

Updated `create-matrix-action` version.

Update test-package.yml

Update test-package.yml

Update test-package.yml

Update test-package.yml
2022-03-10 15:50:09 +01:00
Fabio Caccamo d8cffd8c2c Updated CHANGELOG and version. 2022-03-09 10:14:57 +01:00
Mustafa M. A. U. AbuGhazy 8fe7178a13 Converted dynamic inline CSS to external static CSS using CSS variables. #157 #93 2022-03-09 10:14:57 +01:00
Fabio Caccamo d2b680e477 Update test-package.yml 2022-03-09 10:14:57 +01:00
Fabio Caccamo c07cad01e9 Updated CHANGELOG and version. 2022-02-24 10:24:45 +01:00
Fabio Caccamo 9c3798b155 Sorted imports. [ci skip] 2022-02-24 10:24:28 +01:00
MG Santos 06069644fd Removed public disclosures of the lib's version. #154 2022-02-22 16:22:19 +01:00
Fabio Caccamo f3e7fcef33 Delete label-sponsors.yml 2022-02-18 00:05:28 +01:00
Fabio Caccamo e64614274c Reformatted code with Black. 2022-02-08 18:58:59 +01:00
Fabio Caccamo 9b252d8577 Create label-sponsors.yml 2022-02-07 01:09:56 +01:00
Fabio Caccamo 1db3436e2a Updated CHANGELOG and version. 2022-02-04 22:06:34 +01:00
Fabio Caccamo 0f58934ae4 Updated translations. 2022-02-04 22:04:20 +01:00
Fabio Caccamo ec84ce8119 Added missing closing quote and parenthesis to polish translation. 2022-02-04 16:41:52 +01:00
Kamil 369c5582a6 Added Polish translation. #152 2022-02-04 14:35:51 +01:00
Fabio Caccamo 8c4ea1f749 Create dependabot.yml 2022-02-03 08:45:34 +01:00
leandromsd 7649fef2c2 Correcting spelling error (#151) 2022-01-28 14:17:57 +01:00
Fabio Caccamo 958996f119 Update test-package.yml 2022-01-27 23:26:30 +01:00
Fabio Caccamo 7719ac4277 Updated README. [ci skip] 2022-01-27 23:26:26 +01:00
Fabio Caccamo 8930ba1ddc Fixed login logo max-width and title color. 2022-01-21 14:17:09 +01:00
Fabio Caccamo ee63826836 Updated CHANGELOG and version. 2022-01-21 13:41:56 +01:00
Fabio Caccamo 7c0a105c92 Fixed body scroll reset to top when opening related modal. #150 2022-01-21 13:39:21 +01:00
Fabio Caccamo c8ababb8e4 Create SECURITY.md 2022-01-20 19:26:59 +01:00
leandromsdandLeandro Caixeta 384a63f76f Added portuguese brazil localization. #149
* add portuguese brazil language

* replace empty translations with the original text

Co-authored-by: Leandro Caixeta <leandro.caixeta@buser.com.br>
2022-01-20 13:39:38 +01:00
Fabio Caccamo f6c4d50bb3 Update test-package.yml 2022-01-17 22:11:05 +01:00
Fabio Caccamo 84c15d2b28 Update setup.py 2022-01-12 02:23:16 +01:00
Fabio Caccamo 6d46dfafc2 Updated version and CHANGELOG. 2022-01-05 18:48:55 +01:00
Micah Walter 3f076578bb Added link to admin home page on logo and title. #147 2022-01-05 18:31:07 +01:00
Fabio Caccamo cc4c379465 Fixed missing comma in tests settings MIDDLEWARE_CLASSES. #145 2022-01-04 18:16:53 +01:00
Fabio Caccamo c9f0795a95 Updated workflows.
- Added `create-release.yml` workflow.
- Renamed `pythonpackage.yml` to `test-package.yml`.
2021-12-22 21:56:47 +01:00
Fabio Caccamo 042e93a84b Fixed collapsed inlines rounded bottom borders. 2021-12-21 15:58:39 +01:00
Fabio Caccamo c9e800b5ab Updated README. #115 2021-12-15 11:14:29 +01:00
Fabio Caccamo 7257fbffb3 Merge branch 'master' of https://github.com/fabiocaccamo/django-admin-interface 2021-12-08 15:52:44 +01:00
Fabio Caccamo 1f690978bf Added django 4.0 to CI. 2021-12-08 15:52:41 +01:00
Fabio Caccamo 3d9cfd134d Update pythonpackage.yml 2021-12-07 21:07:33 +01:00
Fabio Caccamo 017f905330 Update pythonpackage.yml 2021-12-07 18:48:23 +01:00
Fabio Caccamo 796cea4a49 Updated CHANGELOG and version. [ci skip] 2021-12-07 11:08:57 +01:00
Fabio Caccamo 0178e0ccff Fixed check_installed_apps checks. 2021-12-07 10:59:57 +01:00
Fabio Caccamo 70ed000f08 Replaced travis with GitHub action workflow. #142 2021-12-07 10:43:46 +01:00
Éric 294f8520ab Fix django default appconfig deprecation warning (#141) 2021-12-06 22:33:33 +01:00
Fabio Caccamo 1b28c183f0 Update README.md 2021-12-06 21:19:21 +01:00
Fabio Caccamo 520dceaa97 Updated CHANGELOG and version. 2021-11-25 11:58:11 +01:00
Fabio Caccamo 2fa85eb964 Fixed migration error. 2021-11-25 11:58:00 +01:00
Fabio Caccamo 3bc6e6fe3b Revert "Removed wrong migration."
This reverts commit 8ded8e160b.
2021-11-25 11:55:57 +01:00
Fabio Caccamo 3dc31df5f1 Updated CHANGELOG and version. 2021-11-25 11:49:22 +01:00
Fabio Caccamo 8ded8e160b Removed wrong migration. 2021-11-25 11:49:13 +01:00
Fabio Caccamo f4e5662e49 Updated README.md. [ci skip] 2021-11-24 18:49:47 +01:00
Fabio Caccamo dba9c35ac8 Updated CHANGELOG and version. 2021-11-24 18:47:05 +01:00
Fabio Caccamo 3431565f74 Removed theme css field. 2021-11-24 18:44:28 +01:00
Fabio Caccamo 6a42df67b1 Updated migration code generated by django. 2021-11-24 18:44:15 +01:00
Fabio Caccamo 593709808f Added foldable apps support. #117 2021-11-23 22:32:01 +01:00
Fabio Caccamo 3a2b59f7cc Create codeql-analysis.yml 2021-10-14 12:23:34 +02:00
79 changed files with 2439 additions and 1308 deletions

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
+71
View File
@@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '26 21 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
+29
View File
@@ -0,0 +1,29 @@
name: Create release
on:
push:
tags:
- '*.*.*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Extract release notes
id: extract-release-notes
uses: ffurrer2/extract-release-notes@v1
- name: Create release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: false
prerelease: false
body: ${{ steps.extract-release-notes.outputs.release_notes }}
+93
View File
@@ -0,0 +1,93 @@
name: Test package
on:
push:
pull_request:
workflow_dispatch:
jobs:
prepare:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Create matrix
uses: fabiocaccamo/create-matrix-action@v2
id: create_matrix
with:
matrix: |
python-version {2.7}, django-version {1.8,1.9,1.10,1.11}, database {sqlite,postgres}
python-version {3.6}, django-version {1.8,1.9,1.10,1.11,2.0,2.1,2.2,3.0,3.1,3.2}, database {sqlite,postgres}
python-version {3.7}, django-version {2.0,2.1,2.2,3.0,3.1,3.2}, database {sqlite,postgres}
python-version {3.8}, django-version {2.2,3.0,3.1,3.2}, database {sqlite,postgres}
python-version {3.9}, django-version {2.2,3.0,3.1,3.2}, database {sqlite,postgres}
python-version {3.10}, django-version {3.2,4.0}, database {sqlite,postgres}
outputs:
matrix: ${{ steps.create_matrix.outputs.matrix }}
test:
needs: prepare
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include: ${{fromJson(needs.prepare.outputs.matrix)}}
services:
postgres:
image: postgres:latest
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
ports:
- 5432:5432
# needed because the postgres container does not provide a healthcheck
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- uses: actions/checkout@v2
- name: Install psycopg2 prerequisites
run: sudo apt-get install libpq-dev
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Upgrade pip version
run: |
pip install pip --upgrade
- name: Install django
run: |
pip install "Django ~= ${{ matrix.django-version }}"
- name: Install requirements
run: |
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Run tests
env:
DATABASE_ENGINE: ${{ matrix.database }}
run: |
coverage run --append --source=admin_interface setup.py test
coverage xml -o ./coverage.xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
fail_ci_if_error: false
files: ./coverage.xml
flags: unittests
verbose: true
+2
View File
@@ -56,3 +56,5 @@ docs/_build/
target/
screenshots
TODO.txt
.idea/
-171
View File
@@ -1,171 +0,0 @@
os: linux
dist: xenial
language: python
cache: pip
jobs:
include:
- python: "2.7"
env: TOX_ENV=py27-dj17-sqlite
- python: "2.7"
env: TOX_ENV=py27-dj17-postgres
- python: "2.7"
env: TOX_ENV=py27-dj18-sqlite
- python: "2.7"
env: TOX_ENV=py27-dj18-postgres
- python: "2.7"
env: TOX_ENV=py27-dj19-sqlite
- python: "2.7"
env: TOX_ENV=py27-dj19-postgres
- python: "2.7"
env: TOX_ENV=py27-dj110-sqlite
- python: "2.7"
env: TOX_ENV=py27-dj110-postgres
- python: "2.7"
env: TOX_ENV=py27-dj111-sqlite
- python: "2.7"
env: TOX_ENV=py27-dj111-postgres
- python: "3.5"
env: TOX_ENV=py35-dj18-sqlite
- python: "3.5"
env: TOX_ENV=py35-dj18-postgres
- python: "3.5"
env: TOX_ENV=py35-dj19-sqlite
- python: "3.5"
env: TOX_ENV=py35-dj19-postgres
- python: "3.5"
env: TOX_ENV=py35-dj110-sqlite
- python: "3.5"
env: TOX_ENV=py35-dj110-postgres
- python: "3.5"
env: TOX_ENV=py35-dj111-sqlite
- python: "3.5"
env: TOX_ENV=py35-dj111-postgres
- python: "3.5"
env: TOX_ENV=py35-dj20-sqlite
- python: "3.5"
env: TOX_ENV=py35-dj20-postgres
- python: "3.5"
env: TOX_ENV=py35-dj21-sqlite
- python: "3.5"
env: TOX_ENV=py35-dj21-postgres
# - python: "3.5"
# env: TOX_ENV=py35-dj22-sqlite
- python: "3.5"
env: TOX_ENV=py35-dj22-postgres
- python: "3.6"
env: TOX_ENV=py36-dj111-sqlite
- python: "3.6"
env: TOX_ENV=py36-dj111-postgres
- python: "3.6"
env: TOX_ENV=py36-dj20-sqlite
- python: "3.6"
env: TOX_ENV=py36-dj20-postgres
- python: "3.6"
env: TOX_ENV=py36-dj21-sqlite
- python: "3.6"
env: TOX_ENV=py36-dj21-postgres
- python: "3.6"
env: TOX_ENV=py36-dj22-sqlite
- python: "3.6"
env: TOX_ENV=py36-dj22-postgres
- python: "3.6"
env: TOX_ENV=py36-dj30-sqlite
- python: "3.6"
env: TOX_ENV=py36-dj30-postgres
- python: "3.6"
env: TOX_ENV=py36-dj31-sqlite
- python: "3.6"
env: TOX_ENV=py36-dj31-postgres
- python: "3.6"
env: TOX_ENV=py36-dj32-sqlite
- python: "3.6"
env: TOX_ENV=py36-dj32-postgres
- python: "3.6"
env: TOX_ENV=py36-djmaster-sqlite
- python: "3.6"
env: TOX_ENV=py36-djmaster-postgres
- python: "3.7"
env: TOX_ENV=py37-dj20-sqlite
- python: "3.7"
env: TOX_ENV=py37-dj20-postgres
- python: "3.7"
env: TOX_ENV=py37-dj21-sqlite
- python: "3.7"
env: TOX_ENV=py37-dj21-postgres
- python: "3.7"
env: TOX_ENV=py37-dj22-sqlite
- python: "3.7"
env: TOX_ENV=py37-dj22-postgres
- python: "3.7"
env: TOX_ENV=py37-dj30-sqlite
- python: "3.7"
env: TOX_ENV=py37-dj30-postgres
- python: "3.7"
env: TOX_ENV=py37-dj31-sqlite
- python: "3.7"
env: TOX_ENV=py37-dj31-postgres
- python: "3.7"
env: TOX_ENV=py37-dj32-sqlite
- python: "3.7"
env: TOX_ENV=py37-dj32-postgres
- python: "3.7"
env: TOX_ENV=py37-djmaster-sqlite
- python: "3.7"
env: TOX_ENV=py37-djmaster-postgres
- python: "3.8"
env: TOX_ENV=py38-dj22-sqlite
- python: "3.8"
env: TOX_ENV=py38-dj22-postgres
- python: "3.8"
env: TOX_ENV=py38-dj30-sqlite
- python: "3.8"
env: TOX_ENV=py38-dj30-postgres
- python: "3.8"
env: TOX_ENV=py38-dj31-sqlite
- python: "3.8"
env: TOX_ENV=py38-dj31-postgres
- python: "3.8"
env: TOX_ENV=py38-dj32-sqlite
- python: "3.8"
env: TOX_ENV=py38-dj32-postgres
- python: "3.8"
env: TOX_ENV=py38-djmaster-sqlite
- python: "3.8"
env: TOX_ENV=py38-djmaster-postgres
- python: "3.9"
env: TOX_ENV=py39-dj22-sqlite
- python: "3.9"
env: TOX_ENV=py39-dj22-postgres
- python: "3.9"
env: TOX_ENV=py39-dj30-sqlite
- python: "3.9"
env: TOX_ENV=py39-dj30-postgres
- python: "3.9"
env: TOX_ENV=py39-dj31-sqlite
- python: "3.9"
env: TOX_ENV=py39-dj31-postgres
- python: "3.9"
env: TOX_ENV=py39-dj32-sqlite
- python: "3.9"
env: TOX_ENV=py39-dj32-postgres
- python: "3.9"
env: TOX_ENV=py39-djmaster-sqlite
- python: "3.9"
env: TOX_ENV=py39-djmaster-postgres
allow_failures:
- env: TOX_ENV=py36-djmaster-sqlite
- env: TOX_ENV=py36-djmaster-postgres
- env: TOX_ENV=py37-djmaster-sqlite
- env: TOX_ENV=py37-djmaster-postgres
- env: TOX_ENV=py38-djmaster-sqlite
- env: TOX_ENV=py38-djmaster-postgres
- env: TOX_ENV=py39-djmaster-sqlite
- env: TOX_ENV=py39-djmaster-postgres
install:
- pip install tox
services:
- postgresql
before_script:
- psql -c 'create database admin_interface;' -U postgres
script:
- tox -e $TOX_ENV
+37
View File
@@ -4,6 +4,43 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.19.0](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.19.0) - 2022-03-08
- Converted dynamic inline CSS to external static CSS using CSS variables. #157 #93 (thanks to [@Mustafa-Abu-Ghazy](https://github.com/Mustafa-Abu-Ghazy))
## [0.18.7](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.18.7) - 2022-02-24
- Removed public disclosures of the lib's version. #154 (thanks to [@mintyPT](https://github.com/mintyPT))
- Reformatted code with **Black**.
## [0.18.6](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.18.6) - 2022-02-04
- Added polish (`pl`) localization by [paduszyk](https://github.com/paduszyk). #152
- Fixed login logo `max-width` and title `color`.
## [0.18.5](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.18.5) - 2022-01-21
- Added portuguese brazil (`pt_BR`) localization by [leandromsd](https://github.com/leandromsd). #149
- Fixed body scroll reset to top when opening related modal. #150
## [0.18.4](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.18.4) - 2022-01-05
- Added official django 4.0 support.
- Added link to admin home page on logo and title. #147
- Fixed collapsed inlines rounded bottom borders.
- Fixed missing comma in tests settings `MIDDLEWARE_CLASSES`. #145
## [0.18.3](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.18.3) - 2021-12-07
- Added official python 3.10 support.
- Replaced travis with GitHub action workflow. #142
- Fixed `check_installed_apps` checks.
- Fixed django default appconfig deprecation warning. #141
## [0.18.2](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.18.2) - 2021-10-25
- Fixed migration error.
## [0.18.1](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.18.1) - 2021-10-25
- Removed wrong migration.
## [0.18.0](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.18.0) - 2021-10-24
- Added foldable apps support. #117
- Removed `css` field from `Theme` model.
## [0.17.3](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.17.3) - 2021-10-12
- Fixed `FileExtensionValidator` `TypeError` on django < 1.11.
+73 -34
View File
@@ -2,22 +2,24 @@
[![](https://img.shields.io/pypi/djversions/django-admin-interface?color=0C4B33&logo=django&logoColor=white&label=django)](https://www.djangoproject.com/)
[![](https://img.shields.io/pypi/v/django-admin-interface.svg?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/django-admin-interface/)
[![](https://pepy.tech/badge/django-admin-interface)](https://pepy.tech/project/django-admin-interface)
[![](https://pepy.tech/badge/django-admin-interface/month)](https://pepy.tech/project/django-admin-interface)
[![](https://img.shields.io/github/stars/fabiocaccamo/django-admin-interface?logo=github)](https://github.com/fabiocaccamo/django-admin-interface/)
[![](https://badges.pufler.dev/visits/fabiocaccamo/django-admin-interface?label=visitors&color=blue)](https://badges.pufler.dev)
[![](https://img.shields.io/pypi/l/django-admin-interface.svg?color=blue)](https://github.com/fabiocaccamo/django-admin-interface/blob/master/LICENSE.txt)
[![](https://img.shields.io/travis/fabiocaccamo/django-admin-interface?logo=travis&label=build)](https://travis-ci.org/fabiocaccamo/django-admin-interface)
[![](https://img.shields.io/github/workflow/status/fabiocaccamo/django-admin-interface/Test%20package?label=build&logo=github)](https://github.com/fabiocaccamo/django-admin-interface)
[![](https://img.shields.io/codecov/c/gh/fabiocaccamo/django-admin-interface?logo=codecov)](https://codecov.io/gh/fabiocaccamo/django-admin-interface)
[![](https://img.shields.io/codacy/grade/21cb657283c04e70b56fb935277a1ad1?logo=codacy)](https://www.codacy.com/app/fabiocaccamo/django-admin-interface)
[![](https://img.shields.io/codeclimate/maintainability/fabiocaccamo/django-admin-interface?logo=code-climate)](https://codeclimate.com/github/fabiocaccamo/django-admin-interface/)
[![](https://requires.io/github/fabiocaccamo/django-admin-interface/requirements.svg?branch=master)](https://requires.io/github/fabiocaccamo/django-admin-interface/requirements/?branch=master)
[![](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
# 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**)*
@@ -26,6 +28,7 @@ django-admin-interface is a modern **responsive flat admin interface customizabl
- Environment name/marker
- Language chooser
- List filter dropdown
- `NEW` **Foldable apps** *(accordions in the navigation bar)*
- `NEW` **List filter sticky**
- `NEW` **Form controls sticky** *(pagination and save/delete buttons)*
- Compatibility / Style optimizations for:
@@ -36,59 +39,63 @@ django-admin-interface is a modern **responsive flat admin interface customizabl
- `django-tabbed-admin`
- `sorl-thumbnail`
---
## Installation
- Run `pip install django-admin-interface`
- Add `admin_interface`, `flat_responsive`, `flat` and `colorfield` to `settings.INSTALLED_APPS` **before** `django.contrib.admin`
```python
INSTALLED_APPS = (
#...
'admin_interface',
'flat_responsive', # only if django version < 2.0
'flat', # only if django version < 1.9
'colorfield',
"admin_interface",
"flat_responsive", # only if django version < 2.0
"flat", # only if django version < 1.9
"colorfield",
#...
'django.contrib.admin',
"django.contrib.admin",
#...
)
# only if django version >= 3.0
X_FRAME_OPTIONS = 'SAMEORIGIN'
SILENCED_SYSTEM_CHECKS = ['security.W019']
X_FRAME_OPTIONS = "SAMEORIGIN"
SILENCED_SYSTEM_CHECKS = ["security.W019"]
```
- Run ``python manage.py migrate``
- Run ``python manage.py collectstatic``
- 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``
- 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``
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``
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``
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``
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``
`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)*.
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.
@@ -119,6 +126,7 @@ You can add **theme support to existing third-party libraries** using the follow
- `--admin-interface-related-modal-background-color`
- `--admin-interface-related-modal-background-opacity`
---
## Screenshots
###### Admin login
@@ -133,11 +141,50 @@ You can add **theme support to existing third-party libraries** using the follow
###### Admin theme customization
![django-admin-interface_theme_customization](https://cloud.githubusercontent.com/assets/1035294/11240250/7350d942-8df1-11e5-9b28-f2f54c333cdc.gif)
---
## FAQ
- #### I already have a custom `base_site.html`, how can I make it work?
### Custom `base-site.html`
> 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`
### Language Chooser not showing
> I have enabled the **Language Chooser**, but it is not visible in the admin, what should I do?
You must configure multilanguage `settings` and `urls` correctly:
```python
LANGUAGES = (
("en", _("English")),
("it", _("Italiano")),
("fr", _("Française")),
# more than one language is expected here
)
LANGUAGE_CODE = "en"
USE_I18N = True
MIDDLEWARE = [
# ...
"django.middleware.locale.LocaleMiddleware",
# ...
]
```
```python
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from django.urls import include, path
# ...
urlpatterns = [
path("i18n/", include("django.conf.urls.i18n")),
]
urlpatterns += i18n_patterns(path("admin/", admin.site.urls))
```
---
## Testing
```bash
# create python virtual environment
@@ -151,6 +198,7 @@ git clone https://github.com/fabiocaccamo/django-admin-interface.git src && cd s
# install dependencies
pip install -r requirements.txt
pip install -r requirements-test.txt
# run tests
tox
@@ -160,24 +208,13 @@ python setup.py test
python -m django test --settings "tests.settings"
```
---
## License
Released under [MIT License](LICENSE.txt).
---
## Supporting
I would like to spend more time on this project, especially to improve it and adding new features.
As everyone knows open-source projects takes up a lot of time that is unpaid. :money_with_wings:
If you are using this package in commercial project(s), please consider the idea to become a sponsor or donating once:
- [GitHub Sponsor](https://github.com/sponsors/fabiocaccamo)
- [PayPal](https://www.paypal.me/fabiocaccamo)
- BTC: bc1q2t0pv8z3udpyuvfnx5kskhqdad4dcvtfuzmvjw
- ETH: 0x8B55Fb7798b5A9F797A4455C00821B6e53daca74
## See also
- [`django-colorfield`](https://github.com/fabiocaccamo/django-colorfield) - simple color field for models with a nice color-picker in the admin. 🎨
@@ -194,4 +231,6 @@ If you are using this package in commercial project(s), please consider the idea
- [`python-codicefiscale`](https://github.com/fabiocaccamo/python-codicefiscale) - encode/decode Italian fiscal codes - codifica/decodifica del Codice Fiscale. 🇮🇹 💳
- [`python-fontbro`](https://github.com/fabiocaccamo/python-fontbro) - friendly font operations. 🧢
- [`python-fsutil`](https://github.com/fabiocaccamo/python-fsutil) - file-system utilities for lazy devs. 🧟‍♂️
+14
View File
@@ -0,0 +1,14 @@
# Security Policy
## Supported Versions
Keep this library updated to the latest version.
| Version | Supported |
| ------- | ------------------ |
| latest | :white_check_mark: |
| oldest | :x: |
## Reporting a Vulnerability
Open an issue.
+3 -2
View File
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import django
default_app_config = 'admin_interface.apps.AdminInterfaceConfig'
if django.VERSION < (3, 2):
default_app_config = "admin_interface.apps.AdminInterfaceConfig"
+173 -119
View File
@@ -1,133 +1,187 @@
# -*- coding: utf-8 -*-
from admin_interface.compat import gettext_lazy as _
from admin_interface.models import Theme
from django.contrib import admin
from django.contrib.auth import models as auth_models
from admin_interface.compat import gettext_lazy as _
from admin_interface.models import Theme, UserTheme
class UserInline(admin.TabularInline):
model = UserTheme
extra = 0
autocomplete_fields = ('user', )
class ThemeAdmin(admin.ModelAdmin):
inlines = [UserInline, ]
list_display = ('name', 'active', )
list_editable = ('active', )
list_display = (
"name",
"active",
"demo",
)
list_editable = ("active",)
list_per_page = 100
show_full_result_count = False
fieldsets = (
(None, {
'classes': ('wide', ),
'fields': ('name', 'active', )
}),
(_('Environment'), {
'classes': ('wide', ),
'fields': (
'env_name',
'env_color',
'env_visible_in_header',
'env_visible_in_favicon',
)
}),
(_('Language chooser'), {
'classes': ('wide', ),
'fields': (
'language_chooser_active',
'language_chooser_display',
)
}),
(_('Logo'), {
'classes': ('wide', ),
'fields': (
'logo',
'logo_max_width',
'logo_max_height',
'logo_color',
'logo_visible',
)
}),
(_('Favicon'), {
'classes': ('wide', ),
'fields': ('favicon', )
}),
(_('Title'), {
'classes': ('wide', ),
'fields': (
'title',
'title_color',
'title_visible',
)
}),
(_('Header'), {
'classes': ('wide', ),
'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_background_selected_color',
'css_module_text_color',
'css_module_link_color',
'css_module_link_selected_color',
'css_module_link_hover_color',
'css_module_rounded_corners',
)
}),
(_('Generic Links'), {
'classes': ('wide', ),
'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',
)
}),
(_('Delete Buttons'), {
'classes': ('wide', ),
'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',
'related_modal_close_button_visible',
)
}),
(_('Form Controls'), {
'classes': ('wide', ),
'fields': (
'form_submit_sticky',
'form_pagination_sticky',
)
}),
(_('List Filter'), {
'classes': ('wide', ),
'fields': (
'list_filter_dropdown',
'list_filter_sticky',
)
}),
(_('Recent Actions'), {
'classes': ('wide', ),
'fields': ('recent_actions_visible', )
}),
(
None,
{
"classes": ("wide",),
"fields": (
"name",
"active",
"demo",
),
},
),
(
_("Environment"),
{
"classes": ("wide",),
"fields": (
"env_name",
"env_color",
"env_visible_in_header",
"env_visible_in_favicon",
),
},
),
(
_("Language chooser"),
{
"classes": ("wide",),
"fields": (
"language_chooser_active",
"language_chooser_display",
),
},
),
(
_("Logo"),
{
"classes": ("wide",),
"fields": (
"logo",
"logo_max_width",
"logo_max_height",
"logo_color",
"logo_visible",
),
},
),
(_("Favicon"), {"classes": ("wide",), "fields": ("favicon",)}),
(
_("Title"),
{
"classes": ("wide",),
"fields": (
"title",
"title_color",
"title_visible",
),
},
),
(
_("Header"),
{
"classes": ("wide",),
"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_background_selected_color",
"css_module_text_color",
"css_module_link_color",
"css_module_link_selected_color",
"css_module_link_hover_color",
"css_module_rounded_corners",
),
},
),
(
_("Generic Links"),
{
"classes": ("wide",),
"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",
),
},
),
(
_("Delete Buttons"),
{
"classes": ("wide",),
"fields": (
"css_delete_button_background_color",
"css_delete_button_background_hover_color",
"css_delete_button_text_color",
),
},
),
(_("Navigation Bar"), {"classes": (
"wide",), "fields": ("foldable_apps",)}),
(
_("Related Modal"),
{
"classes": ("wide",),
"fields": (
"related_modal_active",
"related_modal_background_color",
"related_modal_background_opacity",
"related_modal_rounded_corners",
"related_modal_close_button_visible",
),
},
),
(
_("Form Controls"),
{
"classes": ("wide",),
"fields": (
"form_submit_sticky",
"form_pagination_sticky",
),
},
),
(
_("List Filter"),
{
"classes": ("wide",),
"fields": (
"list_filter_dropdown",
"list_filter_sticky",
),
},
),
(
_("Recent Actions"),
{"classes": ("wide",), "fields": ("recent_actions_visible",)},
),
)
save_on_top = True
+4 -5
View File
@@ -8,9 +8,9 @@ from django.db.models.signals import post_migrate
class AdminInterfaceConfig(AppConfig):
name = 'admin_interface'
verbose_name = _('Admin Interface')
default_auto_field = 'django.db.models.AutoField'
name = "admin_interface"
verbose_name = _("Admin Interface")
default_auto_field = "django.db.models.AutoField"
def ready(self):
@@ -18,5 +18,4 @@ class AdminInterfaceConfig(AppConfig):
from admin_interface.models import Theme
settings.check_installed_apps()
post_migrate.connect(
Theme.post_migrate_handler, sender=self)
post_migrate.connect(Theme.post_migrate_handler, sender=self)
+4 -4
View File
@@ -5,16 +5,16 @@ from django.core.cache import cache, caches
def app_cache():
return caches['admin_interface'] if 'admin_interface' in settings.CACHES else cache
return caches["admin_interface"] if "admin_interface" in settings.CACHES else cache
def del_cached_active_theme():
app_cache().delete('admin_interface_theme')
app_cache().delete("admin_interface_theme")
def get_cached_active_theme():
return app_cache().get('admin_interface_theme', None)
return app_cache().get("admin_interface_theme", None)
def set_cached_active_theme(theme):
app_cache().set('admin_interface_theme', theme)
app_cache().set("admin_interface_theme", theme)
+16 -8
View File
@@ -2,17 +2,25 @@
import django
if django.VERSION >= (1, 11):
from django.core.validators import FileExtensionValidator
else:
def FileExtensionValidator(*args, **kwargs):
def noop(*args, **kwargs):
pass
return noop
if django.VERSION < (1, 10):
from django.core.urlresolvers import NoReverseMatch, reverse
else:
from django.urls import NoReverseMatch, reverse
if django.VERSION < (2, 0):
from django.utils.encoding import force_text as force_str
from django.utils.translation import ugettext_lazy as gettext_lazy
else:
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy
if django.VERSION >= (1, 11):
from django.core.validators import FileExtensionValidator
else:
def FileExtensionValidator(*args, **kwargs):
def noop(*args, **kwargs):
pass
return noop
+36
View File
@@ -0,0 +1,36 @@
from .models import Theme
def get_active_theme(request):
objs_manager = Theme.objects
objs_active_qs = objs_manager.filter(active=True)
objs_active_ls = list(objs_active_qs)
objs_active_count = len(objs_active_ls)
if objs_active_count == 0:
obj = objs_manager.first()
if obj:
obj.set_active()
else:
obj = objs_manager.create()
elif objs_active_count == 1:
obj = objs_active_ls[0]
elif objs_active_count > 1:
# for frame_record in inspect.stack():
# if frame_record[3]=='get_response':
# request = frame_record[0].f_locals['request']
# user = request.user
# break
# else:
# request = None
user = request.user
try:
obj = objs_active_qs.filter(user=user).first()
except:
obj = objs_active_ls[-1]
obj.set_active()
return {
'theme': obj,
}
@@ -27,7 +27,6 @@
"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,
@@ -27,7 +27,6 @@
"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,
@@ -27,7 +27,6 @@
"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,
@@ -27,7 +27,6 @@
"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,
@@ -27,7 +27,6 @@
"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,
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,206 @@
# This file is distributed under the same license as the
# django-admin-interface package.
#
# Translators:
# Kamil Paduszyński <kpaduszy@gmail.com>, 2022
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: django-admin-interface\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-04 09:19+0000\n"
"PO-Revision-Date: 2022-02-04 19:13-0500\n"
"Last-Translator: Kamil Paduszyński <kpaduszy@gmail.com>\n"
"Language-Team: Polish <LL@li.org>\n"
"Language: Polish \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: admin_interface/admin.py:21
msgid "Environment"
msgstr "Środowisko"
#: admin_interface/admin.py:30
msgid "Language chooser"
msgstr "Wybór wersji językowej"
#: admin_interface/admin.py:37
msgid "Logo"
msgstr "Logo"
#: admin_interface/admin.py:45
msgid "Favicon"
msgstr "Ikonka"
#: admin_interface/admin.py:49
msgid "Title"
msgstr "Tytuł"
#: admin_interface/admin.py:57
msgid "Header"
msgstr "Nagłówek"
#: admin_interface/admin.py:66
msgid "Breadcrumbs / Module headers"
msgstr "Pasek nawigacyjny / nagłówki modułów"
#: admin_interface/admin.py:76
msgid "Generic Links"
msgstr "Zwykłe linki"
#: admin_interface/admin.py:83
msgid "Save Buttons"
msgstr "Przyciski zapisywania"
#: admin_interface/admin.py:91
msgid "Delete Buttons"
msgstr "Przyciski usuwania"
#: admin_interface/admin.py:99
msgid "Related Modal"
msgstr "Okno dialogowe"
#: admin_interface/admin.py:109
msgid "List Filter"
msgstr "Filtry"
#: admin_interface/admin.py:113
msgid "Recent Actions"
msgstr "Ostatnie działania"
#: admin_interface/apps.py:11
msgid "Admin Interface"
msgstr "Wygląd panelu administracyjnego"
#: admin_interface/models.py:72 admin_interface/models.py:116
#: admin_interface/models.py:135
msgid "name"
msgstr "nazwa"
#: admin_interface/models.py:75 admin_interface/models.py:132
#: admin_interface/models.py:253
msgid "active"
msgstr "aktywny"
#: admin_interface/models.py:79
#: admin_interface/templates/admin/base_site.html:6
#: admin_interface/templates/admin/base_site.html:60
msgid "Django administration"
msgstr "Administracja Django"
#: admin_interface/models.py:81
msgid "title"
msgstr "tytuł"
#: admin_interface/models.py:87 admin_interface/models.py:102
#: admin_interface/models.py:122
msgid "color"
msgstr "kolor"
#: admin_interface/models.py:90 admin_interface/models.py:105
#: admin_interface/models.py:289
msgid "visible"
msgstr "widoczny"
#: admin_interface/models.py:95
msgid "Leave blank to use the default Django logo"
msgstr "Puste ustawia domyślne logo Django"
#: admin_interface/models.py:96
msgid "logo"
msgstr "logo"
#: admin_interface/models.py:110
msgid "(.ico|.png|.gif - 16x16|32x32 px)"
msgstr "(Format pliku: .ico, .png, .gif; wymiary: 16 x 16 lub 32 x 32 px)."
#: admin_interface/models.py:111
msgid "favicon"
msgstr "ikonka"
#: admin_interface/models.py:120
msgid ""
"(red: #E74C3C, orange: #E67E22, yellow: #F1C40F, green: #2ECC71, blue: "
"#3498DB)"
msgstr ""
"(czerwony: #E74C3C, pomarańczowy: #E67E22, żółty: #F1C40F, zielony: #2ECC71, niebieski: "
"#3498DB)"
#: admin_interface/models.py:125
msgid "visible in header (marker and name)"
msgstr "widoczne w nagłówku (znacznik i nazwa)"
#: admin_interface/models.py:128
msgid "visible in favicon (marker)"
msgstr "widoczne przy ikonce (znacznik)"
#: admin_interface/models.py:134
msgid "code"
msgstr "kod"
#: admin_interface/models.py:141
msgid "display"
msgstr "wyświetlaj"
#: admin_interface/models.py:148 admin_interface/models.py:173
#: admin_interface/models.py:214 admin_interface/models.py:233
#: admin_interface/models.py:259
msgid "background color"
msgstr "kolor tła"
#: admin_interface/models.py:154 admin_interface/models.py:179
#: admin_interface/models.py:226 admin_interface/models.py:245
#: admin_interface/models.py:249
msgid "text color"
msgstr "kolor tekstu"
#: admin_interface/models.py:160 admin_interface/models.py:185
#: admin_interface/models.py:201
msgid "link color"
msgstr "kolor linku"
#: admin_interface/models.py:166 admin_interface/models.py:191
#: admin_interface/models.py:207
msgid "link hover color"
msgstr "kolor wskazywanego linku"
#: admin_interface/models.py:194 admin_interface/models.py:279
msgid "rounded corners"
msgstr "zaokrąglenie narożników"
#: admin_interface/models.py:220 admin_interface/models.py:239
msgid "background hover color"
msgstr "kolor tła wskazywanego przycisku"
#: admin_interface/models.py:276
msgid "background opacity"
msgstr "przeźroczystość tła"
#: admin_interface/models.py:282
msgid "close button visible"
msgstr "pokaż przycisk zamykania"
#: admin_interface/models.py:286
msgid "use dropdown"
msgstr "zastosuj listy rozwijane"
#: admin_interface/models.py:298
msgid "Theme"
msgstr "Schemat"
#: admin_interface/models.py:299
msgid "Themes"
msgstr "Schematy"
#: admin_interface/templates/admin/filter.html:13
#: admin_interface/templates/admin_interface/dropdown_filter.html:4
#, python-format
msgid " By %(filter_title)s "
msgstr " po %(filter_title)s "
#: admin_interface/templates/admin/popup_response.html:3
msgid "Popup closing..."
msgstr "Zamykanie..."
Binary file not shown.
@@ -0,0 +1,234 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-01-28 10:01-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: admin.py:21
msgid "Environment"
msgstr "Ambiente"
#: admin.py:30
msgid "Language chooser"
msgstr "Seletor de idioma"
#: admin.py:37
msgid "Logo"
msgstr "Logo"
#: admin.py:47
msgid "Favicon"
msgstr "Favicon"
#: admin.py:51
msgid "Title"
msgstr "Título"
#: admin.py:59
msgid "Header"
msgstr "Cabeçalho"
#: admin.py:68
msgid "Breadcrumbs / Module headers"
msgstr "Cabeçalhos de módulo"
#: admin.py:80
msgid "Generic Links"
msgstr "Links Genéricos"
#: admin.py:87
msgid "Save Buttons"
msgstr "Botões Salvar"
#: admin.py:95
msgid "Delete Buttons"
msgstr "Botões Deletar"
#: admin.py:103
msgid "Navigation Bar"
msgstr "Barra de Navegação"
#: admin.py:109
msgid "Related Modal"
msgstr "Modal Relacionado"
#: admin.py:119
msgid "Form Controls"
msgstr "Controles de Formulário"
#: admin.py:126
msgid "List Filter"
msgstr "Filtro de lista"
#: admin.py:133
msgid "Recent Actions"
msgstr "Ações recentes"
#: apps.py:12
msgid "Admin Interface"
msgstr "Interface do administrador"
#: models.py:73 models.py:129 models.py:148
msgid "name"
msgstr "nome"
#: models.py:76 models.py:145 models.py:274
msgid "active"
msgstr "ativo"
#: models.py:80 templates/admin/base_site.html:6
#: templates/admin/base_site.html:78
msgid "Django administration"
msgstr "Administração do Django"
#: models.py:82
msgid "title"
msgstr "título"
#: models.py:88 models.py:105 models.py:135
msgid "color"
msgstr "cor"
#: models.py:91 models.py:116 models.py:318
msgid "visible"
msgstr "visível"
#: models.py:98
msgid "Leave blank to use the default Django logo"
msgstr "Deixe em branco para usar o logotipo padrão do Django"
#: models.py:99
msgid "logo"
msgstr "logo"
#: models.py:109
msgid "max width"
msgstr "largura máxima"
#: models.py:113
msgid "max height"
msgstr "altura máxima"
#: models.py:123
msgid "(.ico|.png|.gif - 16x16|32x32 px)"
msgstr "(.ico|.png|.gif - 16x16|32x32 px)"
#: models.py:124
msgid "favicon"
msgstr "favicon"
#: models.py:133
msgid ""
"(red: #E74C3C, orange: #E67E22, yellow: #F1C40F, green: #2ECC71, blue: "
"#3498DB)"
msgstr ""
"(vermelho: #E74C3C, laranja: #E67E22, amarelo: #F1C40F, verde: #2ECC71, "
"azul: #3498DB)"
#: models.py:138
msgid "visible in header (marker and name)"
msgstr "visível no cabeçalho (marcador e nome)"
#: models.py:141
msgid "visible in favicon (marker)"
msgstr "visível no favicon (marcador)"
#: models.py:147
msgid "code"
msgstr "código"
#: models.py:154
msgid "display"
msgstr "exibição"
#: models.py:161 models.py:186 models.py:239 models.py:258 models.py:280
msgid "background color"
msgstr "cor de fundo"
#: models.py:167 models.py:198 models.py:251 models.py:270
msgid "text color"
msgstr "cor do texto"
#: models.py:173 models.py:204 models.py:226
msgid "link color"
msgstr "cor do link"
#: models.py:179 models.py:216 models.py:232
msgid "link hover color"
msgstr "cor de foco do link"
#: models.py:192
msgid "background selected color"
msgstr "cor de fundo selecionada"
#: models.py:210
msgid "link selected color"
msgstr "link cor selecionada"
#: models.py:219 models.py:300
msgid "rounded corners"
msgstr "cantos arredondados"
#: models.py:245 models.py:264
msgid "background hover color"
msgstr "cor de fundo do foco"
#: models.py:297
msgid "background opacity"
msgstr "opacidade de fundo"
#: models.py:303
msgid "close button visible"
msgstr "botão fechar visível"
#: models.py:307
msgid "use dropdown"
msgstr "usar menu suspenso"
#: models.py:310
msgid "sticky position"
msgstr "posição sticky"
#: models.py:314
msgid "foldable apps"
msgstr "aplicativos dobráveis"
#: models.py:322
msgid "sticky submit"
msgstr "envio fixo"
#: models.py:325
msgid "sticky pagination"
msgstr "paginação fixa"
#: models.py:334
msgid "Theme"
msgstr "Tema"
#: models.py:335
msgid "Themes"
msgstr "Temas"
#: templates/admin/filter.html:13
#: templates/admin_interface/dropdown_filter.html:4
#, python-format
msgid " By %(filter_title)s "
msgstr " por %(filter_title)s "
#: templates/admin/popup_response.html:3
msgid "Popup closing..."
msgstr "Pop-up fechando..."
+171 -126
View File
@@ -9,176 +9,221 @@ import colorfield.fields
class Migration(migrations.Migration):
dependencies = [
]
dependencies = []
operations = [
migrations.CreateModel(
name='Theme',
name="Theme",
fields=[
('id',
(
"id",
models.AutoField(
verbose_name='ID',
verbose_name="ID",
serialize=False,
auto_created=True,
primary_key=True)),
('name',
primary_key=True,
),
),
("name", models.CharField(default=b"Django", max_length=50)),
("active", models.BooleanField(default=True)),
(
"title",
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',
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',
default=b"#0C4B33",
help_text=b"#0C4B33",
max_length=10,
verbose_name=b'background color',
blank=True)),
('css_header_title_color',
verbose_name=b"background color",
blank=True,
),
),
(
"css_header_title_color",
colorfield.fields.ColorField(
default=b'#F5DD5D',
help_text=b'#F5DD5D',
default=b"#F5DD5D",
help_text=b"#F5DD5D",
max_length=10,
verbose_name=b'title color',
blank=True)),
('css_header_text_color',
verbose_name=b"title color",
blank=True,
),
),
(
"css_header_text_color",
colorfield.fields.ColorField(
default=b'#44B78B',
help_text=b'#44B78B',
default=b"#44B78B",
help_text=b"#44B78B",
max_length=10,
verbose_name=b'text color',
blank=True)),
('css_header_link_color',
verbose_name=b"text color",
blank=True,
),
),
(
"css_header_link_color",
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
default=b"#FFFFFF",
help_text=b"#FFFFFF",
max_length=10,
verbose_name=b'link color',
blank=True)),
('css_header_link_hover_color',
verbose_name=b"link color",
blank=True,
),
),
(
"css_header_link_hover_color",
colorfield.fields.ColorField(
default=b'#C9F0DD',
help_text=b'#C9F0DD',
default=b"#C9F0DD",
help_text=b"#C9F0DD",
max_length=10,
verbose_name=b'link hover color',
blank=True)),
('css_module_background_color',
verbose_name=b"link hover color",
blank=True,
),
),
(
"css_module_background_color",
colorfield.fields.ColorField(
default=b'#44B78B',
help_text=b'#44B78B',
default=b"#44B78B",
help_text=b"#44B78B",
max_length=10,
verbose_name=b'background color',
blank=True)),
('css_module_text_color',
verbose_name=b"background color",
blank=True,
),
),
(
"css_module_text_color",
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
default=b"#FFFFFF",
help_text=b"#FFFFFF",
max_length=10,
verbose_name=b'text color',
blank=True)),
('css_module_link_color',
verbose_name=b"text color",
blank=True,
),
),
(
"css_module_link_color",
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
default=b"#FFFFFF",
help_text=b"#FFFFFF",
max_length=10,
verbose_name=b'link color',
blank=True)),
('css_module_link_hover_color',
verbose_name=b"link color",
blank=True,
),
),
(
"css_module_link_hover_color",
colorfield.fields.ColorField(
default=b'#C9F0DD',
help_text=b'#C9F0DD',
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',
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',
default=b"#0C3C26",
help_text=b"#0C3C26",
max_length=10,
verbose_name=b'link color',
blank=True)),
('css_generic_link_hover_color',
verbose_name=b"link color",
blank=True,
),
),
(
"css_generic_link_hover_color",
colorfield.fields.ColorField(
default=b'#156641',
help_text=b'#156641',
default=b"#156641",
help_text=b"#156641",
max_length=10,
verbose_name=b'link hover color',
blank=True)),
('css_save_button_background_color',
verbose_name=b"link hover color",
blank=True,
),
),
(
"css_save_button_background_color",
colorfield.fields.ColorField(
default=b'#0C4B33',
help_text=b'#0C4B33',
default=b"#0C4B33",
help_text=b"#0C4B33",
max_length=10,
verbose_name=b'background color',
blank=True)),
('css_save_button_background_hover_color',
verbose_name=b"background color",
blank=True,
),
),
(
"css_save_button_background_hover_color",
colorfield.fields.ColorField(
default=b'#0C3C26',
help_text=b'#0C3C26',
default=b"#0C3C26",
help_text=b"#0C3C26",
max_length=10,
verbose_name=b'background hover color',
blank=True)),
('css_save_button_text_color',
verbose_name=b"background hover color",
blank=True,
),
),
(
"css_save_button_text_color",
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
default=b"#FFFFFF",
help_text=b"#FFFFFF",
max_length=10,
verbose_name=b'text color',
blank=True)),
('css_delete_button_background_color',
verbose_name=b"text color",
blank=True,
),
),
(
"css_delete_button_background_color",
colorfield.fields.ColorField(
default=b'#BA2121',
help_text=b'#BA2121',
default=b"#BA2121",
help_text=b"#BA2121",
max_length=10,
verbose_name=b'background color',
blank=True)),
('css_delete_button_background_hover_color',
verbose_name=b"background color",
blank=True,
),
),
(
"css_delete_button_background_hover_color",
colorfield.fields.ColorField(
default=b'#A41515',
help_text=b'#A41515',
default=b"#A41515",
help_text=b"#A41515",
max_length=10,
verbose_name=b'background hover color',
blank=True)),
('css_delete_button_text_color',
verbose_name=b"background hover color",
blank=True,
),
),
(
"css_delete_button_text_color",
colorfield.fields.ColorField(
default=b'#FFFFFF',
help_text=b'#FFFFFF',
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)),
verbose_name=b"text color",
blank=True,
),
),
("css", models.TextField(blank=True)),
("list_filter_dropdown", models.BooleanField(default=False)),
],
options={
'verbose_name': 'Theme',
'verbose_name_plural': 'Themes',
"verbose_name": "Theme",
"verbose_name_plural": "Themes",
},
),
]
@@ -10,51 +10,54 @@ import colorfield.fields
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0001_initial'),
("admin_interface", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name='theme',
name='list_filter_dropdown',
field=models.BooleanField(
default=False,
verbose_name=b'use dropdown'),
model_name="theme",
name="list_filter_dropdown",
field=models.BooleanField(default=False, verbose_name=b"use dropdown"),
),
migrations.AddField(
model_name='theme',
name='related_modal_active',
field=models.BooleanField(
default=True,
verbose_name=b'active'),
model_name="theme",
name="related_modal_active",
field=models.BooleanField(default=True, verbose_name=b"active"),
),
migrations.AddField(
model_name='theme',
name='related_modal_background_color',
model_name="theme",
name="related_modal_background_color",
field=colorfield.fields.ColorField(
blank=True,
default=b'#000000',
help_text=b'#000000',
default=b"#000000",
help_text=b"#000000",
max_length=10,
verbose_name=b'background color'),
verbose_name=b"background color",
),
),
migrations.AddField(
model_name='theme',
name='related_modal_background_opacity',
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%')],
(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'),
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'),
model_name="theme",
name="related_modal_rounded_corners",
field=models.BooleanField(default=True, verbose_name=b"rounded corners"),
),
]
@@ -10,26 +10,28 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0002_add_related_modal'),
("admin_interface", "0002_add_related_modal"),
]
operations = [
migrations.AddField(
model_name='theme',
name='logo_color',
model_name="theme",
name="logo_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name='logo color'),
verbose_name="logo color",
),
),
migrations.AlterField(
model_name='theme',
name='logo',
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/'),
help_text="(leave blank to use the default Django logo)",
upload_to="admin-interface/logo/",
),
),
]
@@ -8,13 +8,13 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0003_add_logo_color'),
("admin_interface", "0003_add_logo_color"),
]
operations = [
migrations.RenameField(
model_name='theme',
old_name='css_header_title_color',
new_name='title_color',
model_name="theme",
old_name="css_header_title_color",
new_name="title_color",
),
]
@@ -8,15 +8,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0004_rename_title_color'),
("admin_interface", "0004_rename_title_color"),
]
operations = [
migrations.AddField(
model_name='theme',
name='recent_actions_visible',
field=models.BooleanField(
default=True,
verbose_name='visible'),
model_name="theme",
name="recent_actions_visible",
field=models.BooleanField(default=True, verbose_name="visible"),
),
]
+149 -138
View File
@@ -10,257 +10,268 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0005_add_recent_actions_visible'),
("admin_interface", "0005_add_recent_actions_visible"),
]
operations = [
migrations.AlterField(
model_name='theme',
name='css_delete_button_background_color',
model_name="theme",
name="css_delete_button_background_color",
field=colorfield.fields.ColorField(
blank=True,
default='#BA2121',
help_text='#BA2121',
default="#BA2121",
help_text="#BA2121",
max_length=10,
verbose_name='background color'),
verbose_name="background color",
),
),
migrations.AlterField(
model_name='theme',
name='css_delete_button_background_hover_color',
model_name="theme",
name="css_delete_button_background_hover_color",
field=colorfield.fields.ColorField(
blank=True,
default='#A41515',
help_text='#A41515',
default="#A41515",
help_text="#A41515",
max_length=10,
verbose_name='background hover color'),
verbose_name="background hover color",
),
),
migrations.AlterField(
model_name='theme',
name='css_delete_button_text_color',
model_name="theme",
name="css_delete_button_text_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name='text color'),
verbose_name="text color",
),
),
migrations.AlterField(
model_name='theme',
name='css_generic_link_color',
model_name="theme",
name="css_generic_link_color",
field=colorfield.fields.ColorField(
blank=True,
default='#0C3C26',
help_text='#0C3C26',
default="#0C3C26",
help_text="#0C3C26",
max_length=10,
verbose_name='link color'),
verbose_name="link color",
),
),
migrations.AlterField(
model_name='theme',
name='css_generic_link_hover_color',
model_name="theme",
name="css_generic_link_hover_color",
field=colorfield.fields.ColorField(
blank=True,
default='#156641',
help_text='#156641',
default="#156641",
help_text="#156641",
max_length=10,
verbose_name='link hover color'),
verbose_name="link hover color",
),
),
migrations.AlterField(
model_name='theme',
name='css_header_background_color',
model_name="theme",
name="css_header_background_color",
field=colorfield.fields.ColorField(
blank=True,
default='#0C4B33',
help_text='#0C4B33',
default="#0C4B33",
help_text="#0C4B33",
max_length=10,
verbose_name='background color'),
verbose_name="background color",
),
),
migrations.AlterField(
model_name='theme',
name='css_header_link_color',
model_name="theme",
name="css_header_link_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name='link color'),
verbose_name="link color",
),
),
migrations.AlterField(
model_name='theme',
name='css_header_link_hover_color',
model_name="theme",
name="css_header_link_hover_color",
field=colorfield.fields.ColorField(
blank=True,
default='#C9F0DD',
help_text='#C9F0DD',
default="#C9F0DD",
help_text="#C9F0DD",
max_length=10,
verbose_name='link hover color'),
verbose_name="link hover color",
),
),
migrations.AlterField(
model_name='theme',
name='css_header_text_color',
model_name="theme",
name="css_header_text_color",
field=colorfield.fields.ColorField(
blank=True,
default='#44B78B',
help_text='#44B78B',
default="#44B78B",
help_text="#44B78B",
max_length=10,
verbose_name='text color'),
verbose_name="text color",
),
),
migrations.AlterField(
model_name='theme',
name='css_module_background_color',
model_name="theme",
name="css_module_background_color",
field=colorfield.fields.ColorField(
blank=True,
default='#44B78B',
help_text='#44B78B',
default="#44B78B",
help_text="#44B78B",
max_length=10,
verbose_name='background color'),
verbose_name="background color",
),
),
migrations.AlterField(
model_name='theme',
name='css_module_link_color',
model_name="theme",
name="css_module_link_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name='link color'),
verbose_name="link color",
),
),
migrations.AlterField(
model_name='theme',
name='css_module_link_hover_color',
model_name="theme",
name="css_module_link_hover_color",
field=colorfield.fields.ColorField(
blank=True,
default='#C9F0DD',
help_text='#C9F0DD',
default="#C9F0DD",
help_text="#C9F0DD",
max_length=10,
verbose_name='link hover color'),
verbose_name="link hover color",
),
),
migrations.AlterField(
model_name='theme',
name='css_module_rounded_corners',
field=models.BooleanField(
default=True,
verbose_name='rounded corners'),
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',
model_name="theme",
name="css_module_text_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name='text color'),
verbose_name="text color",
),
),
migrations.AlterField(
model_name='theme',
name='css_save_button_background_color',
model_name="theme",
name="css_save_button_background_color",
field=colorfield.fields.ColorField(
blank=True,
default='#0C4B33',
help_text='#0C4B33',
default="#0C4B33",
help_text="#0C4B33",
max_length=10,
verbose_name='background color'),
verbose_name="background color",
),
),
migrations.AlterField(
model_name='theme',
name='css_save_button_background_hover_color',
model_name="theme",
name="css_save_button_background_hover_color",
field=colorfield.fields.ColorField(
blank=True,
default='#0C3C26',
help_text='#0C3C26',
default="#0C3C26",
help_text="#0C3C26",
max_length=10,
verbose_name='background hover color'),
verbose_name="background hover color",
),
),
migrations.AlterField(
model_name='theme',
name='css_save_button_text_color',
model_name="theme",
name="css_save_button_text_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name='text color'),
verbose_name="text color",
),
),
migrations.AlterField(
model_name='theme',
name='list_filter_dropdown',
field=models.BooleanField(
default=False,
verbose_name='use dropdown'),
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'),
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),
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'),
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',
model_name="theme",
name="related_modal_background_color",
field=colorfield.fields.ColorField(
blank=True,
default='#000000',
help_text='#000000',
default="#000000",
help_text="#000000",
max_length=10,
verbose_name='background color'),
verbose_name="background color",
),
),
migrations.AlterField(
model_name='theme',
name='related_modal_background_opacity',
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%')],
(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'),
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'),
model_name="theme",
name="related_modal_rounded_corners",
field=models.BooleanField(default=True, verbose_name="rounded corners"),
),
migrations.AlterField(
model_name='theme',
name='title',
model_name="theme",
name="title",
field=models.CharField(
blank=True,
default='Django administration',
max_length=50),
blank=True, default="Django administration", max_length=50
),
),
migrations.AlterField(
model_name='theme',
name='title_color',
model_name="theme",
name="title_color",
field=colorfield.fields.ColorField(
blank=True,
default='#F5DD5D',
help_text='#F5DD5D',
default="#F5DD5D",
help_text="#F5DD5D",
max_length=10,
verbose_name='title color'),
verbose_name="title color",
),
),
migrations.AlterField(
model_name='theme',
name='title_visible',
field=models.BooleanField(
default=True,
verbose_name='visible'),
model_name="theme",
name="title_visible",
field=models.BooleanField(default=True, verbose_name="visible"),
),
]
@@ -8,17 +8,18 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0006_bytes_to_str'),
("admin_interface", "0006_bytes_to_str"),
]
operations = [
migrations.AddField(
model_name='theme',
name='favicon',
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'),
help_text="(.ico|.png|.gif - 16x16|32x32 px)",
upload_to="admin-interface/favicon/",
verbose_name="favicon",
),
),
]
@@ -8,25 +8,32 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0007_add_favicon'),
("admin_interface", "0007_add_favicon"),
]
operations = [
migrations.RemoveField(
model_name='theme',
name='related_modal_background_opacity'
model_name="theme", name="related_modal_background_opacity"
),
migrations.AddField(
model_name='theme',
name='related_modal_background_opacity',
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%',
("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'),
verbose_name="background opacity",
),
),
]
@@ -8,28 +8,28 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0008_change_related_modal_background_opacity_type'),
("admin_interface", "0008_change_related_modal_background_opacity_type"),
]
operations = [
migrations.AddField(
model_name='theme',
name='env',
model_name="theme",
name="env",
field=models.CharField(
choices=[
('development', 'Development'),
('testing', 'Testing'),
('staging', 'Staging'),
('production', 'Production')],
default='development',
("development", "Development"),
("testing", "Testing"),
("staging", "Staging"),
("production", "Production"),
],
default="development",
max_length=50,
verbose_name='enviroment'),
verbose_name="enviroment",
),
),
migrations.AddField(
model_name='theme',
name='env_visible',
field=models.BooleanField(
default=True,
verbose_name='visible'),
model_name="theme",
name="env_visible",
field=models.BooleanField(default=True, verbose_name="visible"),
),
]
@@ -8,62 +8,60 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0009_add_enviroment'),
("admin_interface", "0009_add_enviroment"),
]
operations = [
migrations.AlterField(
model_name='theme',
name='active',
field=models.BooleanField(
default=True,
verbose_name='active'),
model_name="theme",
name="active",
field=models.BooleanField(default=True, verbose_name="active"),
),
migrations.AlterField(
model_name='theme',
name='css',
field=models.TextField(
blank=True,
verbose_name='text color'),
model_name="theme",
name="css",
field=models.TextField(blank=True, verbose_name="text color"),
),
migrations.AlterField(
model_name='theme',
name='env',
model_name="theme",
name="env",
field=models.CharField(
choices=[
('development', 'Development'),
('testing', 'Testing'),
('staging', 'Staging'),
('production', 'Production')
("development", "Development"),
("testing", "Testing"),
("staging", "Staging"),
("production", "Production"),
],
default='development',
default="development",
max_length=50,
verbose_name='environment'),
verbose_name="environment",
),
),
migrations.AlterField(
model_name='theme',
name='logo',
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/',
verbose_name='logo'),
help_text="Leave blank to use the default Django logo",
upload_to="admin-interface/logo/",
verbose_name="logo",
),
),
migrations.AlterField(
model_name='theme',
name='name',
model_name="theme",
name="name",
field=models.CharField(
default='Django',
max_length=50,
verbose_name='name'),
default="Django", max_length=50, verbose_name="name"
),
),
migrations.AlterField(
model_name='theme',
name='title',
model_name="theme",
name="title",
field=models.CharField(
blank=True,
default='Django administration',
default="Django administration",
max_length=50,
verbose_name='title'),
verbose_name="title",
),
),
]
@@ -10,50 +10,48 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0010_add_localization'),
("admin_interface", "0010_add_localization"),
]
operations = [
migrations.RenameField(
model_name='theme',
old_name='env',
new_name='env_name',
model_name="theme",
old_name="env",
new_name="env_name",
),
migrations.AlterField(
model_name='theme',
name='env_name',
field=models.CharField(
blank=True,
max_length=50,
verbose_name='name'),
model_name="theme",
name="env_name",
field=models.CharField(blank=True, max_length=50, verbose_name="name"),
),
migrations.AddField(
model_name='theme',
name='env_color',
model_name="theme",
name="env_color",
field=colorfield.fields.ColorField(
blank=True,
default='#E74C3C',
help_text='(red: #E74C3C, orange: #E67E22, yellow: #F1C40F, green: #2ECC71, blue: #3498DB)',
default="#E74C3C",
help_text="(red: #E74C3C, orange: #E67E22, yellow: #F1C40F, green: #2ECC71, blue: #3498DB)",
max_length=10,
verbose_name='color'),
verbose_name="color",
),
),
migrations.RenameField(
model_name='theme',
old_name='env_visible',
new_name='env_visible_in_header',
model_name="theme",
old_name="env_visible",
new_name="env_visible_in_header",
),
migrations.AlterField(
model_name='theme',
name='env_visible_in_header',
model_name="theme",
name="env_visible_in_header",
field=models.BooleanField(
default=True,
verbose_name='visible in header (marker and name)'),
default=True, verbose_name="visible in header (marker and name)"
),
),
migrations.AddField(
model_name='theme',
name='env_visible_in_favicon',
model_name="theme",
name="env_visible_in_favicon",
field=models.BooleanField(
default=True,
verbose_name='visible in favicon (marker)'),
default=True, verbose_name="visible in favicon (marker)"
),
),
]
@@ -10,28 +10,30 @@ from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0011_add_environment_options'),
("admin_interface", "0011_add_environment_options"),
]
operations = [
migrations.AlterField(
model_name='theme',
name='logo_color',
model_name="theme",
name="logo_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name='color'),
verbose_name="color",
),
),
migrations.AlterField(
model_name='theme',
name='title_color',
model_name="theme",
name="title_color",
field=colorfield.fields.ColorField(
blank=True,
default='#F5DD5D',
help_text='#F5DD5D',
default="#F5DD5D",
help_text="#F5DD5D",
max_length=10,
verbose_name='color'),
verbose_name="color",
),
),
]
@@ -8,15 +8,15 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0012_update_verbose_names'),
("admin_interface", "0012_update_verbose_names"),
]
operations = [
migrations.AddField(
model_name='theme',
name='related_modal_close_button_visible',
model_name="theme",
name="related_modal_close_button_visible",
field=models.BooleanField(
default=True,
verbose_name='close button visible'),
default=True, verbose_name="close button visible"
),
),
]
@@ -8,17 +8,15 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0013_add_related_modal_close_button'),
("admin_interface", "0013_add_related_modal_close_button"),
]
operations = [
migrations.AlterField(
model_name='theme',
name='name',
model_name="theme",
name="name",
field=models.CharField(
default='Django',
max_length=50,
unique=True,
verbose_name='name'),
default="Django", max_length=50, unique=True, verbose_name="name"
),
),
]
@@ -8,15 +8,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0014_name_unique'),
("admin_interface", "0014_name_unique"),
]
operations = [
migrations.AddField(
model_name='theme',
name='language_chooser_active',
field=models.BooleanField(
default=True,
verbose_name='active'),
model_name="theme",
name="language_chooser_active",
field=models.BooleanField(default=True, verbose_name="active"),
),
]
@@ -8,20 +8,18 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0015_add_language_chooser_active'),
("admin_interface", "0015_add_language_chooser_active"),
]
operations = [
migrations.AddField(
model_name='theme',
name='language_chooser_display',
model_name="theme",
name="language_chooser_display",
field=models.CharField(
choices=[
('code', 'code'),
('name', 'name')
],
default='code',
choices=[("code", "code"), ("name", "name")],
default="code",
max_length=10,
verbose_name='display'),
verbose_name="display",
),
),
]
@@ -8,15 +8,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0016_add_language_chooser_display'),
("admin_interface", "0016_add_language_chooser_display"),
]
operations = [
migrations.AlterField(
model_name='theme',
name='list_filter_dropdown',
field=models.BooleanField(
default=True,
verbose_name='use dropdown'),
model_name="theme",
name="list_filter_dropdown",
field=models.BooleanField(default=True, verbose_name="use dropdown"),
),
]
@@ -8,15 +8,13 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0017_change_list_filter_dropdown'),
("admin_interface", "0017_change_list_filter_dropdown"),
]
operations = [
migrations.AddField(
model_name='theme',
name='list_filter_sticky',
field=models.BooleanField(
default=True,
verbose_name='sticky position'),
model_name="theme",
name="list_filter_sticky",
field=models.BooleanField(default=True, verbose_name="sticky position"),
),
]
@@ -8,22 +8,18 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0018_theme_list_filter_sticky'),
("admin_interface", "0018_theme_list_filter_sticky"),
]
operations = [
migrations.AddField(
model_name='theme',
name='form_pagination_sticky',
field=models.BooleanField(
default=False,
verbose_name='sticky pagination'),
model_name="theme",
name="form_pagination_sticky",
field=models.BooleanField(default=False, verbose_name="sticky pagination"),
),
migrations.AddField(
model_name='theme',
name='form_submit_sticky',
field=models.BooleanField(
default=False,
verbose_name='sticky submit'),
model_name="theme",
name="form_submit_sticky",
field=models.BooleanField(default=False, verbose_name="sticky submit"),
),
]
@@ -12,35 +12,38 @@ def default_link_selected(apps, schema_editor):
Theme = apps.get_model("admin_interface", "Theme")
db_alias = schema_editor.connection.alias
Theme.objects.using(db_alias).update(
css_module_link_selected_color=F('css_module_link_color'))
css_module_link_selected_color=F("css_module_link_color")
)
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0019_add_form_sticky'),
("admin_interface", "0019_add_form_sticky"),
]
operations = [
migrations.AddField(
model_name='theme',
name='css_module_background_selected_color',
model_name="theme",
name="css_module_background_selected_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFCC',
help_text='#FFFFCC',
default="#FFFFCC",
help_text="#FFFFCC",
max_length=10,
verbose_name='background selected color'),
verbose_name="background selected color",
),
),
migrations.AddField(
model_name='theme',
name='css_module_link_selected_color',
model_name="theme",
name="css_module_link_selected_color",
field=colorfield.fields.ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name='link selected color'),
verbose_name="link selected color",
),
),
migrations.RunPython(default_link_selected),
]
@@ -10,36 +10,38 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0020_module_selected_colors'),
("admin_interface", "0020_module_selected_colors"),
]
operations = [
migrations.AlterField(
model_name='theme',
name='favicon',
model_name="theme",
name="favicon",
field=models.FileField(
blank=True,
help_text='(.ico|.png|.gif - 16x16|32x32 px)',
upload_to='admin-interface/favicon/',
help_text="(.ico|.png|.gif - 16x16|32x32 px)",
upload_to="admin-interface/favicon/",
validators=[
FileExtensionValidator(allowed_extensions=[
'gif', 'ico', 'jpg', 'jpeg', 'png', 'svg'
])
FileExtensionValidator(
allowed_extensions=["gif", "ico", "jpg", "jpeg", "png", "svg"]
)
],
verbose_name='favicon'),
verbose_name="favicon",
),
),
migrations.AlterField(
model_name='theme',
name='logo',
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/',
help_text="Leave blank to use the default Django logo",
upload_to="admin-interface/logo/",
validators=[
FileExtensionValidator(allowed_extensions=[
'gif', 'jpg', 'jpeg', 'png', 'svg'
])
FileExtensionValidator(
allowed_extensions=["gif", "jpg", "jpeg", "png", "svg"]
)
],
verbose_name='logo'),
verbose_name="logo",
),
),
]
@@ -8,18 +8,22 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0021_file_extension_validator'),
("admin_interface", "0021_file_extension_validator"),
]
operations = [
migrations.AddField(
model_name='theme',
name='logo_max_height',
field=models.PositiveSmallIntegerField(blank=True, default=100, verbose_name='max height'),
model_name="theme",
name="logo_max_height",
field=models.PositiveSmallIntegerField(
blank=True, default=100, verbose_name="max height"
),
),
migrations.AddField(
model_name='theme',
name='logo_max_width',
field=models.PositiveSmallIntegerField(blank=True, default=400, verbose_name='max width'),
model_name="theme",
name="logo_max_width",
field=models.PositiveSmallIntegerField(
blank=True, default=400, verbose_name="max width"
),
),
]
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("admin_interface", "0022_add_logo_max_width_and_height"),
]
operations = [
migrations.AddField(
model_name="theme",
name="foldable_apps",
field=models.BooleanField(default=True, verbose_name="foldable apps"),
),
]
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("admin_interface", "0023_theme_foldable_apps"),
]
operations = [
migrations.RemoveField(
model_name="theme",
name="css",
),
]
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("admin_interface", "0024_remove_theme_css"),
]
operations = [
migrations.AddField(
model_name="theme",
name="demo",
field=models.BooleanField(default=False, verbose_name="demo"),
),
]
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("admin_interface", "0025_add_demo_option"),
]
operations = [
migrations.AddField(
model_name="theme",
name="user",
field=models.ForeignKey('auth.User', on_delete=models.CASCADE, null=True, blank=True, verbose_name="active for user"),
),
]
@@ -0,0 +1,37 @@
# Generated by Django 3.2.13 on 2022-04-28 16:03
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('admin_interface', '0026_add_user_option'),
]
operations = [
migrations.RemoveField(
model_name='theme',
name='user',
),
migrations.CreateModel(
name='UserTheme',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('theme', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='admin_interface.theme')),
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, unique=True)),
],
options={
'verbose_name': 'Users theme',
'verbose_name_plural': 'Users themes',
},
),
migrations.AddField(
model_name='theme',
name='users',
field=models.ManyToManyField(through='admin_interface.UserTheme', to=settings.AUTH_USER_MODEL),
),
]
+248 -168
View File
@@ -2,20 +2,31 @@
from __future__ import unicode_literals
from admin_interface.cache import del_cached_active_theme
from admin_interface.compat import FileExtensionValidator, force_str, gettext_lazy as _
import inspect
from colorfield.fields import ColorField
from django.db import models
from django.db.models.signals import post_delete, post_save, pre_save
from six import python_2_unicode_compatible
from admin_interface.cache import del_cached_active_theme
from admin_interface.compat import FileExtensionValidator, force_str
from admin_interface.compat import gettext_lazy as _
@python_2_unicode_compatible
class UserTheme(models.Model):
class Meta:
verbose_name = 'Users theme'
verbose_name_plural = 'Users themes'
user = models.ForeignKey(
'auth.User', on_delete=models.CASCADE, null=True, unique=True)
theme = models.ForeignKey('Theme', on_delete=models.CASCADE)
@python_2_unicode_compatible
class Theme(models.Model):
@staticmethod
def post_migrate_handler(**kwargs):
del_cached_active_theme()
@@ -26,22 +37,22 @@ class Theme(models.Model):
del_cached_active_theme()
Theme.get_active_theme()
@staticmethod
def post_save_handler(instance, **kwargs):
del_cached_active_theme()
if instance.active:
Theme.objects.exclude(pk=instance.pk).update(active=False)
Theme.get_active_theme()
# @staticmethod
# def post_save_handler(instance, **kwargs):
# del_cached_active_theme()
# if instance.active:
# Theme.objects.exclude(pk=instance.pk).update(active=False)
# Theme.get_active_theme()
@staticmethod
def pre_save_handler(instance, **kwargs):
if instance.pk is None:
try:
obj = Theme.objects.get(name=instance.name)
if obj:
instance.pk = obj.pk
except Theme.DoesNotExist:
pass
# @staticmethod
# def pre_save_handler(instance, **kwargs):
# if instance.pk is None:
# try:
# obj = Theme.objects.get(name=instance.name)
# if obj:
# instance.pk = obj.pk
# except Theme.DoesNotExist:
# pass
@staticmethod
def get_active_theme():
@@ -61,283 +72,352 @@ class Theme(models.Model):
obj = objs_active_ls[0]
elif objs_active_count > 1:
for frame_record in inspect.stack():
if frame_record[3] == 'get_response':
request = frame_record[0].f_locals['request']
user = request.user
break
else:
request = None
try:
return objs_active_qs.filter(user=user).first()
except:
obj = objs_active_ls[-1]
obj.set_active()
return obj
name = models.CharField(
unique=True,
max_length=50,
default='Django',
verbose_name=_('name'))
active = models.BooleanField(
default=True,
verbose_name=_('active'))
unique=True, max_length=50, default="Django", verbose_name=_("name")
)
active = models.BooleanField(default=True, verbose_name=_("active"))
demo = models.BooleanField(default=False, verbose_name=_("is demo"))
users = models.ManyToManyField('auth.User', through=UserTheme)
title = models.CharField(
max_length=50,
default=_('Django administration'),
default=_("Django administration"),
blank=True,
verbose_name=_('title'))
verbose_name=_("title"),
)
title_color = ColorField(
blank=True,
default='#F5DD5D',
help_text='#F5DD5D',
default="#F5DD5D",
help_text="#F5DD5D",
max_length=10,
verbose_name=_('color'))
verbose_name=_("color"),
)
title_visible = models.BooleanField(
default=True,
verbose_name=_('visible'))
default=True, verbose_name=_("visible"))
logo = models.FileField(
upload_to='admin-interface/logo/',
upload_to="admin-interface/logo/",
blank=True,
validators=[FileExtensionValidator(
allowed_extensions=['gif', 'jpg', 'jpeg', 'png', 'svg'])],
help_text=_('Leave blank to use the default Django logo'),
verbose_name=_('logo'))
validators=[
FileExtensionValidator(
allowed_extensions=["gif", "jpg", "jpeg", "png", "svg"]
)
],
help_text=_("Leave blank to use the default Django logo"),
verbose_name=_("logo"),
)
logo_color = ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name=_('color'))
verbose_name=_("color"),
)
logo_max_width = models.PositiveSmallIntegerField(
blank=True,
default=400,
verbose_name=_('max width'))
blank=True, default=400, verbose_name=_("max width")
)
logo_max_height = models.PositiveSmallIntegerField(
blank=True,
default=100,
verbose_name=_('max height'))
logo_visible = models.BooleanField(
default=True,
verbose_name=_('visible'))
blank=True, default=100, verbose_name=_("max height")
)
logo_visible = models.BooleanField(default=True, verbose_name=_("visible"))
favicon = models.FileField(
upload_to='admin-interface/favicon/',
upload_to="admin-interface/favicon/",
blank=True,
validators=[FileExtensionValidator(
allowed_extensions=['gif', 'ico', 'jpg', 'jpeg', 'png', 'svg'])],
help_text=_('(.ico|.png|.gif - 16x16|32x32 px)'),
verbose_name=_('favicon'))
validators=[
FileExtensionValidator(
allowed_extensions=["gif", "ico", "jpg", "jpeg", "png", "svg"]
)
],
help_text=_("(.ico|.png|.gif - 16x16|32x32 px)"),
verbose_name=_("favicon"),
)
env_name = models.CharField(
blank=True,
max_length=50,
verbose_name=_('name'))
blank=True, max_length=50, verbose_name=_("name"))
env_color = ColorField(
blank=True,
default='#E74C3C',
help_text=_('(red: #E74C3C, orange: #E67E22, yellow: #F1C40F, green: #2ECC71, blue: #3498DB)'),
default="#E74C3C",
help_text=_(
"(red: #E74C3C, orange: #E67E22, yellow: #F1C40F, green: #2ECC71, blue: #3498DB)"
),
max_length=10,
verbose_name=_('color'))
verbose_name=_("color"),
)
env_visible_in_header = models.BooleanField(
default=True,
verbose_name=_('visible in header (marker and name)'))
default=True, verbose_name=_("visible in header (marker and name)")
)
env_visible_in_favicon = models.BooleanField(
default=True,
verbose_name=_('visible in favicon (marker)'))
default=True, verbose_name=_("visible in favicon (marker)")
)
language_chooser_active = models.BooleanField(
default=True,
verbose_name=_('active'))
default=True, verbose_name=_("active")
)
language_chooser_display_choices = (
('code', _('code'), ),
('name', _('name'), ),
(
"code",
_("code"),
),
(
"name",
_("name"),
),
)
language_chooser_display = models.CharField(
max_length=10,
choices=language_chooser_display_choices,
default='code',
verbose_name=_('display'))
default="code",
verbose_name=_("display"),
)
css_header_background_color = ColorField(
blank=True,
default='#0C4B33',
help_text='#0C4B33',
default="#0C4B33",
help_text="#0C4B33",
max_length=10,
verbose_name=_('background color'))
verbose_name=_("background color"),
)
css_header_text_color = ColorField(
blank=True,
default='#44B78B',
help_text='#44B78B',
default="#44B78B",
help_text="#44B78B",
max_length=10,
verbose_name=_('text color'))
verbose_name=_("text color"),
)
css_header_link_color = ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name=_('link color'))
verbose_name=_("link color"),
)
css_header_link_hover_color = ColorField(
blank=True,
default='#C9F0DD',
help_text='#C9F0DD',
default="#C9F0DD",
help_text="#C9F0DD",
max_length=10,
verbose_name=_('link hover color'))
verbose_name=_("link hover color"),
)
css_module_background_color = ColorField(
blank=True,
default='#44B78B',
help_text='#44B78B',
default="#44B78B",
help_text="#44B78B",
max_length=10,
verbose_name=_('background color'))
verbose_name=_("background color"),
)
css_module_background_selected_color = ColorField(
blank=True,
default='#FFFFCC',
help_text='#FFFFCC',
default="#FFFFCC",
help_text="#FFFFCC",
max_length=10,
verbose_name=_('background selected color'))
verbose_name=_("background selected color"),
)
css_module_text_color = ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name=_('text color'))
verbose_name=_("text color"),
)
css_module_link_color = ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name=_('link color'))
verbose_name=_("link color"),
)
css_module_link_selected_color = ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name=_('link selected color'))
verbose_name=_("link selected color"),
)
css_module_link_hover_color = ColorField(
blank=True,
default='#C9F0DD',
help_text='#C9F0DD',
default="#C9F0DD",
help_text="#C9F0DD",
max_length=10,
verbose_name=_('link hover color'))
verbose_name=_("link hover color"),
)
css_module_rounded_corners = models.BooleanField(
default=True,
verbose_name=_('rounded corners'))
default=True, verbose_name=_("rounded corners")
)
css_generic_link_color = ColorField(
blank=True,
default='#0C3C26',
help_text='#0C3C26',
default="#0C3C26",
help_text="#0C3C26",
max_length=10,
verbose_name=_('link color'))
verbose_name=_("link color"),
)
css_generic_link_hover_color = ColorField(
blank=True,
default='#156641',
help_text='#156641',
default="#156641",
help_text="#156641",
max_length=10,
verbose_name=_('link hover color'))
verbose_name=_("link hover color"),
)
css_save_button_background_color = ColorField(
blank=True,
default='#0C4B33',
help_text='#0C4B33',
default="#0C4B33",
help_text="#0C4B33",
max_length=10,
verbose_name=_('background color'))
verbose_name=_("background color"),
)
css_save_button_background_hover_color = ColorField(
blank=True,
default='#0C3C26',
help_text='#0C3C26',
default="#0C3C26",
help_text="#0C3C26",
max_length=10,
verbose_name=_('background hover color'))
verbose_name=_("background hover color"),
)
css_save_button_text_color = ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name=_('text color'))
verbose_name=_("text color"),
)
css_delete_button_background_color = ColorField(
blank=True,
default='#BA2121',
help_text='#BA2121',
default="#BA2121",
help_text="#BA2121",
max_length=10,
verbose_name=_('background color'))
verbose_name=_("background color"),
)
css_delete_button_background_hover_color = ColorField(
blank=True,
default='#A41515',
help_text='#A41515',
default="#A41515",
help_text="#A41515",
max_length=10,
verbose_name=_('background hover color'))
verbose_name=_("background hover color"),
)
css_delete_button_text_color = ColorField(
blank=True,
default='#FFFFFF',
help_text='#FFFFFF',
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name=_('text color'))
css = models.TextField(
blank=True,
verbose_name=_('text color'))
verbose_name=_("text color"),
)
related_modal_active = models.BooleanField(
default=True,
verbose_name=_('active'))
default=True, verbose_name=_("active"))
related_modal_background_color = ColorField(
blank=True,
default='#000000',
help_text='#000000',
default="#000000",
help_text="#000000",
max_length=10,
verbose_name=_('background color'))
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%', ),
(
"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'))
default="0.3",
help_text="20%",
verbose_name=_("background opacity"),
)
related_modal_rounded_corners = models.BooleanField(
default=True,
verbose_name=_('rounded corners'))
default=True, verbose_name=_("rounded corners")
)
related_modal_close_button_visible = models.BooleanField(
default=True,
verbose_name=_('close button visible'))
default=True, verbose_name=_("close button visible")
)
list_filter_dropdown = models.BooleanField(
default=True,
verbose_name=_('use dropdown'))
default=True, verbose_name=_("use dropdown")
)
list_filter_sticky = models.BooleanField(
default=True,
verbose_name=_('sticky position'))
default=True, verbose_name=_("sticky position")
)
foldable_apps = models.BooleanField(
default=True, verbose_name=_("foldable apps"))
recent_actions_visible = models.BooleanField(
default=True,
verbose_name=_('visible'))
default=True, verbose_name=_("visible")
)
form_submit_sticky = models.BooleanField(
default=False,
verbose_name=_('sticky submit'))
default=False, verbose_name=_("sticky submit")
)
form_pagination_sticky = models.BooleanField(
default=False,
verbose_name=_('sticky pagination'))
default=False, verbose_name=_("sticky pagination")
)
def set_active(self):
self.active = True
self.save()
class Meta:
app_label = 'admin_interface'
app_label = "admin_interface"
verbose_name = _('Theme')
verbose_name_plural = _('Themes')
verbose_name = _("Theme")
verbose_name_plural = _("Themes")
def __str__(self):
return force_str(self.name)
post_delete.connect(Theme.post_delete_handler, sender=Theme)
post_save.connect(Theme.post_save_handler, sender=Theme)
pre_save.connect(Theme.pre_save_handler, sender=Theme)
# post_save.connect(Theme.post_save_handler, sender=Theme)
# pre_save.connect(Theme.pre_save_handler, sender=Theme)
+16 -10
View File
@@ -5,23 +5,29 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
def check_installed_app(app, app_dj_version_limit):
def check_installed_app(app, max_dj_version=None):
dj_version = django.VERSION
installed_apps = settings.INSTALLED_APPS
if dj_version < app_dj_version_limit:
if max_dj_version is None:
if app not in installed_apps:
raise ImproperlyConfigured(
'\'{}\' needed before django {}.{}, '
'add it to settings.INSTALLED_APPS.'.format(
app, *app_dj_version_limit))
"'{}' is required, " "add it to settings.INSTALLED_APPS.".format(app)
)
elif dj_version < max_dj_version:
if app not in installed_apps:
raise ImproperlyConfigured(
"'{}' is required before django {}.{}, "
"add it to settings.INSTALLED_APPS.".format(app, *max_dj_version)
)
else:
if app in installed_apps:
raise ImproperlyConfigured(
'\'{}\' not needed since django {}.{}, '
'remove it from settings.INSTALLED_APPS.'.format(
app, *app_dj_version_limit))
"'{}' is no more required since django {}.{}, "
"remove it from settings.INSTALLED_APPS.".format(app, *max_dj_version)
)
def check_installed_apps():
check_installed_app('flat', (1, 9))
check_installed_app('flat_responsive', (2, 0))
check_installed_app("colorfield")
check_installed_app("flat", max_dj_version=(1, 9))
check_installed_app("flat_responsive", max_dj_version=(2, 0))
@@ -0,0 +1,70 @@
.admin-interface.foldable-apps [class^="app-"].module {
visibility: hidden;
}
.admin-interface.foldable-apps [class^="app-"].module.foldable-apps-ready {
visibility: visible;
}
.admin-interface.foldable-apps [class^="app-"].module > table > caption {
position: relative;
z-index: 0;
/* pointer-events: none; */
cursor: pointer;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */
}
.admin-interface.foldable-apps [class^="app-"].module > table > caption > a {
display: inline-block;
/* pointer-events: all !important; */
margin-right: 30px;
}
.admin-interface.foldable-apps [class^="app-"].module > table > caption::after {
position: absolute;
top: 0;
right: 0;
z-index: 10;
width: auto;
height: 100%;
content: "−";
font-size: 16px;
font-weight: lighter;
text-align: center;
padding-left: 10px;
padding-right: 10px;
cursor: pointer;
pointer-events: all !important;
display: flex;
flex-direction: column;
justify-content: center;
}
@media (min-width: 1024px) {
.admin-interface.foldable-apps [class^="app-"].module > table > caption::after {
padding-left: 15px;
padding-right: 15px;
}
}
.admin-interface.foldable-apps [class^="app-"].module > table {
display: table;
width: 100%;
}
.admin-interface.foldable-apps [class^="app-"].module.collapsed {
margin-bottom: 10px;
}
.admin-interface.foldable-apps [class^="app-"].module.collapsed > table > caption::after {
content: "+";
}
.admin-interface.foldable-apps [class^="app-"].module.collapsed > table > tbody {
display: none;
}
@@ -0,0 +1,35 @@
(function() {
window.onload = function() {
for (let moduleEl of document.querySelectorAll('.admin-interface.foldable-apps [class^="app-"].module')) {
// apply collapsed value from localstorage value
let moduleAppClass = null;
let moduleCollapsedClass = 'collapsed';
moduleEl.classList.forEach(function(className) {
if (className.startsWith('app-')) {
moduleAppClass = className;
}
});
if (moduleAppClass) {
let moduleAppKey = 'admin-interface.foldable-apps_' + moduleAppClass + '_collapsed';
let moduleCollapsed = Boolean(parseInt((localStorage.getItem(moduleAppKey) || 0)) || 0);
if (moduleCollapsed === true) {
moduleEl.classList.add(moduleCollapsedClass);
} else {
moduleEl.classList.remove(moduleCollapsedClass);
}
// attach click for togggle collapsed class
for (let captionEl of moduleEl.querySelectorAll('caption')) {
captionEl.onclick = function(event) {
// only when not clicking on the app name link
if (event.target.tagName.toLowerCase() === 'caption') {
moduleEl.classList.toggle(moduleCollapsedClass);
moduleCollapsed = moduleEl.classList.contains(moduleCollapsedClass);
localStorage.setItem(moduleAppKey, (moduleCollapsed ? 1 : 0));
}
};
}
}
moduleEl.classList.add('foldable-apps-ready');
}
};
})();
@@ -108,6 +108,7 @@ if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined')
// open the popup using magnific popup
$.magnificPopup.open({
mainClass: iframeInternalModalClass,
fixedContentPos: false,
showCloseBtn: true,
closeBtnInside: true,
items: {
+19 -20
View File
@@ -2,19 +2,13 @@
{% load i18n static admin_interface_tags %}
{% block title %}
{% get_admin_interface_theme as theme %}
{% if title %}{{ title }} | {% endif %}{% if theme.title %}{% trans theme.title %}{% else %}{{ site_title|default:_('Django administration') }}{% endif %}
{% endblock %}
{% block extrastyle %}
{% get_admin_interface_theme as theme %}
{% get_admin_interface_version as version %}
{% get_admin_interface_nocache as version_md5_cache %}
{% get_current_language as current_lang %}
<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/form-controls.css" %}
@@ -29,11 +23,6 @@ https://github.com/fabiocaccamo/django-admin-interface
{% include "admin_interface/css/tinymce.css" %}
{% include "admin_interface/css/json-widget.css" %}
{% include "admin_interface/css/rtl.css" %}
{% if theme.css %}
{{ theme.css|safe }}
{% endif %}
</style>
{% if current_lang == 'fa' %}
@@ -44,21 +33,31 @@ https://github.com/fabiocaccamo/django-admin-interface
{% block blockbots %}
{{ block.super }}
{% get_admin_interface_theme as theme %}
{% get_admin_interface_version as version %}
{% get_admin_interface_nocache as version_md5_cache %}
{# 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' %}?v={{ version }}">
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive_rtl.css' %}?v={{ version }}" />
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive.css' %}?nocache={{ version_md5_cache }}">
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive_rtl.css' %}?nocache={{ version_md5_cache }}">
{% include "admin_interface/favicon.html" %}
{% include "admin_interface/foldable-apps.html" %}
{% include "admin_interface/related-modal.html" %}
{% endblock %}
{% block bodyclass %}admin-interface flat-theme {% get_admin_interface_theme as theme %}{% if theme.name %}{{ theme.name|slugify }}-theme{% endif %}{% if theme.form_submit_sticky %} sticky-submit {% endif %}{% if theme.form_pagination_sticky %} sticky-pagination {% endif %}{% endblock %}
{% block extrahead %}
{{ block.super }}
{% endblock %}
{% block bodyclass %}
flat-theme admin-interface
{% if theme.name %} {{ theme.name|slugify }}-theme {% endif %}
{% if theme.foldable_apps %} foldable-apps {% endif %}
{% if theme.form_submit_sticky %} sticky-submit {% endif %}
{% if theme.form_pagination_sticky %} sticky-pagination {% endif %}
{% endblock %}
{% block branding %}
{% get_admin_interface_theme as theme %}
<h1 id="site-name">
<a href="{% url 'admin:index' %}">
{% 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 %}>
@@ -69,14 +68,14 @@ https://github.com/fabiocaccamo/django-admin-interface
{% if theme.title_visible %}
<span>{% if theme.title %}{% trans theme.title %}{% else %}{{ site_header|default:_('Django administration') }}{% endif %}</span>
{% endif %}
</a>
</h1>
{% endblock %}
{% block welcome-msg %}
{% get_admin_interface_theme as theme %}
{% if theme.language_chooser_active %}
{% get_admin_interface_languages as languages %}
{% include "admin_interface/language_chooser.html" %}
{% endif %}
{% if theme.env_visible_in_header %}<span class="environment-label {{ theme.env_name }}"></span><br>{% endif %}{{ block.super }}<br>
{% if theme.env_visible_in_header %}<span class="environment-label {{ theme.env_name }}">{{ theme.env_name }}</span><br>{% endif %}{{ block.super }}<br>
{% endblock %}
@@ -26,7 +26,7 @@
min-height: auto;
padding: 10px 30px;
line-height: 30px;
align-items: flex-start;
align-items: center;
justify-content: flex-start;
}
@@ -35,7 +35,6 @@
}
.admin-interface.login #header #branding h1 img.logo {
max-width: 100%;
margin-right: 0;
}
@@ -82,7 +81,7 @@
@media (max-width:1024px) {
.admin-interface #header {
align-items: center;
align-items: start;
}
}
@@ -93,12 +92,6 @@
display:inline-block !important; /* override inline display:none; */
}
@media (max-width:400px) {
.admin-interface #branding h1 img.logo {
max-width: 100%;
}
}
.admin-interface #branding h1 span {
display: inline-block;
}
@@ -133,10 +133,16 @@
display: inline-block;
}
.admin-interface #branding h1 {
.admin-interface #branding h1,
.admin-interface.login #header h1,
.admin-interface.login #header h1 a {
color: {{ theme.title_color }};
}
.admin-interface #branding h1 a {
color: inherit;
}
.admin-interface #branding h1 .logo.default {
background-color: transparent;
background-repeat: no-repeat;
@@ -145,9 +151,13 @@
background-image: url("data:image/svg+xml;utf8,<?xml version='1.0' encoding='utf-8'?><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'><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='{{ theme.logo_color|urlencode }}'><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.21Line truncated
}
.admin-interface #branding h1 img.logo {
.admin-interface #branding h1 img.logo,
.admin-interface.login #header #branding h1 img.logo {
{% if theme.logo_max_width > 0 %}
max-width: {{ theme.logo_max_width }}px;
max-width: min({{ theme.logo_max_width }}px, 100%);
{% else %}
max-width: 100%;
{% endif %}
{% if theme.logo_max_height > 0 %}
max-height: {{ theme.logo_max_height }}px;
@@ -431,6 +441,14 @@
border-bottom-right-radius:0;
{% endif %}
}
.admin-interface .module.collapse.collapsed h2 {
/* fix collapsed inlines rounded bottom borders */
{% if theme.css_module_rounded_corners %}
border-bottom-left-radius:4px;
border-bottom-right-radius:4px;
{% endif %}
}
/* end fix */
.admin-interface #content-related {
@@ -3,7 +3,7 @@
{% if theme.favicon %}
<link rel="icon" href="{{ theme.favicon.url }}">
{% if theme.env_visible_in_favicon %}
<script type="text/javascript" src="{% static 'admin_interface/favico/favico-0.3.10-patched.min.js' %}?v={{ version }}"></script>
<script type="text/javascript" src="{% static 'admin_interface/favico/favico-0.3.10-patched.min.js' %}?nocache={{ version_md5_cache }}"></script>
<script type="text/javascript">
var favicon = new Favico({
type: 'circle',
@@ -0,0 +1,6 @@
{% load static %}
{% if theme.foldable_apps %}
<link rel="stylesheet" type="text/css" href="{% static 'admin_interface/foldable-apps/foldable-apps.css' %}?nocache={{ version_md5_cache }}">
<script type="text/javascript" src="{% static 'admin_interface/foldable-apps/foldable-apps.js' %}?nocache={{ version_md5_cache }}"></script>
{% endif %}
@@ -1,7 +1,7 @@
{% load static %}
{% if theme.related_modal_active %}
<link rel="stylesheet" type="text/css" href="{% static 'admin_interface/magnific-popup/magnific-popup.css' %}?v={{ version }}">
<script type="text/javascript" src="{% static 'admin_interface/magnific-popup/jquery.magnific-popup.js' %}?v={{ version }}"></script>
<script type="text/javascript" src="{% static 'admin_interface/related-modal/related-modal.js' %}?v={{ version }}"></script>
<link rel="stylesheet" type="text/css" href="{% static 'admin_interface/magnific-popup/magnific-popup.css' %}?nocache={{ version_md5_cache }}">
<script type="text/javascript" src="{% static 'admin_interface/magnific-popup/jquery.magnific-popup.js' %}?nocache={{ version_md5_cache }}"></script>
<script type="text/javascript" src="{% static 'admin_interface/related-modal/related-modal.js' %}?nocache={{ version_md5_cache }}"></script>
{% endif %}
@@ -1,24 +1,22 @@
# -*- coding: utf-8 -*-
import django
from django import template, VERSION
import hashlib
import re
from django import template
from django.conf import settings
if django.VERSION < (1, 10):
from django.core.urlresolvers import NoReverseMatch, reverse
else:
from django.urls import NoReverseMatch, reverse
from django.utils import translation
from admin_interface.cache import get_cached_active_theme, set_cached_active_theme
from admin_interface.compat import NoReverseMatch, reverse
from admin_interface.models import Theme
from admin_interface.version import __version__
import re
register = template.Library()
if VERSION < (1, 9):
if django.VERSION < (1, 9):
simple_tag = register.assignment_tag
else:
simple_tag = register.simple_tag
@@ -33,16 +31,16 @@ def get_admin_interface_languages(context):
# less than 2 languages
return None
try:
set_language_url = reverse('set_language')
set_language_url = reverse("set_language")
except NoReverseMatch:
# ImproperlyConfigured - must include i18n urls:
# urlpatterns += [url(r'^i18n/', include('django.conf.urls.i18n')),]
return None
request = context.get('request', None)
request = context.get("request", None)
if not request:
return None
full_path = request.get_full_path()
admin_nolang_url = re.sub(r'^\/([\w]{2})([\-\_]{1}[\w]{2,4})?\/', '/', full_path)
admin_nolang_url = re.sub(r"^\/([\w]{2})([\-\_]{1}[\w]{2,4})?\/", "/", full_path)
if admin_nolang_url == full_path:
# ImproperlyConfigured - must include admin urls using i18n_patterns:
# from django.conf.urls.i18n import i18n_patterns
@@ -55,12 +53,13 @@ def get_admin_interface_languages(context):
lang_code = language[0].lower()
lang_name = language[1].title()
lang_data = {
'code': lang_code,
'name': lang_name,
'default': lang_code == default_lang_code,
'active': lang_code == current_lang_code,
'activation_url': '{}?next=/{}{}'.format(
set_language_url, lang_code, admin_nolang_url)
"code": lang_code,
"name": lang_name,
"default": lang_code == default_lang_code,
"active": lang_code == current_lang_code,
"activation_url": "{}?next=/{}{}".format(
set_language_url, lang_code, admin_nolang_url
),
}
langs_data.append(lang_data)
return langs_data
@@ -68,13 +67,24 @@ def get_admin_interface_languages(context):
@simple_tag(takes_context=True)
def get_admin_interface_theme(context):
theme = get_cached_active_theme()
if not theme:
# theme = get_cached_active_theme()
# if not theme:
theme = Theme.get_active_theme()
set_cached_active_theme(theme)
# set_cached_active_theme(theme)
return theme
@simple_tag(takes_context=False)
def get_admin_interface_version():
return __version__
def hash_string(text):
hash_object = hashlib.md5(text.encode())
md5_hash = hash_object.hexdigest()
return md5_hash
@simple_tag(takes_context=False)
def get_admin_interface_nocache():
return hash_string(__version__)
+1 -1
View File
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
__version__ = '0.17.3'
__version__ = "0.19.3"
+4
View File
@@ -0,0 +1,4 @@
codecov
coverage
psycopg2
tox
-3
View File
@@ -1,8 +1,5 @@
codecov
coverage
django>=1.7
django-colorfield
django-flat-theme
django-flat-responsive
six>=1.9.0
tox
+4 -4
View File
@@ -9,13 +9,13 @@ from django.test.utils import get_runner
def runtests():
os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.settings'
os.environ["DJANGO_SETTINGS_MODULE"] = "tests.settings"
django.setup()
TestRunner = get_runner(settings)
test_runner = TestRunner()
failures = test_runner.run_tests(['tests'])
failures = test_runner.run_tests(["tests"])
sys.exit(bool(failures))
if __name__ == '__main__':
runtests()
if __name__ == "__main__":
runtests()
+72 -50
View File
@@ -5,72 +5,94 @@ from setuptools import find_packages, setup
import os, sys
exec(open('admin_interface/version.py').read())
exec(open("admin_interface/version.py").read())
github_url = 'https://github.com/fabiocaccamo'
package_name = 'django-admin-interface'
package_url = '{}/{}'.format(github_url, package_name)
github_url = "https://github.com/fabiocaccamo"
sponsor_url = "https://github.com/sponsors/fabiocaccamo/"
twitter_url = "https://twitter.com/fabiocaccamo"
package_name = "django-admin-interface"
package_url = "{}/{}".format(github_url, package_name)
package_issues_url = "{}/issues".format(github_url)
package_path = os.path.abspath(os.path.dirname(__file__))
long_description_file_path = os.path.join(package_path, 'README.md')
long_description_content_type = 'text/markdown'
long_description = ''
long_description_file_path = os.path.join(package_path, "README.md")
long_description_content_type = "text/markdown"
long_description = ""
try:
long_description_file_options = {} if sys.version_info[0] < 3 else { 'encoding':'utf-8' }
with open(long_description_file_path, 'r', **long_description_file_options) as f:
long_description_file_options = (
{} if sys.version_info[0] < 3 else {"encoding": "utf-8"}
)
with open(long_description_file_path, "r", **long_description_file_options) as f:
long_description = f.read()
except IOError:
pass
setup(
name=package_name,
packages=find_packages(exclude=['contrib', 'docs', 'tests*']),
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.',
description="django-admin-interface is a modern responsive flat admin interface customizable by the admin itself.",
long_description=long_description,
long_description_content_type=long_description_content_type,
author='Fabio Caccamo',
author_email='fabio.caccamo@gmail.com',
author="Fabio Caccamo",
author_email="fabio.caccamo@gmail.com",
url=package_url,
download_url='{}/archive/{}.tar.gz'.format(package_url, __version__),
keywords=['django', 'admin', 'interface', 'responsive', 'flat', 'theme', 'custom', 'ui'],
requires=['django(>=1.7)'],
download_url="{}/archive/{}.tar.gz".format(package_url, __version__),
project_urls={
"Documentation": package_url,
"Issues": package_issues_url,
"Funding": sponsor_url,
"Twitter": twitter_url,
},
keywords=[
"django",
"admin",
"interface",
"responsive",
"flat",
"theme",
"custom",
"ui",
],
requires=["django(>=1.7)"],
install_requires=[
'django-colorfield >= 0.2, < 1.0',
'django-flat-theme >= 1.0, < 2.0',
'django-flat-responsive >= 1.0, < 3.0',
'six >= 1.9.0, < 2.0.0',
"django-colorfield >= 0.2, < 1.0",
"django-flat-theme >= 1.0, < 2.0",
"django-flat-responsive >= 1.0, < 3.0",
"six >= 1.9.0, < 2.0.0",
],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Framework :: Django',
'Framework :: Django :: 1.7',
'Framework :: Django :: 1.8',
'Framework :: Django :: 1.9',
'Framework :: Django :: 1.10',
'Framework :: Django :: 1.11',
'Framework :: Django :: 2.0',
'Framework :: Django :: 2.1',
'Framework :: Django :: 2.2',
'Framework :: Django :: 3.0',
'Framework :: Django :: 3.1',
'Framework :: Django :: 3.2',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Natural Language :: English',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Topic :: Software Development :: Build Tools',
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Django :: 1.7",
"Framework :: Django :: 1.8",
"Framework :: Django :: 1.9",
"Framework :: Django :: 1.10",
"Framework :: Django :: 1.11",
"Framework :: Django :: 2.0",
"Framework :: Django :: 2.1",
"Framework :: Django :: 2.2",
"Framework :: Django :: 3.0",
"Framework :: Django :: 3.1",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.0",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Topic :: Software Development :: Build Tools",
],
license='MIT',
test_suite='runtests.runtests'
license="MIT",
test_suite="runtests.runtests",
)
+64 -51
View File
@@ -7,69 +7,71 @@ import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = 'django-admin-interface'
SECRET_KEY = "django-admin-interface"
ALLOWED_HOSTS = ['*']
ALLOWED_HOSTS = ["*"]
# Application definition
INSTALLED_APPS = [
'admin_interface',
'colorfield',
"admin_interface",
"colorfield",
]
if django.VERSION < (1, 9):
# ONLY if django version < 1.9
INSTALLED_APPS += [
'flat',
"flat",
]
if django.VERSION < (2, 0):
# ONLY if django version < 2.0
INSTALLED_APPS += [
'flat_responsive',
"flat_responsive",
]
INSTALLED_APPS += [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.messages',
'django.contrib.sessions',
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.messages",
"django.contrib.sessions",
]
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',
"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',
"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',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.request',
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"django.template.context_processors.request",
]
},
},]
},
]
database_engine = os.environ.get('DATABASE_ENGINE', 'sqlite')
database_engine = os.environ.get("DATABASE_ENGINE", "sqlite")
database_config = {
'sqlite': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': ':memory:',
"sqlite": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": ":memory:",
},
# 'mysql': {
# 'ENGINE': 'django.db.backends.mysql',
@@ -79,32 +81,43 @@ database_config = {
# 'HOST': '',
# 'PORT': '',
# },
'postgres': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'admin_interface',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': '',
'PORT': '',
}
"postgres": {
"ENGINE": "django.db.backends.postgresql_psycopg2",
"NAME": "admin_interface",
"USER": "postgres",
"PASSWORD": "postgres",
"HOST": "",
"PORT": "",
},
}
github_workflow = os.environ.get("GITHUB_WORKFLOW")
if github_workflow:
database_config["postgres"]["NAME"] = "postgres"
database_config["postgres"]["HOST"] = "127.0.0.1"
database_config["postgres"]["PORT"] = "5432"
DATABASES = {
'default': database_config.get(database_engine),
"default": database_config.get(database_engine),
}
USE_I18N = True
LANGUAGES = (
('en', 'English', ),
('it', 'Italian', ),
(
"en",
"English",
),
(
"it",
"Italian",
),
)
LANGUAGE_CODE = 'en'
LANGUAGE_CODE = "en"
ROOT_URLCONF = 'tests.urls'
ROOT_URLCONF = "tests.urls"
MEDIA_ROOT = os.path.join(BASE_DIR, 'admin_interface/public/media/')
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'admin_interface/public/static/')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, "admin_interface/public/media/")
MEDIA_URL = "/media/"
STATIC_ROOT = os.path.join(BASE_DIR, "admin_interface/public/static/")
STATIC_URL = "/static/"
+20 -21
View File
@@ -9,7 +9,6 @@ from admin_interface.models import Theme
class AdminInterfaceFixturesTestCase(TestCase):
def setUp(self):
pass
@@ -17,36 +16,36 @@ class AdminInterfaceFixturesTestCase(TestCase):
pass
def __load_theme(self, theme_name):
call_command('loaddata', 'admin_interface_theme_%s.json' % (theme_name, ))
call_command("loaddata", "admin_interface_theme_%s.json" % (theme_name,))
def test_import_initial_data(self):
call_command('loaddata', 'initial_data.json')
self.assertEqual(Theme.objects.count(), 1);
call_command("loaddata", "initial_data.json")
self.assertEqual(Theme.objects.count(), 1)
def test_import_all(self):
self.__load_theme('django')
self.__load_theme('bootstrap')
self.__load_theme('foundation')
self.__load_theme('uswds')
self.assertEqual(Theme.objects.count(), 4);
self.__load_theme("django")
self.__load_theme("bootstrap")
self.__load_theme("foundation")
self.__load_theme("uswds")
self.assertEqual(Theme.objects.count(), 4)
def test_import_idempotency(self):
self.__load_theme('django')
self.__load_theme('django')
self.__load_theme('django')
self.__load_theme('django')
self.__load_theme('django')
self.assertEqual(Theme.objects.count(), 1);
self.__load_theme('bootstrap')
self.__load_theme('bootstrap')
self.__load_theme('bootstrap')
self.assertEqual(Theme.objects.count(), 2);
self.__load_theme("django")
self.__load_theme("django")
self.__load_theme("django")
self.__load_theme("django")
self.__load_theme("django")
self.assertEqual(Theme.objects.count(), 1)
self.__load_theme("bootstrap")
self.__load_theme("bootstrap")
self.__load_theme("bootstrap")
self.assertEqual(Theme.objects.count(), 2)
def test_import_override(self):
obj1 = Theme.get_active_theme()
obj1.title = 'Custom 1'
obj1.title = "Custom 1"
obj1.save()
self.__load_theme('django')
self.__load_theme("django")
obj2 = Theme.get_active_theme()
self.assertEqual(obj1.pk, obj2.pk)
self.assertTrue(obj1.title != obj2.title)
+16 -17
View File
@@ -12,7 +12,6 @@ from admin_interface.models import Theme
class AdminInterfaceModelsTestCase(TestCase):
def setUp(self):
pass
@@ -24,7 +23,7 @@ class AdminInterfaceModelsTestCase(TestCase):
print(theme)
self.assertTrue(theme != None)
self.assertTrue(theme.active)
self.assertEqual(Theme.objects.filter(active=True).count(), 1);
self.assertEqual(Theme.objects.filter(active=True).count(), 1)
def test_default_theme_created_if_no_themes(self):
Theme.objects.all().delete()
@@ -48,36 +47,36 @@ class AdminInterfaceModelsTestCase(TestCase):
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_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_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.__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)
theme_3 = Theme.objects.create(name='Custom 3', active=True)
theme_1 = Theme.objects.create(name="Custom 1", active=True)
theme_2 = Theme.objects.create(name="Custom 2", active=True)
theme_3 = Theme.objects.create(name="Custom 3", active=True)
self.assertEqual(Theme.get_active_theme().pk, theme_3.pk)
self.__test_active_theme()
def test_last_theme_activated_on_multiple_themes_activated(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_4 = Theme.objects.create(name='Custom 4', active=True)
theme_5 = Theme.objects.create(name='Custom 5', active=True)
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)
@@ -88,4 +87,4 @@ class AdminInterfaceModelsTestCase(TestCase):
def test_repr(self):
theme = Theme.get_active_theme()
self.assertEqual('{0}'.format(theme), 'Django')
self.assertEqual("{0}".format(theme), "Django")
+35 -32
View File
@@ -13,11 +13,11 @@ 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',
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.messages",
"django.contrib.sessions",
]
def setUp(self):
@@ -30,65 +30,68 @@ class AdminInterfaceSettingsTestCase(TestCase):
dj_version = django.VERSION
installed_apps = settings.INSTALLED_APPS
if 'colorfield' not in 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):
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):
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):
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):
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
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',
INSTALLED_APPS=[
"admin_interface",
# 'colorfield',
'flat',
'flat_responsive',
] + DJANGO_APPS
"flat",
"flat_responsive",
]
+ DJANGO_APPS
)
def test_installed_apps_no_colorfield(self):
self.__test_installed_apps()
@override_settings(
INSTALLED_APPS = [
'admin_interface',
'colorfield',
INSTALLED_APPS=[
"admin_interface",
"colorfield",
# 'flat',
'flat_responsive',
] + DJANGO_APPS
"flat_responsive",
]
+ DJANGO_APPS
)
def test_installed_apps_no_flat(self):
self.__test_installed_apps()
@override_settings(
INSTALLED_APPS = [
'admin_interface',
'colorfield',
'flat',
INSTALLED_APPS=[
"admin_interface",
"colorfield",
"flat",
# 'flat_responsive',
] + DJANGO_APPS
]
+ DJANGO_APPS
)
def test_installed_apps_no_flat_responsive(self):
self.__test_installed_apps()
+74 -39
View File
@@ -8,11 +8,11 @@ from django.template import Context, Template
from admin_interface.models import Theme
from admin_interface.templatetags import admin_interface_tags as templatetags
from admin_interface.templatetags.admin_interface_tags import hash_string
from admin_interface.version import __version__
class AdminInterfaceTemplateTagsTestCase(TestCase):
def setUp(self):
self.request_factory = RequestFactory()
@@ -23,47 +23,65 @@ class AdminInterfaceTemplateTagsTestCase(TestCase):
return Template(string).render(Context(context or {}))
def test_get_admin_interface_languages(self):
context = Context({
'request': self.request_factory.get('/en/admin/'),
})
context = Context(
{
"request": self.request_factory.get("/en/admin/"),
}
)
languages = templatetags.get_admin_interface_languages(context)
expected_languages = [
{'code': 'en', 'name': 'English', 'default': True, 'active': True, 'activation_url': '/i18n/setlang/?next=/en/admin/'},
{'code': 'it', 'name': 'Italian', 'default': False, 'active': False, 'activation_url': '/i18n/setlang/?next=/it/admin/'}
{
"code": "en",
"name": "English",
"default": True,
"active": True,
"activation_url": "/i18n/setlang/?next=/en/admin/",
},
{
"code": "it",
"name": "Italian",
"default": False,
"active": False,
"activation_url": "/i18n/setlang/?next=/it/admin/",
},
]
self.assertEqual(len(languages), len(expected_languages))
self.assertEqual(languages[0], expected_languages[0])
self.assertEqual(languages[1], expected_languages[1])
@override_settings(
USE_I18N = False,
USE_I18N=False,
)
def test_get_admin_interface_languages_with_i18n_disabled(self):
context = Context({
'request': self.request_factory.get('/en/admin/'),
})
context = Context(
{
"request": self.request_factory.get("/en/admin/"),
}
)
languages = templatetags.get_admin_interface_languages(context)
self.assertEqual(languages, None)
@override_settings(
ROOT_URLCONF = 'tests.urls_without_i18n_patterns',
ROOT_URLCONF="tests.urls_without_i18n_patterns",
)
def test_get_admin_interface_languages_without_i18n_url_patterns(self):
context = Context({
'request': self.request_factory.get('/en/admin/'),
})
context = Context(
{
"request": self.request_factory.get("/en/admin/"),
}
)
languages = templatetags.get_admin_interface_languages(context)
self.assertEqual(languages, None)
@override_settings(
LANGUAGES = (
('en', 'English'),
),
LANGUAGES=(("en", "English"),),
)
def test_get_admin_interface_languages_without_multiple_languages(self):
context = Context({
'request': self.request_factory.get('/en/admin/'),
})
context = Context(
{
"request": self.request_factory.get("/en/admin/"),
}
)
languages = templatetags.get_admin_interface_languages(context)
self.assertEqual(languages, None)
@@ -73,9 +91,11 @@ class AdminInterfaceTemplateTagsTestCase(TestCase):
self.assertEqual(languages, None)
def test_get_admin_interface_languages_without_language_prefix_in_url(self):
context = Context({
'request': self.request_factory.get('/admin/'),
})
context = Context(
{
"request": self.request_factory.get("/admin/"),
}
)
languages = templatetags.get_admin_interface_languages(context)
self.assertEqual(languages, None)
@@ -83,31 +103,46 @@ class AdminInterfaceTemplateTagsTestCase(TestCase):
Theme.objects.all().delete()
context = Context({})
theme = templatetags.get_admin_interface_theme(context)
self.assertEqual(theme.name, 'Django')
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')
"{% load admin_interface_tags %}"
"{% get_admin_interface_theme as theme %}"
"{{ theme.name }}",
context,
)
self.assertEqual(rendered, "Django")
def test_get_theme_with_request(self):
Theme.objects.all().delete()
context = Context({
'request': self.request_factory.get('/')
})
context = Context({"request": self.request_factory.get("/")})
theme = templatetags.get_admin_interface_theme(context)
self.assertEqual(theme.name, 'Django')
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')
"{% load admin_interface_tags %}"
"{% get_admin_interface_theme as theme %}"
"{{ theme.name }}",
context,
)
self.assertEqual(rendered, "Django")
def test_get_version(self):
version = templatetags.get_admin_interface_version()
self.assertEqual(version, __version__)
rendered = self.__render_template(
'{% load admin_interface_tags %}'\
'{% get_admin_interface_version as version %}'\
'{{ version }}')
"{% load admin_interface_tags %}"
"{% get_admin_interface_version as version %}"
"{{ version }}"
)
self.assertEqual(rendered, __version__)
def test_get_version_nocache(self):
hash_from_tag = templatetags.get_admin_interface_nocache()
hash_manual = hash_string(__version__)
self.assertEqual(hash_from_tag, hash_manual)
rendered = self.__render_template(
"{% load admin_interface_tags %}"
"{% get_admin_interface_nocache as version_md5_hash %}"
"{{ version_md5_hash }}"
)
self.assertEqual(rendered, hash_manual)
+3 -2
View File
@@ -4,6 +4,7 @@ from __future__ import unicode_literals
import django
from django.contrib import admin
if django.VERSION < (2, 0):
from django.conf.urls import include, url as re_path
else:
@@ -13,8 +14,8 @@ from django.conf.urls.i18n import i18n_patterns
urlpatterns = []
urlpatterns += [
re_path(r'^i18n/', include('django.conf.urls.i18n')),
re_path(r"^i18n/", include("django.conf.urls.i18n")),
]
urlpatterns += i18n_patterns(
re_path(r'^admin/', admin.site.urls),
re_path(r"^admin/", admin.site.urls),
)
+2 -1
View File
@@ -4,6 +4,7 @@ from __future__ import unicode_literals
import django
from django.contrib import admin
if django.VERSION < (2, 0):
from django.conf.urls import url as re_path
else:
@@ -11,5 +12,5 @@ else:
urlpatterns = [
re_path(r'^admin/', admin.site.urls),
re_path(r"^admin/", admin.site.urls),
]
+17 -7
View File
@@ -1,13 +1,23 @@
[tox]
envlist =
py27-{dj17,dj18,dj19,dj110,dj111}-{sqlite,postgres},
py35-{dj18,dj19,dj110,dj111,dj20,dj21,dj22}-{sqlite,postgres},
py36-{dj18,dj19,dj110,dj111,dj20,dj21,dj22,dj30,dj31,dj32,djmaster}-{sqlite,postgres},
py37-{dj20,dj21,dj22,dj30,dj31,dj32,djmaster}-{sqlite,postgres},
py38-{dj22,dj30,dj31,dj32,djmaster}-{sqlite,postgres},
py39-{dj22,dj30,dj31,dj32,djmaster}-{sqlite,postgres},
py36-{dj18,dj19,dj110,dj111,dj20,dj21,dj22,dj30,dj31,dj32}-{sqlite,postgres},
py37-{dj20,dj21,dj22,dj30,dj31,dj32}-{sqlite,postgres},
py38-{dj22,dj30,dj31,dj32}-{sqlite,postgres},
py39-{dj22,dj30,dj31,dj32}-{sqlite,postgres},
py310-{dj32,dj40}-{sqlite,postgres},
[gh-actions]
python =
2.7: py27
3.6: py36
3.7: py37
3.8: py38
3.9: py39
3.10: py310
[testenv]
passenv = CI TRAVIS TRAVIS_*
passenv = CI GITHUB_WORKFLOW
deps =
dj17: Django == 1.7.*
dj18: Django == 1.8.*
@@ -20,7 +30,7 @@ deps =
dj30: Django == 3.0.*
dj31: Django == 3.1.*
dj32: Django == 3.2.*
djmaster: https://github.com/django/django/archive/master.tar.gz
dj40: Django == 4.0.*
# mysql: mysqlclient
postgres: psycopg2-binary
coverage