diff --git a/SingularityUI/app/collections/RequestHistoricalTasks.coffee b/SingularityUI/app/collections/RequestHistoricalTasks.coffee
index 044ea21255..c26103d3ed 100644
--- a/SingularityUI/app/collections/RequestHistoricalTasks.coffee
+++ b/SingularityUI/app/collections/RequestHistoricalTasks.coffee
@@ -4,7 +4,7 @@ PaginableCollection = require './PaginableCollection'
class HistoricalTasks extends PaginableCollection
model: class TaskHistoryItem extends Backbone.Model
- ignoreAttributes: ['id']
+ ignoreAttributes: ['id', 'canBeRunNow']
url: -> "#{ config.apiRoot }/history/request/#{ @requestId }/tasks"
diff --git a/SingularityUI/app/controllers/RequestDetail.coffee b/SingularityUI/app/controllers/RequestDetail.coffee
index d91896df47..4207566c70 100644
--- a/SingularityUI/app/controllers/RequestDetail.coffee
+++ b/SingularityUI/app/controllers/RequestDetail.coffee
@@ -56,7 +56,7 @@ class RequestDetailController extends Controller
@subviews.header = new SimpleSubview
model: @models.request
template: @templates.header
-
+
# would have used header subview for this info,
# but header expects a request model that
# no longer exists if a request is deleted
@@ -109,6 +109,10 @@ class RequestDetailController extends Controller
app.showView @view
+ addRequestInfo: =>
+ for t in @collections.taskHistory.models
+ t.attributes.canBeRunNow = @models.request.attributes.canBeRunNow
+
refresh: ->
requestFetch = @models.request.fetch()
@@ -124,7 +128,7 @@ class RequestDetailController extends Controller
@collections.activeTasks.fetch().error @ignore404
@collections.scheduledTasks.fetch().error @ignore404
@collections.scheduledTasks.fetch({reset: true}).error @ignore404
-
+
if @collections.requestHistory.currentPage is 1
requestHistoryFetch = @collections.requestHistory.fetch()
requestHistoryFetch.error => @ignore404
@@ -133,8 +137,11 @@ class RequestDetailController extends Controller
if @collections.requestHistory.length is 0
app.router.notFound()
- if @collections.taskHistory.currentPage is 1
- @collections.taskHistory.fetch().error @ignore404
+ requestFetch.done =>
+ if @collections.taskHistory.currentPage is 1
+ @collections.taskHistory.fetch
+ error: @ignore404
+ success: @addRequestInfo
if @collections.deployHistory.currentPage is 1
@collections.deployHistory.fetch().error @ignore404
diff --git a/SingularityUI/app/models/Request.coffee b/SingularityUI/app/models/Request.coffee
index 164ea19551..d5ea48e670 100644
--- a/SingularityUI/app/models/Request.coffee
+++ b/SingularityUI/app/models/Request.coffee
@@ -7,6 +7,7 @@ runTemplate = require '../templates/vex/requestRun'
removeTemplate = require '../templates/vex/requestRemove'
bounceTemplate = require '../templates/vex/requestBounce'
exitCooldownTemplate = require '../templates/vex/exitCooldown'
+TaskHistory = require '../models/TaskHistory'
class Request extends Model
@@ -74,7 +75,7 @@ class Request extends Model
options.processData = false
$.ajax options
-
+
scale: (confirmedOrPromptData) =>
$.ajax
url: "#{ @url() }/instances?user=#{ app.getUsername() }"
@@ -83,7 +84,7 @@ class Request extends Model
data: JSON.stringify
id: @get "id"
instances: confirmedOrPromptData
-
+
bounce: =>
$.ajax
url: "#{ @url() }/bounce?user=#{ app.getUsername() }"
@@ -114,7 +115,7 @@ class Request extends Model
promptScale: (callback) =>
vex.dialog.prompt
- message: scaleTemplate
+ message: scaleTemplate
id: @get "id"
buttons: [
$.extend _.clone(vex.dialog.buttons.YES), text: 'Scale'
@@ -134,8 +135,12 @@ class Request extends Model
promptRun: (callback) =>
vex.dialog.prompt
- message: ""
- input: runTemplate id: @get "id"
+ message: "
Run Task
"
+ input: runTemplate
+ id: @get "id"
+ prefix: @localStorageCommandLineInputKeyPrefix
+ commands: localStorage.getItem(@localStorageCommandLineInputKeyPrefix + @id)
+
buttons: [
$.extend _.clone(vex.dialog.buttons.YES), text: 'Run now'
vex.dialog.buttons.NO
@@ -143,7 +148,7 @@ class Request extends Model
beforeClose: =>
return if @data is false
-
+
fileName = @data.filename.trim()
commandLineInput = @data.commandLineInput.trim()
@@ -152,7 +157,16 @@ class Request extends Model
return false
else
- localStorage.setItem(@localStorageCommandLineInputKeyPrefix + @id, commandLineInput) if commandLineInput?
+ history = localStorage.getItem(@localStorageCommandLineInputKeyPrefix + @id)
+
+ if history?
+ last = history.split(",")[history.split(",").length - 1]
+ history += ","
+ else
+ history = ""
+
+ if commandLineInput != last
+ localStorage.setItem(@localStorageCommandLineInputKeyPrefix + @id, history + commandLineInput) if commandLineInput?
localStorage.setItem('taskRunRedirectFilename', fileName) if filename?
localStorage.setItem('taskRunAutoTail', @data.autoTail)
@data.id = @get 'id'
@@ -160,14 +174,64 @@ class Request extends Model
@run( @data.commandLineInput ).done callback( @data )
return true
- afterOpen: =>
+ afterOpen: =>
$('#filename').val localStorage.getItem('taskRunRedirectFilename')
- $('#commandLineInput').val localStorage.getItem(@localStorageCommandLineInputKeyPrefix + @id)
$('#autoTail').prop 'checked', (localStorage.getItem('taskRunAutoTail') is 'on')
+ cmdString = localStorage.getItem(@localStorageCommandLineInputKeyPrefix + @id)
+ commands = if cmdString then cmdString.split(",").reverse() else []
+ $('#commandLineInput').val commands[0]
+ localStorage.setItem(@localStorageCommandLineInputKeyPrefix + "historyIndex", 0);
+ localStorage.setItem(@localStorageCommandLineInputKeyPrefix + "historyLength", commands.length);
callback: (data) =>
@data = data
+
+ promptRerun: (taskId, callback) =>
+ task = new TaskHistory {taskId}
+ task.fetch()
+ .done =>
+ command = task.attributes.task.taskRequest.pendingTask.cmdLineArgsList
+ vex.dialog.prompt
+ message: "Rerun Task
"
+ input: runTemplate
+ id: @get "id"
+ command: command
+ buttons: [
+ $.extend _.clone(vex.dialog.buttons.YES), text: 'Run now'
+ vex.dialog.buttons.NO
+ ]
+
+ beforeClose: =>
+ return if @data is false
+
+ fileName = @data.filename.trim()
+ commandLineInput = @data.commandLineInput.trim()
+
+ if fileName.length is 0 and @data.autoTail is 'on'
+ $(window.noFilenameError).removeClass('hide')
+ return false
+
+ else
+ localStorage.setItem('taskRunRedirectFilename', fileName) if filename?
+ localStorage.setItem('taskRunAutoTail', @data.autoTail)
+ @data.id = @get 'id'
+
+ @run( @data.commandLineInput ).done callback( @data )
+ return true
+
+ afterOpen: =>
+ $('#filename').val localStorage.getItem('taskRunRedirectFilename')
+ if command is ""
+ history = localStorage.getItem(@localStorageCommandLineInputKeyPrefix + @id)
+ if !!history
+ history = history.split(",")
+ $('#commandLineInput').val history[history.length - 1]
+ $('#autoTail').prop 'checked', (localStorage.getItem('taskRunAutoTail') is 'on')
+
+ callback: (data) =>
+ @data = data
+
promptRemove: (callback) =>
vex.dialog.confirm
message: removeTemplate id: @get "id"
diff --git a/SingularityUI/app/templates/deployDetail/deployInfo.hbs b/SingularityUI/app/templates/deployDetail/deployInfo.hbs
index 48e63d9f15..401f970095 100644
--- a/SingularityUI/app/templates/deployDetail/deployInfo.hbs
+++ b/SingularityUI/app/templates/deployDetail/deployInfo.hbs
@@ -4,57 +4,81 @@
- -
-
-
InitiatedCopy
-
{{ timestampFromNow data.deployMarker.timestamp }}
-
-
- -
-
-
CompletedCopy
-
{{ timestampFromNow data.deployResult.timestamp }}
-
-
- -
-
-
-
{{ data.deploy.executorData.cmd }}
-
-
- -
-
-
ResourcesCopy
-
CPUs: {{ data.deploy.resources.cpus }} | Memory (MB): {{ data.deploy.resources.memoryMb }} | Ports: {{ data.deploy.resources.numPorts }}
-
-
-
- -
-
-
Number of TasksCopy
-
{{ data.deployStatistics.numTasks }}
-
-
- -
-
-
Last Task StateCopy
-
{{ humanizeText data.deployStatistics.lastTaskState }}
-
-
- -
-
-
Sequential RetriesCopy
-
{{ data.deployStatistics.numSequentialRetries }}
-
-
- -
-
-
Average Runtime MillisecondsCopy
-
{{ data.deployStatistics.averageRuntimeMillis }}
-
-
+ {{#if data.deployMarker.timestamp }}
+ -
+
+
InitiatedCopy
+
{{ timestampFromNow data.deployMarker.timestamp }}
+
+
+ {{/if}}
+ {{#if data.deployResult.timestamp}}
+ -
+
+
CompletedCopy
+
{{ timestampFromNow data.deployResult.timestamp }}
+
+
+ {{/if}}
+ {{#if data.deploy.executorData.cmd}}
+ -
+
+
+
{{ data.deploy.executorData.cmd }}
+
+
+ {{/if}}
+ {{#if data.deploy.resources.cpus}}
+ -
+
+
ResourcesCopy
+
CPUs: {{ data.deploy.resources.cpus }} | Memory (MB): {{ data.deploy.resources.memoryMb }} | Ports: {{ data.deploy.resources.numPorts }}
+
+
+
+ {{/if}}
+ {{#if data.deployStatistics.numTasks}}
+ -
+
+
Number of TasksCopy
+
{{ data.deployStatistics.numTasks }}
+
+
+ {{/if}}
+ {{#if data.deployStatistics.lastTaskState}}
+ -
+
+
Last Task StateCopy
+
{{ humanizeText data.deployStatistics.lastTaskState }}
+
+
+ {{/if}}
+ {{#if data.deployStatistics.numSequentialRetries}}
+ -
+
+
Sequential RetriesCopy
+
{{ data.deployStatistics.numSequentialRetries }}
+
+
+ {{/if}}
+ {{#if data.deployStatistics.averageRuntimeMillis}}
+ -
+
+
Average Runtime MillisecondsCopy
+
{{ data.deployStatistics.averageRuntimeMillis }}
+
+
+ {{/if}}
+ {{#if data.deploy.executorData.extraCmdLineArgs}}
+ -
+
+
Extra Command Line ArgumentsCopy
+
{{ data.deploy.executorData.extraCmdLineArgs }}
+
+
+ {{/if}}
diff --git a/SingularityUI/app/templates/requestDetail/requestHistoricalTasks.hbs b/SingularityUI/app/templates/requestDetail/requestHistoricalTasks.hbs
index 46cecba758..af47aebbfa 100644
--- a/SingularityUI/app/templates/requestDetail/requestHistoricalTasks.hbs
+++ b/SingularityUI/app/templates/requestDetail/requestHistoricalTasks.hbs
@@ -27,6 +27,9 @@
{{! Actions }}
|
+
+ {{! Actions }}
+ |
@@ -53,9 +56,18 @@
- ...
+ ···
|
+ {{#if canBeRunNow}}
+
+
+ ↺
+
+ |
+ {{else}}
+ |
+ {{/if}}
{ }
diff --git a/SingularityUI/app/templates/taskDetail/taskInfo.hbs b/SingularityUI/app/templates/taskDetail/taskInfo.hbs
index e9a4480d48..923ce7d9dc 100644
--- a/SingularityUI/app/templates/taskDetail/taskInfo.hbs
+++ b/SingularityUI/app/templates/taskDetail/taskInfo.hbs
@@ -44,5 +44,21 @@
{{/if}}
+ {{#if data.task.taskRequest.deploy.executorData.extraCmdLineArgs}}
+
+
+ Extra Cmd Line Arguments (for Deploy)
+ {{ data.task.taskRequest.deploy.executorData.extraCmdLineArgs }}
+
+
+ {{/if}}
+ {{#if data.task.taskRequest.pendingTask.cmdLineArgsList }}
+
+
+ Extra Cmd Line Arguments (for Task)
+ {{ data.task.taskRequest.pendingTask.cmdLineArgsList }}
+
+
+ {{/if}}
diff --git a/SingularityUI/app/templates/vex/requestRun.hbs b/SingularityUI/app/templates/vex/requestRun.hbs
index e582a2c563..6d221841c9 100644
--- a/SingularityUI/app/templates/vex/requestRun.hbs
+++ b/SingularityUI/app/templates/vex/requestRun.hbs
@@ -3,7 +3,7 @@
Additional command line input: (optional)
-
+
diff --git a/SingularityUI/app/views/request.coffee b/SingularityUI/app/views/request.coffee
index 85578a295e..2b1b161814 100644
--- a/SingularityUI/app/views/request.coffee
+++ b/SingularityUI/app/views/request.coffee
@@ -16,6 +16,7 @@ class RequestView extends View
'click [data-action="remove"]': 'removeRequest'
'click [data-action="run-request-now"]': 'runRequest'
+ 'click [data-action="rerun-task"]': 'rerunTask'
'click [data-action="pause"]': 'pauseRequest'
'click [data-action="scale"]': 'scaleRequest'
'click [data-action="unpause"]': 'unpauseRequest'
@@ -76,6 +77,23 @@ class RequestView extends View
@trigger 'refreshrequest'
setTimeout ( => @trigger 'refreshrequest'), 2500
+ rerunTask: (e) =>
+ taskId = e.target.getAttribute 'data-taskId'
+ @model.promptRerun taskId, (data) =>
+ # If user wants to redirect to a file after the task starts
+ if data.autoTail is 'on'
+ autoTailer = new AutoTailer({
+ requestId: @requestId
+ autoTailFilename: data.filename
+ autoTailTimestamp: +new Date()
+ })
+
+ autoTailer.startAutoTailPolling()
+
+ else
+ @trigger 'refreshrequest'
+ setTimeout ( => @trigger 'refreshrequest'), 2500
+
scaleRequest: (e) =>
@model.promptScale =>
@trigger 'refreshrequest'
|