diff --git a/airflow/www/static/js/connection_form.js b/airflow/www/static/js/connection_form.js index aabe547a88f59..755bfe7614e62 100644 --- a/airflow/www/static/js/connection_form.js +++ b/airflow/www/static/js/connection_form.js @@ -20,7 +20,7 @@ * Created by janomar on 23/07/15. */ -/* global document, DOMParser, $ */ +/* global document, DOMParser, $, CodeMirror */ import { getMetaValue } from './utils'; const restApiEnabled = getMetaValue('rest_api_enabled') === 'True'; @@ -125,11 +125,11 @@ function handleTestConnection(connectionType, testableConnections) { const testConnEnabled = testableConnections.includes(connectionType); if (testConnEnabled) { - // If connection type can be tested in via REST API, enable button and clear toolip. + // If connection type can be tested in via REST API, enable button and clear toolip. $(testButton).prop('disabled', false).removeAttr('title'); } else { - // If connection type can NOT be tested via REST API, disable button and display toolip - // alerting the user. + // If connection type can NOT be tested via REST API, disable button and display toolip + // alerting the user. $(testButton).prop('disabled', true) .attr('title', 'This connection type does not currently support testing via ' + 'Airflow REST API.'); @@ -205,7 +205,7 @@ $(document).ready(() => { alertBox.show(); } else { alertBox = $(`
\n` - + `\n${message}
`); + + `\n${message}`); $('.container .row').prepend(alertBox).show(); } @@ -261,7 +261,7 @@ $(document).ready(() => { Object.entries(extra).forEach(([key, val]) => { extrasObj[key] = val; }); - // Check if field is a custom form field. + // Check if field is a custom form field. } else if (this.name.startsWith('extra__')) { // prior to Airflow 2.3 custom fields were stored in the extra dict with prefix // post-2.3 we allow to use with no prefix @@ -305,4 +305,19 @@ $(document).ready(() => { // Initialize the form by setting a connection type. changeConnType(connTypeElem.value); + + // Change conn.extra TextArea widget to CodeMirror + const textArea = document.getElementById('extra'); + const editor = CodeMirror.fromTextArea(textArea, { + mode: { name: 'javascript', json: true }, + gutters: ['CodeMirror-lint-markers'], + lineWrapping: true, + lint: true, + }); + + // beautify JSON + const jsonData = editor.getValue(); + const data = JSON.parse(jsonData); + const formattedData = JSON.stringify(data, null, 2); + editor.setValue(formattedData); }); diff --git a/airflow/www/templates/airflow/conn_create.html b/airflow/www/templates/airflow/conn_create.html index af89c16cf1a5c..34c2f32dedb8c 100644 --- a/airflow/www/templates/airflow/conn_create.html +++ b/airflow/www/templates/airflow/conn_create.html @@ -20,14 +20,26 @@ {% extends 'appbuilder/general/model/add.html' %} {% block head_css %} - {{ super() }} - - +{{ super() }} + + + +{# required for codemirror #} + + {% endblock %} {% block tail %} - {{ super() }} - - - +{{ super() }} +{# required for codemirror #} + + + + + + + + + {% endblock %} diff --git a/airflow/www/templates/airflow/conn_edit.html b/airflow/www/templates/airflow/conn_edit.html index a9a4164e8981a..e963b8ac0cb50 100644 --- a/airflow/www/templates/airflow/conn_edit.html +++ b/airflow/www/templates/airflow/conn_edit.html @@ -20,14 +20,25 @@ {% extends 'appbuilder/general/model/edit.html' %} {% block head_css %} - {{ super() }} - - +{{ super() }} + + +{# required for codemirror #} + + {% endblock %} {% block tail %} - {{ super() }} - - - +{{ super() }} +{# required for codemirror #} + + + + + + + + + {% endblock %}