From 1128e1ce11081ec27aea2d684cde828fb9ed3f57 Mon Sep 17 00:00:00 2001 From: Shweelan Samson Date: Mon, 22 Apr 2019 14:26:50 +0300 Subject: [PATCH] Introduce large textarea field type --- ui/config-page.ts | 13 ++++++++----- ui/permissions-page.ts | 4 ++-- ui/presets-page.ts | 2 +- ui/put-form-component.ts | 29 +++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/ui/config-page.ts b/ui/config-page.ts index a88ed18..67784bc 100644 --- a/ui/config-page.ts +++ b/ui/config-page.ts @@ -4,13 +4,13 @@ import * as notifications from "./notifications"; import putFormComponent from "./put-form-component"; import uiConfigComponent from "./ui-config-component"; import * as overlay from "./overlay"; -import * as expressionParser from "../lib/common/expression-parser"; +import { parse, stringify } from "../lib/common/expression-parser"; import { loadCodeMirror, loadYaml } from "./dynamic-loader"; import { ClosureComponent, Component, Children } from "mithril"; const attributes = [ { id: "_id", label: "Key" }, - { id: "value", label: "Value" } + { id: "value", label: "Value", type: "textarea" } ]; interface ValidationErrors { @@ -21,12 +21,15 @@ function putActionHandler(action, _object, isNew?): Promise { return new Promise((resolve, reject) => { const object = Object.assign({}, _object); if (action === "save") { - const id = object["_id"]; + let id = object["_id"] || ""; delete object["_id"]; - if (!id) return void resolve({ _id: "ID can not be empty" }); + const regex = /^[0-9a-zA-Z_.-]+$/; + id = id.trim(); + if (!id.match(regex)) return void resolve({ _id: "Invalid ID" }); + try { - expressionParser.parse(object.value); + object.value = stringify(parse(object.value || "")); } catch (err) { return void resolve({ value: "Config value must be valid expression" diff --git a/ui/permissions-page.ts b/ui/permissions-page.ts index 4525bbc..fa64c96 100644 --- a/ui/permissions-page.ts +++ b/ui/permissions-page.ts @@ -36,14 +36,14 @@ const attributes = [ "virtualParameters" ] }, - { id: "filter", label: "Filter" }, + { id: "filter", label: "Filter", type: "textarea" }, { id: "access", label: "Access", type: "combo", options: ["1: count", "2: read", "3: write"] }, - { id: "validate", label: "Validate" } + { id: "validate", label: "Validate", type: "textarea" } ]; const unpackSmartQuery = memoize(query => { diff --git a/ui/presets-page.ts b/ui/presets-page.ts index 2c28437..f02470d 100644 --- a/ui/presets-page.ts +++ b/ui/presets-page.ts @@ -22,7 +22,7 @@ const attributes = [ { id: "weight", label: "Weight" }, { id: "schedule", label: "Schedule" }, { id: "events", label: "Events" }, - { id: "precondition", label: "Precondition" }, + { id: "precondition", label: "Precondition", type: "textarea" }, { id: "provision", label: "Provision", type: "combo" }, { id: "provisionArgs", label: "Arguments" } ]; diff --git a/ui/put-form-component.ts b/ui/put-form-component.ts index 7e88b8c..1d2d0b1 100644 --- a/ui/put-form-component.ts +++ b/ui/put-form-component.ts @@ -87,6 +87,35 @@ function createField(current, attr, focus): Children { e.redraw = false; } }); + } else if (attr.type === "textarea") { + return m("textarea", { + name: attr.id, + value: current.object[attr.id], + readonly: attr.id === "_id" && !current.isNew, + cols: attr.cols || 80, + rows: attr.rows || 4, + style: "resize: none;", + oncreate: focus + ? _vnode => { + const dom = _vnode.dom as HTMLInputElement; + dom.focus(); + dom.setSelectionRange(dom.value.length, dom.value.length); + } + : null, + oninput: e => { + current.object[attr.id] = e.target.value; + e.redraw = false; + }, + onkeypress: e => { + e.redraw = false; + if (e.which === 13 && !e.shiftKey) { + const dom = e.target; + dom.form.querySelector("button[type=submit]").click(); + return false; + } + return true; + } + }); } return m("input", {