kopia lustrzana https://github.com/OpenDroneMap/WebODM
Restart dropdown, added task can_rerun_from field, fixed jest tests
rodzic
2bb43203dc
commit
492fc56587
|
@ -30,10 +30,30 @@ class TaskSerializer(serializers.ModelSerializer):
|
|||
project = serializers.PrimaryKeyRelatedField(queryset=models.Project.objects.all())
|
||||
processing_node = serializers.PrimaryKeyRelatedField(queryset=ProcessingNode.objects.all())
|
||||
images_count = serializers.SerializerMethodField()
|
||||
can_rerun_from = serializers.SerializerMethodField()
|
||||
|
||||
def get_images_count(self, obj):
|
||||
return obj.imageupload_set.count()
|
||||
|
||||
def get_can_rerun_from(self, obj):
|
||||
"""
|
||||
When a task has been associated with a processing node
|
||||
and if the processing node supports the "rerun-from" parameter
|
||||
this method returns the valid values for "rerun-from" for that particular
|
||||
processing node.
|
||||
|
||||
TODO: this could be improved by returning an empty array if a task was created
|
||||
and purged by the processing node (which would require knowing how long a task is being kept
|
||||
see https://github.com/OpenDroneMap/node-OpenDroneMap/issues/32
|
||||
:return: array of valid rerun-from parameters
|
||||
"""
|
||||
if obj.processing_node is not None:
|
||||
rerun_from_option = list(filter(lambda d: 'name' in d and d['name'] == 'rerun-from', obj.processing_node.available_options))
|
||||
if len(rerun_from_option) > 0 and 'domain' in rerun_from_option[0]:
|
||||
return rerun_from_option[0]['domain']
|
||||
|
||||
return []
|
||||
|
||||
class Meta:
|
||||
model = models.Task
|
||||
exclude = ('processing_lock', 'console_output', 'orthophoto_extent', 'dsm_extent', 'dtm_extent', )
|
||||
|
|
|
@ -81,6 +81,7 @@ class ModelView extends React.Component {
|
|||
|
||||
componentDidMount() {
|
||||
let container = this.container;
|
||||
if (!container) return; // Enzyme tests don't have support for all WebGL methods so we just skip this
|
||||
|
||||
window.viewer = new Potree.Viewer(container);
|
||||
viewer.setEDLEnabled(true);
|
||||
|
|
|
@ -163,7 +163,6 @@ class EditTaskForm extends React.Component {
|
|||
.fail((jqXHR, textStatus, errorThrown) => {
|
||||
// I don't expect this to fail, unless it's a development error or connection error.
|
||||
// in which case we don't need to notify the user directly.
|
||||
console.error("Error retrieving processing nodes", jqXHR, textStatus);
|
||||
failed();
|
||||
});
|
||||
}
|
||||
|
@ -256,7 +255,6 @@ class EditTaskForm extends React.Component {
|
|||
.fail((jqXHR, textStatus, errorThrown) => {
|
||||
// I don't expect this to fail, unless it's a development error or connection error.
|
||||
// in which case we don't need to notify the user directly.
|
||||
console.error("Error retrieving processing nodes", jqXHR, textStatus);
|
||||
failed();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
|||
import ErrorMessage from './ErrorMessage';
|
||||
import Utils from '../classes/Utils';
|
||||
import ClipboardInput from './ClipboardInput';
|
||||
import $ from 'jquery';
|
||||
|
||||
class SharePopup extends React.Component{
|
||||
static propTypes = {
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import '../css/TaskList.scss';
|
||||
import TaskListItem from './TaskListItem';
|
||||
import PropTypes from 'prop-types';
|
||||
import $ from 'jquery';
|
||||
|
||||
class TaskList extends React.Component {
|
||||
static propTypes = {
|
||||
|
|
|
@ -241,6 +241,31 @@ class TaskListItem extends React.Component {
|
|||
this.setAutoRefresh();
|
||||
}
|
||||
|
||||
getRestartSubmenuItems(task){
|
||||
// Map rerun-from parameters to display items
|
||||
const rfMap = {
|
||||
"odm_meshing": {
|
||||
label: "Meshing",
|
||||
icon: "fa fa-cube",
|
||||
onClick: (cb) => {
|
||||
console.log("mesh");
|
||||
}
|
||||
},
|
||||
|
||||
"mvs_texturing": {
|
||||
label: "Texturing",
|
||||
icon: "fa fa-connectdevelop",
|
||||
onClick: (cb) => {
|
||||
console.log("tex");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return task.can_rerun_from
|
||||
.map(rf => rfMap[rf])
|
||||
.filter(rf => rf !== undefined);
|
||||
}
|
||||
|
||||
render() {
|
||||
const task = this.state.task;
|
||||
const name = task.name !== null ? task.name : `Task #${task.id}`;
|
||||
|
@ -297,6 +322,7 @@ class TaskListItem extends React.Component {
|
|||
|
||||
if ([statusCodes.FAILED, statusCodes.COMPLETED, statusCodes.CANCELED].indexOf(task.status) !== -1 &&
|
||||
task.processing_node){
|
||||
|
||||
addActionButton("Restart", "btn-primary", "glyphicon glyphicon-repeat", this.genActionApiCall("restart", {
|
||||
success: () => {
|
||||
if (this.console) this.console.clear();
|
||||
|
@ -305,13 +331,7 @@ class TaskListItem extends React.Component {
|
|||
defaultError: "Cannot restart task."
|
||||
}
|
||||
), {
|
||||
subItems: [{
|
||||
label: "Meshing",
|
||||
icon: "glyphicon glyphicon-remove-circle",
|
||||
onClick: (cb) => {
|
||||
console.log("OK");
|
||||
}
|
||||
}]
|
||||
subItems: this.getRestartSubmenuItems(task)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { mount } from 'enzyme';
|
||||
import ClipboardInput from '../ClipboardInput';
|
||||
|
||||
describe('<ClipboardInput />', () => {
|
||||
it('renders without exploding', () => {
|
||||
const wrapper = shallow(<ClipboardInput type="text" />);
|
||||
const wrapper = mount(<ClipboardInput type="text" />);
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
})
|
||||
});
|
|
@ -6,4 +6,14 @@ currentScript.src = "http://bogus";
|
|||
|
||||
Object.defineProperty(document, 'currentScript', {
|
||||
value: currentScript
|
||||
});
|
||||
});
|
||||
|
||||
// local storage mock
|
||||
global.localStorage = {
|
||||
_dict: {},
|
||||
getItem: (key) => global.localStorage._dict[key],
|
||||
setItem: (key, value) => global.localStorage._dict[key] = value
|
||||
}
|
||||
|
||||
// Missing XMLHttpRequest methods
|
||||
XMLHttpRequest.prototype.abort = () => {};
|
|
@ -0,0 +1,5 @@
|
|||
import { configure } from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-react-16';
|
||||
|
||||
configure({ adapter: new Adapter() });
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Prevent warning on missing polyfill
|
||||
global.requestAnimationFrame = function(callback) {
|
||||
setTimeout(callback, 0);
|
||||
};
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
// Bootstrap polyfills
|
||||
$.prototype.modal = () => {};
|
|
@ -124,6 +124,9 @@ class TestApi(BootTestCase):
|
|||
# images_count field exists
|
||||
self.assertTrue(res.data["images_count"] == 0)
|
||||
|
||||
# TODO: test can_rerun_from
|
||||
|
||||
|
||||
# Get console output
|
||||
res = client.get('/api/projects/{}/tasks/{}/output/'.format(project.id, task.id))
|
||||
self.assertEqual(res.status_code, status.HTTP_200_OK)
|
||||
|
|
|
@ -4,5 +4,7 @@ module.exports = {
|
|||
"^.*\\.s?css$": "<rootDir>/app/static/app/js/tests/mocks/empty.scss.js",
|
||||
"jquery": "<rootDir>/app/static/app/js/vendor/jquery-1.11.2.min.js"
|
||||
},
|
||||
setupFiles: ["<rootDir>/app/static/app/js/tests/setup/browserMock.js"]
|
||||
setupFiles: ["<rootDir>/app/static/app/js/tests/setup/shims.js",
|
||||
"<rootDir>/app/static/app/js/tests/setup/setupTests.js",
|
||||
"<rootDir>/app/static/app/js/tests/setup/browserMock.js"]
|
||||
};
|
|
@ -32,10 +32,12 @@
|
|||
"clipboard": "^1.7.1",
|
||||
"css-loader": "^0.25.0",
|
||||
"d3": "^3.5.5",
|
||||
"enzyme": "^2.9.1",
|
||||
"enzyme": "^3.3.0",
|
||||
"enzyme-adapter-react-16": "^1.1.1",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^0.9.0",
|
||||
"gl-matrix": "^2.3.2",
|
||||
"history": "^4.7.2",
|
||||
"immutability-helper": "^2.0.0",
|
||||
"jest": "^21.0.1",
|
||||
"json-loader": "^0.5.4",
|
||||
|
@ -46,7 +48,6 @@
|
|||
"proj4": "^2.4.3",
|
||||
"raw-loader": "^0.5.1",
|
||||
"react": "^16.2.0",
|
||||
"react-addons-test-utils": "^15.6.0",
|
||||
"react-dom": "^16.2.0",
|
||||
"react-router": "^4.1.1",
|
||||
"react-router-dom": "^4.1.1",
|
||||
|
|
Ładowanie…
Reference in New Issue