window.correlation_edit_popup = new class { init({correlation}) { this.overlay = overlays_stack.getById('correlation-form'); this.dialogue = this.overlay.$dialogue[0]; this.form = this.overlay.$dialogue.$body[0].querySelector('form'); this.correlation = correlation; this.correlationid = correlation.correlationid; this.dialogue.addEventListener('click', (e) => { if (e.target.classList.contains('js-condition-add')) { const overlay = PopUp('correlation.condition.edit', {}, { dialogueid: 'correlation-condition-form', dialogue_class: 'modal-popup-medium' }); // Get values from condition popup. overlay.$dialogue[0].addEventListener('condition.dialogue.submit', (e) => { this.#addConditionRow(e.detail); this.#processTypeOfCalculation(); }); } else if (e.target.classList.contains('js-condition-remove')) { e.target.closest('tr').remove(); this.#processTypeOfCalculation(); } }); for (let i = 0; i < Object.values(correlation.conditions).length; i++) { this.#addConditionRow(correlation.conditions[i]); } this.form.querySelector('#evaltype').onchange = () => this.#processTypeOfCalculation(); this.#processTypeOfCalculation(); } /** * Checks the conditions list and shows either expression or custom input formula field. */ #processTypeOfCalculation() { const condition_count = this.form.querySelectorAll('#condition_table tr[id^=conditions_]').length; const evaltype = this.form.querySelector('#evaltype'); if (condition_count <= 1) { evaltype.value = ; } const show_formula = condition_count > 1 && evaltype.value == ; const evaltype_label = this.form.querySelector('#label-evaltype'); const expression = this.form.querySelector('#expression'); const formula = this.form.querySelector('#formula'); if (condition_count > 1) { evaltype.closest('.form-field').style.display = ''; evaltype_label.style.display = ''; } else { evaltype.closest('.form-field').style.display = 'none'; evaltype_label.style.display = 'none'; } if (show_formula) { expression.style.display = 'none'; formula.style.display = ''; formula.removeAttribute('disabled'); } else { expression.style.display = ''; formula.style.display = 'none'; formula.setAttribute('disabled', true); } const conditions = []; const labels = this.form.querySelectorAll('#condition_table .label'); [...labels].forEach((label) => { conditions.push({ id: label.dataset.formulaid, type: label.dataset.conditiontype }); }); expression.innerHTML = getConditionFormula(conditions, + evaltype.value); } /** * Adds a correlation condition row when condition popup is closed. * * @param {object} condition Condition object. */ #addConditionRow(condition) { const row_ids = []; this.form.querySelectorAll('#condition_table tr[id^=conditions_]').forEach((row) => row_ids.push(row.id)); condition.row_index ??= 0; /* * When controller passes data ir gives only one group ID for each condition. Condition popup can give multiple * IDs and then they are split into rows. */ if (condition.groupid) { condition.groupids = condition.groupid; } if (condition.groupids) { Object.keys(condition.groupids).forEach((key) => { let element = {...condition, name: condition.groupids[key], value: key}; element.groupid = key; let has_row = this.#checkConditionRow(element); const result = [has_row.some((element) => element === true)]; if (result[0] === true) { return; } else { while (row_ids.some((id) => id === `conditions_${condition.row_index}`)) { element.row_index++; condition.row_index++; } element.condition_name = this.#getConditionData(condition); element.data = element.name; element.conditiontype = condition.conditiontype; element.label = num2letter(element.row_index); element.groupid = key; condition.row_index++; const template = new Template(this.form.querySelector('#condition-hostgr-row-tmpl').innerHTML); this.form .querySelector('#condition_table tbody') .insertAdjacentHTML('beforeend', template.evaluate(element)); } }); } else { let has_row = this.#checkConditionRow(condition); let template; const result = [has_row.some((element) => element === true)]; if (result[0] === true) { return; } else { while (row_ids.some((id) => id === `conditions_${condition.row_index}`)) { condition.row_index++; } condition.label = num2letter(condition.row_index); switch (parseInt(condition.conditiontype)) { case : case : template = new Template(this.form.querySelector('#condition-tag-row-tmpl').innerHTML); break; case : condition.condition_name2 = this.#getConditionData(condition)[1]; condition.condition_operator = this.#getConditionData(condition)[2]; condition.data_old_tag = this.#getConditionData(condition)[3]; condition.data_new_tag = this.#getConditionData(condition)[4]; template = new Template(this.form.querySelector('#condition-tag-pair-row-tmpl').innerHTML); break; case : case : condition.condition_name = this.#getConditionData(condition)[0]; condition.condition_operator = this.#getConditionData(condition)[1]; condition.tag = this.#getConditionData(condition)[2]; condition.value = this.#getConditionData(condition)[3]; template = new Template(this.form.querySelector('#condition-old-new-tag-row-tmpl').innerHTML); break; } condition.condition_name = this.#getConditionData(condition)[0]; condition.data = this.#getConditionData(condition)[1]; condition.conditiontype = condition.conditiontype; this.form .querySelector('#condition_table tbody') .insertAdjacentHTML('beforeend', template.evaluate(condition)); condition.row_index++; } } } /** * Returns condition name, value and operator depending on condition type. * * @param {object} condition Condition object. * * @return {array} */ #getConditionData(condition) { let condition_name; let condition_name2; let condition_data; let operator; let value; let value2; switch (parseInt(condition.conditiontype)) { case : condition_name = ; condition_name2 = ; operator = condition.operator_name; value = condition.oldtag; value2 = condition.newtag; return [condition_name, condition_name2, operator, value, value2]; case : condition_name = + ' ' + condition.operator_name; condition_data = condition.tag; return [condition_name, condition_data]; case : condition_name = + ' ' + condition.operator_name; condition_data = condition.tag; return [condition_name, condition_data]; case : condition_name = + ' ' + condition.operator_name; return [condition_name]; case : condition_name = ; value = condition.tag; operator = condition.operator_name; value2 = condition.value; return [condition_name, operator, value, value2]; case : condition_name = ; value = condition.tag; operator = condition.operator_name; value2 = condition.value; return [condition_name, operator, value, value2]; } } /** * Checks if given condition already exists. * * @param {object} condition Condition object. * * @return {array} */ #checkConditionRow(condition) { const result = []; [...this.form.querySelectorAll('#condition_table tr[id^=conditions_]')].forEach((element) => { const type = element.querySelector('input[name*="type"]').value; switch (parseInt(type)) { case : case : result.push(condition.conditiontype === type && condition.tag === element.querySelector('input[name*="tag"]').value ); break; case : case : result.push(condition.conditiontype === type && condition.tag === element.querySelector('input[name*="tag"]').value && condition.value === element.querySelector('input[name*="value"]').value ); break; case : result.push(condition.conditiontype === type && condition.oldtag === element.querySelector('input[name*="oldtag"]').value && condition.newtag === element.querySelector('input[name*="newtag"]').value ); break; case : result.push(condition.conditiontype === type && condition.groupid === element.querySelector('input[name*="groupid"]').value ); break; } }); return result; } clone({title, buttons}) { this.correlationid = null; this.overlay.setProperties({title, buttons}); this.overlay.unsetLoading(); this.overlay.recoverFocus(); } delete() { const curl = new Curl('zabbix.php'); curl.setArgument('action', 'correlation.delete'); curl.setArgument('', ); this.#post(curl.getUrl(), {correlationids: [this.correlationid]}, (response) => { overlayDialogueDestroy(this.overlay.dialogueid); this.dialogue.dispatchEvent(new CustomEvent('dialogue.submit', {detail: response.success})); }); } submit() { const fields = getFormFields(this.form); ['name', 'description'].forEach((field) => fields[field] = fields[field].trim()); const curl = new Curl('zabbix.php'); curl.setArgument('action', this.correlationid === null ? 'correlation.create' : 'correlation.update'); this.#post(curl.getUrl(), fields, (response) => { overlayDialogueDestroy(this.overlay.dialogueid); this.dialogue.dispatchEvent(new CustomEvent('dialogue.submit', {detail: response.success})); }); } /** * Sends a POST request to the specified URL with the provided data and executes the success_callback function. * * @param {string} url The URL to send the POST request to. * @param {object} data The data to send with the POST request. * @param {callback} success_callback The function to execute when a successful response is received. */ #post(url, data, success_callback) { fetch(url, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }) .then((response) => response.json()) .then((response) => { if ('error' in response) { throw {error: response.error}; } return response; }) .then(success_callback) .catch((exception) => { for (const element of this.form.parentNode.children) { if (element.matches('.msg-good, .msg-bad, .msg-warning')) { element.parentNode.removeChild(element); } } let title, messages; if (typeof exception === 'object' && 'error' in exception) { title = exception.error.title; messages = exception.error.messages; } else { messages = []; } const message_box = makeMessageBox('bad', messages, title)[0]; this.form.parentNode.insertBefore(message_box, this.form); }) .finally(() => this.overlay.unsetLoading()); } }