diff --git a/octoprint_customControl/static/css/customControls.css b/octoprint_customControl/static/css/customControls.css index 9573176..2a5fbd1 100644 --- a/octoprint_customControl/static/css/customControls.css +++ b/octoprint_customControl/static/css/customControls.css @@ -1 +1 @@ -#customControls .custom_section_horizontal{display:inline-block}#customControls .custom_section_vertical_section{min-width:15px;min-height:15px;margin:8px;padding:8px;border:1px dashed #000}#customControls .custom_section_horizontal_section{float:left}#customControls .accordion-toggle h1{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #E5E5E5;font-weight:400} \ No newline at end of file +#customControls .custom_section_horizontal .custom_control{display:inline-block}#customControls .custom_section_vertical .custom_control{display:block}#customControls .custom_section_vertical_section{min-width:15px;min-height:15px;border:1px dashed #000}#customControls .slider.slider-disabled .slider-track{cursor:default!important}#customControls input[disabled]{background:#fff!important;cursor:text!important}#customControls .custom_section h1{cursor:pointer;display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #E5E5E5;font-weight:400} \ No newline at end of file diff --git a/octoprint_customControl/static/js/customControl.js b/octoprint_customControl/static/js/customControl.js index f140d70..4e1410d 100644 --- a/octoprint_customControl/static/js/customControl.js +++ b/octoprint_customControl/static/js/customControl.js @@ -31,7 +31,7 @@ } }; - self.onStartup = function () { + self.onSettingsShown = function () { self.requestData(); }; @@ -73,13 +73,19 @@ var input = { name: ko.observable(list[i].name), parameter: ko.observable(list[i].parameter), - defaultValue: ko.observable(list[i].defaultValue) + defaultValue: ko.observable(list[i].defaultValue || "0") }; - if (list[i].hasOwnProperty("slider") && typeof list[i].slider == "object") - input.slider = ko.mapping.fromJS(list[i].slider); - else + if (list[i].hasOwnProperty("slider") && typeof list[i].slider == "object") { + input.slider = { + min: ko.observable(list[i].slider.min), + max: ko.observable(list[i].slider.max), + step: ko.observable(list[i].slider.step), + } + } + else { input.slider = false; + } inputs.push(input); } @@ -87,59 +93,50 @@ return inputs; } self._processControl = function (parent, control) { - control.id = ko.observable("settingsCustomControl_id" + self.staticID++); + if (control.processed) { + control.id("settingsCustomControl_id" + self.staticID++); + } + else { + control.id = ko.observable("settingsCustomControl_id" + self.staticID++); + } control.parent = parent; - if (control.hasOwnProperty("template") && control.hasOwnProperty("regex") && control.hasOwnProperty("defaultValue")) { + if (control.processed) { + if (control.hasOwnProperty("children")) { + control.children(self._processControls(control, control.children())); + } + + return control; + } + + if (control.hasOwnProperty("template") && control.hasOwnProperty("regex")) { control.template = ko.observable(control.template); control.regex = ko.observable(control.regex); - control.defaultValue = ko.observable(control.defaultValue); + control.defaultValue = ko.observable(control.defaultValue || ""); } if (control.hasOwnProperty("children")) { - if (control.processed) { - control.children(self._processControls(control, control.children())); - if (control.hasOwnProperty("layout") && !(control.layout() == "vertical" || control.layout() == "horizontal" || control.layout() == "horizontal_grid")) - control.layout("vertical"); + control.children = ko.observableArray(self._processControls(control, control.children)); + if (!control.hasOwnProperty("layout") || !(control.layout == "vertical" || control.layout == "horizontal" || control.layout == "horizontal_grid")) + control.layout = ko.observable("vertical"); + else + control.layout = ko.observable(control.layout); - if (control.hasOwnProperty("name") && control.name() != "") { - if (!control.hasOwnProperty("collapsable")) - control.collapsable = ko.observable(false); - } - } - else { - control.children = ko.observableArray(self._processControls(control, control.children)); - if (!control.hasOwnProperty("layout") || !(control.layout == "vertical" || control.layout == "horizontal" || control.layout == "horizontal_grid")) - control.layout = ko.observable("vertical"); - else - control.layout = ko.observable(control.layout); - - if (control.hasOwnProperty("name") && control.name != "") { - if (control.hasOwnProperty("collapsable")) - control.collapsable = ko.observable(control.collapsable); - else - control.collapsable = ko.observable(false); - } - } + if (control.hasOwnProperty("collapsed")) + control.collapsed = ko.observable(control.collapsed); + else + control.collapsed = ko.observable(false); } - if (!control.processed) { - if (control.hasOwnProperty("name")) - control.name = ko.observable(control.name); - else - control.name = ko.observable(""); - - control.width = ko.observable(control.hasOwnProperty("width") ? control.width : "2"); - control.offset = ko.observable(control.hasOwnProperty("offset") ? control.offset : ""); - } - if (control.hasOwnProperty("input")) { - if (control.processed) - control.input(self._processInput(control.input())); - else - control.input = ko.observableArray(self._processInput(control.input)); + control.input = ko.observableArray(self._processInput(control.input)); } + control.name = ko.observable(control.name || ""); + + control.width = ko.observable(control.hasOwnProperty("width") ? control.width : "2"); + control.offset = ko.observable(control.hasOwnProperty("offset") ? control.offset : ""); + var js; if (control.hasOwnProperty("javascript")) { js = control.javascript; @@ -169,7 +166,7 @@ self.displayMode = function (customControl) { if (customControl.hasOwnProperty("children")) { - return (customControl.hasOwnProperty("name") && customControl.name() != "") ? "settingsCustomControls_containerTemplate_accordion" : "settingsCustomControls_containerTemplate"; + return (customControl.hasOwnProperty("name") && customControl.name() != "") ? "settingsCustomControls_containerTemplate_collapsable" : "settingsCustomControls_containerTemplate_nameless"; } else { return "settingsCustomControls_controlTemplate"; } @@ -204,7 +201,7 @@ } self.createElement = function (invokedOn, contextParent, selectedMenu) { - if (invokedOn.attr('id') == "base") { + if (contextParent.attr('id') == "base") { self.customControlDialogViewModel.reset(); self.customControlDialogViewModel.show(function (ret) { @@ -266,23 +263,49 @@ if (element.hasOwnProperty("name")) { data.name = element.name(); - data.collapsable = element.hasOwnProperty("collapsable") ? element.collapsable() : false; + } + if (element.hasOwnProperty("template")) { + data.template = element.template(); + data.regex = element.regex(); + data.defaultValue = element.defaultValue() || ""; + + title = "Edit Output"; + type = "output"; } if (element.hasOwnProperty("layout")) { data.layout = element.layout(); + data.collapsed = element.collapsed(); + title = "Edit Container"; type = "container"; } if (element.hasOwnProperty("command")) { data.commands = element.command; + title = "Edit Command"; type = "command"; } if (element.hasOwnProperty("commands")) { - data.commands = element.commands; + var commands = ""; + _.each(element.commands, function (e, index, list) { + commands += e; + if (index < list.length) + commands += '\n'; + }); + data.commands = commands; + title = "Edit Command"; type = "command"; } + if (element.hasOwnProperty("script")) { + data.script = element.script; + + title = "Edit Script command"; + type = "script"; + } + if (element.hasOwnProperty("confirm")) { + data.confirm = element.confirm; + } if (element.hasOwnProperty("input")) { data.input = []; @@ -290,20 +313,13 @@ data.input[index] = ko.mapping.toJS(element); }); } - if (element.hasOwnProperty("template")) { - data.template = element.template(); - title = "Edit Output"; - type = "output"; - } - if (element.hasOwnProperty("regex")) - data.regex = element.regex(); - if (element.hasOwnProperty("defaultValue")) - data.defaultValue = element.defaultValue(); - if (element.hasOwnProperty("width")) + if (element.hasOwnProperty("width")) { data.width = element.width(); - if (element.hasOwnProperty("offset")) + } + if (element.hasOwnProperty("offset")) { data.offset = element.offset(); + } self.customControlDialogViewModel.reset(data); self.customControlDialogViewModel.title(gettext(title)); @@ -314,67 +330,65 @@ switch (self.customControlDialogViewModel.type()) { case "container": { - if (ret.hasOwnProperty("name")) - element.name(ret.name); - + element.name(ret.name); element.layout(ret.layout); - - if (ret.hasOwnProperty("collapsable") != "") { - if (element.hasOwnProperty("collapsable")) { - if (!ret.collapsable) { - var e = $('#toggle_' + element.id()); - if (e) - e.height("auto"); - - e = $('#' + element.id() + ' div.accordion-heading a h1'); - if (e) - e.removeClass('icon-caret-right'); - } - - element.collapsable(ret.collapsable); - } - else - element.collapsable = ko.observable(ret.collapsable); - } - else { - if (element.hasOwnProperty("collapsable")) { - element.collapsable(false); - delete element.collapsable; - } - - var e = $('#toggle_' + element.id()); - if (e) - e.height("auto"); - - e = $('#' + element.id() + ' div.accordion-heading a h1'); - if (e) - e.removeClass('icon-caret-right'); - } + element.collapsed(ret.collapsed); break; } case "command": { - if (ret.hasOwnProperty("name")) - element.name(ret.name); + element.name(ret.name); - delete element.command; - delete element.commands; - - if (ret.command != undefined) + if (ret.command != undefined) { element.command = ret.command; - if (ret.commands != undefined) + delete element.commands; + } + if (ret.commands != undefined) { element.commands = ret.commands; + delete element.command; + } + + if (ret.confirm != "") { + element.confirm = ret.confirm; + } if (ret.input != undefined) { element.input(self._processInput(ret.input)); } else delete element.input; + + // Command can also be a output + if (ret.hasOwnProperty("template")) { + if (element.hasOwnProperty("template")) + element.template(ret.template); + else + element.template = ko.observable(ret.template); + + if (element.hasOwnProperty("regex")) + element.regex(ret.regex); + else + element.regex = ko.observable(ret.regex); + + if (element.hasOwnProperty("defaultValue")) + element.defaultValue(ret.defaultValue); + else + element.defaultValue = ko.observable(ret.defaultValue); + } + else + { + if (element.hasOwnProperty("defaultValue")) + element.defaultValue(undefined); + + delete element.template; + delete element.regex; + delete element.defaultValue; + } break; } case "output": { element.template(ret.template); element.regex(ret.regex); - element.deflt(ret.deflt); + element.defaultValue(ret.defaultValue); break; } } @@ -392,33 +406,41 @@ self.controlContextMenu = function (invokedOn, contextParent, selectedMenu) { switch (selectedMenu.attr('cmd')) { - case "createContainer": { - self.customControlDialogViewModel.title(gettext("Create container")); - self.customControlDialogViewModel.type("container"); - - self.createElement(invokedOn, contextParent, selectedMenu); - break; - } - case "createCommand": { - self.customControlDialogViewModel.title(gettext("Create Command")); - self.customControlDialogViewModel.type("command"); - - self.createElement(invokedOn, contextParent, selectedMenu); - break; - } - case "createOutput": { - self.customControlDialogViewModel.title(gettext("Create Output")); - self.customControlDialogViewModel.type("output"); - - self.createElement(invokedOn, contextParent, selectedMenu); + case "editElement": { + self.editElement(invokedOn, contextParent, selectedMenu); break; } case "deleteElement": { self.deleteElement(invokedOn, contextParent, selectedMenu); break; } - case "editElement": { - self.editElement(invokedOn, contextParent, selectedMenu); + default: { + if (selectedMenu.attr('cmd').startsWith("create")) { + switch (selectedMenu.attr('cmd')) { + case "createContainer": { + self.customControlDialogViewModel.title(gettext("Create container")); + self.customControlDialogViewModel.type("container"); + break; + } + case "createCommand": { + self.customControlDialogViewModel.title(gettext("Create Command")); + self.customControlDialogViewModel.type("command"); + break; + } + case "createScript": { + self.customControlDialogViewModel.title(gettext("Create Script")); + self.customControlDialogViewModel.type("script"); + break; + } + case "createOutput": { + self.customControlDialogViewModel.title(gettext("Create Output")); + self.customControlDialogViewModel.type("output"); + break; + } + } + + self.createElement(invokedOn, contextParent, selectedMenu); + } break; } } diff --git a/octoprint_customControl/static/js/customControlDialog.js b/octoprint_customControl/static/js/customControlDialog.js index c5c7c2f..c81f65b 100644 --- a/octoprint_customControl/static/js/customControlDialog.js +++ b/octoprint_customControl/static/js/customControlDialog.js @@ -8,6 +8,8 @@ self.type = ko.observable("container"); self.useInputs = ko.observable(false); + self.useConfirm = ko.observable(false); + self.useOutput = ko.observable(false); self.useJavaScript = ko.observable(false); self.useEnabled = ko.observable(false); @@ -19,7 +21,8 @@ self.types = ko.observableArray([ { name: gettext("Container"), key: "container" }, { name: gettext("Command"), key: "command" }, - { name: gettext("Output"), key: "output" } + { name: gettext("Script"), key: "script" }, + { name: gettext("Output"), key: "output" }, ]); self.hasSlider = ko.computed(function () { @@ -56,8 +59,9 @@ self.reset = function (data) { var element = { name: undefined, - collapsable: true, + collapsed: false, commands: "", + confirm: "", defaultValue: "", script: "", javascript: "", @@ -72,20 +76,15 @@ parent: undefined }; - if (typeof data == "object") + if (typeof data == "object") { element = _.extend(element, data); - var mapped = ko.mapping.fromJS(element); - if (data.hasOwnProperty("input")) { - self.useInputs(true); - - //_.each(mapped.input(), function (e, index, list) { - // if (e.hasOwnProperty("slider") && !$.isFunction(e.slider)) - // e.slider = ko.observable(e.slider); - //}); + self.useConfirm(data.hasOwnProperty("confirm")); + self.useInputs(data.hasOwnProperty("input")); + self.useOutput(data.hasOwnProperty("template")); } - self.element(mapped); + self.element(ko.mapping.fromJS(element)); } self.show = function (f) { var dialog = $("#customControlDialog"); @@ -99,14 +98,9 @@ case "container": { el.name = obj.name; el.layout = obj.layout; - if (obj.name != "") - el.collapsable = obj.collapsable; + el.collapsed = obj.collapsed; el.children = []; - - el.width = obj.width; - el.offset = obj.offset; - break; } case "command": { @@ -114,10 +108,11 @@ if (obj.commands.indexOf('\n') == -1) el.command = obj.commands; else - el.commands = obj.commands; + el.commands = obj.commands.split('\n'); - el.width = obj.width; - el.offset = obj.offset; + if (self.useConfirm()) { + el.confirm = obj.confirm; + } if (self.useInputs()) { el.input = []; @@ -142,19 +137,59 @@ el.input.push(input); }); } + + if (self.useOutput()) { + el.template = obj.template; + el.regex = obj.regex; + el.defaultValue = obj.defaultValue; + } break; } + case "script": + { + el.name = obj.name; + el.script = obj.script; + + if (self.useConfirm()) { + el.confirm = obj.confirm; + } + + if (self.useInputs()) { + el.input = []; + _.each(obj.input, function (element, index, list) { + var input = { + name: element.name, + parameter: element.parameter, + defaultValue: element.defaultValue + }; + if (element.hasOwnProperty("slider") && element.slider != false) { + input["slider"] = { + }; + + if (element.slider.hasOwnProperty("min") && element.slider.min != "") + input.slider.min = element.slider.min; + if (element.slider.hasOwnProperty("max") && element.slider.max != "") + input.slider.max = element.slider.max; + if (element.slider.hasOwnProperty("step") && element.slider.step != "") + input.slider.step = element.slider.step; + } + + el.input.push(input); + }); + } + break; + } case "output": { el.template = obj.template; el.regex = obj.regex; el.defaultValue = obj.defaultValue; - - el.width = obj.width; - el.offset = obj.offset; - break; } } + + el.width = obj.width; + el.offset = obj.offset; + f(el); }); diff --git a/octoprint_customControl/static/less/customControls.less b/octoprint_customControl/static/less/customControls.less index b980cdb..8e255da 100644 --- a/octoprint_customControl/static/less/customControls.less +++ b/octoprint_customControl/static/less/customControls.less @@ -1,29 +1,39 @@ #customControls { - .custom_section_horizontal { + .custom_section_horizontal .custom_control { display:inline-block; } + .custom_section_vertical .custom_control { + display:block; + } .custom_section_vertical_section { min-width:15px; - min-height:15px; - - margin: 8px 8px; - padding: 8px 8px; + min-height:15px; border:1px dashed #000000; } - .custom_section_horizontal_section { - float:left; + + .slider.slider-disabled .slider-track { + cursor: default !important; } - .accordion-toggle h1 { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: 40px; - color: #333; - border: 0; - border-bottom: 1px solid #E5E5E5; - font-weight: normal; + + input[disabled] { + background: #fff !important; + cursor: text !important; + } + + .custom_section { + h1 { + cursor: pointer; + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: 40px; + color: #333; + border: 0; + border-bottom: 1px solid #E5E5E5; + font-weight: normal; + } } } \ No newline at end of file diff --git a/octoprint_customControl/templates/octoprint_customControl.jinja2 b/octoprint_customControl/templates/octoprint_customControl.jinja2 index b807670..87fadab 100644 --- a/octoprint_customControl/templates/octoprint_customControl.jinja2 +++ b/octoprint_customControl/templates/octoprint_customControl.jinja2 @@ -4,7 +4,7 @@