":
+ type = "float";
+ value = values['default'] !== undefined ?
+ parseFloat(values['default']) :
+ 0.0;
+ break;
+ default:
+ type = "string";
+ value = values['default'] !== undefined ?
+ values['default'].trim() :
+ "";
+ }
+
+ if (values['default'] === "True"){
+ type = "bool";
+ value = true;
+ }else if (values['default'] === "False"){
+ type = "bool";
+ value = false;
+ }
+
+ help = help.replace(/\%\(default\)s/g, value);
+
+ odmOptions.push({
+ name, type, value, domain, help
+ });
+ }
+ done(null, odmOptions);
+ }
+ });
+ },
+
+ // Checks that the options (as received from the rest endpoint)
+ // Are valid and within proper ranges.
+ // The result of filtering is passed back via callback
+ // @param options[]
+ filterOptions: function(options, done){
+ assert(odmOptions !== null, "odmOptions is not set. Have you initialized odmOptions properly?");
+
+ try{
+ if (typeof options === "string") options = JSON.parse(options);
+
+ let result = [];
+ let errors = [];
+ function addError(opt, descr){
+ errors.push({
+ name: opt.name,
+ error: descr
+ });
+ }
+
+ let typeConversion = {
+ 'float': Number.parseFloat,
+ 'int': Number.parseInt,
+ 'bool': function(value){
+ if (value === 'true') return true;
+ else if (value === 'false') return false;
+ else if (typeof value === 'boolean') return value;
+ else throw new Error(`Cannot convert ${value} to boolean`);
+ }
+ };
+
+ let domainChecks = [
+ {
+ regex: /^(positive |negative )?(integer|float)$/,
+ validate: function(matches, value){
+ if (matches[1] === 'positive ') return value >= 0;
+ else if (matches[1] === 'negative ') return value <= 0;
+
+ else if (matches[2] === 'integer') return Number.isInteger(value);
+ else if (matches[2] === 'float') return Number.isFinite(value);
+ }
+ },
+ {
+ regex: /^percent$/,
+ validate: function(matches, value){
+ return value >= 0 && value <= 100;
+ }
+ },
+ {
+ regex: /^(float): ([\-\+\.\d]+) <= x <= ([\-\+\.\d]+)$/,
+ validate: function(matches, value){
+ let [str, type, lower, upper] = matches;
+ lower = parseFloat(lower);
+ upper = parseFloat(upper);
+ return value >= lower && value <= upper;
+ }
+ },
+ {
+ regex: /^(float) (>=|>|<|<=) ([\-\+\.\d]+)$/,
+ validate: function(matches, value){
+ let [str, type, oper, bound] = matches;
+ bound = parseFloat(bound);
+ switch(oper){
+ case '>=':
+ return value >= bound;
+ case '>':
+ return value > bound;
+ case '<=':
+ return value <= bound;
+ case '<':
+ return value < bound;
+ default:
+ return false;
+ }
+ }
+ }
+ ];
+
+ function checkDomain(domain, value){
+ let dc, matches;
+
+ if (dc = domainChecks.find(dc => matches = domain.match(dc.regex))){
+ if (!dc.validate(matches, value)) throw new Error(`Invalid value ${value} (out of range)`);
+ }else{
+ throw new Error(`Domain value cannot be handled: '${domain}' : '${value}'`);
+ }
+ }
+
+ // Scan through all possible options
+ for (let odmOption of odmOptions){
+ // Was this option selected by the user?
+ let opt;
+ if (opt = options.find(o => o.name === odmOption.name)){
+ try{
+ // Convert to proper data type
+ let value = typeConversion[odmOption.type](opt.value);
+
+ // Domain check
+ if (odmOption.domain){
+ checkDomain(odmOption.domain, value);
+ }
+
+ result.push({
+ name: odmOption.name,
+ value: value
+ });
+ }catch(e){
+ addError(opt, e.message);
+ }
+ }
+ }
+
+ if (errors.length > 0) done(new Error(JSON.stringify(errors)));
+ else done(null, result);
+ }catch(e){
+ done(e);
+ }
+ }
+};
\ No newline at end of file
diff --git a/libs/odmRunner.js b/libs/odmRunner.js
index 6cd41f7..7299c7f 100644
--- a/libs/odmRunner.js
+++ b/libs/odmRunner.js
@@ -30,19 +30,36 @@ module.exports = {
"--project-path", options.projectPath
], {cwd: ODM_PATH});
+ childProcess
+ .on('exit', (code, signal) => done(null, code, signal))
+ .on('error', done);
+
+ childProcess.stdout.on('data', chunk => outputReceived(chunk.toString()));
+ childProcess.stderr.on('data', chunk => outputReceived(chunk.toString()));
+
+ return childProcess;
+ },
+
+ getJsonOptions: function(done){
+ // Launch
+ let childProcess = spawn("python", [`${__dirname}/../helpers/odmOptionsToJson.py`,
+ "--project-path", ODM_PATH]);
+ let output = [];
+
childProcess
.on('exit', (code, signal) => {
- done(null, code, signal);
+ try{
+ let json = JSON.parse(output.join(""));
+ done(null, json);
+ }catch(err){
+ done(err);
+ }
})
.on('error', done);
- childProcess.stdout.on('data', chunk => {
- outputReceived(chunk.toString());
- });
- childProcess.stderr.on('data', chunk => {
- outputReceived(chunk.toString());
- });
+ let processOutput = chunk => output.push(chunk.toString());
- return childProcess;
+ childProcess.stdout.on('data', processOutput);
+ childProcess.stderr.on('data', processOutput);
}
};
diff --git a/public/css/main.css b/public/css/main.css
index 8b5d502..0da13d7 100644
--- a/public/css/main.css
+++ b/public/css/main.css
@@ -55,4 +55,12 @@
height: 200px;
font-family: monospace;
font-size: 90%;
+}
+
+.selectric-items li{
+ background: #fff;
+}
+
+#options .checkbox{
+ margin-right: 143px;
}
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index 6b970e5..21a2565 100644
--- a/public/index.html
+++ b/public/index.html
@@ -15,7 +15,6 @@
}
-
@@ -41,20 +40,42 @@
-
+
Current Tasks ()
No running tasks.
@@ -113,6 +134,7 @@
+