You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by ry...@apache.org on 2021/02/11 13:59:35 UTC
[airflow] branch master updated: Rework client-side script for
connection form. (#14052)
This is an automated email from the ASF dual-hosted git repository.
ryanahamilton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/master by this push:
new 98bbe5a Rework client-side script for connection form. (#14052)
98bbe5a is described below
commit 98bbe5aec578a012c1544667bf727688da1dadd4
Author: Wong Yong Jie <yj...@gmail.com>
AuthorDate: Thu Feb 11 21:59:21 2021 +0800
Rework client-side script for connection form. (#14052)
* Rework client-side script for connection form.
Before this, fields on the connection form were dynamically changed by
adding and removing the "hide" CSS class. If a provider were to add a
field that requires validation (e.g. InputRequired), or if a different
field type was used (e.g. NumberField), the entire form would be
unsaveable, even if the currently selected connection type had nothing
to do with that provider.
This change takes a different approach; upon loading, the DOM elements
for all extra fields are saved into a Map, then removed from the DOM
tree. When another connection type is selected, these elements are
restored into the DOM.
* Use template string literals in connection form.
Co-authored-by: Ryan Hamilton <ry...@ryanahamilton.com>
Co-authored-by: Ryan Hamilton <ry...@ryanahamilton.com>
---
airflow/www/static/js/connection_form.js | 138 +++++++++++++++++++++++++------
1 file changed, 111 insertions(+), 27 deletions(-)
diff --git a/airflow/www/static/js/connection_form.js b/airflow/www/static/js/connection_form.js
index af6601b..89ecde0 100644
--- a/airflow/www/static/js/connection_form.js
+++ b/airflow/www/static/js/connection_form.js
@@ -24,40 +24,124 @@ function decode(str) {
return new DOMParser().parseFromString(str, "text/html").documentElement.textContent
}
+/**
+ * Returns a map of connection type to its controls.
+ */
+function getConnTypesToControlsMap() {
+ const connTypesToControlsMap = new Map();
+
+ const extraFormControls = Array.from(document.querySelectorAll("[id^='extra__'"));
+ extraFormControls.forEach(control => {
+ const connTypeEnd = control.id.indexOf('__', 'extra__'.length);
+ const connType = control.id.substring('extra__'.length, connTypeEnd);
+
+ const controls = connTypesToControlsMap.has(connType)
+ ? connTypesToControlsMap.get(connType)
+ : [];
+
+ controls.push(control.parentElement.parentElement);
+ connTypesToControlsMap.set(connType, controls);
+ });
+
+ return connTypesToControlsMap;
+}
+
+/**
+ * Returns the DOM element that contains the different controls.
+ */
+function getControlsContainer() {
+ return document.getElementById('conn_id')
+ .parentElement
+ .parentElement
+ .parentElement;
+}
+
$(document).ready(function () {
+ const fieldBehavioursElem = document.getElementById('field_behaviours');
+ const config = JSON.parse(decode(fieldBehavioursElem.textContent));
- function connTypeChange(connectionType) {
- $(".hide").removeClass("hide");
- $.each($("[id^='extra__']"), function () {
- $(this).parent().parent().addClass('hide')
+ // Save all DOM elements into a map on load.
+ const controlsContainer = getControlsContainer();
+ const connTypesToControlsMap = getConnTypesToControlsMap();
+
+ /**
+ * Changes the connection type.
+ * @param {string} connType The connection type to change to.
+ */
+ function changeConnType(connType) {
+ Array.from(connTypesToControlsMap.values()).forEach(controls => {
+ controls
+ .filter(control => control.parentElement === controlsContainer)
+ .forEach(control => controlsContainer.removeChild(control));
});
- $.each($("[id^='extra__" + connectionType + "__']"), function () {
- $(this).parent().parent().removeClass('hide')
+
+ const controls = connTypesToControlsMap.get(connType) || [];
+ controls.forEach(control => controlsContainer.appendChild(control));
+
+ // Restore field behaviours.
+ restoreFieldBehaviours();
+
+ // Apply behaviours to fields.
+ applyFieldBehaviours(connType);
+ }
+
+ /**
+ * Restores the behaviour for all fields. Used to restore fields to a
+ * well-known state during the change of connection types.
+ */
+ function restoreFieldBehaviours() {
+ Array.from(document.querySelectorAll('label[data-origText]')).forEach(elem => {
+ elem.innerText = elem.dataset.origText;
+ delete elem.dataset.origText;
});
- $("label[orig_text]").each(function () {
- $(this).text($(this).attr("orig_text"));
+
+ Array.from(document.querySelectorAll('.form-control')).forEach(elem => {
+ elem.placeholder = '';
+ elem.parentElement.parentElement.classList.remove('hide');
});
- $(".form-control").each(function(){$(this).attr('placeholder', '')});
- let config = JSON.parse(decode($("#field_behaviours").text()))
- if (config[connectionType] != undefined) {
- $.each(config[connectionType].hidden_fields, function (i, field) {
- $("#" + field).parent().parent().addClass('hide')
- });
- $.each(config[connectionType].relabeling, function (k, v) {
- lbl = $("label[for='" + k + "']");
- lbl.attr("orig_text", lbl.text());
- $("label[for='" + k + "']").text(v);
- });
- $.each(config[connectionType].placeholders, function(k, v){
- $("#" + k).attr('placeholder', v);
- });
+ }
+
+ /**
+ * Applies special behaviour for fields. The behaviour is defined through
+ * config, passed by the server.
+ *
+ * @param {string} connType The connection type to apply.
+ */
+ function applyFieldBehaviours(connType) {
+ if (config[connType]) {
+ if (Array.isArray(config[connType].hidden_fields)) {
+ config[connType].hidden_fields.forEach(field => {
+ document.getElementById(field)
+ .parentElement
+ .parentElement
+ .classList
+ .add('hide');
+ });
+ }
+
+ if (config[connType].relabeling) {
+ Object.keys(config[connType].relabeling).forEach(field => {
+ const label = document.querySelector(`label[for='${field}']`);
+ label.dataset.origText = label.innerText;
+ label.innerText = config[connType].relabeling[field];
+ });
+ }
+
+ if (config[connType].placeholders) {
+ Object.keys(config[connType].placeholders).forEach(field => {
+ const placeholder = config[connType].placeholders[field];
+ document.getElementById(field).placeholder = placeholder;
+ });
+ }
}
}
- var connectionType = $("#conn_type").val();
- $("#conn_type").on('change', function (e) {
- connectionType = $("#conn_type").val();
- connTypeChange(connectionType);
+ const connTypeElem = document.getElementById('conn_type');
+ $(connTypeElem).on('change', (e) => {
+ connType = e.target.value;
+ changeConnType(connType);
});
- connTypeChange(connectionType);
+
+ // Initialize the form by setting a connection type.
+ changeConnType(connTypeElem.value);
});