UNPKG

node-red-contrib-tekosbot

Version:

Tekos bot based on matrix

644 lines (589 loc) 22.2 kB
<script type="text/x-red" data-template-name="form"> <style> .switch { position: relative; display: inline-block; width: 30px; height: 18px; } .switch input {display:none;} .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; -webkit-transition: .4s; transition: .4s; } .slider:before { position: absolute; content: ""; height: 15px; width: 15px; left: 2px; bottom: 2px; background-color: white; -webkit-transition: .4s; transition: .4s; } input:checked + .slider { background-color: #910000; } input:focus + .slider { box-shadow: 0 0 1px #2196F3; } input:checked + .slider:before { -webkit-transform: translateX(11px); -ms-transform: translateX(11px); transform: translateX(11px); } /* Rounded sliders */ .slider.round { border-radius: 34px; } .slider.round:before { border-radius: 50%; } </style> <div class="form-row"> <label for="node-input-name"><i class="icon-tag"></i>Name</label> <input type="text" id="node-input-name" placeholder="Name" /> </div> <div class="form-row"> <label for="node-input-title"><i class="icon-tag"></i>Title</label> <input type="text" id="node-input-title" placeholder="Title" /> </div> <div class="form-row"> <label for="node-input-posturl"><i class="icon-tag"></i>Post Url</label> <input type="text" id="node-input-posturl" placeholder="Post url" /> </div> <div class="form-row"> <label for="node-input-subtitle"><i class="icon-tag"></i>Subtitle</label> <input type="text" id="node-input-subtitle" placeholder="Subtitle" /> </div> <div class="form-row"> <label for="node-input-formId"><i class="icon-tag"></i>FormID</label> <input type="text" id="node-input-formId" placeholder="" /> </div> <div class="form-row"> <label for="node-input-action"><i class="icon-tag"></i>Action</label> <input type="text" id="node-input-action" placeholder="Envoyer" /> </div> <div class="form-row"> <label for="node-input-cancel"><i class="icon-tag"></i>Cancel</label> <input type="text" id="node-input-cancel" placeholder="Cancel Text" /> </div> <div class="form-row node-input-option-container-row" style="margin-bottom:0px; width:100%; min-width:520px"> <label style="vertical-align:top;"><i class="fa fa-list-alt"></i> Form elements</label> <div style="width:78%; border:1px solid #ccc; border-radius:5px; box-sizing:border-box;"> <div id="node-input-option-container-div" style=" height: 257px; padding: 5px; overflow-y:scroll;"> <ol id="node-input-option-container" style=" list-style-type:none; margin: 0;"></ol> </div> </div> </div> <div class="form-row"> <a href="#" class="editor-button editor-button-small" id="node-input-add-option" style="margin-top: 4px; margin-left: 103px;"><i class="fa fa-plus"></i> <span>add element</span></a> </div> </script> <script type="text/x-red" data-help-name="form"> <h3>Node Form</h3> <h6>Definitions</h6> <p>Displays form input into tekos bot messaging, and set up a new entry point to receive the submitted data</p> <h6>Pre conditions</h6> <p>To display the form into tekos bot, you need to follow the following steps</p> <ul> <li>1. Setting up tekos bot</li> <li>2. Link <b class="underline">tekos in</b> node before the form node</li> <li>3. Link <b class="underline">tekos out</b> node after the form node</li> <li>4. <i>Optional</i>: in tekos out config insert in the next listener input <b>chat/null</b></li> , this will make the postback of the submit button not related to your official tekos in, otherwise, if you like to detect if the user clicked on “cancel” you can add new tekos in listener (exp: chat/form/{id}/response) and insert the same listener path in your tekos out , see more about tekos out next listerner</li> <li>5. Insert form title and subtitle (double click on the node)</li> <li>6. Insert form ID , to identify your form</li> <li>7. Insert Action, it will be used to display the form action button name</li> <li>8. Insert form inputs into the details. For the input type “List” you can insert the value:label like the placeholder describes</li> </ul> <h6>Post conditions</h6> <p>In order to get the submitted data</p> <ul> <li>1. Insert new tekos in node with the <b>event: chat/FormId/{yourFormID}</b></li> <li>2. Insert a debug node to see your data</li> <li>3. Open <b class="underline">tekos bot <b class="underline"></li> <li>4. Insert your data and click on the action button (exp, submit)</li> <li>5. See your data in the debug section in the flow</li> </ul> </script> <script type="text/javascript"> $.ajax({ url: "/appParams", async: true, method: "GET", success: res => {} }); $("#sidebar").on("DOMNodeInserted", e => { $.ajax({ url: "/appParams", async: true, method: "GET", success: res => { if ($("#urlFlow").text() && $("#urlFlow").text() == "/app?text=form") { $("#urlFlow").text( `https://box.tekos.co/@${res.app_uri}.${res.app_name}/app?text=form` ); } } }); }); RED.nodes.registerType("form", { category: "Dialogue", color: "#f7fdb1", defaults: { name: { value: "" }, title: { value: "" }, subtitle: { value: "" }, formId: { value: "", required: true }, posturl: { value: "", required: true }, action: { value: "" }, cancel: { value: "Cancel" }, options: { value: [{ value: "", label: "", maxLength: "",required: true }], validate: function(value) { if (value.length) { for (var i = 0; i < value.length; i++) { if (!value[i].value) { return false; } } } else { return false; } return true; }, required: true }, formValue: { value: {} }, payload: { value: "" }, topic: { value: "" } }, inputs: 1, outputs: 1, paletteLabel: "Form", icon: "forms.png", label: function label() { return this.name || "Form"; }, labelStyle: function() { return this.name ? "node_label_italic" : ""; }, oneditprepare: function oneditprepare() { var node = this; $("#node-input-add-option").click(function() { generateOption( $("#node-input-option-container").children().length + 1, {} ); $("#node-input-option-container-div").scrollTop( $("#node-input-option-container-div").get(0).scrollHeight ); }); for (var i = 0; i < this.options.length; i++) { var option = this.options[i]; recoverOption(i + 1, option); } $("#node-input-option-container").sortable({ axis: "y", handle: ".node-input-option-handle", cursor: "move" }); function generateOption(i, option) { var container = $("<li/>", { style: "background: #fff; margin:0; padding:8px 0px 0px; border-bottom: 1px solid #ccc;" }); var row = $("<div/>").appendTo(container); var row2 = $("<div/>", { style: "padding-top:5px; padding-left:175px;" }).appendTo(container); var row3 = $("<div/>", { style: "padding-top:5px; padding-left:120px;" }).appendTo(container); $( '<i style="color:#eee; cursor:move; margin-left:3px;" class="node-input-option-handle fa fa-bars"></i>' ).appendTo(row); var finalspan = $("<div/>", { style: "float: right; margin: 12px" }).appendTo(row); var deleteButton = $("<a/>", { href: "#", class: "editor-button editor-button-small", style: "left:35%; position:relative; width:30px" }).appendTo(finalspan); $("<i/>", { class: "fa fa-remove" }).appendTo(deleteButton); var typeField = $("<select/>", { class: "node-input-option-type", type: "text", style: "width:200px; margin-top:5px;margin-left: 5px; text-align: center;" }) .attr("placeholder", "Select field type") .appendTo(row); typeField.append($('<option value="">Select Field type</option>')); var arr = [ { val: "text", text: "Text" }, { val: "textarea", text: "textarea" }, { val: "tel", text: "tel" }, { val: "url", text: "url" }, { val: "number", text: "Number" }, { val: "email", text: "E-mail" }, { val: "password", text: "Password" }, /* { val: "checkbox", text: "Checkbox" }, { val: "switch", text: "Switch" }, //, */ { val: "list", text: "List" } //, //{val : "file", text: 'File'}//, /* { val: "datetime", text: "Date & Time" }, { val: "date", text: "Date" }, { val: "hidden", text: "Hidden" } */ ]; $(arr).each(function() { var isSelected = false; if (option.type == this.val) { isSelected = true; } typeField.append( $("<option>") .attr("value", this.val) .text(this.text) .prop("selected", isSelected) ); }); typeField .change(function() { labelField.val(""); listField.val(""); valueField.val(""); maxLengthField.val(""); required.attr("checked", false); if ($(this).val() === "list") { labelField.show(); valueField.show(); labelForRequried.show(); requiredContainer.show(); maxLengthField.hide(); listField.show(); } else if ($(this).val() === "") { labelField.hide(); valueField.hide(); listField.hide(); maxLengthField.hide(); requiredContainer.hide(); } else if ($(this).val() === "text") { labelField.show(); valueField.show(); labelForRequried.show(); requiredContainer.show(); listField.hide(); maxLengthField.show(); } else { labelField.show(); valueField.show(); labelForRequried.show(); requiredContainer.show(); listField.hide(); maxLengthField.hide(); } }) .appendTo(row); var labelField = $("<input/>", { class: "node-input-option-label", type: "text", style: "margin-left:22px;margin-top:5px; width:85%;", placeholder: "Label", value: option.label }).appendTo(row); labelField.hide(); var valueClass = "node-input-option-value"; var valueField = $("<input/>", { class: valueClass, type: "text", style: "margin-left: 22px;margin-top:5px; width: 85%;", placeholder: "Value", value: option.value }).appendTo(row); var maxLengthField = $("<input/>", { class: "node-input-option-maxLength", type: "text", style: "margin-left: 22px;margin-top:5px; width: 85%;", placeholder: "maxlength", value: option.maxLength }).appendTo(row); maxLengthField.hide(); valueField.keyup(function() { if ($(this).val() && $(this).hasClass("input-error")) { $(this).removeClass("input-error"); } else { if (!$(this).val()) { $(this).addClass("input-error"); } } }); valueField.hide(); var listField = $("<input/>", { class: "node-input-option-list", type: "text", style: "margin-left:22px; margin-top:5px; width:85%;", placeholder: "value1:label 1, value2:label 2, ...", value: option.list }).appendTo(row); listField.hide(); var labelForRequried = $("<span/>", { style: "margin: 22px;" }) .text("Required") .appendTo(row); labelForRequried.hide(); var requiredContainer = $("<div/>", { style: "display:inline-block; height:34px; margin-left:7px; width:18%;" }).appendTo(row); requiredContainer.hide(); var requiredInnerContainer = $("<div/>", { style: "left:35%; position:relative; width:30px" }).appendTo(requiredContainer); var reqRow = $("<label />", { class: "switch", style: "top:10px; width:30px;" }).appendTo(requiredInnerContainer); var required = $("<input/>", { class: "node-input-option-required", type: "checkbox", checked: option.required }).appendTo(reqRow); var reqDiv = $("<div/>", { class: "slider round" }).appendTo(reqRow); deleteButton.click(function() { container.find(".node-input-option-value").removeAttr("required"); container.css({ background: "#fee" }); container.fadeOut(300, function() { $(this).remove(); }); }); $("#node-input-option-container").append(container); } function recoverOption(i, option) { var container = $("<li/>", { style: "background: #fff; margin:0; padding:8px 0px 0px; border-bottom: 1px solid #ccc;" }); var row = $("<div/>").appendTo(container); var row2 = $("<div/>", { style: "padding-top:5px; padding-left:175px;" }).appendTo(container); var row3 = $("<div/>", { style: "padding-top:5px; padding-left:120px;" }).appendTo(container); $( '<i style="color:#eee; cursor:move; margin-left:3px;" class="node-input-option-handle fa fa-bars"></i>' ).appendTo(row); var typeField = $("<select/>", { class: "node-input-option-type", type: "text", style: "width:200px; margin-left: 5px; text-align: center;" }) .attr("placeholder", "Select field type") .appendTo(row); var finalspan = $("<div/>", { style: "float: right; margin: 12px" }).appendTo(row); var deleteButton = $("<a/>", { href: "#", class: "editor-button editor-button-small", style: "left:35%; position:relative; width:30px" }).appendTo(finalspan); $("<i/>", { class: "fa fa-remove" }).appendTo(deleteButton); typeField.append($('<option value="">Select Field type</option>')); var arr = [ { val: "text", text: "Text" }, { val: "textarea", text: "textarea" }, { val: "tel", text: "tel" }, { val: "url", text: "url" }, { val: "number", text: "Number" }, { val: "email", text: "E-mail" }, { val: "password", text: "Password" }, { val: "checkbox", text: "Checkbox" }, { val: "switch", text: "Switch" }, //, { val: "list", text: "List" }, //, //{val : "file", text: 'File'}//, { val: "datetime", text: "Date & Time" }, { val: "date", text: "Date" } ]; //var sel = $('<select>').appendTo('body'); $(arr).each(function() { var isSelected = false; if (option.type == this.val) { isSelected = true; } typeField.append( $("<option>") .attr("value", this.val) .text(this.text) .prop("selected", isSelected) ); }); typeField.appendTo(row); var labelField = $("<input/>", { class: "node-input-option-label", type: "text", style: "margin-left:22px;margin-top:5px; width:85%;", placeholder: "Label", value: option.label }).appendTo(row); var valueClass = "node-input-option-value"; var valueField = $("<input/>", { class: valueClass, type: "text", style: "margin-left: 22px;margin-top:5px; width: 85%;", placeholder: "Value", value: option.value }).appendTo(row); var maxLengthField = $("<input/>",{ class: "node-input-option-maxLength", type: "text", style: "margin-left:22px;margin-top:5px; width:85%;", placeholder: "Max Length", value : option.maxLength }).appendTo(row); valueField.keyup(function() { if ($(this).val() && $(this).hasClass("input-error")) { $(this).removeClass("input-error"); } else { if (!$(this).val()) { $(this).addClass("input-error"); } } }); var listClass = "node-input-option-list"; if (!option.list) { valueClass = "node-input-option-list input-error"; } var listField = $("<input/>", { class: listClass, type: "text", style: "margin-left:22px; margin-top:5px; width:85%;", placeholder: "value1:label 1, value2:label 2, ...", value: option.list }).appendTo(row); listField.hide(); var labelForRequried = $("<span/>", { style: "margin: 22px;" }) .text("Required") .appendTo(row); var requiredContainer = $("<div/>", { style: "display:inline-block; height:34px; margin-left:7px; width:18%;" }).appendTo(row); var requiredInnerContainer = $("<div/>", { style: "left:35%; position:relative; width:30px" }).appendTo(requiredContainer); var reqRow = $("<label />", { class: "switch", style: "top:10px; width:30px;" }).appendTo(requiredInnerContainer); var required = $("<input/>", { class: "node-input-option-required", type: "checkbox", checked: option.required }).appendTo(reqRow); var reqDiv = $("<div />", { class: "slider round" }).appendTo(reqRow); deleteButton.click(function() { container.find(".node-input-option-value").removeAttr("required"); container.css({ background: "#fee" }); container.fadeOut(300, function() { $(this).remove(); }); }); typeField.init(function() { if (option.type === "list") { labelField.show(); valueField.show(); listField.show(); maxLengthField.hide(); } else if (option.type === "") { labelField.hide(); valueField.hide(); listField.hide(); maxLengthField.hide(); requiredContainer.hide(); }else if (option.type === "text") { labelField.show(); valueField.show(); maxLengthField.show(); listField.hide(); }else { labelField.show(); valueField.show(); maxLengthField.hide(); listField.hide(); } }); typeField.change(function() { labelField.val(""); listField.val(""); valueField.val(""); maxLengthField.val(""); required.attr("checked", false); if ($(this).val() === "list") { labelField.show(); valueField.show(); listField.show(); labelForRequried.show(); requiredContainer.show(); } else if ($(this).val() === "") { labelField.hide(); valueField.hide(); listField.hide(); maxLengthField.hide(); requiredContainer.hide(); }else if (option.type === "text") { labelField.show(); valueField.show(); labelForRequried.show(); requiredContainer.show(); listField.hide(); maxLengthField.show() }else { labelField.show(); valueField.show(); labelForRequried.show(); requiredContainer.show(); listField.hide(); maxLengthField.hide(); } }); $("#node-input-option-container").append(container); } }, oneditsave: function() { var options = $("#node-input-option-container").children(); var node = this; var o = {}; node.options = []; node.formValue = {}; options.each(function(i) { var option = $(this); var o = { label: option.find(".node-input-option-label").val(), //typedInput('value'), value: option.find(".node-input-option-value").val(), maxLength: option.find(".node-input-option-maxLength").val(), //typedInput('value'), type: option.find(".node-input-option-type").val(), //typedInput('value') list: option.find(".node-input-option-list").val(), //typedInput('value') required: option.find(".node-input-option-required").is(":checked") }; o.value = o.value || o.label || o.maxLength || o.type + "_" + i; node.formValue[o.value] = o.type == "checkbox" || o.type == "switch" ? false : ""; node.options.push(o); //console.log(o); }); // update metadata in database and variable // fetch metadata at the beginning of the request } }); </script> <style type="text/css"> .underline { text-decoration: underline; } </style>