kopia lustrzana https://github.com/OpenDroneMap/WebODM
commit
9b83da5ca4
10
app/boot.py
10
app/boot.py
|
@ -71,13 +71,15 @@ def boot():
|
||||||
if created:
|
if created:
|
||||||
logger.info("Created default theme")
|
logger.info("Created default theme")
|
||||||
|
|
||||||
if Setting.objects.all().count() == 0:
|
if settings.DEFAULT_THEME_CSS:
|
||||||
default_logo = os.path.join('app', 'static', 'app', 'img', 'logo512.png')
|
default_theme.css = settings.DEFAULT_THEME_CSS
|
||||||
|
default_theme.save()
|
||||||
|
|
||||||
|
if Setting.objects.all().count() == 0:
|
||||||
s = Setting.objects.create(
|
s = Setting.objects.create(
|
||||||
app_name='WebODM',
|
app_name=settings.APP_NAME,
|
||||||
theme=default_theme)
|
theme=default_theme)
|
||||||
s.app_logo.save(os.path.basename(default_logo), File(open(default_logo, 'rb')))
|
s.app_logo.save(os.path.basename(settings.APP_DEFAULT_LOGO), File(open(settings.APP_DEFAULT_LOGO, 'rb')))
|
||||||
|
|
||||||
logger.info("Created settings")
|
logger.info("Created settings")
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,17 @@ logger = logging.getLogger('app.logger')
|
||||||
class GrassEngine:
|
class GrassEngine:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.grass_binary = shutil.which('grass7') or \
|
self.grass_binary = shutil.which('grass7') or \
|
||||||
|
shutil.which('grass7.bat') or \
|
||||||
shutil.which('grass72') or \
|
shutil.which('grass72') or \
|
||||||
|
shutil.which('grass72.bat') or \
|
||||||
shutil.which('grass74') or \
|
shutil.which('grass74') or \
|
||||||
|
shutil.which('grass74.bat') or \
|
||||||
shutil.which('grass76') or \
|
shutil.which('grass76') or \
|
||||||
|
shutil.which('grass76.bat') or \
|
||||||
shutil.which('grass78') or \
|
shutil.which('grass78') or \
|
||||||
shutil.which('grass80')
|
shutil.which('grass78.bat') or \
|
||||||
|
shutil.which('grass80') or \
|
||||||
|
shutil.which('grass80.bat')
|
||||||
|
|
||||||
if self.grass_binary is None:
|
if self.grass_binary is None:
|
||||||
logger.warning("Could not find a GRASS 7 executable. GRASS scripts will not work.")
|
logger.warning("Could not find a GRASS 7 executable. GRASS scripts will not work.")
|
||||||
|
@ -34,7 +40,7 @@ class GrassContext:
|
||||||
if tmpdir is None:
|
if tmpdir is None:
|
||||||
tmpdir = os.path.basename(tempfile.mkdtemp('_grass_engine', dir=settings.MEDIA_TMP))
|
tmpdir = os.path.basename(tempfile.mkdtemp('_grass_engine', dir=settings.MEDIA_TMP))
|
||||||
self.tmpdir = tmpdir
|
self.tmpdir = tmpdir
|
||||||
self.script_opts = script_opts
|
self.script_opts = script_opts.copy()
|
||||||
self.location = location
|
self.location = location
|
||||||
self.auto_cleanup = auto_cleanup
|
self.auto_cleanup = auto_cleanup
|
||||||
|
|
||||||
|
@ -95,7 +101,7 @@ class GrassContext:
|
||||||
try:
|
try:
|
||||||
out = subprocess.check_output(command, cwd=self.get_cwd()).decode('utf-8').strip()
|
out = subprocess.check_output(command, cwd=self.get_cwd()).decode('utf-8').strip()
|
||||||
success = True
|
success = True
|
||||||
except subprocess.CalledProcessError:
|
except:
|
||||||
success = False
|
success = False
|
||||||
err = out
|
err = out
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -42,5 +42,8 @@ def export_raster_index(input, expression, output):
|
||||||
index_band[index_band>1e+30] = -9999
|
index_band[index_band>1e+30] = -9999
|
||||||
index_band[index_band<-1e+30] = -9999
|
index_band[index_band<-1e+30] = -9999
|
||||||
|
|
||||||
|
# Make sure this is float32
|
||||||
|
arr = arr.astype(np.float32)
|
||||||
|
|
||||||
with rasterio.open(output, 'w', **profile) as dst:
|
with rasterio.open(output, 'w', **profile) as dst:
|
||||||
dst.write(arr)
|
dst.write(arr)
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
{% extends "app/base.html" %}
|
{% extends "app/base.html" %}
|
||||||
{% load i18n static %}
|
{% load i18n static settings %}
|
||||||
|
|
||||||
|
|
||||||
{% block navbar-top-links %}
|
{% block navbar-top-links %}
|
||||||
|
{% is_single_user_mode as single_user %}
|
||||||
|
|
||||||
|
{% if not single_user %}
|
||||||
<ul class="nav navbar-top-links navbar-right">
|
<ul class="nav navbar-top-links navbar-right">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
||||||
|
@ -21,6 +23,7 @@
|
||||||
</li>
|
</li>
|
||||||
<!-- /.dropdown -->
|
<!-- /.dropdown -->
|
||||||
</ul>
|
</ul>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block navbar-sidebar %}
|
{% block navbar-sidebar %}
|
||||||
<div class="navbar-default sidebar" role="navigation">
|
<div class="navbar-default sidebar" role="navigation">
|
||||||
|
@ -75,12 +78,16 @@
|
||||||
<li>
|
<li>
|
||||||
<a href="#"><i class="fa fa-cogs fa-fw"></i> {% trans 'Administration' %}<span class="fa arrow"></span></a>
|
<a href="#"><i class="fa fa-cogs fa-fw"></i> {% trans 'Administration' %}<span class="fa arrow"></span></a>
|
||||||
<ul class="nav nav-second-level">
|
<ul class="nav nav-second-level">
|
||||||
|
{% is_single_user_mode as hide_users %}
|
||||||
|
{% if not hide_users %}
|
||||||
<li>
|
<li>
|
||||||
<a href="/admin/auth/user/"><i class="fa fa-user fa-fw"></i> {% trans 'Accounts' %}</a>
|
<a href="/admin/auth/user/"><i class="fa fa-user fa-fw"></i> {% trans 'Accounts' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/admin/auth/group/"><i class="fa fa-users fa-fw"></i> {% trans 'Groups' %}</a>
|
<a href="/admin/auth/group/"><i class="fa fa-users fa-fw"></i> {% trans 'Groups' %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="{% url 'admin:app_setting_change' SETTINGS.id %}"><i class="fa fa-magic fa-fw"></i> {% trans 'Brand' %}</a>
|
<a href="{% url 'admin:app_setting_change' SETTINGS.id %}"><i class="fa fa-magic fa-fw"></i> {% trans 'Brand' %}</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{% extends 'registration/registration_base.html' %}
|
{% extends 'registration/registration_base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
{% load settings %}
|
||||||
|
|
||||||
{% block registration_content %}
|
{% block registration_content %}
|
||||||
{% if form.errors %}
|
{% if form.errors %}
|
||||||
|
@ -7,6 +8,12 @@
|
||||||
<p><strong>{% trans "Invalid credentials." %}</strong> {% trans "Note that both fields are case-sensitive." %}</p>
|
<p><strong>{% trans "Invalid credentials." %}</strong> {% trans "Note that both fields are case-sensitive." %}</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% is_single_user_mode as autologin %}
|
||||||
|
|
||||||
|
{% if autologin %}
|
||||||
|
<script>location.href='/';</script>
|
||||||
|
{% else %}
|
||||||
<form action="{% url 'login' %}" method="post" class="form-horizontal" role="form">{% csrf_token %}
|
<form action="{% url 'login' %}" method="post" class="form-horizontal" role="form">{% csrf_token %}
|
||||||
{% for field in form %}
|
{% for field in form %}
|
||||||
{% include 'registration/form_field.html' %}
|
{% include 'registration/form_field.html' %}
|
||||||
|
@ -27,4 +34,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -2,10 +2,15 @@ import datetime
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from django import template
|
from django import template
|
||||||
|
from webodm import settings
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
logger = logging.getLogger('app.logger')
|
logger = logging.getLogger('app.logger')
|
||||||
|
|
||||||
|
@register.simple_tag
|
||||||
|
def is_single_user_mode():
|
||||||
|
return settings.SINGLE_USER_MODE
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
def settings_image_url(context, image):
|
def settings_image_url(context, image):
|
||||||
|
|
|
@ -13,19 +13,30 @@ from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from webodm import settings
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
# Check first access where the user is expected to
|
# Check first access
|
||||||
# create an admin account
|
|
||||||
if User.objects.filter(is_superuser=True).count() == 0:
|
if User.objects.filter(is_superuser=True).count() == 0:
|
||||||
|
if settings.SINGLE_USER_MODE:
|
||||||
|
# Automatically create a default account
|
||||||
|
User.objects.create_superuser('admin', 'admin@localhost', 'admin')
|
||||||
|
else:
|
||||||
|
# the user is expected to create an admin account
|
||||||
return redirect('welcome')
|
return redirect('welcome')
|
||||||
|
|
||||||
return redirect('dashboard' if request.user.is_authenticated
|
if settings.SINGLE_USER_MODE and not request.user.is_authenticated:
|
||||||
else 'login')
|
login(request, User.objects.get(username="admin"), 'django.contrib.auth.backends.ModelBackend')
|
||||||
|
|
||||||
|
return redirect(settings.LOGIN_REDIRECT_URL if request.user.is_authenticated
|
||||||
|
else settings.LOGIN_URL)
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def dashboard(request):
|
def dashboard(request):
|
||||||
no_processingnodes = ProcessingNode.objects.count() == 0
|
no_processingnodes = ProcessingNode.objects.count() == 0
|
||||||
|
if no_processingnodes and settings.PROCESSING_NODES_ONBOARDING is not None:
|
||||||
|
return redirect(settings.PROCESSING_NODES_ONBOARDING)
|
||||||
|
|
||||||
no_tasks = Task.objects.filter(project__owner=request.user).count() == 0
|
no_tasks = Task.objects.filter(project__owner=request.user).count() == 0
|
||||||
|
|
||||||
# Create first project automatically
|
# Create first project automatically
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "WebODM",
|
"name": "WebODM",
|
||||||
"version": "1.3.3",
|
"version": "1.3.4",
|
||||||
"description": "User-friendly, extendable application and API for processing aerial imagery.",
|
"description": "User-friendly, extendable application and API for processing aerial imagery.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -56,6 +56,19 @@ INTERNAL_IPS = ['127.0.0.1']
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
|
||||||
|
# Branding
|
||||||
|
APP_NAME = "WebODM"
|
||||||
|
APP_DEFAULT_LOGO = os.path.join('app', 'static', 'app', 'img', 'logo512.png')
|
||||||
|
|
||||||
|
# In single user mode, a default admin account is created and automatically
|
||||||
|
# used so that no login windows are displayed
|
||||||
|
SINGLE_USER_MODE = False
|
||||||
|
|
||||||
|
# URL to redirect to if there are no processing nodes when visiting the dashboard
|
||||||
|
PROCESSING_NODES_ONBOARDING = None
|
||||||
|
|
||||||
|
# Default CSS to add to theme
|
||||||
|
DEFAULT_THEME_CSS = ''
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue