Compare commits

...
Author SHA1 Message Date
Guido 8185c7edf6 typho 2024-07-15 22:48:29 +02:00
Guido 51862ad3ed logo e/o favicon potrebbero mancare! 2024-07-15 19:19:29 +02:00
Davide Borgonovo 0eed8c8679 Incremento di versione 2023-10-27 12:49:55 +02:00
Davide Borgonovo d74fcd4001 location messa nel windowRef, altrimenti non funzionava la modale 2023-10-27 12:49:25 +02:00
Guido 97e1a2b315 rendo invertibile questa migrazione 2023-06-21 22:38:51 +02:00
Pietro 45266906a3 pulsante logout in django 4 2023-05-22 16:14:40 +02:00
davide_borgonovo 5496f996be Fixes #1
Fixes #2
2023-03-14 16:54:05 +01:00
davide_borgonovo d85690fb9c Aggiunto default per quando un utente non ha un tema attivo assegnato o se è un non utente. In questo modo non usa un tema a caso ma quello settato come default 2023-01-30 15:08:33 +01:00
davide_borgonovo c44621dae1 Ho messo un attribute error che non era vero 2023-01-10 18:18:41 +01:00
davide_borgonovo 5f2e2982b1 Updated version 2022-12-27 10:44:46 +01:00
davide_borgonovo 1b0d20f494 Corretto il get_active_theme nel context_processor e nel modello 2022-12-27 10:43:38 +01:00
davide_borgonovo 7e85ebac9b Importo ImportMixin o non funziona 2022-11-22 10:09:05 +01:00
davide_borgonovo 95fb2df285 Import mixin non veniva usato 2022-11-22 10:05:38 +01:00
davide_borgonovo 363bc310a1 Aggiunta import dei temi con uno .zip 2022-10-27 16:12:11 +02:00
davide_borgonovo 2ee03fc2de Non so perchè non si era preso dentro queste modifiche nella migrazione 29 2022-10-26 10:25:58 +02:00
davide_borgonovo 74dacaba2c Updated version 2022-10-25 18:00:29 +02:00
davide_borgonovo 9272e6563b Tolto tema di default con Django e warning brutto 2022-10-25 17:59:57 +02:00
davide_borgonovo a96cede14f white-space: normal nello user-tools che altrimenti nella versione mobile tagliava i link in alto a dx 2022-09-14 14:34:35 +02:00
Guido 903417ab79 theme.env_name everywere 2022-09-13 19:04:50 +02:00
davide_borgonovo d76c64c2d6 Messa la migrazione che altrimenti voleva fare la prima volta che si faceva makemigrations. Mi era scapapto un verbose name 2022-08-26 11:23:12 +02:00
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
Fabio Caccamo b7d9b969b4 Updated CHANGELOG and version. 2021-10-12 10:28:36 +02:00
Fabio Caccamo cacf0e0534 Fixed FileExtensionValidator TypeError on django < 1.11. 2021-10-12 10:28:19 +02:00
Fabio Caccamo e2239dcb99 Updated CHANGELOG and version. 2021-10-08 16:57:29 +02:00
Fabio Caccamo c769a449f2 Fixed FileExtensionValidator TypeError on django < 1.11. 2021-10-08 16:29:44 +02:00
Fabio Caccamo 3cff729a8a Updated CHANGELOG and version. 2021-09-24 09:08:05 +02:00
Fabio Caccamo c44db23b31 Fixed favicon fetching incompatible with django-storages S3. #128 2021-09-24 09:07:53 +02:00
Robert Durica 485f5400db Removed: Checking condition for colorfield package (#134) 2021-09-22 23:27:56 +02:00
Fabio Caccamo a2329fdae5 Updated CHANGELOG and version. 2021-09-16 15:48:16 +02:00
Fabio Caccamo a388ec234c Added logo_max_width and logo_max_height. #127 2021-09-16 15:47:14 +02:00
Fabio Caccamo a3b3f8922d Update CHANGELOG.md 2021-09-16 14:35:26 +02:00
Fabio Caccamo 6b6eed3aa0 Updated CHANGELOG and version. 2021-09-16 14:33:53 +02:00
Mason Neipp fd48e5ca97 Fixed 0020 migration for multiple dbs. #132 2021-09-04 14:45:49 +02:00
Fabio Caccamo fbc29246ff Improved header elements vertical alignment. 2021-05-06 23:34:49 +02:00
Fabio Caccamo 1569828c67 Updated README Installation section. [ci skip] 2021-05-02 10:39:56 +02:00
Fabio Caccamo bb73fafeff Fixed inlines vertical overlow. 2021-04-26 15:29:46 +02:00
Fabio Caccamo f76a41ff14 Fixed sticky pagination width and border-bottom. 2021-04-26 11:51:06 +02:00
Fabio Caccamo 4351751193 Updated CHANGELOG and version. 2021-04-26 10:18:58 +02:00
Fabio Caccamo 044ad518e0 Formatted migrations. 2021-04-26 10:16:03 +02:00
Fabio Caccamo 5b976adb1d Added missing 0021_file_extension_validator migration. #126 2021-04-26 10:15:24 +02:00
Fabio Caccamo 74732ec9a9 Added compat module. 2021-04-26 10:14:36 +02:00
Fabio Caccamo 5c85dc9cd4 Updated version and CHANGELOG. 2021-04-23 15:00:26 +02:00
Fabio Caccamo 66966501f8 Added FileExtensionValidator to logo and favicon fields. #112 2021-04-23 14:53:02 +02:00
Fabio Caccamo 30af685edf Improved selects min-width. 2021-04-21 11:30:30 +02:00
Fabio Caccamo 96d1568c13 Added min-width to selects. 2021-04-20 16:54:29 +02:00
Fabio Caccamo 7c04b35b44 Fixed related widget wrapper margin/padding with normal select. 2021-04-20 16:54:13 +02:00
Fabio Caccamo 004cd5fbcb Improved tabular inlines horizontal scroll. 2021-04-20 15:04:51 +02:00
Fabio Caccamo 8e37cdd218 Fixed related widget wrapper margin/padding in inlines. 2021-04-20 15:04:30 +02:00
Fabio Caccamo ba6807b7f3 Fixed changelist search and actions horizontal margins. 2021-04-16 12:33:21 +02:00
Fabio Caccamo 59a8b4d2d7 Removed invalid property. 2021-04-16 12:32:36 +02:00
Fabio Caccamo f72aac8848 Fixed changelist submit button margin left (with html minified). 2021-04-14 16:03:52 +02:00
Fabio Caccamo 41c6d5b7f1 Fixed header min-height. 2021-04-14 11:31:38 +02:00
Fabio Caccamo 554d8d27b7 Fixed models.W042 warning on django 3.2. 2021-04-14 11:18:58 +02:00
Fabio Caccamo c337c21a03 Added python 3.9 and django 3.2 to tox and travis. 2021-04-12 10:00:22 +02:00
Fabio Caccamo 0f9d502e4f Updated CHANGELOG and version. 2021-04-07 15:16:36 +02:00
Fabio Caccamo c961de3391 Overridden dark-mode css variables introduced in django 3.2. #124 2021-04-07 15:14:36 +02:00
Fabio Caccamo aec7ede184 Fixed delete confirmation styles selector prefix. 2021-04-07 15:13:23 +02:00
Natán d338e5914e Added custom style for the "Delete" and "Save" buttons from the delete confirmation page. (#123)
![Confirmation page](https://i.imgur.com/h4hflxu.png)
2021-04-07 15:09:20 +02:00
Fabio Caccamo 36971ad662 Fixed README links. [ci skip] 2021-03-30 18:17:29 +02:00
Fabio Caccamo d2c8885afa Updated CHANGELOG and version. 2021-03-30 18:13:11 +02:00
Fabio Caccamo e9b0694c0b Added supporting section to README. 2021-03-30 18:05:58 +02:00
Fabio Caccamo 14aa681e7d Removed unused funding options. 2021-03-30 18:02:02 +02:00
Fabio Caccamo c2e3545f46 Added responsive_rtl.css stylesheet. #98 2021-03-30 18:01:39 +02:00
Fabio Caccamo aed5afbfa7 Updated vazir-font version to 27.2.2. #98 2021-03-30 17:59:56 +02:00
Fabio Caccamo 9b7c6ee3fe Added css variables for css_module_background_selected_color and css_module_link_selected_color. #122 2021-03-30 17:57:44 +02:00
Henri Chain a8322872ab Added customizable colors for selected apps and models in dashboard. #122 2021-03-29 09:49:07 +02:00
Fabio Caccamo e5318b688b Updated CHANGELOG and version. 2021-03-26 19:17:05 +01:00
Fabio Caccamo 455259f3ef Fixed inline changelink style. 2021-03-26 19:14:39 +01:00
Fabio Caccamo 7d2d29a42c Made globally available presentRelatedObjectModal and presentRelatedObjectModalOnClickOn. 2021-03-26 19:14:22 +01:00
Henri Chain 5ed9fd75cc support show_change_link with related modal (#120) 2021-03-26 18:35:06 +01:00
Fabio Caccamo ca71642ecf Updated CHANGELOG and version. 2021-03-02 09:52:48 +01:00
Fabio Caccamo 4369288928 Fixed sticky submit and pagination z-index issue with related modal. 2021-03-02 09:52:36 +01:00
Fabio Caccamo f167bbf2c4 Updated README, CHANGELOG and version. 2021-03-01 23:32:26 +01:00
Fabio Caccamo 1b60af57e0 Fixed sticky submit and pagination z-index issue with sticky list_filter and django-json-widget. 2021-03-01 23:32:05 +01:00
Fabio Caccamo 947202f915 Updated version and CHANGELOG. 2021-02-08 11:21:37 +01:00
Fabio Caccamo 7eb6371104 Fixed sticky submit and pagination width when admin.site.enable_nav_sidebar = False. #113 2021-02-08 11:21:04 +01:00
Fabio Caccamo c315f366f3 Updated version and CHANGELOG. 2021-02-03 21:24:27 +01:00
Fabio Caccamo f2a2a98ad9 Improved sticky submit and pagination backward compatibility. 2021-02-03 21:23:05 +01:00
Fabio Caccamo 5b606153de Fixed body classes template rendering. 2021-02-03 21:22:06 +01:00
Fabio Caccamo 87396a1b5e Updated version and CHANGELOG. 2021-02-03 17:15:13 +01:00
Fabio Caccamo b35a2987cc Fixed and improved sticky form controls and pagination style. 2021-02-03 17:15:01 +01:00
Fabio Caccamo 2baed25204 Updated version and CHANGELOG. 2021-02-03 14:35:45 +01:00
Fabio Caccamo 3f5a3f9ded Updated README. 2021-02-03 14:35:25 +01:00
Fabio Caccamo 6189a7bbdb Renamed migration. 2021-02-03 14:35:10 +01:00
Amir Ajorloo d1cda34a52 Add sticky action button option. (#110)
* Add sticky action button option.

* Add sticky_pagination field. Handle top submit row. Update Admin section

* Add sticky-pagination styles. Fix trailing whitespace issue in models.

* Update sticky pagination max-width
2021-02-03 10:26:07 +01:00
Fabio Caccamo fdbacba4bb Added support to 4-digit language code in language chooser. #111 2021-01-29 15:57:39 +01:00
Fabio Caccamo 5c56f3a2db Added theme css variables. 2021-01-11 15:34:58 +01:00
Fabio Caccamo 17bb35c559 Fixed app module section link hover color. 2021-01-11 15:34:42 +01:00
Fabio Caccamo ed25f0fdde Updated version and CHANGELOG. 2021-01-04 13:55:07 +01:00
Fabio Caccamo a18e35f4c3 Updated LICENSE copyright year to present. 2021-01-04 13:54:57 +01:00
Fabio Caccamo f9817da531 Fixed module header selected link color. 2021-01-04 13:50:40 +01:00
Fabio Caccamo d94c6321aa Disabled sidebar transition. 2021-01-04 12:24:43 +01:00
Fabio Caccamo 3c77bad4ae Fixed tabular inline scroll bar. #101 2021-01-04 12:24:24 +01:00
Fabio Caccamo aa36776490 Fixed main content width when admin.site.enable_nav_sidebar is False. 2021-01-04 12:16:28 +01:00
anatolzakandAnatol Zakrividoroga d375b04941 added transition to nav sidebar and toggle nav sidebar button (#104)
* added transition to nav sidebar and toggle nav sidebar button

* specified transition properties instead of using all

* removed extra blank line

Co-authored-by: Anatol Zakrividoroga <anatol@Anatols-MacBook-Pro.local>
2020-12-15 16:32:15 +01:00
Fabio Caccamo cceb0b1721 Updated README. [ci skip] 2020-11-27 13:11:07 +01:00
Fabio Caccamo e364f9da1c Updated CHANGELOG and version. 2020-11-12 13:28:06 +01:00
Fabio Caccamo aec847070f Fixed sticky list-filter floating. #100 2020-11-12 13:27:51 +01:00
Fabio Caccamo 11f7440273 Improved tests coverage. 2020-10-21 12:27:14 +02:00
Fabio Caccamo 02cde83181 Fixed long description encoding. 2020-10-21 12:26:31 +02:00
Fabio Caccamo a302c87724 Updated CHANGELOG and version. 2020-10-15 11:14:12 +02:00
Fabio Caccamo d61ef86dd6 Added list filter sticky option (only for django >= 3.1.2). 2020-10-15 10:49:26 +02:00
Fabio Caccamo 071fe476a6 Enabled list filter dropdown by default. 2020-10-15 10:48:16 +02:00
Fabio Caccamo 9b611d1dcb Fixed searchbar style. 2020-10-15 10:42:40 +02:00
Fabio Caccamo 61c1720fd7 Fixed searchbar style. 2020-10-15 10:06:58 +02:00
Fabio Caccamo 962267de1d Updated CHANGELOG and version. 2020-10-14 18:37:50 +02:00
Fabio Caccamo f632929183 Improved responsive widgets style. 2020-10-14 18:35:59 +02:00
Fabio Caccamo 308858a0d0 Prevented body horizontal scroll. 2020-10-14 18:35:39 +02:00
Fabio Caccamo db7e0770b2 Fixed tabular inline horizontal scroll. 2020-10-14 18:34:56 +02:00
Fabio Caccamo 195ef2c44f Fixed changelist filter min-width. 2020-10-14 18:34:31 +02:00
Fabio Caccamo 48d3952e68 Fixed changelist and toolbar theme rounded corners. 2020-10-14 18:33:41 +02:00
Fabio Caccamo 96570502cc Fixed calendar and timelist buttons theme color. 2020-10-14 18:33:14 +02:00
Fabio Caccamo 759b5a6f49 Fixed list filter select size. 2020-10-14 18:32:49 +02:00
Fabio Caccamo 92710be337 Fixed content max-width with django 3.1.2 2020-10-14 13:57:35 +02:00
Fabio Caccamo c721359eea Updated CHANGELOG and version. 2020-10-14 13:00:34 +02:00
Fabio Caccamo 79ea1729cc Fixed logo, content and changelist-filter max-width. 2020-10-14 12:55:57 +02:00
Fabio Caccamo 8c4520d4b7 Added .admin-interface prefix to rtl selectors. 2020-10-14 12:55:26 +02:00
Fabio Caccamo b703f77f80 Re-added .gitignore [ci skip] 2020-10-14 10:02:25 +02:00
13b1d9f15f Add persian language (#98)
* add fa language translations
* add rtl css file. fix side-nav issue in rtl mode

Co-authored-by: Amir Ajorloo <amirajorloo@gmail.coml>
Co-authored-by: Fabio Caccamo <fabio.caccamo@gmail.com>
2020-10-14 10:00:45 +02:00
Fabio Caccamo e989e623db Updated README. [ci skip] 2020-10-13 15:38:20 +02:00
Fabio Caccamo 2113d009f4 Removed python 3.9 from travis. 2020-10-07 10:50:23 +02:00
Fabio Caccamo e967d09c8b Added python 3.9 to tests. 2020-10-06 10:59:09 +02:00
Fabio Caccamo c050c4f94c Updated CHANGELOG and version. 2020-09-15 09:54:30 +02:00
Fabio Caccamo 97cea97307 Removed python 3.4 from tox test matrix. 2020-09-15 09:54:01 +02:00
Fabio Caccamo 826340c9be Fixed loaddata error with initial_data.json fixture. #97 2020-09-15 09:49:50 +02:00
Fabio Caccamo 28dfc70474 Fixed tests warning (admin.W411). 2020-09-15 09:47:01 +02:00
Fabio Caccamo e9038157be Fixed changelist thead links color. 2020-09-07 23:30:35 +02:00
Fabio Caccamo be21550c6a Fixed changelist filter links hover color. 2020-09-07 14:10:53 +02:00
Fabio Caccamo db87a2aae2 Added "See also" section to README. [ci skip] 2020-09-04 17:00:02 +02:00
Fabio Caccamo 97ac8268b6 Updated version and CHANGELOG. 2020-09-04 15:35:54 +02:00
Fabio Caccamo 941835b5ee Removed old import. 2020-09-04 15:32:58 +02:00
Fabio Caccamo b050d7cb61 Added conditional imports to avoid Django deprecation warnings. #92 2020-09-04 15:30:03 +02:00
Fabio Caccamo 7d64545031 Updated header user-tools margins. 2020-09-04 11:43:42 +02:00
Fabio Caccamo 892bfa5e16 Changed header content vertical align to top. 2020-09-02 18:08:48 +02:00
Fabio Caccamo b165e6d27c Updated version. 2020-09-02 14:53:28 +02:00
Fabio Caccamo f0a72d5e40 Added django-json-widget theming support. 2020-09-02 14:53:19 +02:00
Fabio Caccamo 869d4c31ad Updated README testing section. [ci skip] 2020-08-27 12:52:48 +02:00
Fabio Caccamo a7788b98ed Updated requirements. [ci skip] 2020-08-27 12:52:38 +02:00
Fabio Caccamo 1045690678 Updated changelog and version. 2020-08-21 17:49:29 +02:00
Fabio Caccamo 09548dbcdc Fixed related modal not closing on edit save and create with django 3.1 - #96 2020-08-21 17:48:27 +02:00
Fabio Caccamo 0a4949c75a Updated CHANGELOG and version. 2020-08-18 17:53:37 +02:00
Fabio Caccamo f36e904faf Resized toogle-nav-sidebar button. 2020-08-18 17:51:10 +02:00
Fabio Caccamo f9a6f501e1 Added border when there is not breadcrumbs module. 2020-08-18 17:50:34 +02:00
Fabio Caccamo f9629f5ef1 Added max-width to logo. 2020-08-18 17:16:43 +02:00
Fabio Caccamo 084b0d65f3 Increased sidebar padding-top. 2020-08-18 16:41:32 +02:00
Fabio Caccamo 5935ee9d40 Added requirements-dev.txt 2020-08-18 16:39:45 +02:00
Fabio Caccamo ac66bfddb9 Added views badge to README. [ci skip] 2020-08-06 11:29:40 +02:00
Fabio Caccamo 62ccb31793 Updated CHANGELOG. 2020-08-05 21:24:30 +02:00
Fabio Caccamo 4e243962d1 Updated version. 2020-08-05 21:21:52 +02:00
Fabio Caccamo 51202a1def Improved header style. 2020-08-05 21:21:37 +02:00
Fabio Caccamo d799242714 Improved nav-sidebar style. 2020-08-05 21:19:22 +02:00
Fabio Caccamo e37142e0f4 Fixed tox django version error. 2020-08-04 17:43:03 +02:00
Fabio Caccamo 79dcc111da Added django 3.1 to CI. 2020-08-04 17:38:33 +02:00
Fabio Caccamo 651557bfc2 Updated CHANGELOG.md [ci skip] 2020-07-20 17:57:22 +02:00
Fabio Caccamo 5456e7ac53 Updated version. 2020-07-20 17:14:49 +02:00
Fabio Caccamo 03f8a2704e Fixed unreadable text in autocomplete multi-selects. #83 2020-07-20 17:14:40 +02:00
Fabio Caccamo ceab3232ad Unmerged admin-index PR. 2020-07-13 14:41:53 +02:00
Fabio Caccamo 6a0576cb7a Merge pull request #87 from carlosmonari/master
Hi again Mr Fabio, add suport a django-admin-index
2020-07-01 13:47:11 +02:00
carlosmonari 2935c890cf include stylishment to package django-admin-index
include stylishment to package https://github.com/maykinmedia/django-admin-index
2020-06-28 18:16:30 -03:00
carlosmonari 36f13ce164 include stylishment to package django-admin-index
include stylishment to package https://github.com/maykinmedia/django-admin-index
2020-06-28 18:13:02 -03:00
101 changed files with 4527 additions and 1136 deletions

No files matched your search

-4
View File
@@ -1,6 +1,2 @@
github: [fabiocaccamo]
patreon: fabiocaccamo
ko_fi: fabiocaccamo
liberapay: fabiocaccamo
issuehunt: fabiocaccamo
custom: ['https://www.paypal.me/fabiocaccamo']
+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/
-125
View File
@@ -1,125 +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-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-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-djmaster-sqlite
- python: "3.8"
env: TOX_ENV=py38-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
install:
- pip install tox
services:
- postgresql
before_script:
- psql -c 'create database admin_interface;' -U postgres
script:
- tox -e $TOX_ENV
+164
View File
@@ -4,6 +4,170 @@ 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.
## [0.17.2](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.17.2) - 2021-10-08
- Fixed `FileExtensionValidator` `TypeError` on django < 1.11.
## [0.17.1](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.17.1) - 2021-09-24
- Fixed `TemplateDoesNotExist` error on `django==4.0.a1` removing checking condition for `colorfield` package. #134
- Fixed favicon fetching incompatible with `django-storages` `S3`. #128
## [0.17.0](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.17.0) - 2021-09-16
- Added `logo_max_width` and `logo_max_height`. #127
## [0.16.4](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.16.4) - 2021-09-04
- Fixed `0020_module_selected_colors` migration for multiple dbs. #132
- Fixed sticky pagination `width` and `border-bottom`.
- Fixed inlines vertical overlow.
- Improved header elements vertical alignment.
## [0.16.3](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.16.3) - 2021-04-26
- Added `compat` module.
- Added missing `0021_file_extension_validator` migration. #126
- Formatted migrations.
## [0.16.2](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.16.2) - 2021-04-23
- Added `python 3.9` and `django 3.2` to CI.
- Added `FileExtensionValidator` to `logo` and `favicon` fields. #112
- Fixed `models.W042` warning on `django 3.2`.
- Fixed header `min-height`.
- Fixed selects `min-width`.
- Fixed changelist search, actions and submit button horizontal margins.
- Fixed related widget wrapper margin/padding with normal select and in inlines.
- Fixed tabular inlines horizontal scroll.
## [0.16.1](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.16.1) - 2021-04-07
- Fixed style of "Delete" and "Save" buttons in the delete confirmation page. #123
- Overridden dark-mode css variables introduced in `django 3.2`. #124
## [0.16.0](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.16.0) - 2021-03-30
- Added customizable colors for selected apps and models in dashboard. #122
- Added `responsive_rtl.css` stylesheet. #98
- Updated `vazir-font` version to `27.2.2`. #98
## [0.15.6](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.15.6) - 2021-03-26
- Fixed `show_change_link` related modal support. #120
- Fixed inline changelink style.
- Made globally available `presentRelatedObjectModal` and `presentRelatedObjectModalOnClickOn` js functions.
## [0.15.5](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.15.5) - 2021-03-02
- Fixed sticky submit and pagination `z-index` issue with related modal.
## [0.15.4](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.15.4) - 2021-03-01
- Fixed sticky submit and pagination `z-index` issue with sticky `list_filter` and `django-json-widget`.
## [0.15.3](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.15.3) - 2021-02-08
- Fixed sticky submit and pagination width when `admin.site.enable_nav_sidebar = False`. #113
## [0.15.2](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.15.2) - 2021-02-03
- Fixed body classes template rendering.
- Improved sticky submit and pagination backward compatibility.
## [0.15.1](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.15.1) - 2021-02-03
- Fixed and improved sticky form controls and pagination style.
## [0.15.0](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.15.0) - 2021-02-03
- Added sticky form controls and pagination options. #110
- Added support to 4-digit language code in language chooser. #111
- Added theme css variables for third-party libraries.
- Fixed app module section link hover color.
## [0.14.2](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.14.2) - 2021-01-04
- Fixed tabular inline scroll bar. #101
- Fixed module header selected link color. #102
- Fixed main content width when `admin.site.enable_nav_sidebar = False`. #105
## [0.14.1](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.14.1) - 2020-11-12
- Fixed sticky list-filter floating. #100
## [0.14.0](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.14.0) - 2020-10-15
- Added list filter sticky option (only for `django >= 3.1.2`).
- Enabled list filter dropdown by default.
- Fixed changelist searchbar style.
## [0.13.7](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.13.7) - 2020-10-14
- Improved responsive widgets style.
- Prevented body horizontal scroll.
- Fixed tabular inline horizontal scroll.
- Fixed changelist filter min-width.
- Fixed changelist and toolbar theme rounded corners.
- Fixed calendar and timelist buttons theme color.
- Fixed list filter select size.
- Fixed content max-width with `django >= 3.1`.
## [0.13.6](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.13.6) - 2020-10-14
- Added persian language. #98
- Fixed logo max-width on small screens.
- Fixed content max-width when nav-sidebar is collapsed.
- Fixed changelist max-width on medium screens.
## [0.13.5](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.13.5) - 2020-09-15
- Fixed loaddata error with initial_data.json fixture. #97
- Fixed tests warning (admin.W411).
- Fixed changelist thead links color.
- Fixed changelist filter links hover color.
## [0.13.4](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.13.4) - 2020-09-04
- Added conditional imports to avoid Django deprecation warnings. #92
- Changed admin header content vertical align to top.
## [0.13.3](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.13.3) - 2020-09-02
- Added `django-json-widget` theming support.
## [0.13.2](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.13.2) - 2020-08-21
- Fixed related modal not closing on edit save and create with django 3.1 - #96
## [0.13.1](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.13.1) - 2020-08-18
- Improved header and nav-sidebar style.
- Added `max-width` to logo.
- Added `requirements-dev.txt`
## [0.13.0](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.13.0) - 2020-08-05
- Improved nav-sidebar style (`django>=3.1` support).
- Improved header style.
## [0.12.3](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.12.3) - 2020-07-20
- Fixed unreadable text in autocomplete multi-selects. #83
## [0.12.2](https://github.com/fabiocaccamo/django-admin-interface/releases/tag/0.12.2) - 2020-04-07
- Fixed popup javascript error when related modal is inactive. #76
- Fixed js self invoking anonymous function expression.
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2016 Fabio Caccamo - fabio.caccamo@gmail.com
Copyright (c) 2016 - present, Fabio Caccamo - fabio.caccamo@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+150 -24
View File
@@ -2,90 +2,132 @@
[![](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**)*
- Responsive
- List filter dropdown *(optional)*
- `NEW` **Related modal** *(instead of the old popup window, optional)*
- `NEW` **Environment name/marker**
- `NEW` **Language chooser**
- Related modal *(instead of the old popup window)*
- 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:
- `django-ckeditor`
- `django-dynamic-raw-id`
- `django-json-widget`
- `django-modeltranslation`
- `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",
#...
)
X_FRAME_OPTIONS='SAMEORIGIN' # only if django version >= 3.0
# only if django version >= 3.0
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.
### Add theme support to third-party libraries
You can add **theme support to existing third-party libraries** using the following **css variables**:
- `--admin-interface-title-color`
- `--admin-interface-logo-color`
- `--admin-interface-env-color`
- `--admin-interface-header-background-color:`
- `--admin-interface-header-text-color`
- `--admin-interface-header-link-color`
- `--admin-interface-header-link_hover-color`
- `--admin-interface-module-background-color`
- `--admin-interface-module-background-selected-color`
- `--admin-interface-module-text-color`
- `--admin-interface-module-link-color`
- `--admin-interface-module-link-selected-color`
- `--admin-interface-module-link-hover-color`
- `--admin-interface-generic-link-color`
- `--admin-interface-generic-link-hover-color`
- `--admin-interface-save-button-background-color`
- `--admin-interface-save-button-background-hover-color`
- `--admin-interface-save-button-text-color`
- `--admin-interface-delete-button-background-color`
- `--admin-interface-delete-button-background-hover-color`
- `--admin-interface-delete-button-text-color`
- `--admin-interface-related-modal-background-color`
- `--admin-interface-related-modal-background-opacity`
---
## Screenshots
###### Admin login
![django-admin-interface_login](https://cloud.githubusercontent.com/assets/1035294/11240233/55c8d4ba-8df1-11e5-9568-00fdc987ede8.gif)
@@ -99,12 +141,96 @@ You can add a theme you've created through the admin to this repository by [send
###### 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
virtualenv testing_django_admin_interface
# activate virtualenv
cd testing_django_admin_interface && . bin/activate
# clone repo
git clone https://github.com/fabiocaccamo/django-admin-interface.git src && cd src
# install dependencies
pip install -r requirements.txt
pip install -r requirements-test.txt
# run tests
tox
# or
python setup.py test
# or
python -m django test --settings "tests.settings"
```
---
## License
Released under [MIT License](LICENSE.txt).
---
## See also
- [`django-colorfield`](https://github.com/fabiocaccamo/django-colorfield) - simple color field for models with a nice color-picker in the admin. 🎨
- [`django-extra-settings`](https://github.com/fabiocaccamo/django-extra-settings) - config and manage typed extra settings using just the django admin. ⚙️
- [`django-maintenance-mode`](https://github.com/fabiocaccamo/django-maintenance-mode) - shows a 503 error page when maintenance-mode is on. 🚧 🛠️
- [`django-redirects`](https://github.com/fabiocaccamo/django-redirects) - redirects with full control. ↪️
- [`django-treenode`](https://github.com/fabiocaccamo/django-treenode) - probably the best abstract model / admin for your tree based stuff. 🌳
- [`python-benedict`](https://github.com/fabiocaccamo/python-benedict) - dict subclass with keylist/keypath support, I/O shortcuts (base64, csv, json, pickle, plist, query-string, toml, xml, yaml) and many utilities. 📘
- [`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"
+178 -106
View File
@@ -1,119 +1,191 @@
# -*- coding: utf-8 -*-
from admin_interface.models import Theme
from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import models as auth_models
from admin_interface.compat import gettext_lazy as _
from admin_interface.models import Theme, UserTheme
from .import_tema.admin import ImportMixin
class ThemeAdmin(admin.ModelAdmin):
class UserInline(admin.TabularInline):
model = UserTheme
extra = 0
autocomplete_fields = ('user', )
list_display = ('name', 'active', )
list_editable = ('active', )
class ThemeAdmin(ImportMixin, admin.ModelAdmin):
inlines = [UserInline, ]
list_display = (
"name",
"active",
"demo",
"default",
)
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_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_text_color',
'css_module_link_color',
'css_module_link_hover_color',
'css_module_rounded_corners',
)
}),
(_('Generic Links'), {
'classes': ('wide', ),
'fields': (
'css_generic_link_color',
'css_generic_link_hover_color',
)
}),
(_('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',
)
}),
(_('List Filter'), {
'classes': ('wide', ),
'fields': ('list_filter_dropdown', )
}),
(_('Recent Actions'), {
'classes': ('wide', ),
'fields': ('recent_actions_visible', )
}),
(
None,
{
"classes": ("wide",),
"fields": (
"name",
"active",
"demo",
"default",
),
},
),
(
_("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
+6 -5
View File
@@ -1,14 +1,16 @@
# -*- coding: utf-8 -*-
from admin_interface.compat import gettext_lazy as _
from django.apps import AppConfig
from django.db.models.signals import post_migrate
from django.utils.translation import ugettext_lazy as _
class AdminInterfaceConfig(AppConfig):
name = 'admin_interface'
verbose_name = _('Admin Interface')
name = "admin_interface"
verbose_name = _("Admin Interface")
default_auto_field = "django.db.models.AutoField"
def ready(self):
@@ -16,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)
+26
View File
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
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
+43
View File
@@ -0,0 +1,43 @@
from .models import Theme, UserTheme
def get_active_theme(request):
objs_manager = Theme.objects
user_theme_manager = UserTheme.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 = user_theme_manager.filter(user=user, theme__active=True).first().theme
except:
objs_default_qs = objs_active_qs.filter(default=True)
if len(objs_default_qs) == 0:
obj = objs_active_qs.first()
if obj:
obj.set_default()
else:
obj = objs_default_qs.first()
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,
+38 -1
View File
@@ -1 +1,38 @@
[{"model": "admin_interface.theme", "pk": 1, "fields": {"name": "Django", "active": true, "title": "Django administration", "title_visible": true, "logo": "", "logo_visible": true, "css_header_background_color": "#0C4B33", "css_header_title_color": "#F5DD5D", "css_header_text_color": "#44B78B", "css_header_link_color": "#FFFFFF", "css_header_link_hover_color": "#C9F0DD", "css_module_background_color": "#44B78B", "css_module_text_color": "#FFFFFF", "css_module_link_color": "#FFFFFF", "css_module_link_hover_color": "#C9F0DD", "css_module_rounded_corners": true, "css_generic_link_color": "#0C3C26", "css_generic_link_hover_color": "#156641", "css_save_button_background_color": "#0C4B33", "css_save_button_background_hover_color": "#0C3C26", "css_save_button_text_color": "#FFFFFF", "css_delete_button_background_color": "#BA2121", "css_delete_button_background_hover_color": "#A41515", "css_delete_button_text_color": "#FFFFFF", "css": "", "related_modal_active": true, "related_modal_background_color": "#000000", "related_modal_background_opacity": 0.2, "related_modal_rounded_corners": true, "list_filter_dropdown": false}}]
[
{
"model": "admin_interface.theme",
"fields": {
"name": "Django",
"active": true,
"title": "Django administration",
"title_color": "#F5DD5D",
"title_visible": true,
"logo": "",
"logo_color": "#FFFFFF",
"logo_visible": true,
"css_header_background_color": "#0C4B33",
"css_header_text_color": "#44B78B",
"css_header_link_color": "#FFFFFF",
"css_header_link_hover_color": "#C9F0DD",
"css_module_background_color": "#44B78B",
"css_module_text_color": "#FFFFFF",
"css_module_link_color": "#FFFFFF",
"css_module_link_hover_color": "#C9F0DD",
"css_module_rounded_corners": true,
"css_generic_link_color": "#0C3C26",
"css_generic_link_hover_color": "#156641",
"css_save_button_background_color": "#0C4B33",
"css_save_button_background_hover_color": "#0C3C26",
"css_save_button_text_color": "#FFFFFF",
"css_delete_button_background_color": "#BA2121",
"css_delete_button_background_hover_color": "#A41515",
"css_delete_button_text_color": "#FFFFFF",
"related_modal_active": true,
"related_modal_background_color": "#000000",
"related_modal_background_opacity": 0.2,
"related_modal_rounded_corners": true,
"list_filter_dropdown": false,
"recent_actions_visible": true
}
}
]
Whitespace-only changes.
+160
View File
@@ -0,0 +1,160 @@
import json
import os
import tempfile
import zipfile
import django
from django import forms
from django.conf import settings
from django.contrib import admin, messages
from django.contrib.auth import get_permission_codename
from django.core.exceptions import PermissionDenied
from django.core.files.storage import default_storage
from django.http import HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import path, reverse
from django.utils.translation import gettext_lazy as _
from .. import models
from .forms import ImportForm
class ImportMixin(admin.ModelAdmin):
"""
Import mixin.
This is intended to be mixed with django.contrib.admin.ModelAdmin
https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#modeladmin-objects
"""
#: template for change_list view
change_list_template = 'admin/import_export/change_list_import.html'
#: template for import view
import_template_name = 'admin/import_export/import.html'
def get_model_info(self):
app_label = self.model._meta.app_label
return (self.model._meta.app_label, self.model._meta.model_name)
def has_import_permission(self, request):
"""
Returns whether a request has import permission.
"""
IMPORT_PERMISSION_CODE = getattr(settings, 'IMPORT_EXPORT_IMPORT_PERMISSION_CODE', None)
if IMPORT_PERMISSION_CODE is None:
return True
opts = self.opts
codename = get_permission_codename(IMPORT_PERMISSION_CODE, opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))
def get_urls(self):
urls = super().get_urls()
info = self.get_model_info()
my_urls = [
path('import/',
self.admin_site.admin_view(self.import_action),
name='%s_%s_import' % info),
]
return my_urls + urls
def get_import_context_data(self, **kwargs):
return self.get_context_data(**kwargs)
def get_context_data(self, **kwargs):
return {}
def get_form_kwargs(self, form, *args, **kwargs):
"""
Prepare/returns kwargs for the import form.
To distinguish between import and confirm import forms,
the following approach may be used:
if isinstance(form, ImportForm):
# your code here for the import form kwargs
# e.g. update.kwargs({...})
elif isinstance(form, ConfirmImportForm):
# your code here for the confirm import form kwargs
# e.g. update.kwargs({...})
...
"""
return kwargs
def import_action(self, request, *args, **kwargs):
"""
Perform a dry_run of the import to make sure the import will not
result in errors. If there where no error, save the user
uploaded file to a local temp file that will be used by
'process_import' for the actual import.
"""
if not self.has_import_permission(request):
raise PermissionDenied
context = self.get_import_context_data()
form_type = ImportForm
form_kwargs = self.get_form_kwargs(form_type, *args, **kwargs)
form = form_type(request.POST or None,
request.FILES or None,
**form_kwargs)
if request.POST and form.is_valid():
import_file_tema = form.cleaned_data['tema']
if zipfile.is_zipfile(import_file_tema):
with zipfile.ZipFile(import_file_tema, 'r') as zip_ref:
with tempfile.TemporaryDirectory() as tempdir:
zip_ref.extractall(tempdir)
lst = os.listdir(tempdir)
allowed_extensions=[".gif", ".jpg", ".jpeg", ".png", ".svg"]
try:
tema_json = [s for s in os.listdir(f'{tempdir}/{lst[0]}') if '.json' in s][0]
logo = [s for s in os.listdir(f'{tempdir}/{lst[0]}/logo') if any(ele in s for ele in allowed_extensions)]
logo = logo[0] if logo else None
favicon = [s for s in os.listdir(f'{tempdir}/{lst[0]}/favicon') if any(ele in s for ele in allowed_extensions)]
favicon = favicon[0] if favicon else None
with open(f'{tempdir}/{lst[0]}/{tema_json}', 'r') as temporary_file:
result = json.loads(temporary_file.read())
if logo:
with open(f'{tempdir}/{lst[0]}/logo/{logo}', 'rb') as temporary_file:
default_storage.save(f"admin-interface/logo/{temporary_file.name.split('/')[-1]}", temporary_file)
if favicon:
with open(f'{tempdir}/{lst[0]}/favicon/{favicon}', 'rb') as temporary_file:
default_storage.save(f"admin-interface/favicon/{temporary_file.name.split('/')[-1]}", temporary_file)
skip_result = False
except FileNotFoundError as e:
messages.error(request, 'Struttura del file .zip errata.')
skip_result = True
if not skip_result:
try:
new_theme = models.Theme(
**result[0]['fields']
)
new_theme.save()
messages.success(request, _('Import finished'))
except:
messages.error(request, 'Struttura del file .json errata.')
else:
messages.error(request, 'È richiesto un file .zip')
url = reverse('admin:%s_%s_changelist' % self.get_model_info(),
current_app=self.admin_site.name)
return HttpResponseRedirect(url)
else:
context.update(self.admin_site.each_context(request))
context['title'] = _("Import")
context['form'] = form
context['opts'] = self.model._meta
request.current_app = self.admin_site.name
return TemplateResponse(request, [self.import_template_name],
context)
def changelist_view(self, request, extra_context=None):
if extra_context is None:
extra_context = {}
extra_context['has_import_permission'] = self.has_import_permission(request)
return super().changelist_view(request, extra_context)
+11
View File
@@ -0,0 +1,11 @@
import os.path
from django import forms
from django.contrib.admin.helpers import ActionForm
from django.utils.translation import gettext_lazy as _
class ImportForm(forms.Form):
tema = forms.FileField(
label='Zip'
)
@@ -0,0 +1,139 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Christian Galeffi <chri@gallochri.com>, 2015.
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-04 09:27+0200\n"
"PO-Revision-Date: 2015-08-30 20:32+0100\n"
"Last-Translator: Christian Galeffi <chri@gallochri.com>\n"
"Language-Team: Italian <kde-i18n-it@kde.org>\n"
"Language: it\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"
"X-Generator: Poedit 1.5.4\n"
#: admin.py:194
#, python-format
msgid "%s through import_export"
msgstr ""
#: admin.py:200
msgid "Import finished, with {} new and {} updated {}."
msgstr ""
#: admin.py:298
#, python-format
msgid "<h1>Imported file has a wrong encoding: %s</h1>"
msgstr ""
#: admin.py:300
#, python-format
msgid "<h1>%s encountered while trying to read file: %s</h1>"
msgstr ""
#: admin.py:331 templates/admin/import_export/change_list_import_item.html:5
#: templates/admin/import_export/import.html:10
msgid "Import"
msgstr "Importare"
#: admin.py:496 templates/admin/import_export/change_list_export_item.html:5
#: templates/admin/import_export/export.html:7
msgid "Export"
msgstr "Esportare"
#: admin.py:554
msgid "You must select an export format."
msgstr "Devi selezionare un formato di esportazione."
#: admin.py:567
#, python-format
msgid "Export selected %(verbose_name_plural)s"
msgstr "Esporta selezionati %(verbose_name_plural)s"
#: forms.py:10
msgid "File to import"
msgstr "File da importare"
#: forms.py:13 forms.py:41 forms.py:66
msgid "Format"
msgstr "Formato"
#: templates/admin/import_export/base.html:11
msgid "Home"
msgstr "Home"
#: templates/admin/import_export/export.html:31
#: templates/admin/import_export/import.html:52
msgid "Submit"
msgstr "Inviare"
#: templates/admin/import_export/import.html:20
msgid ""
"Below is a preview of data to be imported. If you are satisfied with the "
"results, click 'Confirm import'"
msgstr ""
"Questa è un'anteprima dei dati che saranno importati. Se il risultato è "
"soddisfacente, premi 'Conferma importazione'"
#: templates/admin/import_export/import.html:23
msgid "Confirm import"
msgstr "Conferma importazione"
#: templates/admin/import_export/import.html:31
msgid "This importer will import the following fields: "
msgstr "Verranno importati i seguenti campi:"
#: templates/admin/import_export/import.html:61
#: templates/admin/import_export/import.html:90
msgid "Errors"
msgstr "Errori"
#: templates/admin/import_export/import.html:72
msgid "Line number"
msgstr "Numero linea"
#: templates/admin/import_export/import.html:82
msgid "Some rows failed to validate"
msgstr ""
#: templates/admin/import_export/import.html:84
msgid ""
"Please correct these errors in your data where possible, then reupload it "
"using the form above."
msgstr ""
#: templates/admin/import_export/import.html:89
msgid "Row"
msgstr ""
#: templates/admin/import_export/import.html:116
msgid "Non field specific"
msgstr ""
#: templates/admin/import_export/import.html:137
msgid "Preview"
msgstr "Anteprima"
#: templates/admin/import_export/import.html:152
msgid "New"
msgstr "Nuovo"
#: templates/admin/import_export/import.html:154
msgid "Skipped"
msgstr "Salta"
#: templates/admin/import_export/import.html:156
msgid "Delete"
msgstr "Cancella"
#: templates/admin/import_export/import.html:158
msgid "Update"
msgstr "Aggiorna"
#~ msgid "Import finished"
#~ msgstr "Importazione terminata"
@@ -0,0 +1,81 @@
.import-preview .errors {
position: relative;
}
.validation-error-count {
display: inline-block;
background-color: #e40000;
border-radius: 6px;
color: white;
font-size: 0.9em;
position: relative;
font-weight: bold;
margin-top: -2px;
padding: 0.2em 0.4em;
}
.validation-error-container {
position: absolute;
opacity: 0;
pointer-events: none;
background-color: #ffc1c1;
padding: 14px 15px 10px;
top: 25px;
margin: 0 0 20px 0;
width: 200px;
z-index: 2;
}
table.import-preview tr.skip {
background-color: #d2d2d2;
}
table.import-preview tr.new {
background-color: #bdd8b2;
}
table.import-preview tr.delete {
background-color: #f9bebf;
}
table.import-preview tr.update {
background-color: #fdfdcf;
}
.import-preview td:hover .validation-error-count {
z-index: 3;
}
.import-preview td:hover .validation-error-container {
opacity: 1;
pointer-events: auto;
}
.validation-error-list {
margin: 0;
padding: 0;
}
.validation-error-list li {
list-style: none;
margin: 0;
}
.validation-error-list > li > ul {
margin: 8px 0;
padding: 0;
}
.validation-error-list > li > ul > li {
padding: 0;
margin: 0 0 10px;
line-height: 1.28em;
}
.validation-error-field-label {
display: block;
border-bottom: 1px solid #e40000;
color: #e40000;
text-transform: uppercase;
font-weight: bold;
font-size: 0.85em;
}
@@ -0,0 +1,17 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_modify %}
{% load admin_urls %}
{% load static %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
{% block bodyclass %}{{ block.super }} {{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %}
{% if not is_popup %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>
&rsaquo; {% block breadcrumbs_last %}{% endblock %}
</div>
{% endblock %}
{% endif %}
@@ -0,0 +1,13 @@
{% extends "admin/change_list.html" %}
{# Original template renders object-tools only when has_add_permission is True. #}
{# This hack allows sub templates to add to object-tools #}
{% block object-tools %}
<ul class="object-tools">
{% block object-tools-items %}
{% if has_add_permission %}
{{ block.super }}
{% endif %}
{% endblock %}
</ul>
{% endblock %}
@@ -0,0 +1,6 @@
{% extends "admin/import_export/change_list.html" %}
{% block object-tools-items %}
{% include "admin/import_export/change_list_import_item.html" %}
{{ block.super }}
{% endblock %}
@@ -0,0 +1,171 @@
{% extends "admin/import_export/base.html" %}
{% load i18n %}
{% load admin_urls %}
{% load import_export_tags %}
{% load static %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "import_export/import.css" %}" />{% endblock %}
{% block breadcrumbs_last %}
{% trans "Import" %}
{% endblock %}
{% block content %}
{% if confirm_form %}
<form action="{% url opts|admin_urlname:"process_import" %}" method="POST">
{% csrf_token %}
{{ confirm_form.as_p }}
<p>
{% trans "Below is a preview of data to be imported. If you are satisfied with the results, click 'Confirm import'" %}
</p>
<div class="submit-row">
<input type="submit" class="default" name="confirm" value="{% trans "Confirm import" %}">
</div>
</form>
{% else %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>
{% trans "This importer will import the following fields: " %}
<code>{{ fields|join:", " }}</code>
</p>
<fieldset class="module aligned">
{% for field in form %}
<div class="form-row">
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
{% if field.field.help_text %}
<p class="help">{{ field.field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
</fieldset>
<div class="submit-row">
<input type="submit" class="default" value="{% trans "Submit" %}">
</div>
</form>
{% endif %}
{% if result %}
{% if result.has_errors %}
<h2>{% trans "Errors" %}</h2>
<ul>
{% for error in result.base_errors %}
<li>
{{ error.error }}
<div class="traceback">{{ error.traceback|linebreaks }}</div>
</li>
{% endfor %}
{% for line, errors in result.row_errors %}
{% for error in errors %}
<li>
{% trans "Line number" %}: {{ line }} - {{ error.error }}
<div><code>{{ error.row.values|join:", " }}</code></div>
<div class="traceback">{{ error.traceback|linebreaks }}</div>
</li>
{% endfor %}
{% endfor %}
</ul>
{% elif result.has_validation_errors %}
<h2>{% trans "Some rows failed to validate" %}</h2>
<p>{% trans "Please correct these errors in your data where possible, then reupload it using the form above." %}</p>
<table class="import-preview">
<thead>
<tr>
<th>{% trans "Row" %}</th>
<th>{% trans "Errors" %}</th>
{% for field in result.diff_headers %}
<th>{{ field }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in result.invalid_rows %}
<tr>
<td>{{ row.number }} </td>
<td class="errors">
<span class="validation-error-count">{{ row.error_count }}</span>
<div class="validation-error-container">
<ul class="validation-error-list">
{% for field_name, error_list in row.field_specific_errors.items %}
<li>
<span class="validation-error-field-label">{{ field_name }}</span>
<ul>
{% for error in error_list %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
{% if row.non_field_specific_errors %}
<li>
<span class="validation-error-field-label">{% trans "Non field specific" %}</span>
<ul>
{% for error in row.non_field_specific_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
</div>
</td>
{% for field in row.values %}
<td>{{ field }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<h2>{% trans "Preview" %}</h2>
<table class="import-preview">
<thead>
<tr>
<th></th>
{% for field in result.diff_headers %}
<th>{{ field }}</th>
{% endfor %}
</tr>
</thead>
{% for row in result.valid_rows %}
<tr class="{{ row.import_type }}">
<td class="import-type">
{% if row.import_type == 'new' %}
{% trans "New" %}
{% elif row.import_type == 'skip' %}
{% trans "Skipped" %}
{% elif row.import_type == 'delete' %}
{% trans "Delete" %}
{% elif row.import_type == 'update' %}
{% trans "Update" %}
{% endif %}
</td>
{% for field in row.diff %}
<td>{{ field }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
{% endif %}
{% endif %}
{% endblock %}
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,205 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Amir Ajorloo <amirajorloo@gmail.com>, 2020.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: django-admin-interface\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-12 19:23+0330\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Amir Ajorloo <amirajorloo@gmail.com>\n"
"Language-Team: Farsi <LL@li.org>\n"
"Language: Farsi"
"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 "محیط"
#: admin_interface/admin.py:30
msgid "Language chooser"
msgstr "انتخاب زبان"
#: admin_interface/admin.py:37
msgid "Logo"
msgstr "لوگو"
#: admin_interface/admin.py:45
msgid "Favicon"
msgstr "آیکون تب"
#: admin_interface/admin.py:49
msgid "Title"
msgstr "عنوان"
#: admin_interface/admin.py:57
msgid "Header"
msgstr "هدر"
#: admin_interface/admin.py:66
msgid "Breadcrumbs / Module headers"
msgstr "مسیر صفحه"
#: admin_interface/admin.py:76
msgid "Generic Links"
msgstr "لینک‌های عمومی"
#: admin_interface/admin.py:83
msgid "Save Buttons"
msgstr "دکمه‌های ذخیره"
#: admin_interface/admin.py:91
msgid "Delete Buttons"
msgstr "دکمه‌های حذف"
#: admin_interface/admin.py:99
msgid "Related Modal"
msgstr "مدل‌های مرتبط"
#: admin_interface/admin.py:109
msgid "List Filter"
msgstr "فیلتر‌های لیست"
#: admin_interface/admin.py:113
msgid "Recent Actions"
msgstr "فعالیت‌های اخیر"
#: admin_interface/apps.py:11
msgid "Admin Interface"
msgstr "ظاهر ادمین"
#: admin_interface/models.py:72 admin_interface/models.py:116
#: admin_interface/models.py:135
msgid "name"
msgstr "نام"
#: admin_interface/models.py:75 admin_interface/models.py:132
#: admin_interface/models.py:253
msgid "active"
msgstr "فعال"
#: 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 "مدیریت جنگو"
#: admin_interface/models.py:81
msgid "title"
msgstr "عنوان"
#: admin_interface/models.py:87 admin_interface/models.py:102
#: admin_interface/models.py:122
msgid "color"
msgstr "رنگ"
#: admin_interface/models.py:90 admin_interface/models.py:105
#: admin_interface/models.py:289
msgid "visible"
msgstr "نمایان"
#: admin_interface/models.py:95
msgid "Leave blank to use the default Django logo"
msgstr "برای نمایش لوگوی پیش فرض، خالی بگذارید."
#: admin_interface/models.py:96
msgid "logo"
msgstr "لوگو"
#: admin_interface/models.py:110
msgid "(.ico|.png|.gif - 16x16|32x32 px)"
msgstr "(.ico|.png|.gif - 16x16|32x32 px)"
#: admin_interface/models.py:111
msgid "favicon"
msgstr "آیکون تب"
#: admin_interface/models.py:120
msgid ""
"(red: #E74C3C, orange: #E67E22, yellow: #F1C40F, green: #2ECC71, blue: "
"#3498DB)"
msgstr ""
"(قرمز: #E74C3C, نارنجی: #E67E22, زرد: #F1C40F, سبز: #2ECC71, آبی: "
"#3498DB)"
#: admin_interface/models.py:125
msgid "visible in header (marker and name)"
msgstr "نمایان در هدر"
#: admin_interface/models.py:128
msgid "visible in favicon (marker)"
msgstr "نمایان در آیکون تب"
#: admin_interface/models.py:134
msgid "code"
msgstr "کد"
#: admin_interface/models.py:141
msgid "display"
msgstr "نمایش"
#: 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 "رنگ پس‌زمینه"
#: 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 "رنگ متن"
#: admin_interface/models.py:160 admin_interface/models.py:185
#: admin_interface/models.py:201
msgid "link color"
msgstr "رنگ لینک"
#: admin_interface/models.py:166 admin_interface/models.py:191
#: admin_interface/models.py:207
msgid "link hover color"
msgstr "رنگ لینک در حالت هاور"
#: admin_interface/models.py:194 admin_interface/models.py:279
msgid "rounded corners"
msgstr "گوشه‌های خمیده"
#: admin_interface/models.py:220 admin_interface/models.py:239
msgid "background hover color"
msgstr "رنگ پس‌زمینه در حالت هاور"
#: admin_interface/models.py:276
msgid "background opacity"
msgstr "شفافیت بکگراند"
#: admin_interface/models.py:282
msgid "close button visible"
msgstr "دکمه بستن نمایان باشد"
#: admin_interface/models.py:286
msgid "use dropdown"
msgstr "استفاده از دراپ داون"
#: admin_interface/models.py:298
msgid "Theme"
msgstr "تم"
#: admin_interface/models.py:299
msgid "Themes"
msgstr "تم‌ها"
#: admin_interface/templates/admin/filter.html:13
#: admin_interface/templates/admin_interface/dropdown_filter.html:4
#, python-format
msgid " By %(filter_title)s "
msgstr " توسط %(filter_title)s "
#: admin_interface/templates/admin/popup_response.html:3
msgid "Popup closing..."
msgstr "پاپ آپ در حال بسته شدن..."
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,18 +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',
field=models.CharField(choices=[('development', 'Development'), ('testing', 'Testing'), ('staging', 'Staging'), ('production', 'Production')], default='development', max_length=50, verbose_name='enviroment'),
model_name="theme",
name="env",
field=models.CharField(
choices=[
("development", "Development"),
("testing", "Testing"),
("staging", "Staging"),
("production", "Production"),
],
default="development",
max_length=50,
verbose_name="enviroment",
),
),
migrations.AddField(
model_name='theme',
name='env_visible',
field=models.BooleanField(default=True, verbose_name='visible'),
model_name="theme",
name="env_visible",
field=models.BooleanField(default=True, verbose_name="visible"),
),
]
@@ -8,38 +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',
field=models.CharField(choices=[('development', 'Development'), ('testing', 'Testing'), ('staging', 'Staging'), ('production', 'Production')], default='development', max_length=50, verbose_name='environment'),
model_name="theme",
name="env",
field=models.CharField(
choices=[
("development", "Development"),
("testing", "Testing"),
("staging", "Staging"),
("production", "Production"),
],
default="development",
max_length=50,
verbose_name="environment",
),
),
migrations.AlterField(
model_name='theme',
name='logo',
field=models.FileField(blank=True, help_text='Leave blank to use the default Django logo', upload_to='admin-interface/logo/', verbose_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",
),
),
migrations.AlterField(
model_name='theme',
name='name',
field=models.CharField(default='Django', max_length=50, verbose_name='name'),
model_name="theme",
name="name",
field=models.CharField(
default="Django", max_length=50, verbose_name="name"
),
),
migrations.AlterField(
model_name='theme',
name='title',
field=models.CharField(blank=True, default='Django administration', max_length=50, verbose_name='title'),
model_name="theme",
name="title",
field=models.CharField(
blank=True,
default="Django administration",
max_length=50,
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,18 +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',
field=colorfield.fields.ColorField(blank=True, default='#FFFFFF', help_text='#FFFFFF', max_length=10, verbose_name='color'),
model_name="theme",
name="logo_color",
field=colorfield.fields.ColorField(
blank=True,
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name="color",
),
),
migrations.AlterField(
model_name='theme',
name='title_color',
field=colorfield.fields.ColorField(blank=True, default='#F5DD5D', help_text='#F5DD5D', max_length=10, verbose_name='color'),
model_name="theme",
name="title_color",
field=colorfield.fields.ColorField(
blank=True,
default="#F5DD5D",
help_text="#F5DD5D",
max_length=10,
verbose_name="color",
),
),
]
@@ -8,13 +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',
field=models.BooleanField(default=True, verbose_name='close button visible'),
model_name="theme",
name="related_modal_close_button_visible",
field=models.BooleanField(
default=True, verbose_name="close button visible"
),
),
]
@@ -8,13 +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',
field=models.CharField(default='Django', max_length=50, unique=True, verbose_name='name'),
model_name="theme",
name="name",
field=models.CharField(
default="Django", max_length=50, unique=True, verbose_name="name"
),
),
]
@@ -8,13 +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,13 +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',
field=models.CharField(choices=[('code', 'code'), ('name', 'name')], default='code', max_length=10, verbose_name='display'),
model_name="theme",
name="language_chooser_display",
field=models.CharField(
choices=[("code", "code"), ("name", "name")],
default="code",
max_length=10,
verbose_name="display",
),
),
]
@@ -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", "0016_add_language_chooser_display"),
]
operations = [
migrations.AlterField(
model_name="theme",
name="list_filter_dropdown",
field=models.BooleanField(default=True, verbose_name="use dropdown"),
),
]
@@ -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", "0017_change_list_filter_dropdown"),
]
operations = [
migrations.AddField(
model_name="theme",
name="list_filter_sticky",
field=models.BooleanField(default=True, verbose_name="sticky position"),
),
]
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("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"),
),
migrations.AddField(
model_name="theme",
name="form_submit_sticky",
field=models.BooleanField(default=False, verbose_name="sticky submit"),
),
]
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations
from django.db.models import F
import colorfield.fields
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")
)
class Migration(migrations.Migration):
dependencies = [
("admin_interface", "0019_add_form_sticky"),
]
operations = [
migrations.AddField(
model_name="theme",
name="css_module_background_selected_color",
field=colorfield.fields.ColorField(
blank=True,
default="#FFFFCC",
help_text="#FFFFCC",
max_length=10,
verbose_name="background selected color",
),
),
migrations.AddField(
model_name="theme",
name="css_module_link_selected_color",
field=colorfield.fields.ColorField(
blank=True,
default="#FFFFFF",
help_text="#FFFFFF",
max_length=10,
verbose_name="link selected color",
),
),
migrations.RunPython(default_link_selected,migrations.RunPython.noop),
]
@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from admin_interface.compat import FileExtensionValidator
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("admin_interface", "0020_module_selected_colors"),
]
operations = [
migrations.AlterField(
model_name="theme",
name="favicon",
field=models.FileField(
blank=True,
help_text="(.ico|.png|.gif - 16x16|32x32 px)",
upload_to="admin-interface/favicon/",
validators=[
FileExtensionValidator(
allowed_extensions=["gif", "ico", "jpg", "jpeg", "png", "svg"]
)
],
verbose_name="favicon",
),
),
migrations.AlterField(
model_name="theme",
name="logo",
field=models.FileField(
blank=True,
help_text="Leave blank to use the default Django logo",
upload_to="admin-interface/logo/",
validators=[
FileExtensionValidator(
allowed_extensions=["gif", "jpg", "jpeg", "png", "svg"]
)
],
verbose_name="logo",
),
),
]
@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("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"
),
),
migrations.AddField(
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),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.0.4 on 2022-08-25 14:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0027_usertheme_m2m'),
]
operations = [
migrations.AlterField(
model_name='theme',
name='demo',
field=models.BooleanField(default=False, verbose_name='is demo'),
),
]
@@ -0,0 +1,32 @@
# Generated by Django 4.0.3 on 2022-10-25 13:59
from django.conf import settings
import django.db.models.deletion
from django.db import connection, migrations, models, transaction
def forward(apps, schema_editor):
Theme = apps.get_model("admin_interface", "Theme")
if len(Theme.objects.all()) == 1 and Theme.objects.first().name == 'Django':
with transaction.atomic():
cursor = connection.cursor()
cursor.execute("""truncate table "admin_interface_theme" restart identity;""")
def reverse(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0028_alter_theme_demo'),
]
operations = [
migrations.RunPython(forward, reverse),
migrations.AlterField(
model_name='usertheme',
name='user',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 4.0.3 on 2023-01-30 14:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('admin_interface', '0029_auto_20221025_1559'),
]
operations = [
migrations.AddField(
model_name='theme',
name='default',
field=models.BooleanField(default=False, verbose_name='default'),
),
]
+285 -153
View File
@@ -2,21 +2,31 @@
from __future__ import unicode_literals
from admin_interface.cache import del_cached_active_theme
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 django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
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.OneToOneField(
'auth.User', on_delete=models.CASCADE, null=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()
@@ -27,26 +37,27 @@ 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():
objs_manager = Theme.objects
user_theme_manager = UserTheme.objects
objs_active_qs = objs_manager.filter(active=True)
objs_active_ls = list(objs_active_qs)
objs_active_count = len(objs_active_ls)
@@ -55,255 +66,376 @@ class Theme(models.Model):
obj = objs_manager.all().first()
if obj:
obj.set_active()
else:
obj = objs_manager.create()
# else:
# obj = objs_manager.create()
elif objs_active_count == 1:
obj = objs_active_ls[0]
elif objs_active_count > 1:
obj = objs_active_ls[-1]
obj.set_active()
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 user_theme_manager.filter(user=user, theme__active=True).first().theme
except:
objs_default_qs = objs_active_qs.filter(default=True)
if len(objs_default_qs) == 0:
obj = objs_active_qs.first()
if obj:
obj.set_default()
else:
obj = objs_default_qs.first()
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"))
default = models.BooleanField(default=False, verbose_name="default")
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,
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'))
logo_visible = models.BooleanField(
default=True,
verbose_name=_('visible'))
verbose_name=_("color"),
)
logo_max_width = models.PositiveSmallIntegerField(
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"))
favicon = models.FileField(
upload_to='admin-interface/favicon/',
upload_to="admin-interface/favicon/",
blank=True,
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",
max_length=10,
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",
max_length=10,
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=False,
verbose_name=_('use dropdown'))
default=True, verbose_name=_("use dropdown")
)
list_filter_sticky = models.BooleanField(
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")
)
form_pagination_sticky = models.BooleanField(
default=False, verbose_name=_("sticky pagination")
)
def set_active(self):
self.active = True
self.save()
class Meta:
app_label = 'admin_interface'
def set_default(self):
self.default = True
self.save()
verbose_name = _('Theme')
verbose_name_plural = _('Themes')
def save(self):
if self.default:
Theme.objects.update(default=False)
super().save()
class Meta:
app_label = "admin_interface"
verbose_name = _("Theme")
verbose_name_plural = _("Themes")
def __str__(self):
return force_text(self.name)
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 -11
View File
@@ -5,24 +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('colorfield', (4, 0))
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))
@@ -10,8 +10,13 @@
openerRef = windowRef.parent;
windowName = windowRef.name;
widgetName = windowName.replace(/^(change|add|delete|lookup)_/, '');
if (typeof(openerRef.id_to_windowname) === 'function') {
// django < 3.1 compatibility
widgetName = openerRef.id_to_windowname(widgetName);
}
windowRef = {
name: openerRef.id_to_windowname(widgetName),
name: widgetName,
location: windowRef.location,
close: function() {
openerRef.dismissRelatedObjectModal();
}
@@ -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: {
@@ -130,6 +131,10 @@ if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined')
el.click(data, presentRelatedObjectModal);
}
// assign functions to global variables
window.presentRelatedObjectModal = presentRelatedObjectModal;
window.presentRelatedObjectModalOnClickOn = presentRelatedObjectModalOnClickOn;
// django 1.7 compatibility
// $('a.add-another').removeAttr('onclick').click({ lookup:false }, presentRelatedObjectModal);
presentRelatedObjectModalOnClickOn('a.add-another');
@@ -145,6 +150,9 @@ if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined')
// django-dynamic-raw-id support - #61
// https://github.com/lincolnloop/django-dynamic-raw-id
presentRelatedObjectModalOnClickOn('a.dynamic_raw_id-related-lookup', true);
// show_change_link=True support
presentRelatedObjectModalOnClickOn('a.inlinechangelink');
});
})(django.jQuery);
+24 -17
View File
@@ -2,20 +2,15 @@
{% 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_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" %}
{% include "admin_interface/css/list-filter-dropdown.css" %}
{% include "admin_interface/css/recent-actions.css" %}
{% include "admin_interface/css/related-modal.css" %}
@@ -25,30 +20,42 @@ https://github.com/fabiocaccamo/django-admin-interface
{% include "admin_interface/css/tabbed-admin.css" %}
{% include "admin_interface/css/ckeditor.css" %}
{% include "admin_interface/css/tinymce.css" %}
{% include "admin_interface/css/json-widget.css" %}
{% include "admin_interface/css/rtl.css" %}
</style>
{% if theme.css %}
{{ theme.css|safe }}
{% if current_lang == 'fa' %}
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/rastikerdar/vazir-font@v27.2.2/dist/font-face.css" />
{% endif %}
</style>
{% endblock %}
{% block blockbots %}
{{ block.super }}
{% get_admin_interface_theme as theme %}
{% get_admin_interface_version as version %}
{# https://github.com/elky/django-flat-responsive#important-note #}
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" href="{% static 'admin/css/responsive.css' %}?v={{ version }}">
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'admin/css/responsive_rtl.css' %}">
{% 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 %}{% 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 %}>
@@ -59,14 +66,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> - {% endif %}{{ block.super }}<br>
{% if theme.env_visible_in_header %}<span class="environment-label"></span><br>{% endif %}{{ block.super }}<br>
{% endblock %}
@@ -1,79 +1,121 @@
.admin-interface {
overflow-x: hidden;
}
/* fix login */
.admin-interface.login #container {
width:320px;
margin:90px auto;
width: 100%;
max-width: 360px;
margin: 15px auto;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
}
.admin-interface.login #content {
padding:15px 30px 10px 30px;
padding: 15px 30px 30px 30px;
}
@media (max-width:767px){
@media (min-width:768px){
.admin-interface.login #container {
margin:0px auto;
}
.admin-interface.login #content {
padding:20px 30px 30px 30px;
margin: 90px auto;
}
}
.admin-interface.login #header {
padding:15px 30px 10px;
min-height: auto;
padding: 10px 30px;
line-height: 30px;
align-items: center;
justify-content: flex-start;
}
.admin-interface.login #branding h1 {
.admin-interface.login #header #branding h1 {
margin-right:0;
}
.admin-interface.login #branding h1 img.logo {
max-width:100%;
.admin-interface.login #header #branding h1 img.logo {
margin-right: 0;
}
.admin-interface.login #header #branding h1 img.logo+span {
display: block;
margin-bottom: 5px;
}
.admin-interface.login .submit-row {
padding-left:0;
text-align:right;
.admin-interface.login #login-form {
display: flex;
flex-direction: column;
}
@media (max-width:767px){
.admin-interface.login .submit-row label {
display:none;
}
.admin-interface.login .submit-row {
float: left;
width: 100%;
margin-top: 20px;
margin-bottom: 30px;
padding-top: 0;
padding-left: 0;
text-align: right;
}
.admin-interface.login .submit-row label {
display: none;
}
.admin-interface.login .submit-row input[type="submit"] {
width: 100%;
text-transform: uppercase;
}
.admin-interface.login #footer {
display: none;
}
/* end login fix*/
.admin-interface #header {
height: auto;
min-height:40px;
min-height: 55px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
}
@media (max-width:1024px) {
.admin-interface #header {
align-items: start;
}
}
.admin-interface #branding h1 img.logo {
max-height:100px;
margin-top:10px;
margin-bottom:10px;
margin-right:15px;
display:inline-block !important; /* override inline display:none; */
}
.admin-interface #branding h1 span {
display: inline-block;
}
.admin-interface #branding h1 img.logo+span {
white-space:nowrap;
}
.admin-interface #user-tools {
margin-top: 10px;
margin-bottom: 10px;
white-space: normal;
align-self: flex-start;
}
.admin-interface #user-tools br {
display: none;
}
@media (max-width: 768px) {
.admin-interface #user-tools br {
display: block;
}
}
.admin-interface fieldset.collapse {
border: 1px solid transparent;
}
@@ -87,11 +129,12 @@
padding: 0 1px;
}
/*
#changelist table tbody tr.selected {
background-color:#FFFFCC;
@media (min-width: 1024px) {
.admin-interface #changelist .actions .button,
.admin-interface #changelist .actions .action-counter {
margin-left: 8px;
}
}
*/
.admin-interface #changelist .paginator {
margin-top:-1px; /* merge 2 borders into 1 */
@@ -135,6 +178,12 @@ body.admin-interface .paginator a.showall:visited {
margin-left: 5px;
}
.admin-interface .inline-group .inlinechangelink {
background-size: contain;
padding-left: 15px;
margin-left: 10px;
}
.admin-interface .file-thumbnail > a {
display: inline-block;
}
@@ -149,7 +198,6 @@ body.admin-interface .paginator a.showall:visited {
.admin-interface form .form-row p.file-upload .clearable-file-input {
display:inline-block;
margin-left:
}
.admin-interface form .form-row p.file-upload .clearable-file-input label {
@@ -177,6 +225,7 @@ body.admin-interface .paginator a.showall:visited {
.admin-interface form .form-row p.file-upload .clearable-file-input {
display: block;
margin-top: 10px;
margin-left: 0;
margin-bottom: -10px;
}
@@ -222,8 +271,13 @@ body.admin-interface .paginator a.showall:visited {
}
.admin-interface .module.filtered #changelist-filter {
border-bottom-left-radius:4px;
border-bottom-right-radius:4px;
min-width: 240px;
}
@media (max-width: 1024px) {
.admin-interface .module.filtered #changelist-filter {
min-width: 200px;
}
}
.admin-interface .module.filtered #changelist-filter h2 {
@@ -240,8 +294,11 @@ body.admin-interface .paginator a.showall:visited {
/* begin fix lateral padding to align text with field labels */
.admin-interface .module h2,
.admin-interface.dashboard .module caption,
.admin-interface.dashboard .module th,
.admin-interface .module.filtered h2,
.admin-interface .inline-group h2 {
.admin-interface .inline-group h2,
.admin-interface #nav-sidebar .module caption,
.admin-interface #nav-sidebar .module th {
padding-left: 10px;
padding-right: 10px;
}
@@ -259,9 +316,23 @@ body.admin-interface .paginator a.showall:visited {
}
/* end fix */
/* begin fix issue #10 - Related widget broken in long tabular inline */
.admin-interface .inline-group .tabular .related-widget-wrapper {
/* begin fix tabular inlines horizontal scroll */
.admin-interface .inline-related.tabular {
overflow-x: scroll;
overflow-y: hidden;
}
.admin-interface .inline-related.tabular fieldset.module {
display: contents;
width: 100%;
white-space: nowrap;
position: relative;
}
.admin-interface .inline-related.tabular fieldset.module h2 {
position: sticky;
left: 0;
}
.admin-interface .inline-related.tabular fieldset.module table tbody tr {
position: relative;
}
/* end fix */
@@ -306,17 +377,6 @@ body.admin-interface .paginator a.showall:visited {
background-color:#AAAAAA;
}
/* fix textarea horizontal scroll on Firefox */
@media (max-width: 767px){
.admin-interface .aligned .form-row textarea {
width: 100% !important;
flex: 0 1 auto;
}
.admin-interface .aligned .form-row input[type="file"] {
width: 100% !important;
}
}
/* improve responsive selector */
/* fix [stacked, not-stacked] equalize horizontal and vertical select padding for selector */
@@ -337,3 +397,186 @@ body.admin-interface .paginator a.showall:visited {
.admin-interface .selector:not(.stacked) .selector-chosen select {
height: calc(46px + 17.2em) !important;
}
/* fix nav-sidebar (added in django 3.1.0) */
.admin-interface #toggle-nav-sidebar {
top: 10px;
left: 0;
z-index: 20;
flex: 0 0 30px;
width: 30px;
height: 45px;
margin-top: 10px;
margin-right: 10px;
background-color: #FFFFFF;
font-size: 16px;
border: 1px solid #eaeaea;
border-left: none;
outline: none;
-webkit-box-shadow: 4px 2px 8px -4px #DBDBDB;
-moz-box-shadow: 4px 2px 8px -4px #DBDBDB;
box-shadow: 4px 2px 8px -4px #DBDBDB;
/*transition: left .3s;*/
}
.admin-interface .toggle-nav-sidebar::before {
margin-top: -2px;
}
.admin-interface .main > #nav-sidebar + .content,
.admin-interface .main.shifted > #nav-sidebar + .content {
max-width: 100%;
}
/* hide nav-sidebar below 1280px to prevent horizontal overflow issues */
@media (max-width:1279px) {
.admin-interface #nav-sidebar,
.admin-interface #toggle-nav-sidebar {
display: none;
}
}
.admin-interface #nav-sidebar {
flex: 0 0 320px;
left: -320px;
margin-left: -360px;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
padding: 40px 40px 40px 0px;
border-top: none;
border-bottom: none;
border-left: none;
/*transition: left .3s, margin-left .3s;*/
}
@media (min-width:1280px) {
.admin-interface #main.shifted > #toggle-nav-sidebar {
left: 359px;
}
.admin-interface #main.shifted > #nav-sidebar {
left: 0px;
margin-left: 0;
}
.admin-interface #main:not(.shifted) > .content {
max-width: 100%;
}
.admin-interface.change-list:not(.popup) #main.shifted > #nav-sidebar + .content,
.admin-interface.change-form:not(.popup) #main.shifted > #nav-sidebar + .content {
max-width: calc(100% - 360px);
}
}
/* fixed related widget and select2 */
/* begin fix issue #10 - Related widget broken in long tabular inline */
.admin-interface .related-widget-wrapper {
white-space: nowrap;
}
/* end fix */
.admin-interface .related-widget-wrapper select + .related-widget-wrapper-link,
.admin-interface .related-widget-wrapper .select2-container + .related-widget-wrapper-link {
margin-left: 12px !important;
}
@media (min-width: 768px) {
.admin-interface.change-form select {
min-width: 150px;
}
}
@media (min-width: 1024px) {
.admin-interface.change-form select {
min-width: 200px;
}
}
.admin-interface.change-form .inline-related.tabular select {
min-width: auto !important;
}
/* fixed time widget header border radius */
.admin-interface .clockbox.module h2 {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
/* fix searchbar overriden padding */
.admin-interface #changelist #changelist-search #searchbar {
padding: 2px 5px 3px 5px;
}
@media (min-width: 1024px) {
.admin-interface #changelist #changelist-search #searchbar,
.admin-interface #changelist #changelist-search input[type="submit"],
.admin-interface #changelist #changelist-search .quiet {
margin-left: 8px;
}
.admin-interface #changelist #changelist-search label img {
vertical-align: text-top;
margin-right: 0px;
}
}
@media (max-width: 1024px) {
.admin-interface #changelist #toolbar {
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
}
/* fixed changelist search size when there are search results and .quiet is visible */
.admin-interface #changelist-search label img {
margin-top: 2px;
}
.admin-interface #changelist-search .quiet {
margin: 0 0 0 10px;
align-self: center;
flex-basis: content;
}
}
@media (max-width: 767px) {
/* fixed responsive widgets */
.admin-interface .aligned.collapsed .form-row {
display: none;
}
.admin-interface .aligned .form-row > div {
display: flex;
max-width: 100vw;
flex-direction: column;
align-items: flex-start;
}
.admin-interface .aligned .form-row .help {
margin-left: 0;
}
.admin-interface .aligned .form-row .checkbox-row label {
margin: 10px 0 0 0;
padding: 0;
}
.admin-interface .aligned .form-row input[type="file"],
.admin-interface .aligned .form-row input[type="text"],
.admin-interface .aligned .form-row input[type="email"] {
width: 100%;
}
/* fix textarea horizontal scroll on Firefox */
.admin-interface .aligned .form-row textarea {
width: 100% !important;
flex: 0 1 auto;
}
.admin-interface .aligned .form-row .datetime input[type="text"] {
width: 50%;
}
.admin-interface .aligned .form-row span + .file-upload {
margin-top: 10px;
}
.admin-interface .aligned .form-row .file-upload input[type="file"] {
margin-top: 5px;
}
}
@@ -1,8 +1,84 @@
@media (prefers-color-scheme: dark) {
:root .admin-interface {
--primary: #79aec8;
--secondary: #417690;
--accent: #f5dd5d;
--primary-fg: #fff;
--body-fg: #333;
--body-bg: #fff;
--body-quiet-color: #666;
--body-loud-color: #000;
--header-color: #ffc;
--header-branding-color: var(--accent);
--header-bg: var(--secondary);
--header-link-color: var(--primary-fg);
--breadcrumbs-fg: #c4dce8;
--breadcrumbs-link-fg: var(--body-bg);
--breadcrumbs-bg: var(--primary);
--link-fg: #447e9b;
--link-hover-color: #036;
--link-selected-fg: #5b80b2;
--hairline-color: #e8e8e8;
--border-color: #ccc;
--error-fg: #ba2121;
--message-success-bg: #dfd;
--message-warning-bg: #ffc;
--message-error-bg: #ffefef;
--darkened-bg: #f8f8f8;
--selected-bg: #e4e4e4;
--selected-row: #ffc;
--button-fg: #fff;
--button-bg: var(--primary);
--button-hover-bg: #609ab6;
--default-button-bg: var(--secondary);
--default-button-hover-bg: #205067;
--close-button-bg: #888;
--close-button-hover-bg: #747474;
--delete-button-bg: #ba2121;
--delete-button-hover-bg: #a41515;
--object-tools-fg: var(--button-fg);
--object-tools-bg: var(--close-button-bg);
--object-tools-hover-bg: var(--close-button-hover-bg);
}
}
:root .admin-interface {
--admin-interface-title-color: {{ theme.title_color }};
--admin-interface-logo-color: {{ theme.logo_color }};
--admin-interface-env-color: {{ theme.env_color }};
--admin-interface-header-background-color: {{ theme.css_header_background_color }};
--admin-interface-header-text-color: {{ theme.css_header_text_color }};
--admin-interface-header-link-color: {{ theme.css_header_link_color }};
--admin-interface-header-link_hover-color: {{ theme.css_header_link_hover_color }};
--admin-interface-module-background-color: {{ theme.css_module_background_color }};
--admin-interface-module-background-selected-color: {{ theme.css_module_background_selected_color }};
--admin-interface-module-text-color: {{ theme.css_module_text_color }};
--admin-interface-module-link-color: {{ theme.css_module_link_color }};
--admin-interface-module-link-selected-color: {{ theme.css_module_link_selected_color }};
--admin-interface-module-link-hover-color: {{ theme.css_module_link_hover_color }};
--admin-interface-generic-link-color: {{ theme.css_generic_link_color }};
--admin-interface-generic-link-hover-color: {{ theme.css_generic_link_hover_color }};
--admin-interface-save-button-background-color: {{ theme.css_save_button_background_color }};
--admin-interface-save-button-background-hover-color: {{ theme.css_save_button_background_hover_color }};
--admin-interface-save-button-text-color: {{ theme.css_save_button_text_color }};
--admin-interface-delete-button-background-color: {{ theme.css_delete_button_background_color }};
--admin-interface-delete-button-background-hover-color: {{ theme.css_delete_button_background_hover_color }};
--admin-interface-delete-button-text-color: {{ theme.css_delete_button_text_color }};
--admin-interface-related-modal-background-color: {{ theme.related_modal_background_color }};
--admin-interface-related-modal-background-opacity: {{ theme.related_modal_background_opacity }};
}
.admin-interface #header {
background: {{ theme.css_header_background_color }};
color: {{ theme.css_header_text_color }};
}
.admin-interface #header + #main {
{% if theme.css_header_background_color != theme.css_module_background_color %}
border-top: 10px solid {{ theme.css_module_background_color }};
{% endif %}
}
.admin-interface .environment-label {
}
@@ -19,15 +95,35 @@
-webkit-box-sizing: border-box;
}
.admin-interface .environment-label::after {
content: "{{ theme.env_name }} - ";
}
@media (max-width:1024px) {
.admin-interface .environment-label::after {
content: "{{ theme.env_name }}";
}
}
.admin-interface .language-chooser {
display: inline-block;
position: absolute;
top: 15px;
right: 15px;
z-index: 10;
}
@media (min-width:768px) {
.admin-interface .language-chooser {
right: 30px;
}
}
@media (min-width:1024px) {
.admin-interface .language-chooser {
position: static;
float: right;
margin-left: 20px;
}
}
.admin-interface .language-chooser-hidden-form {
display: none;
@@ -37,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;
@@ -49,25 +151,51 @@
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 #user-tools br {
display: none;
}
@media (max-width: 768px){
.admin-interface #user-tools br {
display: block;
}
.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;
{% endif %}
}
.admin-interface #header #user-tools a {
.admin-interface #header #user-tools a,
.admin-interface #header #user-tools button {
color:{{ theme.css_header_link_color }};
}
.admin-interface #header #user-tools a:hover,
.admin-interface #header #user-tools a:active {
.admin-interface #header #user-tools a:active,
.admin-interface #header #user-tools button:active,
.admin-interface #header #user-tools button:hover {
color:{{ theme.css_header_link_hover_color }};
border-bottom-color:rgba(255, 255, 255, 0.5);
}
.admin-interface #nav-sidebar .current-app .section:link,
.admin-interface #nav-sidebar .current-app .section:visited {
color: {{ theme.css_module_link_selected_color }};
font-weight: normal;
}
.admin-interface #nav-sidebar .current-app .section:focus,
.admin-interface #nav-sidebar .current-app .section:hover {
color: {{ theme.css_module_link_hover_color }};
}
.admin-interface #nav-sidebar .current-model {
background: {{ theme.css_module_background_selected_color }};
}
.admin-interface #changelist table tbody tr.selected {
background-color: {{ theme.css_module_background_selected_color }};
}
.admin-interface .module h2,
.admin-interface .module caption,
.admin-interface .module.filtered h2 {
@@ -153,6 +281,14 @@
color:{{ theme.css_generic_link_hover_color }};
}
.admin-interface thead th a,
.admin-interface thead th a:link,
.admin-interface thead th a:visited,
.admin-interface thead th a:focus,
.admin-interface thead th a:hover {
color: #666666;
}
.admin-interface .button,
.admin-interface input[type=submit],
.admin-interface input[type=button],
@@ -189,19 +325,22 @@
.admin-interface .button.default:hover,
.admin-interface input[type=submit].default:active,
.admin-interface input[type=submit].default:focus,
.admin-interface input[type=submit].default:hover {
.admin-interface input[type=submit].default:hover,
.admin-interface.delete-confirmation form .cancel-link:hover {
background:{{ theme.css_save_button_background_hover_color }};
color:{{ theme.css_save_button_text_color }};
outline: none;
}
.admin-interface .submit-row a.deletelink:link,
.admin-interface .submit-row a.deletelink:visited {
.admin-interface .submit-row a.deletelink:visited,
.admin-interface.delete-confirmation form input[type="submit"] {
background:{{ theme.css_delete_button_background_color }};
color:{{ theme.css_delete_button_text_color }};
}
.admin-interface .submit-row a.deletelink:hover {
.admin-interface .submit-row a.deletelink:hover,
.admin-interface.delete-confirmation form input[type="submit"]:hover {
background:{{ theme.css_delete_button_background_hover_color }};
color:{{ theme.css_delete_button_text_color }};
}
@@ -242,14 +381,57 @@
color:{{ theme.css_generic_link_hover_color }};
}
/* list-filter sticky */
{% if theme.list_filter_sticky %}
@media (min-width: 768px) {
.admin-interface .module.filtered #changelist-filter {
position: sticky;
top: 40px;
float: right;
z-index: 30;
}
/* feature not available for django < 3.1.2 */
.admin-interface .module.filtered #toolbar + #changelist-filter {
position: absolute;
top: 0px;
z-index: 30;
}
}
{% endif %}
.admin-interface .module.filtered #changelist-filter {
{% if theme.css_module_rounded_corners %}
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
{% endif %}
}
.admin-interface .module.filtered #changelist-filter #changelist-filter-clear a:focus,
.admin-interface .module.filtered #changelist-filter #changelist-filter-clear a:hover {
color: #666;
text-decoration: none;
}
.admin-interface .module.filtered #changelist-filter li a:focus,
.admin-interface .module.filtered #changelist-filter li a:hover {
color: #666;
text-decoration: none;
}
.admin-interface .module.filtered #changelist-filter li.selected a,
.admin-interface .module.filtered #changelist-filter li.selected a:link,
.admin-interface .module.filtered #changelist-filter li.selected a:visited,
.admin-interface .module.filtered #changelist-filter li.selected a:focus,
.admin-interface .module.filtered #changelist-filter li.selected a:hover {
color: {{ theme.css_generic_link_color }};
/* color: #666; */
color: {{ theme.css_generic_link_hover_color }};
}
/* begin fix issue #11 - Inline border bottom should not be rounded */
.admin-interface .module h2,
.admin-interface.dashboard .module caption,
.admin-interface #nav-sidebar .module th,
.admin-interface #nav-sidebar .module caption,
.admin-interface .module.filtered h2 {
{% if theme.css_module_rounded_corners %}
border-radius:4px;
@@ -262,6 +444,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 {
@@ -271,5 +461,30 @@
}
.admin-interface .select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
background-color: {{ theme.css_header_background_color }};
background-color: {{ theme.css_module_background_color }};
color: {{ theme.css_module_text_color }};
}
.admin-interface #toggle-nav-sidebar {
{% if theme.css_module_rounded_corners %}
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
{% endif %}
color: {{ theme.css_generic_link_color }};
}
.admin-interface #toggle-nav-sidebar:focus,
.admin-interface #toggle-nav-sidebar:hover,
.admin-interface #toggle-nav-sidebar:active {
color: {{ theme.css_generic_link_hover_color }};
}
.admin-interface .calendar td.selected a,
.admin-interface .calendar td a:active,
.admin-interface .calendar td a:focus,
.admin-interface .calendar td a:hover,
.admin-interface .timelist a:active,
.admin-interface .timelist a:focus,
.admin-interface .timelist a:hover {
background: {{ theme.css_module_background_color }};
}
@@ -0,0 +1,95 @@
/* sticky pagination */
.admin-interface.sticky-pagination.change-list #content-main {
padding-bottom: 4.375rem;
}
.admin-interface.sticky-pagination.change-list .paginator {
width: 100%;
position: fixed;
bottom: 0;
right: 0;
z-index: 40;
box-sizing: border-box;
padding-left: 15px;
padding-right: 15px;
white-space: nowrap;
text-overflow: ellipsis;
border-radius: 0;
border-top: 1px solid #EEEEEE;
border-bottom: none;
margin: 0;
}
.admin-interface.sticky-pagination.change-list.popup .paginator {
padding-left: 20px;
padding-right: 20px;
}
@media (min-width:768px) {
.admin-interface.sticky-pagination.change-list:not(.popup) .paginator {
padding-left: 30px;
padding-right: 30px;
}
}
@media (min-width:1024px) {
.admin-interface.sticky-pagination.change-list:not(.popup) .paginator {
padding-left: 40px;
padding-right: 40px;
}
}
@media (min-width:1280px) {
.admin-interface.sticky-pagination.change-list:not(.popup) #main.shifted > #nav-sidebar + .content .paginator {
width: calc(100% - 360px);
}
}
/* sticky submit */
@media (min-width:768px) {
.admin-interface.sticky-submit.change-form #content-main {
padding-bottom: 4.375rem;
}
.admin-interface.sticky-submit.change-form .submit-row:last-of-type {
width: 100%;
position: fixed;
bottom: 0;
right: 0;
z-index: 40;
box-sizing: border-box;
padding-left: 15px;
padding-right: 15px;
white-space: nowrap;
text-overflow: ellipsis;
border-radius: 0;
border-top: 1px solid #EEEEEE;
border-bottom: none !important;
margin: 0;
}
.admin-interface.sticky-submit.change-form.popup .submit-row:last-of-type {
padding-left: 20px;
padding-right: 20px;
}
.admin-interface.sticky-submit.change-form:not(.popup) .submit-row:last-of-type {
padding-left: 30px;
padding-right: 30px;
}
}
@media (min-width:1024px) {
.admin-interface.sticky-submit.change-form:not(.popup) .submit-row:last-of-type {
padding-left: 40px;
padding-right: 40px;
}
}
@media (min-width:1280px) {
.admin-interface.sticky-submit.change-form:not(.popup) #main.shifted > #nav-sidebar + .content .submit-row:last-of-type {
width: calc(100% - 359px);
}
}
@@ -0,0 +1,29 @@
/*
django-json-widget support
https://github.com/jmrivas86/django-json-widget
*/
.admin-interface div.jsoneditor {
border: 1px solid {{ theme.css_module_background_color }};
{% if theme.css_module_rounded_corners %}
border-radius: 4px;
overflow: hidden;
{% endif %}
}
.admin-interface div.jsoneditor-menu {
background-color: {{ theme.css_module_background_color }};
border-bottom: 1px solid {{ theme.css_module_background_color }};
}
.admin-interface div.jsoneditor-menu a.jsoneditor-poweredBy {
color: {{ theme.css_module_link_color }};
}
.admin-interface div.jsoneditor-contextmenu ul li button.jsoneditor-selected,
.admin-interface div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus,
.admin-interface div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover {
background-color: {{ theme.css_module_background_selected_color }};
color: #000000;
font-weight: bold;
}
@@ -9,6 +9,6 @@ list-filter-dropdown
.admin-interface .list-filter-dropdown select {
background-color: #FFFFFF;
width:90%;
margin-right:5%;
width: calc(100% - 30px);
margin-right: 15px;
}
@@ -0,0 +1,34 @@
[dir="rtl"] .admin-interface,
[dir="rtl"] .admin-interface * {
font-family: 'Vazir', sans-serif !important;
}
[dir="rtl"] .admin-interface .main .toggle-nav-sidebar.sticky {
left: auto !important;
right: 0px !important;
margin-right: 0px !important;
margin-left: 10px;
border: 1px solid #eaeaea !important;
border-right: none !important;
border-top-right-radius: 0px !important;
border-bottom-right-radius: 0px !important;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
box-shadow: -4px 2px 8px -2px #DBDBDB !important;
}
[dir="rtl"] .admin-interface #main.shifted > #toggle-nav-sidebar {
right: 359px !important;
}
[dir="rtl"] .admin-interface #main > #nav-sidebar {
margin-right: -360px !important;
margin-left: 0px !important;
right: -320px !important;
}
[dir="rtl"] .admin-interface #main.shifted > #nav-sidebar {
border-left: 1px solid #eaeaea;
margin-right: 0px !important;
padding: 40px 0px 40px 40px !important;
}
@@ -1,9 +1,9 @@
{% load static %}
{% if theme.favicon %}
<link rel="icon" href="{{ theme.favicon.url }}?v={{ version }}">
<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' %}"></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' %}">
<script type="text/javascript" src="{% static 'admin_interface/foldable-apps/foldable-apps.js' %}"></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' %}">
<script type="text/javascript" src="{% static 'admin_interface/magnific-popup/jquery.magnific-popup.js' %}"></script>
<script type="text/javascript" src="{% static 'admin_interface/related-modal/related-modal.js' %}"></script>
{% endif %}
@@ -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})?\/', '/', 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.12.2'
__version__ = "0.19.8"
+4
View File
@@ -0,0 +1,4 @@
codecov
coverage
psycopg2
tox
+1
View File
@@ -1,3 +1,4 @@
django>=1.7
django-colorfield
django-flat-theme
django-flat-responsive
+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()
+73 -47
View File
@@ -3,70 +3,96 @@
from setuptools import find_packages, setup
import os
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:
with open(long_description_file_path) 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',
'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',
'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",
)
+70 -45
View File
@@ -1,72 +1,77 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import django
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',
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',
@@ -76,23 +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),
}
MEDIA_ROOT = os.path.join(BASE_DIR, 'admin_interface/public/media/')
MEDIA_URL = '/media/'
USE_I18N = True
LANGUAGES = (
(
"en",
"English",
),
(
"it",
"Italian",
),
)
LANGUAGE_CODE = "en"
STATIC_ROOT = os.path.join(BASE_DIR, 'admin_interface/public/static/')
STATIC_URL = '/static/'
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/"
+24 -19
View File
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.core.management import call_command
from django.test import TestCase
@@ -7,7 +9,6 @@ from admin_interface.models import Theme
class AdminInterfaceFixturesTestCase(TestCase):
def setUp(self):
pass
@@ -15,32 +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)
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)
+18 -17
View File
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.conf import settings
from django.test import TestCase
@@ -10,7 +12,6 @@ from admin_interface.models import Theme
class AdminInterfaceModelsTestCase(TestCase):
def setUp(self):
pass
@@ -22,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()
@@ -46,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)
@@ -86,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")
+33 -28
View File
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import django
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
@@ -11,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):
@@ -28,19 +30,19 @@ 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:
@@ -48,45 +50,48 @@ class AdminInterfaceSettingsTestCase(TestCase):
@override_settings(
INSTALLED_APPS=[
'admin_interface',
'colorfield',
'flat',
'flat_responsive',
] + DJANGO_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',
"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',
"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',
"admin_interface",
"colorfield",
"flat",
# 'flat_responsive',
] + DJANGO_APPS
]
+ DJANGO_APPS
)
def test_installed_apps_no_flat_responsive(self):
self.__test_installed_apps()
+112 -18
View File
@@ -1,16 +1,18 @@
# -*- coding: utf-8 -*-
from django.test import TestCase
from __future__ import unicode_literals
from django.test import override_settings, TestCase
from django.test.client import RequestFactory
from django.template import Context, Template
from admin_interface.models import Theme
from admin_interface.templatetags import admin_interface_tags as templatetags
from admin_interface.templatetags.admin_interface_tags import hash_string
from admin_interface.version import __version__
class AdminInterfaceTemplateTagsTestCase(TestCase):
def setUp(self):
self.request_factory = RequestFactory()
@@ -20,35 +22,127 @@ class AdminInterfaceTemplateTagsTestCase(TestCase):
def __render_template(self, string, context=None):
return Template(string).render(Context(context or {}))
def test_get_admin_interface_languages(self):
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/",
},
]
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,
)
def test_get_admin_interface_languages_with_i18n_disabled(self):
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",
)
def test_get_admin_interface_languages_without_i18n_url_patterns(self):
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"),),
)
def test_get_admin_interface_languages_without_multiple_languages(self):
context = Context(
{
"request": self.request_factory.get("/en/admin/"),
}
)
languages = templatetags.get_admin_interface_languages(context)
self.assertEqual(languages, None)
def test_get_admin_interface_languages_without_request(self):
context = Context({})
languages = templatetags.get_admin_interface_languages(context)
self.assertEqual(languages, None)
def test_get_admin_interface_languages_without_language_prefix_in_url(self):
context = Context(
{
"request": self.request_factory.get("/admin/"),
}
)
languages = templatetags.get_admin_interface_languages(context)
self.assertEqual(languages, None)
def test_get_theme(self):
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)
+21
View File
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
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:
from django.urls import include, re_path
from django.conf.urls.i18n import i18n_patterns
urlpatterns = []
urlpatterns += [
re_path(r"^i18n/", include("django.conf.urls.i18n")),
]
urlpatterns += i18n_patterns(
re_path(r"^admin/", admin.site.urls),
)
+16
View File
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
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:
from django.urls import re_path
urlpatterns = [
re_path(r"^admin/", admin.site.urls),
]
Loaded 100 of 101 files, more files were not shown because too many files have changed in this diff. Show more