diff --git a/app/admin.py b/app/admin.py index ef34ef52..be7e5e83 100644 --- a/app/admin.py +++ b/app/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from guardian.admin import GuardedModelAdmin from app.models import Preset -from .models import Project, Task, ImageUpload +from .models import Project, Task, ImageUpload, Setting, Theme admin.site.register(Project, GuardedModelAdmin) @@ -17,3 +17,12 @@ admin.site.register(ImageUpload, ImageUploadAdmin) admin.site.register(Preset, admin.ModelAdmin) + +class SettingAdmin(admin.ModelAdmin): + def has_add_permission(self, request): + # if there's already an entry, do not allow adding + count = Setting.objects.all().count() + return count == 0 + +admin.site.register(Setting, SettingAdmin) +admin.site.register(Theme, admin.ModelAdmin) \ No newline at end of file diff --git a/app/boot.py b/app/boot.py index 5b82a32a..63085ae5 100644 --- a/app/boot.py +++ b/app/boot.py @@ -1,15 +1,20 @@ +import os + from django.contrib.auth.models import Permission from django.contrib.auth.models import User, Group from django.core.exceptions import ObjectDoesNotExist +from django.core.files import File from django.db.utils import ProgrammingError from guardian.shortcuts import assign_perm from app.models import Preset +from app.models import Theme from nodeodm.models import ProcessingNode # noinspection PyUnresolvedReferences +from webodm.settings import MEDIA_ROOT from . import scheduler, signals import logging -from .models import Task +from .models import Task, Setting from webodm import settings from webodm.wsgi import booted @@ -65,6 +70,23 @@ def boot(): ]) Preset.objects.get_or_create(name='Default', system=True, options=[{'name': 'dsm', 'value': True}]) + # Add settings + Setting.objects.all().delete() + Theme.objects.all().delete() + + default_theme, created = Theme.objects.get_or_create(name='Default') + if created: + logger.info("Created default theme") + + if Setting.objects.all().count() == 0: + s = Setting.objects.create( + app_name='WebODM', + theme=default_theme) + default_logo = os.path.join('app', 'static', 'app', 'img', 'logo512.png') + s.app_logo.save(os.path.basename(default_logo), File(open(default_logo, 'rb'))) + + logger.info("Created settings") + # Unlock any Task that might have been locked Task.objects.filter(processing_lock=True).update(processing_lock=False) diff --git a/app/models/__init__.py b/app/models/__init__.py index 184de3f5..7b510c73 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -2,3 +2,6 @@ from .image_upload import ImageUpload, image_directory_path from .project import Project from .task import Task, validate_task_options, gcp_directory_path from .preset import Preset +from .theme import Theme +from .setting import Setting + diff --git a/app/models/setting.py b/app/models/setting.py new file mode 100644 index 00000000..164cf4a2 --- /dev/null +++ b/app/models/setting.py @@ -0,0 +1,30 @@ +import logging + +from django.db import models +from imagekit.models import ImageSpecField +from imagekit.processors import ResizeToFit + +from .theme import Theme + +logger = logging.getLogger('app.logger') + + +class Setting(models.Model): + app_name = models.CharField(max_length=255, blank=False, null=False, help_text="The name of your application") + app_logo = models.ImageField(upload_to="settings/", blank=False, null=False, help_text="A 512x512 logo of your application (.png or .jpeg)") + app_logo_36 = ImageSpecField(source='app_logo', + processors=[ResizeToFit(36, 36)], + format='PNG', + options={'quality': 90}) + app_logo_favicon = ImageSpecField(source='app_logo', + processors=[ResizeToFit(48, 48)], + format='PNG', + options={'quality': 90}) + + organization_name = models.CharField(max_length=255, blank=True, null=True, help_text="The name of your organization") + organization_website = models.URLField(max_length=255, blank=True, null=True, help_text="The website URL of your organization") + theme = models.ForeignKey(Theme, blank=False, null=False, on_delete=models.DO_NOTHING, + help_text="Active theme") + + def __str__(self): + return "Application" \ No newline at end of file diff --git a/app/models/theme.py b/app/models/theme.py new file mode 100644 index 00000000..a315083e --- /dev/null +++ b/app/models/theme.py @@ -0,0 +1,31 @@ +import logging + +from django.db import models +from colorfield.fields import ColorField + +logger = logging.getLogger('app.logger') + +class Theme(models.Model): + name = models.CharField(max_length=255, blank=False, null=False, help_text="Name of theme") + + # Similar to how discourse.org does it + primary = ColorField(default='#2c3e50', help_text="Most text, icons, and borders.") + secondary = ColorField(default='#ffffff', help_text="The main background color, and text color of some buttons.") + tertiary = ColorField(default='#18bc9c', help_text="Navigation links.") + + button_primary = ColorField(default='#2c3e50', help_text="Primary button color.") + button_default = ColorField(default='#95a5a6', help_text="Default button color.") + button_danger = ColorField(default='#95a5a6', help_text="Delete button color.") + + header_background = ColorField(default='#18bc9c', help_text="Background color of the site's header.") + header_primary = ColorField(default='#ffffff', help_text="Text and icons in the site's header.") + highlight = ColorField(default='#f7f7f7', help_text="The background color of panels.") + + dialog_warning = ColorField(default='#f39c12', help_text="The border color of warning dialogs.") + + failed = ColorField(default='#ffcbcb', help_text="The background color of failed notifications.") + success = ColorField(default='#cbffcd', help_text="The background color of success notifications.") + + def __str__(self): + return self.name + diff --git a/app/static/app/android-chrome-192x192.png b/app/static/app/android-chrome-192x192.png deleted file mode 100644 index c047cd29..00000000 Binary files a/app/static/app/android-chrome-192x192.png and /dev/null differ diff --git a/app/static/app/android-chrome-512x512.png b/app/static/app/android-chrome-512x512.png deleted file mode 100644 index 2b0ceb36..00000000 Binary files a/app/static/app/android-chrome-512x512.png and /dev/null differ diff --git a/app/static/app/apple-touch-icon.png b/app/static/app/apple-touch-icon.png deleted file mode 100644 index 00f374c7..00000000 Binary files a/app/static/app/apple-touch-icon.png and /dev/null differ diff --git a/app/static/app/browserconfig.xml b/app/static/app/browserconfig.xml deleted file mode 100644 index 658b5609..00000000 --- a/app/static/app/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #00aba9 - - - diff --git a/app/static/app/css/main.scss b/app/static/app/css/main.scss index c81fea74..47ae9281 100644 --- a/app/static/app/css/main.scss +++ b/app/static/app/css/main.scss @@ -218,9 +218,3 @@ button i.glyphicon{ top: 0px; left: 50px; } - -.navbar-link { - position: absolute; - top: 0px; -} - diff --git a/app/static/app/favicon-16x16.png b/app/static/app/favicon-16x16.png deleted file mode 100644 index 4d107580..00000000 Binary files a/app/static/app/favicon-16x16.png and /dev/null differ diff --git a/app/static/app/favicon-32x32.png b/app/static/app/favicon-32x32.png deleted file mode 100644 index bc4c6c92..00000000 Binary files a/app/static/app/favicon-32x32.png and /dev/null differ diff --git a/app/static/app/favicon.ico b/app/static/app/favicon.ico deleted file mode 100644 index 8385c33a..00000000 Binary files a/app/static/app/favicon.ico and /dev/null differ diff --git a/app/static/app/img/logo36.png b/app/static/app/img/logo36.png deleted file mode 100644 index 21de5410..00000000 Binary files a/app/static/app/img/logo36.png and /dev/null differ diff --git a/app/static/app/js/MapView.jsx b/app/static/app/js/MapView.jsx index 0f8bd8a4..51d6dbab 100644 --- a/app/static/app/js/MapView.jsx +++ b/app/static/app/js/MapView.jsx @@ -89,7 +89,7 @@ class MapView extends React.Component { + className={"btn btn-sm " + (mapType.type === this.state.selectedMapType ? "btn-primary" : "btn-default")}>{mapType.label} )} diff --git a/app/static/app/manifest.json b/app/static/app/manifest.json deleted file mode 100644 index 325a0752..00000000 --- a/app/static/app/manifest.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "WebODM", - "icons": [ - { - "src": "\/static\/app\/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image\/png" - }, - { - "src": "\/static\/app\/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image\/png" - } - ], - "theme_color": "#ffffff", - "display": "standalone" -} diff --git a/app/static/app/mstile-150x150.png b/app/static/app/mstile-150x150.png deleted file mode 100644 index 9ddd5d0d..00000000 Binary files a/app/static/app/mstile-150x150.png and /dev/null differ diff --git a/app/static/app/safari-pinned-tab.svg b/app/static/app/safari-pinned-tab.svg deleted file mode 100644 index 86ec3f00..00000000 --- a/app/static/app/safari-pinned-tab.svg +++ /dev/null @@ -1,448 +0,0 @@ - - - - -Created by potrace 1.11, written by Peter Selinger 2001-2013 - - - - - diff --git a/app/templates/app/base.html b/app/templates/app/base.html index d7ece283..96180dbc 100644 --- a/app/templates/app/base.html +++ b/app/templates/app/base.html @@ -1,21 +1,15 @@ - {% load i18n static %} + {% load i18n static settings %} + {% get_settings as settings %} + - - - - - - - - - - - + + + @@ -29,7 +23,8 @@ {% load render_bundle from webpack_loader %} {% render_bundle 'main' %} - {{title|default:"Login"}} - WebODM + {{title|default:"Login"}} - {{ settings.app_name }} +