django-microsys 2.1.9__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_microsys-2.1.9 → django_microsys-2.2.0}/PKG-INFO +1 -1
- {django_microsys-2.1.9 → django_microsys-2.2.0}/django_microsys.egg-info/PKG-INFO +1 -1
- {django_microsys-2.1.9 → django_microsys-2.2.0}/django_microsys.egg-info/SOURCES.txt +12 -4
- django_microsys-2.2.0/microsys/VERSION +1 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/context_processors.py +29 -2
- django_microsys-2.2.0/microsys/fonts.py +72 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/forms.py +147 -33
- django_microsys-2.2.0/microsys/migrations/0005_systemsettings_allow_user_font_override_and_more.py +29 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/models.py +17 -17
- django_microsys-2.2.0/microsys/static/microsys/fonts/cairo-bold.woff2 +0 -0
- django_microsys-2.2.0/microsys/static/microsys/fonts/cairo-medium.woff2 +0 -0
- django_microsys-2.2.0/microsys/static/microsys/fonts/cairo-regular.woff2 +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/language/css/main.css +1 -1
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/main.css +17 -25
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/js/base_head.js +7 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/js/base_runtime.js +1 -2
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/js/options.js +21 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/js/system_setup.js +64 -1
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/base.html +9 -3
- django_microsys-2.2.0/microsys/templates/microsys/includes/font_previews.html +23 -0
- django_microsys-2.2.0/microsys/templates/microsys/includes/font_settings_matrix.html +63 -0
- django_microsys-2.2.0/microsys/templates/microsys/includes/language_fonts_editor.html +36 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/options.html +25 -1
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templatetags/microsys_tags.py +11 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/translations.py +9 -5
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/utils.py +78 -8
- django_microsys-2.1.9/microsys/VERSION +0 -1
- {django_microsys-2.1.9 → django_microsys-2.2.0}/LICENSE +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/MANIFEST.in +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/README.md +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/django_microsys.egg-info/dependency_links.txt +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/django_microsys.egg-info/entry_points.txt +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/django_microsys.egg-info/requires.txt +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/django_microsys.egg-info/top_level.txt +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/__init__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/__main__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/admin.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/api.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/apps.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/cli.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/constants.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/discovery.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/fetcher.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/filters.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/formats/__init__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/formats/ar/__init__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/formats/ar/formats.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/formats/en/__init__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/formats/en/formats.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/guards.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/management/commands/__init__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/management/commands/microsys_check.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/management/commands/microsys_setup.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/management/commands/migrator.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/management/commands/seed_activity_log.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/managers.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/middleware.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/migrations/0001_initial.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/migrations/0002_public_registration.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/migrations/0003_public_root_split.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/migrations/0004_client_ip_and_trusted_devices.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/migrations/__init__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/patches.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/registration.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/README.md.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/__init__.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/apps.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/filters.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/forms.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/migrations/__init__.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/models.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/tables.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/templates/example_record_confirm_delete.html.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/templates/example_record_detail.html.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/templates/example_record_form.html.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/templates/example_record_list.html.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/tests/__init__.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/tests/test_app.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/translations.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/urls.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/app/views.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/.nginx/nginx.conf.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/.secrets/.env.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/Dockerfile.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/README.md.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/compose.dev.yml.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/compose.yml.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/dockerignore.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/docs/README.md.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/entrypoint.sh.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/gitattributes.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/gitignore.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/gunicorn.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/manage.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/package/__init__.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/package/asgi.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/package/celery.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/package/settings.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/package/urls.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/package/wsgi.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/req.txt.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/start.ps1.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/start.sh.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/tests/__init__.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/tests/test_scaffold.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/scaffold_templates/project/tools/smtp_relay.py.tmpl +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/signals.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap-icons.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap-icons.woff +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap-icons.woff2 +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap.bundle.min.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap.bundle.min.js.map +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap.min.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap.min.css.map +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap.rtl.min.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/bootstrap/bootstrap.rtl.min.css.map +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/favicon.ico +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/img/base_logo.webp +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/img/default_profile.webp +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/img/login_logo.webp +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/accessibility/css/main.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/accessibility/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/activitylog/js/main.js +0 -0
- {django_microsys-2.1.9/microsys/static/microsys/language → django_microsys-2.2.0/microsys/static/microsys}/fonts/TwemojiCountryFlags.woff2 +0 -0
- /django_microsys-2.1.9/microsys/static/microsys/main/fonts/Shabwa-Bold.woff2 → /django_microsys-2.2.0/microsys/static/microsys/fonts/shabwa-bold.woff2 +0 -0
- /django_microsys-2.1.9/microsys/static/microsys/main/fonts/Shabwa-Medium.woff2 → /django_microsys-2.2.0/microsys/static/microsys/fonts/shabwa-medium.woff2 +0 -0
- /django_microsys-2.1.9/microsys/static/microsys/main/fonts/Shabwa.woff2 → /django_microsys-2.2.0/microsys/static/microsys/fonts/shabwa-regular.woff2 +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/forms/css/file_field.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/forms/css/form_actions.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/forms/css/form_fields.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/forms/js/file_field.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/forms/js/filter_form.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/autofill/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/context_menu/css/main.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/context_menu/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/context_menu/js/section_manager.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/dynamic_modal/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/prevent_double_submit.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/scan_link/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/scan_link/js/scan_button.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/helpers/wizard/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/language/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/language/js/translations.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/buttons.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/dropdowns.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/index_cards.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/options.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/pagination.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/selectors.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/system_setup.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/tables.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/template_cleanup.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/css/titlebar.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/js/selectors.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/main/js/tables.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/sections/js/manage_sections.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/sidebar/css/main.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/sidebar/css/reorder.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/sidebar/css/theme_picker.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/sidebar/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/sidebar/js/preload.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/sidebar/js/reorder.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/sidebar/js/theme_picker.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/blue.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/dark.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/gold.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/gothic.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/green.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/light.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/mono.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/neon.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/red.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/css/retro.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/themes/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/tutorial/css/main.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/tutorial/js/driver.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/tutorial/js/main.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/css/login.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/css/permissions.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/css/profile.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/css/user_hub.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/js/login.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/js/manage_users.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/js/permissions.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/js/profile_2fa.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/js/profile_image_widget.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/js/twofa_verify.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/users/js/user_hub.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/vanillajs-datepicker/datepicker-bs5.min.css +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/vanillajs-datepicker/datepicker.min.js +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/tables.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/bootstrap5/layout/field_file.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/2fa/verify.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/activitylog/activity_log.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/activitylog/activity_log_detail_modal.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/form_base.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/forms/assets_head.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/forms/assets_scripts.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/forms/crispy_file_field.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/forms/file_input.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/forms/filter_assets_head.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/forms/filter_assets_scripts.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/helpers/dynamic_modal.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/helpers/dynamic_modal_combined.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/helpers/dynamic_modal_detail.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/helpers/dynamic_modal_form.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/helpers/dynamic_modal_list.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/helpers/micro_context_menu.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/language_catalog_editor.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/language_previews.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/sidebar_builder.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/sidebar_density_previews.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/sidebar_items.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/system_names_editor.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/system_setup.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/table_density_previews.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/theme_previews.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/theme_settings_matrix.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/titlebar.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/translation_matrix_editor.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/includes/tutorial.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/list_base.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/registration/pending.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/scopes/scope_actions.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/scopes/scope_form.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/scopes/scope_manager.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/sections/manage_sections.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/sections/subsection_select.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/sidebar/auto.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/sidebar/extra_groups.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/sidebar/main.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/sidebar/tree.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/tables/table.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/users/grouped_permissions.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/users/manage_users.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/users/profile.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/users/profile_image_widget.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/users/user_detail_modal.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/microsys/users/user_hub.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/registration/email/verify_registration.txt +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/registration/login.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/registration/register.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/registration/register_sent.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templates/registration/register_verify.html +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templatetags/__init__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templatetags/microsys_translation.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/templatetags/sidebar_tags.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/themes.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/urls.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/__init__.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/activitylog.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/general.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/profile.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/registration.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/scopes.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/sections.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/sidebar.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/twofa.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/views/users.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/widgets.py +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/pyproject.toml +0 -0
- {django_microsys-2.1.9 → django_microsys-2.2.0}/setup.cfg +0 -0
|
@@ -20,6 +20,7 @@ microsys/context_processors.py
|
|
|
20
20
|
microsys/discovery.py
|
|
21
21
|
microsys/fetcher.py
|
|
22
22
|
microsys/filters.py
|
|
23
|
+
microsys/fonts.py
|
|
23
24
|
microsys/forms.py
|
|
24
25
|
microsys/guards.py
|
|
25
26
|
microsys/managers.py
|
|
@@ -49,6 +50,7 @@ microsys/migrations/0001_initial.py
|
|
|
49
50
|
microsys/migrations/0002_public_registration.py
|
|
50
51
|
microsys/migrations/0003_public_root_split.py
|
|
51
52
|
microsys/migrations/0004_client_ip_and_trusted_devices.py
|
|
53
|
+
microsys/migrations/0005_systemsettings_allow_user_font_override_and_more.py
|
|
52
54
|
microsys/migrations/__init__.py
|
|
53
55
|
microsys/scaffold_templates/app/README.md.tmpl
|
|
54
56
|
microsys/scaffold_templates/app/__init__.py.tmpl
|
|
@@ -108,6 +110,13 @@ microsys/static/img/login_logo.webp
|
|
|
108
110
|
microsys/static/microsys/accessibility/css/main.css
|
|
109
111
|
microsys/static/microsys/accessibility/js/main.js
|
|
110
112
|
microsys/static/microsys/activitylog/js/main.js
|
|
113
|
+
microsys/static/microsys/fonts/TwemojiCountryFlags.woff2
|
|
114
|
+
microsys/static/microsys/fonts/cairo-bold.woff2
|
|
115
|
+
microsys/static/microsys/fonts/cairo-medium.woff2
|
|
116
|
+
microsys/static/microsys/fonts/cairo-regular.woff2
|
|
117
|
+
microsys/static/microsys/fonts/shabwa-bold.woff2
|
|
118
|
+
microsys/static/microsys/fonts/shabwa-medium.woff2
|
|
119
|
+
microsys/static/microsys/fonts/shabwa-regular.woff2
|
|
111
120
|
microsys/static/microsys/forms/css/file_field.css
|
|
112
121
|
microsys/static/microsys/forms/css/form_actions.css
|
|
113
122
|
microsys/static/microsys/forms/css/form_fields.css
|
|
@@ -123,7 +132,6 @@ microsys/static/microsys/helpers/scan_link/js/main.js
|
|
|
123
132
|
microsys/static/microsys/helpers/scan_link/js/scan_button.js
|
|
124
133
|
microsys/static/microsys/helpers/wizard/js/main.js
|
|
125
134
|
microsys/static/microsys/language/css/main.css
|
|
126
|
-
microsys/static/microsys/language/fonts/TwemojiCountryFlags.woff2
|
|
127
135
|
microsys/static/microsys/language/js/main.js
|
|
128
136
|
microsys/static/microsys/language/js/translations.js
|
|
129
137
|
microsys/static/microsys/main/css/buttons.css
|
|
@@ -137,9 +145,6 @@ microsys/static/microsys/main/css/system_setup.css
|
|
|
137
145
|
microsys/static/microsys/main/css/tables.css
|
|
138
146
|
microsys/static/microsys/main/css/template_cleanup.css
|
|
139
147
|
microsys/static/microsys/main/css/titlebar.css
|
|
140
|
-
microsys/static/microsys/main/fonts/Shabwa-Bold.woff2
|
|
141
|
-
microsys/static/microsys/main/fonts/Shabwa-Medium.woff2
|
|
142
|
-
microsys/static/microsys/main/fonts/Shabwa.woff2
|
|
143
148
|
microsys/static/microsys/main/js/base_head.js
|
|
144
149
|
microsys/static/microsys/main/js/base_runtime.js
|
|
145
150
|
microsys/static/microsys/main/js/options.js
|
|
@@ -200,7 +205,10 @@ microsys/templates/microsys/helpers/dynamic_modal_detail.html
|
|
|
200
205
|
microsys/templates/microsys/helpers/dynamic_modal_form.html
|
|
201
206
|
microsys/templates/microsys/helpers/dynamic_modal_list.html
|
|
202
207
|
microsys/templates/microsys/helpers/micro_context_menu.html
|
|
208
|
+
microsys/templates/microsys/includes/font_previews.html
|
|
209
|
+
microsys/templates/microsys/includes/font_settings_matrix.html
|
|
203
210
|
microsys/templates/microsys/includes/language_catalog_editor.html
|
|
211
|
+
microsys/templates/microsys/includes/language_fonts_editor.html
|
|
204
212
|
microsys/templates/microsys/includes/language_previews.html
|
|
205
213
|
microsys/templates/microsys/includes/options.html
|
|
206
214
|
microsys/templates/microsys/includes/sidebar_builder.html
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.2.0
|
|
@@ -177,7 +177,7 @@ def microsys_context(request):
|
|
|
177
177
|
context = {}
|
|
178
178
|
|
|
179
179
|
# 1. Branding / App Config
|
|
180
|
-
from .utils import build_config_groups, get_system_config
|
|
180
|
+
from .utils import build_config_groups, get_system_config, normalize_allowed_fonts
|
|
181
181
|
final_config = get_system_config()
|
|
182
182
|
|
|
183
183
|
# 4. Language / i18n (resolved BEFORE branding overrides so we know current_lang)
|
|
@@ -342,7 +342,34 @@ def microsys_context(request):
|
|
|
342
342
|
final_config,
|
|
343
343
|
context['titlebar'],
|
|
344
344
|
)
|
|
345
|
-
|
|
345
|
+
# 8. Font Resolution
|
|
346
|
+
from .fonts import generate_font_face_css, get_builtin_fonts
|
|
347
|
+
allowed_fonts = normalize_allowed_fonts(final_config.get('allowed_fonts'))
|
|
348
|
+
context['font_face_css'] = generate_font_face_css(allowed_fonts)
|
|
349
|
+
|
|
350
|
+
allow_user_font_override = bool(final_config.get('allow_user_font_override', True))
|
|
351
|
+
default_fonts_by_lang = final_config.get('default_fonts', {})
|
|
352
|
+
|
|
353
|
+
active_font = None
|
|
354
|
+
if allow_user_font_override:
|
|
355
|
+
active_font = user_prefs.get('font')
|
|
356
|
+
|
|
357
|
+
if not active_font or active_font not in allowed_fonts:
|
|
358
|
+
active_font = default_fonts_by_lang.get(current_lang)
|
|
359
|
+
|
|
360
|
+
if not active_font or active_font not in allowed_fonts:
|
|
361
|
+
# Global fallback based on current language
|
|
362
|
+
active_font = 'shabwa' if current_lang == 'ar' else 'cairo'
|
|
363
|
+
|
|
364
|
+
# Ensure active_font is valid, else hard fallback to shabwa
|
|
365
|
+
if active_font not in allowed_fonts and allowed_fonts:
|
|
366
|
+
active_font = allowed_fonts[0]
|
|
367
|
+
elif not active_font:
|
|
368
|
+
active_font = 'shabwa'
|
|
369
|
+
|
|
370
|
+
context['active_font'] = active_font
|
|
371
|
+
context['font_picker_enabled'] = bool(allow_user_font_override and len(allowed_fonts) > 1)
|
|
372
|
+
|
|
346
373
|
return context
|
|
347
374
|
|
|
348
375
|
def clear_sidebar_cache():
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from functools import lru_cache
|
|
2
|
+
from django.conf import settings
|
|
3
|
+
from django.templatetags.static import static
|
|
4
|
+
|
|
5
|
+
# Registry for built-in fonts provided by the package
|
|
6
|
+
_FONT_REGISTRY = (
|
|
7
|
+
{
|
|
8
|
+
'slug': 'shabwa',
|
|
9
|
+
'family': 'Shabwa',
|
|
10
|
+
'label': 'Shabwa',
|
|
11
|
+
'variants': [
|
|
12
|
+
{'weight': 400, 'path': 'microsys/fonts/shabwa-regular.woff2'},
|
|
13
|
+
{'weight': 600, 'path': 'microsys/fonts/shabwa-medium.woff2'},
|
|
14
|
+
{'weight': 800, 'path': 'microsys/fonts/shabwa-bold.woff2'},
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
'slug': 'cairo',
|
|
19
|
+
'family': 'Cairo',
|
|
20
|
+
'label': 'Cairo',
|
|
21
|
+
'variants': [
|
|
22
|
+
{'weight': 400, 'path': 'microsys/fonts/cairo-regular.woff2'},
|
|
23
|
+
{'weight': 600, 'path': 'microsys/fonts/cairo-medium.woff2'},
|
|
24
|
+
{'weight': 800, 'path': 'microsys/fonts/cairo-bold.woff2'},
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
@lru_cache(maxsize=1)
|
|
30
|
+
def get_builtin_fonts():
|
|
31
|
+
"""Returns the list of hardcoded fonts available in the package."""
|
|
32
|
+
return _FONT_REGISTRY
|
|
33
|
+
|
|
34
|
+
def get_font_choices():
|
|
35
|
+
"""Returns a tuple of (slug, label) for form fields."""
|
|
36
|
+
return tuple((f['slug'], f['label']) for f in _FONT_REGISTRY)
|
|
37
|
+
|
|
38
|
+
def get_font_by_slug(slug):
|
|
39
|
+
"""Returns the font configuration dict for a given slug."""
|
|
40
|
+
for font in _FONT_REGISTRY:
|
|
41
|
+
if font['slug'] == slug:
|
|
42
|
+
return font
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
def generate_font_face_css(allowed_fonts=None):
|
|
46
|
+
"""
|
|
47
|
+
Generates the @font-face CSS block for all allowed fonts.
|
|
48
|
+
This can be injected into the base template.
|
|
49
|
+
"""
|
|
50
|
+
fonts_to_load = []
|
|
51
|
+
if allowed_fonts:
|
|
52
|
+
for slug in allowed_fonts:
|
|
53
|
+
font = get_font_by_slug(slug)
|
|
54
|
+
if font:
|
|
55
|
+
fonts_to_load.append(font)
|
|
56
|
+
else:
|
|
57
|
+
fonts_to_load = _FONT_REGISTRY
|
|
58
|
+
|
|
59
|
+
css_lines = []
|
|
60
|
+
for font in fonts_to_load:
|
|
61
|
+
for variant in font['variants']:
|
|
62
|
+
# We use static() to resolve the path correctly
|
|
63
|
+
url = static(variant['path'])
|
|
64
|
+
css_lines.append(f"@font-face {{")
|
|
65
|
+
css_lines.append(f" font-family: '{font['family']}';")
|
|
66
|
+
css_lines.append(f" font-weight: {variant['weight']};")
|
|
67
|
+
css_lines.append(f" font-style: normal;")
|
|
68
|
+
css_lines.append(f" src: url('{url}') format('woff2');")
|
|
69
|
+
css_lines.append(f" font-display: swap;")
|
|
70
|
+
css_lines.append(f"}}")
|
|
71
|
+
|
|
72
|
+
return "\n".join(css_lines)
|
|
@@ -73,12 +73,15 @@ from .utils import (
|
|
|
73
73
|
normalize_sidebar_behavior,
|
|
74
74
|
normalize_system_names,
|
|
75
75
|
normalize_titlebar_config,
|
|
76
|
+
normalize_allowed_fonts,
|
|
76
77
|
)
|
|
77
78
|
from .widgets import MicrosysChoiceSelectorWidget
|
|
78
79
|
|
|
79
80
|
User = get_user_model()
|
|
80
81
|
|
|
81
82
|
THEME_CHOICES = get_theme_choices()
|
|
83
|
+
from .fonts import get_font_choices
|
|
84
|
+
FONT_CHOICES = get_font_choices()
|
|
82
85
|
PERMISSION_UI_EXCLUDED_APP_LABELS = [
|
|
83
86
|
'admin',
|
|
84
87
|
'contenttypes',
|
|
@@ -1456,6 +1459,18 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
1456
1459
|
required=False,
|
|
1457
1460
|
initial=True,
|
|
1458
1461
|
)
|
|
1462
|
+
allowed_fonts = forms.MultipleChoiceField(
|
|
1463
|
+
required=False,
|
|
1464
|
+
choices=FONT_CHOICES,
|
|
1465
|
+
)
|
|
1466
|
+
allow_user_font_override = forms.BooleanField(
|
|
1467
|
+
required=False,
|
|
1468
|
+
initial=True,
|
|
1469
|
+
)
|
|
1470
|
+
default_fonts = forms.CharField(
|
|
1471
|
+
widget=forms.HiddenInput(),
|
|
1472
|
+
required=False,
|
|
1473
|
+
)
|
|
1459
1474
|
default_table_density = forms.ChoiceField(
|
|
1460
1475
|
required=True,
|
|
1461
1476
|
choices=TABLE_DENSITY_CHOICES,
|
|
@@ -1629,6 +1644,9 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
1629
1644
|
'default_theme',
|
|
1630
1645
|
'allowed_themes',
|
|
1631
1646
|
'allow_user_theme_override',
|
|
1647
|
+
'allowed_fonts',
|
|
1648
|
+
'allow_user_font_override',
|
|
1649
|
+
'default_fonts',
|
|
1632
1650
|
'allow_user_language_override',
|
|
1633
1651
|
'default_table_density',
|
|
1634
1652
|
'email_2fa',
|
|
@@ -1665,7 +1683,7 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
1665
1683
|
parsed_step = int(raw_step)
|
|
1666
1684
|
except (TypeError, ValueError):
|
|
1667
1685
|
parsed_step = None
|
|
1668
|
-
if parsed_step in (0, 1, 2, 3, 4):
|
|
1686
|
+
if parsed_step in (0, 1, 2, 3, 4, 5):
|
|
1669
1687
|
self.single_step_mode = True
|
|
1670
1688
|
self.single_step_index = parsed_step
|
|
1671
1689
|
|
|
@@ -1748,11 +1766,21 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
1748
1766
|
'help_sys_allow_user_theme_override',
|
|
1749
1767
|
'Allow users to switch between the allowed themes at runtime from Options and the sidebar toolbar.',
|
|
1750
1768
|
)
|
|
1751
|
-
self.fields['allow_user_language_override'].label = s.get('form_sys_allow_user_language_override', 'Allow user language override')
|
|
1752
1769
|
self.fields['allow_user_language_override'].help_text = s.get(
|
|
1753
1770
|
'help_sys_allow_user_language_override',
|
|
1754
1771
|
'Allow users to change their display language from Options. When disabled, the system default language is enforced.',
|
|
1755
1772
|
)
|
|
1773
|
+
self.fields['allowed_fonts'].label = s.get('form_sys_allowed_fonts', 'Allowed fonts')
|
|
1774
|
+
self.fields['allowed_fonts'].help_text = s.get(
|
|
1775
|
+
'help_sys_allowed_fonts',
|
|
1776
|
+
'Choose which fonts are available in this project. The default fonts for each language must remain enabled.',
|
|
1777
|
+
)
|
|
1778
|
+
self.fields['allow_user_font_override'].label = s.get('form_sys_allow_user_font_override', 'Allow user font override')
|
|
1779
|
+
self.fields['allow_user_font_override'].help_text = s.get(
|
|
1780
|
+
'help_sys_allow_user_font_override',
|
|
1781
|
+
'Allow users to switch between the allowed fonts at runtime from Options.',
|
|
1782
|
+
)
|
|
1783
|
+
self.fields['default_fonts'].label = s.get('form_sys_default_fonts', 'Default fonts by language')
|
|
1756
1784
|
self.fields['default_table_density'].label = s.get('form_sys_default_table_density', "Default Table Density")
|
|
1757
1785
|
self.fields['default_table_density'].help_text = s.get(
|
|
1758
1786
|
'help_sys_default_table_density',
|
|
@@ -2136,6 +2164,23 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
2136
2164
|
if (not getattr(self.instance, 'pk', None) and not getattr(self.instance, 'is_configured', False))
|
|
2137
2165
|
else getattr(self.instance, 'allow_user_theme_override', config.get('allow_user_theme_override', True))
|
|
2138
2166
|
)
|
|
2167
|
+
self.initial['allow_user_font_override'] = bool(
|
|
2168
|
+
config.get('allow_user_font_override', True)
|
|
2169
|
+
if (not getattr(self.instance, 'pk', None) and not getattr(self.instance, 'is_configured', False))
|
|
2170
|
+
else getattr(self.instance, 'allow_user_font_override', config.get('allow_user_font_override', True))
|
|
2171
|
+
)
|
|
2172
|
+
initial_allowed_fonts = normalize_allowed_fonts(
|
|
2173
|
+
(
|
|
2174
|
+
config.get('allowed_fonts')
|
|
2175
|
+
if (not getattr(self.instance, 'pk', None) and not getattr(self.instance, 'is_configured', False))
|
|
2176
|
+
else getattr(self.instance, 'allowed_fonts', None)
|
|
2177
|
+
) or config.get('allowed_fonts')
|
|
2178
|
+
)
|
|
2179
|
+
self.initial['allowed_fonts'] = list(initial_allowed_fonts)
|
|
2180
|
+
instance_default_fonts = getattr(self.instance, 'default_fonts', {}) or {}
|
|
2181
|
+
if not instance_default_fonts:
|
|
2182
|
+
instance_default_fonts = config.get('default_fonts', {})
|
|
2183
|
+
self.initial['default_fonts'] = _json_dump(instance_default_fonts, ensure_ascii=False)
|
|
2139
2184
|
self.initial['allow_user_language_override'] = bool(
|
|
2140
2185
|
config.get('allow_user_language_override', True)
|
|
2141
2186
|
if (not getattr(self.instance, 'pk', None) and not getattr(self.instance, 'is_configured', False))
|
|
@@ -2267,12 +2312,12 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
2267
2312
|
sidebar_config['home_url_name'] = None
|
|
2268
2313
|
self.initial['sidebar_config'] = _json_dump(sidebar_config, ensure_ascii=False)
|
|
2269
2314
|
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2315
|
+
initial_sidebar_config = self.initial.get('sidebar_config') or {}
|
|
2316
|
+
if isinstance(initial_sidebar_config, str):
|
|
2317
|
+
try:
|
|
2318
|
+
initial_sidebar_config = json.loads(initial_sidebar_config)
|
|
2319
|
+
except (TypeError, ValueError, json.JSONDecodeError):
|
|
2320
|
+
initial_sidebar_config = {}
|
|
2276
2321
|
|
|
2277
2322
|
self.initial['sidebar_enabled'] = bool(initial_sidebar_config.get('enabled', True))
|
|
2278
2323
|
self.initial['sidebar_enable_reorder'] = bool(initial_sidebar_config.get('enable_reorder', True))
|
|
@@ -2329,26 +2374,32 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
2329
2374
|
self.fields['public_root_url_discovered'].widget.option_meta = home_url_option_meta
|
|
2330
2375
|
self.initial['public_root_url_discovered'] = current_public_root_url if current_public_root_url in seen_home_urls else ''
|
|
2331
2376
|
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2377
|
+
initial_languages = self.initial.get('languages') or {}
|
|
2378
|
+
if isinstance(initial_languages, str):
|
|
2379
|
+
try:
|
|
2380
|
+
initial_languages = json.loads(initial_languages)
|
|
2381
|
+
except (TypeError, ValueError, json.JSONDecodeError):
|
|
2382
|
+
initial_languages = {}
|
|
2336
2383
|
current_languages = normalize_language_catalog(initial_languages)
|
|
2337
2384
|
self.initial['languages'] = _json_dump(current_languages, ensure_ascii=False)
|
|
2338
2385
|
if self.initial.get('default_language') not in current_languages:
|
|
2339
2386
|
self.initial['default_language'] = 'en' if 'en' in current_languages else next(iter(current_languages), 'en')
|
|
2340
2387
|
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2388
|
+
initial_system_names = self.initial.get('system_names') or {}
|
|
2389
|
+
if isinstance(initial_system_names, str):
|
|
2390
|
+
try:
|
|
2391
|
+
initial_system_names = json.loads(initial_system_names)
|
|
2392
|
+
except (TypeError, ValueError, json.JSONDecodeError):
|
|
2393
|
+
initial_system_names = {}
|
|
2345
2394
|
initial_system_names = normalize_system_names(initial_system_names)
|
|
2346
2395
|
self.initial['system_names'] = _json_dump(initial_system_names, ensure_ascii=False)
|
|
2347
2396
|
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2397
|
+
initial_translation_overrides = self.initial.get('translations_override') or {}
|
|
2398
|
+
if isinstance(initial_translation_overrides, str):
|
|
2399
|
+
try:
|
|
2400
|
+
initial_translation_overrides = json.loads(initial_translation_overrides)
|
|
2401
|
+
except (TypeError, ValueError, json.JSONDecodeError):
|
|
2402
|
+
initial_translation_overrides = {}
|
|
2352
2403
|
if not isinstance(initial_translation_overrides, dict):
|
|
2353
2404
|
initial_translation_overrides = {}
|
|
2354
2405
|
suggested_languages = [
|
|
@@ -2410,13 +2461,45 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
2410
2461
|
'picker_mode': 'setup',
|
|
2411
2462
|
'input_id': 'id_default_theme',
|
|
2412
2463
|
'allowed_input_name': 'allowed_themes',
|
|
2413
|
-
'allowed_themes': set(self.initial.get('allowed_themes', [])
|
|
2464
|
+
'allowed_themes': set(self.initial.get('allowed_themes') if isinstance(self.initial.get('allowed_themes'), (list, tuple, set)) else []),
|
|
2414
2465
|
'MS_TRANS': s,
|
|
2415
2466
|
'MICROSYS_THEMES': get_theme_options(s),
|
|
2416
2467
|
'label': self.fields['default_theme'].label,
|
|
2417
2468
|
'help_text': self.fields['allowed_themes'].help_text,
|
|
2418
2469
|
},
|
|
2419
2470
|
)
|
|
2471
|
+
|
|
2472
|
+
from .fonts import get_builtin_fonts
|
|
2473
|
+
self.font_picker_html = render_to_string(
|
|
2474
|
+
'microsys/includes/font_settings_matrix.html',
|
|
2475
|
+
{
|
|
2476
|
+
'picker_mode': 'setup',
|
|
2477
|
+
'input_id': 'id_allowed_fonts',
|
|
2478
|
+
'allowed_input_name': 'allowed_fonts',
|
|
2479
|
+
'allowed_fonts': set(self.initial.get('allowed_fonts') if isinstance(self.initial.get('allowed_fonts'), (list, tuple, set)) else []),
|
|
2480
|
+
'MS_TRANS': s,
|
|
2481
|
+
'MICROSYS_FONTS': get_builtin_fonts(),
|
|
2482
|
+
'label': self.fields['allowed_fonts'].label,
|
|
2483
|
+
'help_text': self.fields['allowed_fonts'].help_text,
|
|
2484
|
+
},
|
|
2485
|
+
)
|
|
2486
|
+
|
|
2487
|
+
default_fonts_data = self.initial.get('default_fonts') or {}
|
|
2488
|
+
if isinstance(default_fonts_data, str):
|
|
2489
|
+
try:
|
|
2490
|
+
default_fonts_data = json.loads(default_fonts_data)
|
|
2491
|
+
except (TypeError, ValueError, json.JSONDecodeError):
|
|
2492
|
+
default_fonts_data = {}
|
|
2493
|
+
|
|
2494
|
+
self.language_fonts_editor_html = render_to_string(
|
|
2495
|
+
'microsys/includes/language_fonts_editor.html',
|
|
2496
|
+
{
|
|
2497
|
+
'current_languages': current_languages,
|
|
2498
|
+
'default_fonts': default_fonts_data,
|
|
2499
|
+
'MICROSYS_FONTS': get_builtin_fonts(),
|
|
2500
|
+
'MS_TRANS': s,
|
|
2501
|
+
},
|
|
2502
|
+
)
|
|
2420
2503
|
|
|
2421
2504
|
self.sidebar_builder_html = render_to_string(
|
|
2422
2505
|
'microsys/includes/sidebar_builder.html',
|
|
@@ -2424,7 +2507,7 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
2424
2507
|
'sidebar_catalog': self.sidebar_catalog,
|
|
2425
2508
|
'sidebar_catalog_json': _json_dump(self.sidebar_catalog, ensure_ascii=False),
|
|
2426
2509
|
'sidebar_catalog_fallback_json': _json_dump(self.sidebar_catalog_fallback, ensure_ascii=False),
|
|
2427
|
-
'sidebar_config_json': self.initial.get('sidebar_config',
|
|
2510
|
+
'sidebar_config_json': _json_dump(self.initial.get('sidebar_config', {}), ensure_ascii=False),
|
|
2428
2511
|
'mode': self.mode,
|
|
2429
2512
|
'MS_TRANS': s,
|
|
2430
2513
|
},
|
|
@@ -2664,17 +2747,7 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
2664
2747
|
css_class=_step_css_class(3),
|
|
2665
2748
|
),
|
|
2666
2749
|
Div(
|
|
2667
|
-
HTML(f"<div class='mb-3'><span class='badge rounded-pill text-bg-primary'>{s.get('system_setup_step5', 'Step 5:
|
|
2668
|
-
Row(
|
|
2669
|
-
Div(
|
|
2670
|
-
HTML(self.theme_picker_html),
|
|
2671
|
-
Field('default_theme'),
|
|
2672
|
-
css_class='mb-3'
|
|
2673
|
-
),
|
|
2674
|
-
),
|
|
2675
|
-
Row(
|
|
2676
|
-
build_settings_toggle_field(self, 'allow_user_theme_override', css_class='col-12')
|
|
2677
|
-
),
|
|
2750
|
+
HTML(f"<div class='mb-3'><span class='badge rounded-pill text-bg-primary'>{s.get('system_setup_step5', 'Step 5: UI & Layout')}</span></div>"),
|
|
2678
2751
|
HTML(f"<h6 class='fw-bold my-3'>{s.get('tables_settings_title', 'Tables Settings')}</h6>"),
|
|
2679
2752
|
Row(
|
|
2680
2753
|
Div(Field('default_table_density'), css_class='col'),
|
|
@@ -2700,6 +2773,26 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
2700
2773
|
),
|
|
2701
2774
|
css_class=_step_css_class(4),
|
|
2702
2775
|
),
|
|
2776
|
+
Div(
|
|
2777
|
+
HTML(f"<div class='mb-3'><span class='badge rounded-pill text-bg-primary'>{s.get('system_setup_step6', 'Step 6: Appearance')}</span></div>"),
|
|
2778
|
+
Row(
|
|
2779
|
+
Div(
|
|
2780
|
+
HTML(self.theme_picker_html),
|
|
2781
|
+
Field('default_theme'),
|
|
2782
|
+
css_class='mb-3'
|
|
2783
|
+
),
|
|
2784
|
+
),
|
|
2785
|
+
Row(
|
|
2786
|
+
build_settings_toggle_field(self, 'allow_user_theme_override', css_class='col-12')
|
|
2787
|
+
),
|
|
2788
|
+
HTML(f"<h6 class='fw-bold my-3'>{s.get('typography_settings_title', 'Typography Settings')}</h6>"),
|
|
2789
|
+
HTML(self.font_picker_html),
|
|
2790
|
+
# Field('allowed_fonts'),
|
|
2791
|
+
build_settings_toggle_field(self, 'allow_user_font_override', css_class='col-12 mt-2'),
|
|
2792
|
+
HTML(self.language_fonts_editor_html),
|
|
2793
|
+
Field('default_fonts'),
|
|
2794
|
+
css_class=_step_css_class(5),
|
|
2795
|
+
),
|
|
2703
2796
|
FormActions(
|
|
2704
2797
|
HTML(
|
|
2705
2798
|
f"<div class='d-flex flex-wrap justify-content-end align-items-center gap-2 mt-4 ms-setup-wizard-actions' dir='{_get_ui_direction()}'>"
|
|
@@ -2772,6 +2865,24 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
2772
2865
|
def clean_default_language(self):
|
|
2773
2866
|
return str(self.cleaned_data.get('default_language') or 'en').strip().lower().replace('_', '-')
|
|
2774
2867
|
|
|
2868
|
+
def clean_allowed_fonts(self):
|
|
2869
|
+
data = self.cleaned_data.get('allowed_fonts')
|
|
2870
|
+
if not data:
|
|
2871
|
+
return []
|
|
2872
|
+
return list(data)
|
|
2873
|
+
|
|
2874
|
+
def clean_default_fonts(self):
|
|
2875
|
+
data = self.cleaned_data.get('default_fonts')
|
|
2876
|
+
if not data:
|
|
2877
|
+
return {}
|
|
2878
|
+
try:
|
|
2879
|
+
parsed = json.loads(data) if isinstance(data, str) else data
|
|
2880
|
+
if not isinstance(parsed, dict):
|
|
2881
|
+
return {}
|
|
2882
|
+
return parsed
|
|
2883
|
+
except json.JSONDecodeError:
|
|
2884
|
+
return {}
|
|
2885
|
+
|
|
2775
2886
|
def clean_default_theme(self):
|
|
2776
2887
|
value = self.cleaned_data.get('default_theme') or 'light'
|
|
2777
2888
|
if not is_valid_theme(value):
|
|
@@ -3152,6 +3263,9 @@ class SystemSettingsForm(forms.ModelForm):
|
|
|
3152
3263
|
instance.translations_override = self.cleaned_data.get('translations_override', {})
|
|
3153
3264
|
instance.allowed_themes = self.cleaned_data.get('allowed_themes', list(normalize_allowed_themes()))
|
|
3154
3265
|
instance.allow_user_theme_override = bool(self.cleaned_data.get('allow_user_theme_override', True))
|
|
3266
|
+
instance.allowed_fonts = self.cleaned_data.get('allowed_fonts', [])
|
|
3267
|
+
instance.allow_user_font_override = bool(self.cleaned_data.get('allow_user_font_override', True))
|
|
3268
|
+
instance.default_fonts = self.cleaned_data.get('default_fonts', {})
|
|
3155
3269
|
instance.allow_user_language_override = bool(self.cleaned_data.get('allow_user_language_override', True))
|
|
3156
3270
|
instance.client_ip_config = self.cleaned_data.get('client_ip_config', default_client_ip_config())
|
|
3157
3271
|
instance.titlebar_config = self.cleaned_data.get('titlebar_config', default_titlebar_config())
|
django_microsys-2.2.0/microsys/migrations/0005_systemsettings_allow_user_font_override_and_more.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Generated by Django 6.0.5 on 2026-05-16 09:39
|
|
2
|
+
|
|
3
|
+
import microsys.models
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('microsys', '0004_client_ip_and_trusted_devices'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name='systemsettings',
|
|
16
|
+
name='allow_user_font_override',
|
|
17
|
+
field=models.BooleanField(default=True, verbose_name='Allow User Font Override'),
|
|
18
|
+
),
|
|
19
|
+
migrations.AddField(
|
|
20
|
+
model_name='systemsettings',
|
|
21
|
+
name='allowed_fonts',
|
|
22
|
+
field=models.JSONField(blank=True, default=microsys.models.default_allowed_fonts, verbose_name='Allowed Fonts'),
|
|
23
|
+
),
|
|
24
|
+
migrations.AddField(
|
|
25
|
+
model_name='systemsettings',
|
|
26
|
+
name='default_fonts',
|
|
27
|
+
field=models.JSONField(blank=True, default=dict, verbose_name='Default Fonts by Language'),
|
|
28
|
+
),
|
|
29
|
+
]
|
|
@@ -28,6 +28,11 @@ from datetime import timedelta
|
|
|
28
28
|
from PIL import Image
|
|
29
29
|
|
|
30
30
|
|
|
31
|
+
def default_allowed_fonts():
|
|
32
|
+
from .fonts import get_builtin_fonts
|
|
33
|
+
return [f['slug'] for f in get_builtin_fonts()]
|
|
34
|
+
|
|
35
|
+
|
|
31
36
|
def default_allowed_themes():
|
|
32
37
|
from .themes import get_theme_names
|
|
33
38
|
return list(get_theme_names())
|
|
@@ -144,6 +149,12 @@ class SingletonModel(models.Model):
|
|
|
144
149
|
obj.registration_activation_mode = config.get('registration_activation_mode')
|
|
145
150
|
if hasattr(obj, 'registration_throttle_enabled') and 'registration_throttle_enabled' in config:
|
|
146
151
|
obj.registration_throttle_enabled = bool(config.get('registration_throttle_enabled'))
|
|
152
|
+
if hasattr(obj, 'allowed_fonts') and isinstance(config.get('allowed_fonts'), (list, tuple, set)):
|
|
153
|
+
obj.allowed_fonts = list(config.get('allowed_fonts'))
|
|
154
|
+
if hasattr(obj, 'default_fonts') and isinstance(config.get('default_fonts'), dict):
|
|
155
|
+
obj.default_fonts = config.get('default_fonts')
|
|
156
|
+
if hasattr(obj, 'allow_user_font_override') and 'allow_user_font_override' in config:
|
|
157
|
+
obj.allow_user_font_override = bool(config.get('allow_user_font_override'))
|
|
147
158
|
obj.save()
|
|
148
159
|
cache.set(cls.__name__, obj, timeout=86400)
|
|
149
160
|
return obj
|
|
@@ -166,6 +177,9 @@ class SystemSettings(SingletonModel):
|
|
|
166
177
|
)
|
|
167
178
|
allowed_themes = models.JSONField(default=default_allowed_themes, blank=True, verbose_name="Allowed Themes")
|
|
168
179
|
allow_user_theme_override = models.BooleanField(default=True, verbose_name="Allow User Theme Override")
|
|
180
|
+
allowed_fonts = models.JSONField(default=default_allowed_fonts, blank=True, verbose_name="Allowed Fonts")
|
|
181
|
+
default_fonts = models.JSONField(default=dict, blank=True, verbose_name="Default Fonts by Language")
|
|
182
|
+
allow_user_font_override = models.BooleanField(default=True, verbose_name="Allow User Font Override")
|
|
169
183
|
allow_user_language_override = models.BooleanField(default=True, verbose_name="Allow User Language Override")
|
|
170
184
|
home_url = models.CharField(max_length=255, default=DEFAULT_HOME_URL, verbose_name="Home URL")
|
|
171
185
|
is_configured = models.BooleanField(default=False, verbose_name="Is Configured")
|
|
@@ -617,27 +631,13 @@ class UserActivityLog(ScopedModel):
|
|
|
617
631
|
"""Auto-resolve related object for dynamic modal detail view."""
|
|
618
632
|
related_object = None
|
|
619
633
|
if self.model_name and self.object_id:
|
|
634
|
+
from .utils import resolve_model_by_name
|
|
620
635
|
try:
|
|
621
|
-
target_model =
|
|
622
|
-
if '.' in self.model_name:
|
|
623
|
-
try:
|
|
624
|
-
target_model = apps.get_model(self.model_name)
|
|
625
|
-
except LookupError:
|
|
626
|
-
pass
|
|
627
|
-
if not target_model:
|
|
628
|
-
import unicodedata
|
|
629
|
-
def normalize(s):
|
|
630
|
-
return unicodedata.normalize('NFKD', s).casefold() if s else ""
|
|
631
|
-
log_model_norm = normalize(self.model_name)
|
|
632
|
-
for model in apps.get_models():
|
|
633
|
-
if normalize(model._meta.verbose_name) == log_model_norm or \
|
|
634
|
-
normalize(model._meta.object_name) == log_model_norm:
|
|
635
|
-
target_model = model
|
|
636
|
-
break
|
|
636
|
+
target_model = resolve_model_by_name(self.model_name)
|
|
637
637
|
if target_model:
|
|
638
638
|
try:
|
|
639
639
|
related_object = target_model._default_manager.get(pk=self.object_id)
|
|
640
|
-
except target_model.DoesNotExist:
|
|
640
|
+
except (target_model.DoesNotExist, ValueError, TypeError):
|
|
641
641
|
pass
|
|
642
642
|
except Exception:
|
|
643
643
|
pass
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
{django_microsys-2.1.9 → django_microsys-2.2.0}/microsys/static/microsys/language/css/main.css
RENAMED
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
@font-face {
|
|
74
74
|
font-family: 'Twemoji Country Flags';
|
|
75
75
|
unicode-range: U+1F1E6-1F1FF, U+1F3F4, U+E0062-E0063, U+E0065-E0067, U+E006C, U+E006E, U+E0073-E0074, U+E0077, U+E007F;
|
|
76
|
-
src: url('
|
|
76
|
+
src: url('../../fonts/TwemojiCountryFlags.woff2') format('woff2');
|
|
77
77
|
font-display: swap;
|
|
78
78
|
}
|
|
79
79
|
|