From 750f43ca9d9ef4a594c05680b588ab8f0d0006aa Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Tue, 25 Jul 2017 13:54:41 -0400 Subject: [PATCH] Create default presets at boot --- app/boot.py | 14 ++++++++++++ app/migrations/0010_auto_20170725_1324.py | 22 +++++++++++++++++++ app/models/preset.py | 2 +- app/static/app/js/components/EditTaskForm.jsx | 21 +++++++++++++----- app/static/app/js/components/TaskListItem.jsx | 5 +++-- app/static/app/js/css/EditTaskForm.scss | 4 ++++ app/tests/test_api_preset.py | 12 +++++++--- 7 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 app/migrations/0010_auto_20170725_1324.py diff --git a/app/boot.py b/app/boot.py index 6daf412b..072a5973 100644 --- a/app/boot.py +++ b/app/boot.py @@ -4,6 +4,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.db.utils import ProgrammingError from guardian.shortcuts import assign_perm +from app.models import Preset from nodeodm.models import ProcessingNode # noinspection PyUnresolvedReferences from . import scheduler, signals @@ -50,6 +51,19 @@ def boot(): # Add permission to view processing nodes default_group.permissions.add(Permission.objects.get(codename="view_processingnode")) + # Add default presets + Preset.objects.get_or_create(name='DSM + DTM', system=True, + options=[{'name': 'dsm', 'value': True}, {'name': 'dtm', 'value': True}]) + Preset.objects.get_or_create(name='High Quality', system=True, + options=[{'name': 'dsm', 'value': True}, + {'name': 'skip-resize', 'value': True}, + {'name': 'mesh-octree-depth', 'value': "12"}, + {'name': 'use-25dmesh', 'value': True}, + {'name': 'dem-resolution', 'value': "0.04"}, + {'name': 'orthophoto-resolution', 'value': "60"}, + ]) + Preset.objects.get_or_create(name='Default', system=True, options=[{'name': 'dsm', 'value': True}]) + # Unlock any Task that might have been locked Task.objects.filter(processing_lock=True).update(processing_lock=False) diff --git a/app/migrations/0010_auto_20170725_1324.py b/app/migrations/0010_auto_20170725_1324.py new file mode 100644 index 00000000..188b3bf4 --- /dev/null +++ b/app/migrations/0010_auto_20170725_1324.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.1 on 2017-07-25 17:24 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('app', '0009_auto_20170721_1332'), + ] + + operations = [ + migrations.AlterField( + model_name='preset', + name='owner', + field=models.ForeignKey(blank=True, help_text='The person who owns this preset', null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/app/models/preset.py b/app/models/preset.py index 170f6e70..5a571e03 100644 --- a/app/models/preset.py +++ b/app/models/preset.py @@ -10,7 +10,7 @@ logger = logging.getLogger('app.logger') class Preset(models.Model): - owner = models.ForeignKey(User, on_delete=models.CASCADE, help_text="The person who owns this preset") + owner = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE, help_text="The person who owns this preset") name = models.CharField(max_length=255, blank=False, null=False, help_text="A label used to describe the preset") options = JSONField(default=list(), blank=True, help_text="Options that define this preset (same format as in a Task's options).", validators=[validate_task_options]) diff --git a/app/static/app/js/components/EditTaskForm.jsx b/app/static/app/js/components/EditTaskForm.jsx index 04505217..55bdf4c1 100644 --- a/app/static/app/js/components/EditTaskForm.jsx +++ b/app/static/app/js/components/EditTaskForm.jsx @@ -64,6 +64,8 @@ class EditTaskForm extends React.Component { this.handleDeletePreset = this.handleDeletePreset.bind(this); this.findFirstPresetMatching = this.findFirstPresetMatching.bind(this); this.getAvailableOptionsOnly = this.getAvailableOptionsOnly.bind(this); + this.getAvailableOptionsOnlyText = this.getAvailableOptionsOnlyText.bind(this); + } notifyFormLoaded(){ @@ -209,7 +211,7 @@ class EditTaskForm extends React.Component { } this.presetsRequest = - $.getJSON("/api/presets/?ordering=-created_at", presets => { + $.getJSON("/api/presets/?ordering=-system,-created_at", presets => { if (Array.isArray(presets)){ // Add custom preset const customPreset = { @@ -218,7 +220,7 @@ class EditTaskForm extends React.Component { options: [], system: true }; - presets.push(customPreset); + presets.unshift(customPreset); // Choose preset let selectedPreset = presets[0], @@ -298,6 +300,11 @@ class EditTaskForm extends React.Component { return options.filter(opt => optionNames[opt.name]); } + getAvailableOptionsOnlyText(options, availableOptions){ + const opts = this.getAvailableOptionsOnly(options, availableOptions); + return opts.map(opt => `${opt.name}:${opt.value}`).join(", "); + } + getTaskInfo(){ const { name, selectedNode, selectedPreset } = this.state; @@ -323,7 +330,7 @@ class EditTaskForm extends React.Component { options: [], system: true }; - presets.push(customPreset); + presets.unshift(customPreset); this.setState({presets}); } customPreset.options = Utils.clone(selectedPreset.options); @@ -463,9 +470,13 @@ class EditTaskForm extends React.Component {
- {this.state.presets.map(preset => - + )} diff --git a/app/static/app/js/components/TaskListItem.jsx b/app/static/app/js/components/TaskListItem.jsx index b62ec16f..59d5fa41 100644 --- a/app/static/app/js/components/TaskListItem.jsx +++ b/app/static/app/js/components/TaskListItem.jsx @@ -38,12 +38,13 @@ class TaskListItem extends React.Component { } shouldRefresh(){ + if (this.state.task.pending_action !== null) return true; + // If a task is completed, or failed, etc. we don't expect it to change if ([statusCodes.COMPLETED, statusCodes.FAILED, statusCodes.CANCELED].indexOf(this.state.task.status) !== -1) return false; return (([statusCodes.QUEUED, statusCodes.RUNNING, null].indexOf(this.state.task.status) !== -1 && this.state.task.processing_node) || - (!this.state.task.uuid && this.state.task.processing_node && !this.state.task.last_error) || - this.state.task.pending_action !== null); + (!this.state.task.uuid && this.state.task.processing_node && !this.state.task.last_error)); } loadTimer(startTime){ diff --git a/app/static/app/js/css/EditTaskForm.scss b/app/static/app/js/css/EditTaskForm.scss index 83d787d5..8bad7aec 100644 --- a/app/static/app/js/css/EditTaskForm.scss +++ b/app/static/app/js/css/EditTaskForm.scss @@ -10,4 +10,8 @@ .preset-error{ margin-top: 12px; } + + .system-preset{ + background-color: #eee; + } } \ No newline at end of file diff --git a/app/tests/test_api_preset.py b/app/tests/test_api_preset.py index 509080c0..3c0fd46c 100644 --- a/app/tests/test_api_preset.py +++ b/app/tests/test_api_preset.py @@ -16,10 +16,15 @@ class TestApiPreset(BootTestCase): superuser = User.objects.get(username='testsuperuser') - Preset.objects.create(owner=superuser, name='Global Preset #1', system=True, options=[{'test': True}]) - Preset.objects.create(owner=superuser, name='Global Preset #2', system=True, options=[{'test2': True}]) + Preset.objects.create(name='Global Preset #1', system=True, options=[{'test': True}]) + Preset.objects.create(name='Global Preset #2', system=True, options=[{'test2': True}]) Preset.objects.create(owner=superuser, name='Local Preset #1', system=False, options=[{'test3': True}]) + def check_default_presets(self): + self.assertTrue(Preset.objects.filter(name="Default", system=True).exists()) + self.assertTrue(Preset.objects.filter(name="DSM + DTM", system=True).exists()) + self.assertTrue(Preset.objects.filter(name="High Quality", system=True).exists()) + def test_preset(self): client = APIClient() @@ -48,8 +53,9 @@ class TestApiPreset(BootTestCase): self.assertTrue(res.status_code == status.HTTP_200_OK) # Only ours and global presets are available - self.assertTrue(len(res.data) == 3) + self.assertTrue(len(res.data) == 6) self.assertTrue('My Local Preset' in [preset['name'] for preset in res.data]) + self.assertTrue('High Quality' in [preset['name'] for preset in res.data]) self.assertTrue('Global Preset #1' in [preset['name'] for preset in res.data]) self.assertTrue('Global Preset #2' in [preset['name'] for preset in res.data]) self.assertFalse('Local Preset #1' in [preset['name'] for preset in res.data])