| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- /*!
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- /* global document, CodeMirror, window, $ */
- let jsonForm;
- const objectFields = new Map();
- const recentConfigList = document.getElementById("recent_configs");
- /**
- * Update the generated JSON DagRun.conf JSON field if any field changed
- */
- function updateJSONconf() {
- const jsonStart = document.getElementById("json_start").value;
- const params = JSON.parse(jsonStart);
- const elements = document.getElementById("trigger_form");
- for (let i = 0; i < elements.length; i += 1) {
- if (elements[i].name && elements[i].name.startsWith("element_")) {
- const keyName = elements[i].name.substr(8);
- if (elements[i].type === "checkbox") {
- params[keyName] = elements[i].checked;
- } else if (
- elements[i].attributes.valuetype &&
- elements[i].attributes.valuetype.value === "array"
- ) {
- const lines = elements[i].value.split("\n");
- const values = [];
- for (let j = 0; j < lines.length; j += 1) {
- if (lines[j].trim().length > 0) {
- values[values.length] = lines[j].trim();
- }
- }
- params[keyName] = values.length === 0 ? null : values;
- } else if (
- elements[i].attributes.valuetype &&
- elements[i].attributes.valuetype.value === "multiselect"
- ) {
- const { options } = elements[i];
- const values = [];
- for (let j = 0; j < options.length; j += 1) {
- if (options[j].selected) {
- values[values.length] = options[j].value;
- }
- }
- params[keyName] = values.length === 0 ? null : values;
- } else if (
- elements[i].attributes.valuetype &&
- (elements[i].attributes.valuetype.value === "object" ||
- elements[i].attributes.valuetype.value === "advancedarray")
- ) {
- try {
- const textValue = objectFields.get(elements[i].name).getValue();
- if (textValue.length > 0) {
- const objValue = JSON.parse(textValue);
- params[keyName] = objValue;
- objectFields
- .get(elements[i].name)
- .setValue(JSON.stringify(objValue, null, 4));
- } else {
- params[keyName] = null;
- }
- } catch (e) {
- // ignore JSON parsing errors
- // we don't want to bother users during entry, error will be displayed before submit
- }
- } else if (elements[i].value.length === 0) {
- params[keyName] = null;
- } else if (Number.isNaN(elements[i].value)) {
- params[keyName] = elements[i].value;
- } else if (
- elements[i].attributes.valuetype &&
- elements[i].attributes.valuetype.value === "number"
- ) {
- params[keyName] = Number(elements[i].value);
- } else {
- params[keyName] = elements[i].value;
- }
- }
- }
- jsonForm.setValue(JSON.stringify(params, null, 4));
- }
- /**
- * If the user hits ENTER key inside an input, ensure JSON data is updated.
- */
- function handleEnter() {
- updateJSONconf();
- // somehow following is needed to enforce form is submitted correctly from CodeMirror
- document.getElementById("json").value = jsonForm.getValue();
- }
- /**
- * Track user changes in input fields, ensure JSON is updated when user presses enter
- * See https://github.com/apache/airflow/issues/42157
- */
- function enterInputField() {
- const form = document.getElementById("trigger_form");
- form.addEventListener("submit", handleEnter);
- }
- /**
- * Stop tracking user changes in input fields
- */
- function leaveInputField() {
- const form = document.getElementById("trigger_form");
- form.removeEventListener("submit", handleEnter);
- updateJSONconf();
- }
- /**
- * Initialize the form during load of the web page
- */
- function initForm() {
- const formSectionsElement = document.getElementById("form_sections");
- const formHasFields = formSectionsElement != null;
- // Initialize the Generated JSON form or JSON entry form
- const minHeight = 300;
- const maxHeight =
- (formHasFields ? window.innerHeight / 2 : window.innerHeight) - 550;
- const height = maxHeight > minHeight ? maxHeight : minHeight;
- jsonForm = CodeMirror.fromTextArea(document.getElementById("json"), {
- lineNumbers: true,
- mode: { name: "javascript", json: true },
- gutters: ["CodeMirror-lint-markers"],
- lint: true,
- indentUnit: 4,
- });
- jsonForm.setSize(null, height);
- if (formHasFields) {
- // Initialize jQuery and Chakra fields
- const elements = document.getElementById("trigger_form");
- for (let i = 0; i < elements.length; i += 1) {
- if (elements[i].name && elements[i].name.startsWith("element_")) {
- if (
- elements[i].attributes.valuetype &&
- (elements[i].attributes.valuetype.value === "object" ||
- elements[i].attributes.valuetype.value === "advancedarray")
- ) {
- // Apply JSON formatting and linting to all object fields in the form
- const field = CodeMirror.fromTextArea(elements[i], {
- lineNumbers: true,
- mode: { name: "javascript", json: true },
- gutters: ["CodeMirror-lint-markers"],
- lint: true,
- indentUnit: 4,
- });
- field.on("blur", updateJSONconf);
- objectFields.set(elements[i].name, field);
- } else if (elements[i].nodeName === "SELECT") {
- // Activate select2 multi select boxes
- const elementId = `#${elements[i].name}`;
- $(elementId).select2({
- placeholder: "Select Values",
- allowClear: true,
- });
- elements[i].addEventListener("blur", updateJSONconf);
- } else if (elements[i].type === "checkbox") {
- elements[i].addEventListener("change", updateJSONconf);
- } else {
- elements[i].addEventListener("focus", enterInputField);
- elements[i].addEventListener("blur", leaveInputField);
- }
- }
- }
- // Refreshes JSON entry box sizes when they toggle display
- const formSections = formSectionsElement.value.split(",");
- for (let i = 0; i < formSections.length; i += 1) {
- const toggleBlock = document.getElementById(`${formSections[i]}_toggle`);
- if (toggleBlock) {
- toggleBlock.addEventListener("click", () => {
- setTimeout(() => {
- objectFields.forEach((cm) => {
- cm.refresh();
- });
- }, 300);
- });
- }
- }
- // Validate JSON entry fields before submission
- elements.addEventListener("submit", (event) => {
- updateJSONconf();
- objectFields.forEach((cm) => {
- const textValue = cm.getValue();
- try {
- if (textValue.trim().length > 0) {
- JSON.parse(textValue);
- }
- } catch (ex) {
- // eslint-disable-next-line no-alert
- window.alert(`Invalid JSON entered, please correct:\n\n${textValue}`);
- cm.focus();
- event.preventDefault();
- }
- });
- });
- // Ensure layout is refreshed on generated JSON as well
- document
- .getElementById("generated_json_toggle")
- .addEventListener("click", () => {
- setTimeout(() => {
- jsonForm.refresh();
- }, 300);
- });
- // Update generated conf once
- setTimeout(updateJSONconf, 100);
- }
- }
- $(document).ready(() => {
- initForm();
- });
- window.updateJSONconf = updateJSONconf;
- function setRecentConfig(e) {
- const dropdownValue = e.target.value;
- let dropdownJson;
- let value;
- try {
- dropdownJson = JSON.parse(dropdownValue);
- value = JSON.stringify(dropdownJson, null, 4);
- } catch (err) {
- // eslint-disable-next-line no-console
- console.error(`config is not valid JSON format: ${dropdownValue}`);
- }
- // Form fields need to be populated from recent config
- const keys = Object.keys(dropdownJson);
- for (let i = 0; i < keys.length; i += 1) {
- const element = document.getElementById(`element_${keys[i]}`);
- if (element) {
- const newValue = dropdownJson[keys[i]];
- if (element.type === "checkbox") {
- element.checked = newValue;
- } else if (newValue === "" || newValue == null) {
- element.value = "";
- } else if (
- element.attributes.valuetype &&
- element.attributes.valuetype.value === "array"
- ) {
- element.value = newValue.join("\n");
- } else if (
- element.attributes.valuetype &&
- (element.attributes.valuetype.value === "object" ||
- element.attributes.valuetype.value === "advancedarray")
- ) {
- objectFields
- .get(`element_${keys[i]}`)
- .setValue(JSON.stringify(newValue, null, 4));
- } else if (element.nodeName === "SELECT") {
- $(`#${element.name}`).select2("val", [newValue]);
- } else {
- element.value = newValue;
- }
- }
- }
- // Populate JSON field
- jsonForm.setValue(value);
- }
- if (recentConfigList) {
- recentConfigList.addEventListener("change", setRecentConfig);
- }
|