diff --git a/src/Lib/default/local_tool_connectors/MispConnector.php b/src/Lib/default/local_tool_connectors/MispConnector.php index 473573a..a021839 100644 --- a/src/Lib/default/local_tool_connectors/MispConnector.php +++ b/src/Lib/default/local_tool_connectors/MispConnector.php @@ -122,6 +122,11 @@ class MispConnector extends CommonConnectorTools 'type' => 'boolean' ], ]; + public $settingsPlaceholder = [ + 'url' => 'https://your.misp.intance', + 'authkey' => '', + 'skip_ssl' => '0', + ]; public function addSettingValidatorRules($validator) { diff --git a/src/Lib/default/local_tool_connectors/SkeletonConnectorExample.php b/src/Lib/default/local_tool_connectors/SkeletonConnectorExample.php index ce9b62d..362c514 100644 --- a/src/Lib/default/local_tool_connectors/SkeletonConnectorExample.php +++ b/src/Lib/default/local_tool_connectors/SkeletonConnectorExample.php @@ -46,6 +46,22 @@ class SkeletonConnector extends CommonConnectorTools 'redirect' => 'serverSettingsAction' ] ]; + public $settings = [ + 'url' => [ + 'type' => 'text' + ], + 'authkey' => [ + 'type' => 'text' + ], + 'skip_ssl' => [ + 'type' => 'boolean' + ], + ]; + public $settingsPlaceholder = [ + 'url' => 'https://your.url', + 'authkey' => '', + 'skip_ssl' => '0', + ]; public function health(Object $connection): array { diff --git a/src/Model/Table/LocalToolsTable.php b/src/Model/Table/LocalToolsTable.php index ac29bf9..64d6168 100644 --- a/src/Model/Table/LocalToolsTable.php +++ b/src/Model/Table/LocalToolsTable.php @@ -143,7 +143,8 @@ class LocalToolsTable extends AppTable 'connector' => $connector_type, 'connector_version' => $connector_class->version, 'connector_description' => $connector_class->description, - 'connector_settings' => $connector_class->settings ?? [] + 'connector_settings' => $connector_class->settings ?? [], + 'connector_settings_placeholder' => $connector_class->settingsPlaceholder ?? [], ]; if ($includeConnections) { $connector['connections'] = $this->healthCheck($connector_type, $connector_class); diff --git a/templates/LocalTools/add.php b/templates/LocalTools/add.php index 184f0e6..5197f21 100644 --- a/templates/LocalTools/add.php +++ b/templates/LocalTools/add.php @@ -22,7 +22,8 @@ 'codemirror' => [ 'height' => '10rem', 'hints' => $connectors[0]['connector_settings'] - ] + ], + 'placeholder' => json_encode($connectors[0]['connector_settings_placeholder'], JSON_FORCE_OBJECT | JSON_PRETTY_PRINT) ], [ 'field' => 'description', diff --git a/templates/layout/default.php b/templates/layout/default.php index 849592e..59d2efe 100644 --- a/templates/layout/default.php +++ b/templates/layout/default.php @@ -52,6 +52,7 @@ $sidebarOpen = $loggedUser->user_settings_by_name_with_fallback['ui.sidebar.expa Html->script('CodeMirror/addon/lint/json-lint') ?> Html->script('CodeMirror/addon/edit/matchbrackets') ?> Html->script('CodeMirror/addon/edit/closebrackets') ?> + Html->script('CodeMirror/addon/display/placeholder') ?> Html->css('CodeMirror/codemirror') ?> Html->css('CodeMirror/codemirror-additional') ?> Html->css('CodeMirror/addon/hint/show-hint') ?> diff --git a/webroot/css/CodeMirror/codemirror-additional.css b/webroot/css/CodeMirror/codemirror-additional.css index 0c62e18..4399c1a 100644 --- a/webroot/css/CodeMirror/codemirror-additional.css +++ b/webroot/css/CodeMirror/codemirror-additional.css @@ -26,4 +26,8 @@ .CodeMirror-hints { z-index: 1060 !important; /* Make sure hint is above modal */ +} + +.CodeMirror pre.CodeMirror-placeholder { + color: #999; } \ No newline at end of file diff --git a/webroot/js/CodeMirror/addon/display/placeholder.js b/webroot/js/CodeMirror/addon/display/placeholder.js new file mode 100644 index 0000000..d8e2dbd --- /dev/null +++ b/webroot/js/CodeMirror/addon/display/placeholder.js @@ -0,0 +1,78 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/LICENSE + +(function (mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function (CodeMirror) { + CodeMirror.defineOption("placeholder", "", function (cm, val, old) { + var prev = old && old != CodeMirror.Init; + if (val && !prev) { + cm.on("blur", onBlur); + cm.on("change", onChange); + cm.on("swapDoc", onChange); + CodeMirror.on(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose = function () { onComposition(cm) }) + onChange(cm); + } else if (!val && prev) { + cm.off("blur", onBlur); + cm.off("change", onChange); + cm.off("swapDoc", onChange); + CodeMirror.off(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose) + clearPlaceholder(cm); + var wrapper = cm.getWrapperElement(); + wrapper.className = wrapper.className.replace(" CodeMirror-empty", ""); + } + + if (val && !cm.hasFocus()) onBlur(cm); + }); + + function clearPlaceholder(cm) { + if (cm.state.placeholder) { + cm.state.placeholder.parentNode.removeChild(cm.state.placeholder); + cm.state.placeholder = null; + } + } + function setPlaceholder(cm) { + clearPlaceholder(cm); + var elt = cm.state.placeholder = document.createElement("pre"); + elt.style.cssText = "height: 0; overflow: visible"; + elt.style.direction = cm.getOption("direction"); + elt.className = "CodeMirror-placeholder CodeMirror-line-like"; + var placeHolder = cm.getOption("placeholder") + if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder) + elt.appendChild(placeHolder) + cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild); + } + + function onComposition(cm) { + setTimeout(function () { + var empty = false + if (cm.lineCount() == 1) { + var input = cm.getInputField() + empty = input.nodeName == "TEXTAREA" ? !cm.getLine(0).length + : !/[^\u200b]/.test(input.querySelector(".CodeMirror-line").textContent) + } + if (empty) setPlaceholder(cm) + else clearPlaceholder(cm) + }, 20) + } + + function onBlur(cm) { + if (isEmpty(cm)) setPlaceholder(cm); + } + function onChange(cm) { + var wrapper = cm.getWrapperElement(), empty = isEmpty(cm); + wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : ""); + + if (empty) setPlaceholder(cm); + else clearPlaceholder(cm); + } + + function isEmpty(cm) { + return (cm.lineCount() === 1) && (cm.getLine(0) === ""); + } +});