2017-02-09 18:06:44 +00:00
import '../css/EditTaskForm.scss' ;
import React from 'react' ;
import Utils from '../classes/Utils' ;
2017-07-24 16:39:12 +00:00
import EditPresetDialog from './EditPresetDialog' ;
2017-07-25 16:37:42 +00:00
import ErrorMessage from './ErrorMessage' ;
2017-07-25 18:09:51 +00:00
import PropTypes from 'prop-types' ;
2017-07-25 19:54:31 +00:00
import Storage from '../classes/Storage' ;
2017-07-25 16:37:42 +00:00
import $ from 'jquery' ;
2017-02-09 18:06:44 +00:00
class EditTaskForm extends React . Component {
static defaultProps = {
2017-02-10 16:29:59 +00:00
selectedNode : null ,
2018-12-31 21:50:51 +00:00
task : null ,
onFormChanged : ( ) => { } ,
2019-06-26 14:20:22 +00:00
inReview : false
2017-02-09 18:06:44 +00:00
} ;
static propTypes = {
2017-07-25 18:09:51 +00:00
selectedNode : PropTypes . oneOfType ( [
PropTypes . string ,
PropTypes . number
2017-02-09 18:06:44 +00:00
] ) ,
2017-07-25 18:09:51 +00:00
onFormLoaded : PropTypes . func ,
2018-12-31 21:50:51 +00:00
onFormChanged : PropTypes . func ,
2019-06-26 14:20:22 +00:00
inReview : PropTypes . bool ,
2019-08-29 02:16:39 +00:00
task : PropTypes . object ,
2020-12-15 20:56:00 +00:00
suggestedTaskName : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . func ] )
2017-02-09 18:06:44 +00:00
} ;
constructor ( props ) {
super ( props ) ;
this . state = {
error : "" ,
2017-07-25 16:37:42 +00:00
presetError : "" ,
presetActionPerforming : false ,
2020-12-15 20:56:00 +00:00
namePlaceholder : typeof props . suggestedTaskName === "string" ? props . suggestedTaskName : ( props . task !== null ? ( props . task . name || "" ) : "Task of " + ( new Date ( ) ) . toISOString ( ) ) ,
name : typeof props . suggestedTaskName === "string" ? props . suggestedTaskName : ( props . task !== null ? ( props . task . name || "" ) : "" ) ,
2017-02-09 18:06:44 +00:00
loadedProcessingNodes : false ,
2017-07-24 16:39:12 +00:00
loadedPresets : false ,
2017-02-09 18:06:44 +00:00
selectedNode : null ,
2017-07-21 20:48:01 +00:00
processingNodes : [ ] ,
2017-07-24 16:39:12 +00:00
selectedPreset : null ,
2017-07-24 20:59:57 +00:00
presets : [ ] ,
2020-12-15 20:56:00 +00:00
editingPreset : false ,
loadingTaskName : false
2017-02-09 18:06:44 +00:00
} ;
this . handleNameChange = this . handleNameChange . bind ( this ) ;
this . handleSelectNode = this . handleSelectNode . bind ( this ) ;
this . loadProcessingNodes = this . loadProcessingNodes . bind ( this ) ;
2017-07-24 16:39:12 +00:00
this . retryLoad = this . retryLoad . bind ( this ) ;
2017-02-09 18:06:44 +00:00
this . selectNodeByKey = this . selectNodeByKey . bind ( this ) ;
this . getTaskInfo = this . getTaskInfo . bind ( this ) ;
2017-07-24 16:39:12 +00:00
this . notifyFormLoaded = this . notifyFormLoaded . bind ( this ) ;
this . loadPresets = this . loadPresets . bind ( this ) ;
this . handleSelectPreset = this . handleSelectPreset . bind ( this ) ;
this . selectPresetById = this . selectPresetById . bind ( this ) ;
this . handleEditPreset = this . handleEditPreset . bind ( this ) ;
2017-07-24 20:59:57 +00:00
this . handleCancelEditPreset = this . handleCancelEditPreset . bind ( this ) ;
2017-07-25 16:37:42 +00:00
this . handlePresetSave = this . handlePresetSave . bind ( this ) ;
this . handleDuplicateSavePreset = this . handleDuplicateSavePreset . bind ( this ) ;
this . handleDeletePreset = this . handleDeletePreset . bind ( this ) ;
this . findFirstPresetMatching = this . findFirstPresetMatching . bind ( this ) ;
this . getAvailableOptionsOnly = this . getAvailableOptionsOnly . bind ( this ) ;
2017-07-25 17:54:41 +00:00
this . getAvailableOptionsOnlyText = this . getAvailableOptionsOnlyText . bind ( this ) ;
2017-07-25 19:54:31 +00:00
this . saveLastPresetToStorage = this . saveLastPresetToStorage . bind ( this ) ;
2018-12-31 21:50:51 +00:00
this . formReady = this . formReady . bind ( this ) ;
}
formReady ( ) {
return this . state . loadedProcessingNodes &&
this . state . selectedNode &&
this . state . loadedPresets &&
this . state . selectedPreset ;
2017-07-24 16:39:12 +00:00
}
notifyFormLoaded ( ) {
2018-12-31 21:50:51 +00:00
if ( this . props . onFormLoaded && this . formReady ( ) ) this . props . onFormLoaded ( ) ;
2017-02-09 18:06:44 +00:00
}
loadProcessingNodes ( ) {
2018-01-18 18:03:02 +00:00
const failed = ( ) => {
this . setState ( { error : "Could not load list of processing nodes. Are you connected to the internet?" } ) ;
2017-02-09 18:06:44 +00:00
}
this . nodesRequest =
$ . getJSON ( "/api/processingnodes/?has_available_options=True" , json => {
if ( Array . isArray ( json ) ) {
// No nodes with options?
const noProcessingNodesError = ( nodes ) => {
var extra = nodes ? "We tried to reach:<ul>" + nodes . map ( n => Utils . html ` <li><a href=" ${ n . url } "> ${ n . label } </a></li> ` ) . join ( "" ) + "</ul>" : "" ;
this . setState ( { error : ` There are no usable processing nodes. ${ extra } Make sure that at least one processing node is reachable and
that you have granted the current user sufficient permissions to view
the processing node ( by going to Administration -- Processing Nodes -- Select Node -- Object Permissions -- Add User / Group and check CAN VIEW PROCESSING NODE ) .
If you are bringing a node back online , it will take about 30 seconds for WebODM to recognize it . ` });
2017-02-15 19:20:41 +00:00
} ;
2017-02-09 18:06:44 +00:00
if ( json . length === 0 ) {
noProcessingNodesError ( ) ;
return ;
}
let now = new Date ( ) ;
let nodes = json . map ( node => {
return {
id : node . id ,
key : node . id ,
2019-01-15 14:06:22 +00:00
label : ` ${ node . label } (queue: ${ node . queue _count } ) ` ,
2017-02-09 18:06:44 +00:00
options : node . available _options ,
queue _count : node . queue _count ,
2017-03-06 22:59:00 +00:00
enabled : node . online ,
2017-02-09 18:06:44 +00:00
url : ` http:// ${ node . hostname } : ${ node . port } `
} ;
} ) ;
2017-02-15 19:20:41 +00:00
let autoNode = null ;
2017-02-09 18:06:44 +00:00
2017-02-15 19:25:47 +00:00
// If the user has selected auto, and a processing node has been assigned
2017-02-15 19:20:41 +00:00
// we need attempt to find the "auto" node to be the one that has been assigned
if ( this . props . task && this . props . task . processing _node && this . props . task . auto _processing _node ) {
autoNode = nodes . find ( node => node . id === this . props . task . processing _node ) ;
2017-02-09 18:06:44 +00:00
}
2017-02-15 19:20:41 +00:00
if ( ! autoNode ) {
// Find a node with lowest queue count
let minQueueCount = Math . min ( ... nodes . filter ( node => node . enabled ) . map ( node => node . queue _count ) ) ;
let minQueueCountNodes = nodes . filter ( node => node . enabled && node . queue _count === minQueueCount ) ;
if ( minQueueCountNodes . length === 0 ) {
noProcessingNodesError ( nodes ) ;
return ;
}
// Choose at random
autoNode = minQueueCountNodes [ ~ ~ ( Math . random ( ) * minQueueCountNodes . length ) ] ;
}
2017-02-09 18:06:44 +00:00
nodes . unshift ( {
id : autoNode . id ,
key : "auto" ,
label : "Auto" ,
options : autoNode . options ,
enabled : true
} ) ;
this . setState ( {
processingNodes : nodes ,
loadedProcessingNodes : true
} ) ;
// Have we specified a node?
2017-02-10 16:29:59 +00:00
if ( this . props . task && this . props . task . processing _node ) {
2017-02-15 19:20:41 +00:00
if ( this . props . task . auto _processing _node ) {
this . selectNodeByKey ( "auto" ) ;
} else {
this . selectNodeByKey ( this . props . task . processing _node ) ;
}
2019-06-27 15:19:52 +00:00
} else if ( this . props . selectedNode ) {
this . selectNodeByKey ( this . props . selectedNode ) ;
2017-02-09 18:06:44 +00:00
} else {
2017-02-15 19:20:41 +00:00
this . selectNodeByKey ( "auto" ) ;
2017-02-09 18:06:44 +00:00
}
2017-07-24 16:39:12 +00:00
this . notifyFormLoaded ( ) ;
2017-02-09 18:06:44 +00:00
} else {
console . error ( "Got invalid json response for processing nodes" , json ) ;
failed ( ) ;
}
} )
. 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.
failed ( ) ;
} ) ;
}
2017-07-24 16:39:12 +00:00
retryLoad ( ) {
2017-02-09 18:06:44 +00:00
this . setState ( { error : "" } ) ;
this . loadProcessingNodes ( ) ;
2017-07-24 16:39:12 +00:00
this . loadPresets ( ) ;
}
2017-07-25 16:37:42 +00:00
findFirstPresetMatching ( presets , options ) {
for ( let i = 0 ; i < presets . length ; i ++ ) {
const preset = presets [ i ] ;
if ( options . length === preset . options . length ) {
let dict = { } ;
options . forEach ( opt => {
dict [ opt . name ] = opt . value ;
} ) ;
let matchingOptions = 0 ;
for ( let j = 0 ; j < preset . options . length ; j ++ ) {
if ( dict [ preset . options [ j ] . name ] !== preset . options [ j ] . value ) {
break ;
} else {
matchingOptions ++ ;
}
}
// If we terminated the loop above, all options match
if ( matchingOptions === options . length ) return preset ;
}
}
return null ;
}
2017-07-24 16:39:12 +00:00
loadPresets ( ) {
2018-01-18 18:03:02 +00:00
const failed = ( ) => {
this . setState ( { error : "Could not load list of presets. Are you connected to the internet?" } ) ;
2017-07-24 16:39:12 +00:00
}
this . presetsRequest =
2017-07-25 17:54:41 +00:00
$ . getJSON ( "/api/presets/?ordering=-system,-created_at" , presets => {
2017-07-24 16:39:12 +00:00
if ( Array . isArray ( presets ) ) {
2017-07-25 16:37:42 +00:00
// Add custom preset
const customPreset = {
id : - 1 ,
name : "(Custom)" ,
options : [ ] ,
system : true
} ;
2017-07-25 17:54:41 +00:00
presets . unshift ( customPreset ) ;
2017-07-24 16:39:12 +00:00
// Choose preset
let selectedPreset = presets [ 0 ] ,
defaultPreset = presets . find ( p => p . name === "Default" ) ; // Do not translate Default
if ( defaultPreset ) selectedPreset = defaultPreset ;
2017-07-25 16:37:42 +00:00
// If task's options are set attempt
// to find a preset that matches the current task options
if ( this . props . task && Array . isArray ( this . props . task . options ) && this . props . task . options . length > 0 ) {
const taskPreset = this . findFirstPresetMatching ( presets , this . props . task . options ) ;
if ( taskPreset !== null ) {
selectedPreset = taskPreset ;
} else {
customPreset . options = Utils . clone ( this . props . task . options ) ;
selectedPreset = customPreset ;
}
2017-07-25 19:54:31 +00:00
} else {
// Check local storage for last used preset
const lastPresetId = Storage . getItem ( "last_preset_id" ) ;
if ( lastPresetId !== null ) {
const lastPreset = presets . find ( p => p . id == lastPresetId ) ;
if ( lastPreset ) selectedPreset = lastPreset ;
}
2017-07-25 16:37:42 +00:00
}
2017-07-24 16:39:12 +00:00
this . setState ( {
loadedPresets : true ,
presets : presets ,
selectedPreset : selectedPreset
} ) ;
this . notifyFormLoaded ( ) ;
} else {
console . error ( "Got invalid json response for presets" , json ) ;
failed ( ) ;
}
} )
. 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.
failed ( ) ;
} ) ;
}
2020-12-15 20:56:00 +00:00
loadSuggestedName = ( ) => {
if ( typeof this . props . suggestedTaskName === "function" ) {
this . setState ( { loadingTaskName : true } ) ;
this . props . suggestedTaskName ( ) . then ( name => {
if ( this . state . loadingTaskName ) {
this . setState ( { loadingTaskName : false , name } ) ;
} else {
// User started typing its own name
}
} ) . catch ( e => {
// Do Nothing
this . setState ( { loadingTaskName : false } ) ;
} )
}
}
2017-07-24 16:39:12 +00:00
handleSelectPreset ( e ) {
this . selectPresetById ( e . target . value ) ;
}
selectPresetById ( id ) {
let preset = this . state . presets . find ( p => p . id === parseInt ( id ) ) ;
if ( preset ) this . setState ( { selectedPreset : preset } ) ;
2017-02-09 18:06:44 +00:00
}
componentDidMount ( ) {
this . loadProcessingNodes ( ) ;
2017-07-24 16:39:12 +00:00
this . loadPresets ( ) ;
2020-12-15 20:56:00 +00:00
this . loadSuggestedName ( ) ;
2017-02-09 18:06:44 +00:00
}
2018-12-31 21:50:51 +00:00
componentDidUpdate ( prevProps , prevState ) {
// Monitor changes of certain form items (user driven)
// and fire event when appropriate
if ( ! this . formReady ( ) ) return ;
let changed = false ;
[ 'name' , 'selectedNode' , 'selectedPreset' ] . forEach ( prop => {
if ( prevState [ prop ] !== this . state [ prop ] ) changed = true ;
} ) ;
if ( changed ) this . props . onFormChanged ( ) ;
}
2017-02-09 18:06:44 +00:00
componentWillUnmount ( ) {
2017-07-24 16:39:12 +00:00
if ( this . nodesRequest ) this . nodesRequest . abort ( ) ;
if ( this . presetsRequest ) this . presetsRequest . abort ( ) ;
2017-02-09 18:06:44 +00:00
}
handleNameChange ( e ) {
2020-12-15 20:56:00 +00:00
this . setState ( { name : e . target . value , loadingTaskName : false } ) ;
2017-02-09 18:06:44 +00:00
}
selectNodeByKey ( key ) {
let node = this . state . processingNodes . find ( node => node . key == key ) ;
if ( node ) this . setState ( { selectedNode : node } ) ;
2019-06-27 15:19:52 +00:00
else {
console . warn ( ` Node ${ key } does not exist, selecting auto ` ) ;
this . selectNodeByKey ( "auto" ) ;
}
2017-02-09 18:06:44 +00:00
}
handleSelectNode ( e ) {
this . selectNodeByKey ( e . target . value ) ;
}
2017-07-25 16:37:42 +00:00
// Filter a list of options based on the ones that
// are available (usually options are from a preset and availableOptions
// from a processing node)
getAvailableOptionsOnly ( options , availableOptions ) {
const optionNames = { } ;
availableOptions . forEach ( opt => optionNames [ opt . name ] = true ) ;
return options . filter ( opt => optionNames [ opt . name ] ) ;
}
2017-07-25 17:54:41 +00:00
getAvailableOptionsOnlyText ( options , availableOptions ) {
const opts = this . getAvailableOptionsOnly ( options , availableOptions ) ;
2019-06-26 14:20:22 +00:00
let res = opts . map ( opt => ` ${ opt . name } : ${ opt . value } ` ) . join ( ", " ) ;
if ( ! res ) res = "Default" ;
return res ;
2017-07-25 17:54:41 +00:00
}
2017-07-25 19:54:31 +00:00
saveLastPresetToStorage ( ) {
if ( this . state . selectedPreset ) {
Storage . setItem ( 'last_preset_id' , this . state . selectedPreset . id ) ;
}
}
2017-02-09 18:06:44 +00:00
getTaskInfo ( ) {
2017-07-25 16:37:42 +00:00
const { name , selectedNode , selectedPreset } = this . state ;
2017-02-09 18:06:44 +00:00
return {
2017-07-25 16:37:42 +00:00
name : name !== "" ? name : this . namePlaceholder ,
selectedNode : selectedNode ,
options : this . getAvailableOptionsOnly ( selectedPreset . options , selectedNode . options )
2017-02-09 18:06:44 +00:00
} ;
}
2017-07-24 16:39:12 +00:00
handleEditPreset ( ) {
2017-07-25 16:37:42 +00:00
// If the user tries to edit a system preset
// set the "Custom..." options to it
const { selectedPreset , presets } = this . state ;
if ( selectedPreset . system ) {
let customPreset = presets . find ( p => p . id === - 1 ) ;
// Might have been deleted
if ( ! customPreset ) {
customPreset = {
id : - 1 ,
name : "(Custom)" ,
options : [ ] ,
system : true
} ;
2017-07-25 17:54:41 +00:00
presets . unshift ( customPreset ) ;
2017-07-25 16:37:42 +00:00
this . setState ( { presets } ) ;
}
customPreset . options = Utils . clone ( selectedPreset . options ) ;
this . setState ( { selectedPreset : customPreset } ) ;
}
2017-07-24 20:59:57 +00:00
this . setState ( { editingPreset : true } ) ;
}
handleCancelEditPreset ( ) {
this . setState ( { editingPreset : false } ) ;
2017-02-10 16:29:59 +00:00
}
2017-07-25 16:37:42 +00:00
handlePresetSave ( preset ) {
const done = ( ) => {
// Update presets and selected preset
let p = this . state . presets . find ( p => p . id === preset . id ) ;
p . name = preset . name ;
p . options = preset . options ;
this . setState ( { selectedPreset : p } ) ;
} ;
// If it's a custom preset do not update server-side
if ( preset . id === - 1 ) {
done ( ) ;
return $ . Deferred ( ) . resolve ( ) ;
} else {
return $ . ajax ( {
url : ` /api/presets/ ${ preset . id } / ` ,
contentType : 'application/json' ,
data : JSON . stringify ( {
name : preset . name ,
options : preset . options
} ) ,
dataType : 'json' ,
type : 'PATCH'
} ) . done ( done ) ;
}
}
handleDuplicateSavePreset ( ) {
// Create a new preset with the same settings as the
// currently selected preset
const { selectedPreset , presets } = this . state ;
this . setState ( { presetActionPerforming : true } ) ;
const isCustom = selectedPreset . id === - 1 ,
name = isCustom ? "My Preset" : "Copy of " + selectedPreset . name ;
$ . ajax ( {
url : ` /api/presets/ ` ,
contentType : 'application/json' ,
data : JSON . stringify ( {
name : name ,
options : selectedPreset . options
} ) ,
dataType : 'json' ,
type : 'POST'
} ) . done ( preset => {
// If the original preset was a custom one,
// we remove it from the list (since we just saved it)
if ( isCustom ) {
presets . splice ( presets . indexOf ( selectedPreset ) , 1 ) ;
}
// Add new preset to list, select it, then edit
presets . push ( preset ) ;
this . setState ( { presets , selectedPreset : preset } ) ;
this . handleEditPreset ( ) ;
} ) . fail ( ( ) => {
this . setState ( { presetError : "Could not duplicate the preset. Please try to refresh the page." } ) ;
} ) . always ( ( ) => {
this . setState ( { presetActionPerforming : false } ) ;
} ) ;
}
handleDeletePreset ( ) {
const { selectedPreset , presets } = this . state ;
if ( selectedPreset . system ) {
this . setState ( { presetError : "System presets can only be removed by a staff member from the Administration panel." } ) ;
return ;
}
if ( window . confirm ( ` Are you sure you want to delete " ${ selectedPreset . name } "? ` ) ) {
this . setState ( { presetActionPerforming : true } ) ;
return $ . ajax ( {
url : ` /api/presets/ ${ selectedPreset . id } / ` ,
contentType : 'application/json' ,
type : 'DELETE'
} ) . done ( ( ) => {
presets . splice ( presets . indexOf ( selectedPreset ) , 1 ) ;
// Select first by default
this . setState ( { presets , selectedPreset : presets [ 0 ] , editingPreset : false } ) ;
} ) . fail ( ( ) => {
this . setState ( { presetError : "Could not delete the preset. Please try to refresh the page." } ) ;
} ) . always ( ( ) => {
this . setState ( { presetActionPerforming : false } ) ;
} ) ;
} else {
return $ . Deferred ( ) . resolve ( ) ;
}
}
2017-02-09 18:06:44 +00:00
render ( ) {
if ( this . state . error ) {
return ( < div className = "edit-task-panel" >
< div className = "alert alert-warning" >
< div dangerouslySetInnerHTML = { { _ _html : this . state . error } } > < / div >
2017-07-24 16:39:12 +00:00
< button className = "btn btn-sm btn-primary" onClick = { this . retryLoad } >
2017-02-09 18:06:44 +00:00
< i className = "fa fa-rotate-left" > < / i > Retry
< / button >
< / div >
< / div > ) ;
}
2017-07-24 16:39:12 +00:00
let taskOptions = "" ;
2018-12-31 21:50:51 +00:00
if ( this . formReady ( ) ) {
2017-02-10 16:29:59 +00:00
2019-06-26 14:20:22 +00:00
const optionsSelector = ( < div >
< select
title = { this . getAvailableOptionsOnlyText ( this . state . selectedPreset . options , this . state . selectedNode . options ) }
className = "form-control"
value = { this . state . selectedPreset . id }
onChange = { this . handleSelectPreset } >
{ this . state . presets . map ( preset =>
< option value = { preset . id } key = { preset . id } className = { preset . system ? "system-preset" : "" } > { preset . name } < / option >
) }
< / select >
{ ! this . state . presetActionPerforming ?
< div className = "btn-group presets-dropdown" >
2020-05-17 15:13:59 +00:00
< button type = "button" className = "btn btn-default" title = "Edit Task Options" onClick = { this . handleEditPreset } >
< i className = "fa fa-sliders-h" > < / i > Edit
2019-06-26 14:20:22 +00:00
< / button >
< button type = "button" className = "btn btn-default dropdown-toggle" data - toggle = "dropdown" >
< span className = "caret" > < / span >
< / button >
< ul className = "dropdown-menu" >
< li >
2019-12-13 03:36:00 +00:00
< a href = "javascript:void(0);" onClick = { this . handleEditPreset } > < i className = "fa fa-sliders-h" > < / i > Edit < / a >
2019-06-26 14:20:22 +00:00
< / li >
< li className = "divider" > < / li >
{ this . state . selectedPreset . id !== - 1 ?
< li >
< a href = "javascript:void(0);" onClick = { this . handleDuplicateSavePreset } > < i className = "fa fa-copy" > < / i > Duplicate < / a >
< / li >
:
< li >
< a href = "javascript:void(0);" onClick = { this . handleDuplicateSavePreset } > < i className = "fa fa-save" > < / i > Save < / a >
< / li >
}
< li className = { this . state . selectedPreset . system ? "disabled" : "" } >
2019-11-07 21:24:02 +00:00
< a href = "javascript:void(0);" onClick = { this . handleDeletePreset } > < i className = "fa fa-trash" > < / i > Delete < / a >
2019-06-26 14:20:22 +00:00
< / li >
< / ul >
< / div >
: < i className = "preset-performing-action-icon fa fa-cog fa-spin fa-fw" > < / i > }
< ErrorMessage className = "preset-error" bind = { [ this , 'presetError' ] } / >
< / div > ) ;
2017-07-24 16:39:12 +00:00
taskOptions = (
2017-02-09 18:06:44 +00:00
< div >
< div className = "form-group" >
< label className = "col-sm-2 control-label" > Processing Node < / label >
< div className = "col-sm-10" >
< select className = "form-control" value = { this . state . selectedNode . key } onChange = { this . handleSelectNode } >
{ this . state . processingNodes . map ( node =>
< option value = { node . key } key = { node . key } disabled = { ! node . enabled } > { node . label } < / option >
) }
< / select >
< / div >
< / div >
2017-07-24 16:39:12 +00:00
< div className = "form-group form-inline" >
2017-02-09 18:06:44 +00:00
< label className = "col-sm-2 control-label" > Options < / label >
< div className = "col-sm-10" >
2019-06-26 14:20:22 +00:00
{ ! this . props . inReview ? optionsSelector :
< div className = "review-options" >
{ this . getAvailableOptionsOnlyText ( this . state . selectedPreset . options , this . state . selectedNode . options ) }
< / div > }
2017-02-09 18:06:44 +00:00
< / div >
< / div >
2017-07-24 20:59:57 +00:00
{ this . state . editingPreset ?
< EditPresetDialog
preset = { this . state . selectedPreset }
availableOptions = { this . state . selectedNode . options }
onHide = { this . handleCancelEditPreset }
2017-07-25 16:37:42 +00:00
saveAction = { this . handlePresetSave }
deleteAction = { this . handleDeletePreset }
2017-07-24 20:59:57 +00:00
ref = { ( domNode ) => { if ( domNode ) this . editPresetDialog = domNode ; } }
/ >
: "" }
2017-02-09 18:06:44 +00:00
< / div >
) ;
} else {
2017-07-24 16:39:12 +00:00
taskOptions = ( < div className = "form-group" >
2019-11-07 21:24:02 +00:00
< div className = "col-sm-offset-2 col-sm-10" > Loading processing nodes and presets ... < i className = "fa fa-sync fa-spin fa-fw" > < / i > < / div >
2017-02-09 18:06:44 +00:00
< / div > ) ;
}
return (
< div className = "edit-task-form" >
< div className = "form-group" >
< label className = "col-sm-2 control-label" > Name < / label >
< div className = "col-sm-10" >
2020-12-15 20:56:00 +00:00
{ this . state . loadingTaskName ?
< i className = "fa fa-circle-notch fa-spin fa-fw name-loading" > < / i >
: "" }
2017-02-10 16:29:59 +00:00
< input type = "text"
onChange = { this . handleNameChange }
2017-07-24 16:39:12 +00:00
className = "form-control"
2020-12-15 20:56:00 +00:00
placeholder = { this . state . namePlaceholder }
2017-02-10 16:29:59 +00:00
value = { this . state . name }
/ >
2017-02-09 18:06:44 +00:00
< / div >
< / div >
2017-07-24 16:39:12 +00:00
{ taskOptions }
2017-02-09 18:06:44 +00:00
< / div >
) ;
}
}
export default EditTaskForm ;