Commit 66054ae1 authored by Jerome Mariette's avatar Jerome Mariette
Browse files

handle multiple parameters from gui

parent 851c30e2
......@@ -29,6 +29,7 @@ try:
except ImportError:
sys.exc_clear()
import jflow
from jflow.workflows_manager import WorkflowsManager
from jflow.config_reader import JFlowConfigReader
from jflow.workflow import Workflow
......@@ -39,6 +40,8 @@ from cctools.util import time_format
class JFlowServer (object):
MULTIPLE_TYPE_SPLITER = "._."
def __init__(self):
# Create a workflow manager to get access to our workflows
self.wfmanager = WorkflowsManager()
......@@ -113,15 +116,34 @@ class JFlowServer (object):
for instance in wf_instances:
parameters, parameters_per_groups, groups = [], {}, ["default"]
for param in instance.parameters:
# if it's a multiple action change the action by the name
if param.action == jflow.parameter.MiltipleAction:
action = "MiltipleAction"
elif param.action == jflow.parameter.MiltipleAppendAction:
action = "MiltipleAppendAction"
else:
action = param.action
hash_param = {"help": param.help,
"required": param.required,
"default": param.default,
"choices": param.choices,
"action": param.action,
"action": action,
"type": param.get_type(),
"name": param.name,
"display_name": param.display_name,
"group": param.group}
# if it's a multiple type add sub parameters
if type(param.type) == jflow.parameter.MultipleParameters:
hash_param["sub_parameters"] = []
for sub_param in param.sub_parameters:
hash_param["sub_parameters"].append({"help": sub_param.help,
"required": sub_param.required,
"default": sub_param.default,
"choices": sub_param.choices,
"action": sub_param.action,
"type": sub_param.get_type(),
"name": param.name + JFlowServer.MULTIPLE_TYPE_SPLITER + sub_param.flag,
"display_name": sub_param.display_name})
parameters.append(hash_param)
if parameters_per_groups.has_key(param.group):
parameters_per_groups[param.group].append(hash_param)
......@@ -138,7 +160,17 @@ class JFlowServer (object):
@cherrypy.expose
@jsonify
def run_workflow(self, **kwargs):
workflow = self.wfmanager.run_workflow(kwargs["workflow_class"], kwargs)
kwargs_modified = {}
for key in kwargs.keys():
parts = key.split(JFlowServer.MULTIPLE_TYPE_SPLITER)
if len(parts) == 1:
kwargs_modified[key] = kwargs[key]
elif len(parts) == 2:
if kwargs_modified.has_key(parts[0]):
kwargs_modified[parts[0]].append((parts[1], kwargs[key]))
else:
kwargs_modified[parts[0]] = [(parts[1], kwargs[key])]
workflow = self.wfmanager.run_workflow(kwargs_modified["workflow_class"], kwargs_modified)
return self.jsonify_workflow_status(workflow, True)
@cherrypy.expose
......
......@@ -295,7 +295,9 @@ class Workflow(threading.Thread):
# find the value
value = None
for values in arg:
if values[0] == sub_param.flag: value = values[1]
if values[0] == sub_param.flag:
try: value = values[1].encode('ascii','ignore')
except: value = values[1]
if value == None: value = sub_param.default
sub_hash[sub_param.name] = value
extended_args[param.name].append(sub_hash)
......@@ -321,7 +323,9 @@ class Workflow(threading.Thread):
# find the value
value = None
for values in args[param.name]:
if values[0] == sub_param.flag: value = values[1]
if values[0] == sub_param.flag:
try: value = values[1].encode('ascii','ignore')
except: value = values[1]
if value == None: value = sub_param.default
extended_args[param.name][sub_param.name] = value
else:
......
......@@ -29,11 +29,23 @@
}
$element.addClass(errorClass).removeClass(validClass);
// add the bootstrap error class
$element.parents("div.control-group").addClass("error");
if ($element.parent().parent("blockquote").find("div").length > 0) {
// if it's a multiple type
$element.parent().parent("blockquote").parent("div.controls").parent("div.control-group").addClass(errorClass);
//highlight append button as well$
$element.parent().parent("blockquote").find("div.input-append").each(function() {
$(this).find(".btn").addClass("btn-danger");
$(this).find(".icon-calendar").addClass("icon-white");
});
} else {
$element.parents("div.control-group").addClass(errorClass);
}
// if it's a calendar
if ($element.parent("div.input-append").find(".btn").length > 0) {
$element.parent("div.input-append").find(".btn").addClass("btn-danger");
$element.parent("div.input-append").find(".icon-calendar").addClass("icon-white");
}
},
unhighlight: function (element, errorClass, validClass) {
var $element;
......@@ -44,24 +56,37 @@
}
$element.removeClass(errorClass).addClass(validClass);
// remove the bootstrap error class
if ($element.parents("div.control-group").find("." + errorClass).length == 0) {
if ($element.parent().parent("blockquote").find("div").length > 0) {
// if it's a multiple type, check if there is no other error
if ($element.parent().parent("blockquote").find("input." + errorClass).length == 0) {
$element.parents("div.control-group").removeClass(errorClass).addClass(validClass);
$element.parent().parent("blockquote").find("div.input-append").each(function() {
$(this).find(".btn").removeClass("btn-danger");
$(this).find(".icon-calendar").removeClass("icon-white");
});
}
} else if ($element.parents("div.control-group").find("input." + errorClass).length == 0) {
// Only remove the class if there are no other errors
$element.parents("div.control-group").removeClass(errorClass).addClass(validClass);
}
if ($element.parent("div.input-append").find(".btn").length > 0) {
$element.parent("div.input-append").find(".btn").removeClass("btn-danger");
$element.parent("div.input-append").find(".icon-calendar").removeClass("icon-white");
}
$element.parents(errorClass).removeClass(errorClass);
if ($element.parent("div.input-append").find(".btn").length > 0) {
$element.parent("div.input-append").find(".btn").removeClass("btn-danger");
$element.parent("div.input-append").find(".icon-calendar").removeClass("icon-white");
}
}
},
errorPlacement: function(error, element) {
error.addClass("help-block");
if (element.parent("div.input-append").length > 0) {
error.insertAfter(element.parent("div.input-append"));
} else if (element.parent("div.input-prepend").length > 0) {
error.insertAfter(element.parent("div.input-prepend"));
} else {
error.insertAfter(element);
}
},
errorElement: "span",
errorClass: "help-block error"
errorClass: "error"
});
jQuery.validator.addMethod("exlude", function(value, element, options) {
......@@ -167,35 +192,17 @@ jQuery.validator.addMethod("exlude", function(value, element, options) {
$this.$element.trigger('loaded', $this.workflow);
$this.$element.html("");
$.tmpl($this.options.template, {workflow: $this.workflow, display_run_button: $this.options.displayRunButton,
display_reset_button: $this.options.displayResetButton, parameters: $this.options.parameters}).appendTo($this.$element);
display_reset_button: $this.options.displayResetButton, parameters: $this.options.parameters,
getParameterDisplay:$this._getParameterDisplay, parameterTemplate: $this.options.parameterTemplate}).appendTo($this.$element);
$('.date').datepicker().on('changeDate', function(ev){ $('.date').datepicker('hide');} );
for (var i in $this.workflow.parameters) {
if ($this.workflow.parameters[i].type == "int") {
rules[$this.workflow.parameters[i].name] = {
required: $this.workflow.parameters[i].required,
number: true
}
} else if ($this.workflow.parameters[i].type == "date") {
rules[$this.workflow.parameters[i].name] = {
required: $this.workflow.parameters[i].required,
date: true
}
} else if ($this.workflow.parameters[i].type == "str") {
rules[$this.workflow.parameters[i].name] = {
required: $this.workflow.parameters[i].required
}
// if it is not a known type, check from the custom ones, using the validate_field address
// if it's a multiple parameter add its sub parameters as rules
if ($this.workflow.parameters[i].type == "MultipleParameters") {
for (var j in $this.workflow.parameters[i].sub_parameters) {
rules[$this.workflow.parameters[i].sub_parameters[j].name] = $this._getParameterRule($this.workflow.parameters[i].sub_parameters[j], $this.options.serverURL);
}
} else {
rules[$this.workflow.parameters[i].name] = {
required: $this.workflow.parameters[i].required,
remote: {
url: $this.options.serverURL + '/validate_field?callback=?',
type: "post",
data: {
type: $this.workflow.parameters[i].type
}
}
}
rules[$this.workflow.parameters[i].name] = $this._getParameterRule($this.workflow.parameters[i], $this.options.serverURL);
}
if ($this.workflow.parameters[i].group.indexOf("exclude-") != -1) {
rules[$this.workflow.parameters[i].name]["exlude"] = "."+$this.workflow.parameters[i].group;
......@@ -212,6 +219,40 @@ jQuery.validator.addMethod("exlude", function(value, element, options) {
});
}
WFForm.prototype._getParameterRule = function(param, server_url) {
if (param.type == "int") {
return {
required: param.required,
number: true
}
} else if (param.type == "date") {
return {
required: param.required,
date: true
}
} else if (param.type == "str") {
return {
required: param.required
}
// if it is not a known type, check from the custom ones, using the validate_field address
} else {
return {
required: param.required,
remote: {
url: server_url + '/validate_field?callback=?',
type: "post",
data: {
type: param.type
}
}
}
}
}
WFForm.prototype._getParameterDisplay = function(param, template, input_size="input-xlarge", check_title="") {
return $.tmpl(template, {param:param, input_size:input_size, check_title:check_title}).html();
}
/* WFForm PLUGIN DEFINITION
* ========================== */
......@@ -233,7 +274,37 @@ jQuery.validator.addMethod("exlude", function(value, element, options) {
}
$.fn.wfform.defaults = {
serverURL: "http://localhost:8080",
serverURL: "http://localhost:8080",
parameterTemplate: ['<div> {{if param.choices}}',
// if it's a multiple choice parameter, add a select
' <select id="${param.name}" name="${param.name}" class="${param.group} ${input_size}">',
' {{each(j, choice) param.choices}}',
' {{if choice == param.default}}',
' <option selected>${choice}</option>',
' {{else}}',
' <option>${choice}</option>',
' {{/if}}',
' {{/each}}',
' </select>',
// if param is a date
'{{else param.type == "date"}}',
' <div class="input-append date" data-date="${param.default}" data-date-format="dd/mm/yyyy">',
' <input id="${param.name}" name="${param.name}" class="${param.group} ${input_size} span2" type="text" value="${param.default}">',
' <button class="btn" type="button"><i class="icon-calendar"></i></button>',
' </div>',
// if param is a boolean
'{{else param.type == "bool"}}',
' <label class="checkbox">',
' {{if param.default == true}}',
' <input id="${param.name}" name="${param.name}" class="${param.group}" value="${param.default}" type="checkbox" checked> ${check_title}',
' {{else}}',
' <input id="${param.name}" name="${param.name}" class="${param.group}" value="${param.default}" type="checkbox"> ${check_title}',
' {{/if}}',
'</label>',
// else a simple text input
'{{else}}',
' <input id="${param.name}" name="${param.name}" value="${param.default}" class="${param.group} ${input_size}" type="text">',
'{{/if}}</div>'].join('\n'),
template: ['<form id="workflow_form" class="form-horizontal">',
'<fieldset>',
' {{each(gindex, group) workflow.groups}}',
......@@ -246,38 +317,26 @@ jQuery.validator.addMethod("exlude", function(value, element, options) {
' {{/if}}',
' <label class="control-label">${param.display_name}</label>',
' <div class="controls">',
// if it's a multiple choice parameter, add a select
' {{if param.choices}}',
' <select id="${param.name}" name="${param.name}" class="${param.group} input-xlarge">',
' {{each(j, choice) param.choices}}',
' {{if choice == param.default}}',
' <option selected>${choice}</option>',
// if it's a multiple type
' {{if param.type == "MultipleParameters"}}',
' <blockquote>',
' {{each(spindex, sub_param) param.sub_parameters}}',
' {{if sub_param.type == "bool"}}',
' {{html getParameterDisplay(sub_param, parameterTemplate, "input-medium", sub_param.display_name)}}',
' {{else}}',
' <option>${choice}</option>',
' <div class="input-prepend">',
' <span class="add-on">${sub_param.display_name}</span>',
' {{html getParameterDisplay(sub_param, parameterTemplate, "input-medium")}}',
' </div>',
' {{/if}}',
' <span class="help-block">${sub_param.help}</span> <br />',
' {{/each}}',
' </select>',
// if param is a date
' {{else param.type == "date"}}',
' <div class="input-append date" data-date="${param.default}" data-date-format="dd/mm/yyyy">',
' <input id="${param.name}" name="${param.name}" class="${param.group} input-xlarge span2" type="text" value="${param.default}">',
' <button class="btn" type="button"><i class="icon-calendar"></i></button>',
' </div>',
// if param is a boolean
' {{else param.type == "bool"}}',
' <label class="checkbox">',
' {{if param.default == true}}',
' <input id="${param.name}" name="${param.name}" class="${param.group}" value="${param.default}" type="checkbox" checked>',
' {{else}}',
' <input id="${param.name}" name="${param.name}" class="${param.group}" value="${param.default}" type="checkbox">',
' {{/if}}',
' </label>',
// else a simple text input
' </blockquote>',
' {{else}}',
' <input id="${param.name}" name="${param.name}" value="${param.default}" class="${param.group} input-xlarge" type="text">',
' {{html getParameterDisplay(param, parameterTemplate)}}',
' <span class="help-block">${param.help}</span>',
' {{/if}}',
' <span class="help-block">${param.help}</span>',
' </div>',
' </div>',
' </div>',
' {{else}}',
// if the param is already settled, hide it
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment