[UPDT] HORILLA AUTOMATIONS: Optimize form submit handler for #{{view_id}}Form:

This commit is contained in:
Horilla
2025-08-13 16:34:22 +05:30
parent 1a4195b53e
commit 4cd7a96b63
4 changed files with 259 additions and 259 deletions

View File

@@ -1,56 +1,50 @@
from django.apps import AppConfig
"""
App configuration for the Horilla Automations app.
Initializes model choices and starts automation when the server runs.
"""
from horilla_automations.signals import start_automation
import os
import sys
from django.apps import AppConfig
class HorillaAutomationConfig(AppConfig):
"""Configuration class for the Horilla Automations Django app."""
default_auto_field = "django.db.models.BigAutoField"
name = "horilla_automations"
def ready(self) -> None:
ready = super().ready()
try:
def ready(self):
"""Run initialization tasks when the app is ready."""
from base.templatetags.horillafilters import app_installed
from employee.models import Employee
from horilla_automations.methods.methods import get_related_models
from horilla_automations.models import MODEL_CHOICES as model_choices
from base.templatetags.horillafilters import app_installed
from employee.models import Employee
from horilla_automations.methods.methods import get_related_models
from horilla_automations.models import MODEL_CHOICES
# Build MODEL_CHOICES
models = [Employee]
if app_installed("recruitment"):
from recruitment.models import Candidate
recruitment_installed = False
if app_installed("recruitment"):
recruitment_installed = True
models.append(Candidate)
models = [Employee]
if recruitment_installed:
from recruitment.models import Candidate
for main_model in models:
for model in get_related_models(main_model):
model_choices.append(
(f"{model.__module__}.{model.__name__}", model.__name__)
)
models.append(Candidate)
model_choices.append(("employee.models.Employee", "Employee"))
model_choices.append(("pms.models.EmployeeKeyResult", "Employee Key Results"))
model_choices[:] = list(set(model_choices)) # Update in-place
main_models = models
for main_model in main_models:
related_models = get_related_models(main_model)
# Only start automation when running the server
if (
len(sys.argv) >= 2
and sys.argv[1] == "runserver"
and os.environ.get("RUN_MAIN") == "true"
):
from horilla_automations.signals import start_automation
for model in related_models:
path = f"{model.__module__}.{model.__name__}"
MODEL_CHOICES.append((path, model.__name__))
MODEL_CHOICES.append(("employee.models.Employee", "Employee"))
MODEL_CHOICES.append(
("pms.models.EmployeeKeyResult", "Employee Key Results"),
)
MODEL_CHOICES.append(
("pms.models.Comment", "Key Result Comment"),
)
MODEL_CHOICES = list(set(MODEL_CHOICES))
try:
start_automation()
except Exception as e:
print(e)
"""
Migrations are not affected yet
"""
except:
"""
Models not ready yet
"""
return ready
start_automation()

View File

@@ -84,13 +84,16 @@ class AutomationForm(ModelForm):
# --- Field: mail_template ---
self.fields["mail_template"].empty_label = "----------"
# --- Instance condition fields ---
if self.instance.pk:
self.fields["condition"].initial = self.instance.condition_html
self.fields["condition_html"].initial = self.instance.condition_html
self.fields["condition_querystring"].initial = (
self.instance.condition_querystring
)
# --- Field: condition fields ---
self.fields["condition"].initial = getattr(
self.instance, "condition", None
) or self.data.get("condition")
self.fields["condition_html"].initial = getattr(
self.instance, "condition_html", None
) or self.data.get("condition_html")
self.fields["condition_querystring"].initial = getattr(
self.instance, "condition", None
) or self.data.get("condition_html")
# --- Apply option template name for all select fields ---
for field in self.fields.values():

View File

@@ -1,48 +1,48 @@
function getToMail(element) {
model = element.val();
$.ajax({
type: "get",
url: "/get-to-mail-field",
data: {
model: model,
},
success: function (response) {
$(".dynamic-condition-row").remove();
select = $("#id_mail_to");
select.html("");
detailSelect = $("#id_mail_details");
detailSelect.html("");
mailTo = response.choices;
mailDetail = response.mail_details_choice;
model = element.val();
$.ajax({
type: "get",
url: "/get-to-mail-field",
data: {
model: model,
},
success: function (response) {
$(".dynamic-condition-row").remove();
select = $("#id_mail_to");
select.html("");
detailSelect = $("#id_mail_details");
detailSelect.html("");
mailTo = response.choices;
mailDetail = response.mail_details_choice;
for (let option = 0; option < mailTo.length; option++) {
const element = mailTo[option];
for (let option = 0; option < mailTo.length; option++) {
const element = mailTo[option];
var selected = option === 0; // Set the first option as selected
var newOption = new Option(element[1], element[0], selected, selected);
select.append(newOption);
}
for (let option = 0; option < mailDetail.length; option++) {
const element = mailDetail[option];
var selected = option === 0; // Set the first option as selected
var newOption = new Option(element[1], element[0], selected, selected);
select.append(newOption);
}
for (let option = 0; option < mailDetail.length; option++) {
const element = mailDetail[option];
var selected = option === 0; // Set the first option as selected
var newOption = new Option(element[1], element[0], selected, selected);
detailSelect.append(newOption);
}
select.trigger("change");
detailSelect.trigger("change");
var selected = option === 0; // Set the first option as selected
var newOption = new Option(element[1], element[0], selected, selected);
detailSelect.append(newOption);
}
select.trigger("change");
detailSelect.trigger("change");
table = $("#multipleConditionTable");
$("#multipleConditionTable select").select2("destroy");
table = $("#multipleConditionTable");
$("#multipleConditionTable select").select2("destroy");
totalRows = "C" + (table.find(".dynamic-condition-row").length + 1);
totalRows = "C" + (table.find(".dynamic-condition-row").length + 1);
fieldsChoices = [];
$.each(response.serialized_form, function (indexInArray, valueOfElement) {
fieldsChoices.push([valueOfElement["name"], valueOfElement["label"]]);
});
selectField = populateSelect(fieldsChoices, response);
tr = `
fieldsChoices = [];
$.each(response.serialized_form, function (indexInArray, valueOfElement) {
fieldsChoices.push([valueOfElement["name"], valueOfElement["label"]]);
});
selectField = populateSelect(fieldsChoices, response);
tr = `
<tr class="dynamic-condition-row">
<td class="sn">${totalRows}</td>
<td id="conditionalField">
@@ -92,17 +92,17 @@ function getToMail(element) {
</td>
</tr>
`;
table.find("tr:last").after(tr);
$("#conditionalField").append(selectField);
$("#multipleConditionTable select").select2();
selectField.trigger("change");
selectField.attr("name", "automation_multiple_condition");
},
});
table.find("tr:last").after(tr);
$("#conditionalField").append(selectField);
$("#multipleConditionTable select").select2();
selectField.trigger("change");
selectField.attr("name", "automation_multiple_condition");
},
});
}
function getHtml() {
var htmlCode = `
var htmlCode = `
<form id ="multipleConditionForm">
<table id="multipleConditionTable">
<tr>
@@ -124,193 +124,191 @@ function getHtml() {
$("#multipleConditionTable").closest("[contenteditable=true]").removeAttr("contenteditable");
</script>
`;
return $(htmlCode);
return $(htmlCode);
}
function populateSelect(data, response) {
const selectElement = $(
`<select class="w-100" onchange="updateValue($(this));addSelectedAttr(event)"></select>`
);
const selectElement = $(
`<select class="w-100" onchange="updateValue($(this));addSelectedAttr(event)"></select>`
);
data.forEach((item) => {
const $option = $("<option></option>");
$option.val(item[0]);
$option.text(item[1]);
selectElement.append($option);
});
return selectElement;
data.forEach((item) => {
const $option = $("<option></option>");
$option.val(item[0]);
$option.text(item[1]);
selectElement.append($option);
});
return selectElement;
}
function updateValue(element) {
console.log(">>>>>>>>>>>>>>>>>>>>>>")
json = element.closest('table').find('#conditionalField div[hidden]').text()
console.log(json)
json = element.closest('table').find('#conditionalField div[hidden]').text()
field = element.val();
// attr = json
// .replace(/[\u0000-\u001F\u007F-\u009F]/g, "")
// .replace(/\\n/g, "\\\\n")
// .replace(/\\t/g, "\\\\t");
field = element.val();
// attr = json
// .replace(/[\u0000-\u001F\u007F-\u009F]/g, "")
// .replace(/\\n/g, "\\\\n")
// .replace(/\\t/g, "\\\\t");
response = JSON.parse(json);
response = JSON.parse(json);
valueElement = createElement(field, response);
element.closest("tr").find(".condition-value-th").html("");
element.closest("tr").find(".condition-value-th").html(valueElement);
if (valueElement.is("select")) {
valueElement.select2();
}
valueElement = createElement(field, response);
element.closest("tr").find(".condition-value-th").html("");
element.closest("tr").find(".condition-value-th").html(valueElement);
if (valueElement.is("select")) {
valueElement.select2();
}
}
function createElement(field, serialized_form) {
let element;
fieldItem = {};
let element;
fieldItem = {};
$.each(serialized_form, function (indexInArray, valueOfElement) {
if (valueOfElement.name == field) {
fieldItem = valueOfElement;
}
});
switch (fieldItem.type) {
case "CheckboxInput":
element = document.createElement("input");
element.type = "checkbox";
element.checked = true;
element.onchange = function () {
if (this.checked) {
$(this).attr("checked", true);
$(this).val("on");
} else {
$(this).attr("checked", false);
$(this).val("off");
$.each(serialized_form, function (indexInArray, valueOfElement) {
if (valueOfElement.name == field) {
fieldItem = valueOfElement;
}
};
element.name = "automation_multiple_condition";
element.className = "oh-switch__checkbox oh-switch__checkbox";
// Create the wrapping div
const wrapperDiv = document.createElement("div");
wrapperDiv.className = "oh-switch";
wrapperDiv.style.width = "30px";
// Append the checkbox input to the div
wrapperDiv.appendChild(element);
$(element).change();
element = wrapperDiv;
break;
});
case "Select":
case "SelectMultiple":
element = document.createElement("select");
if (fieldItem.type === "SelectMultiple") {
element.multiple = true;
}
element.onchange = function (event) {
addSelectedAttr(event);
};
fieldItem.options.forEach((optionValue) => {
if (optionValue.value) {
const option = document.createElement("option");
option.value = optionValue.value;
option.textContent = optionValue.label;
element.appendChild(option);
}
});
break;
switch (fieldItem.type) {
case "CheckboxInput":
element = document.createElement("input");
element.type = "checkbox";
element.checked = true;
element.onchange = function () {
if (this.checked) {
$(this).attr("checked", true);
$(this).val("on");
} else {
$(this).attr("checked", false);
$(this).val("off");
}
};
element.name = "automation_multiple_condition";
element.className = "oh-switch__checkbox oh-switch__checkbox";
// Create the wrapping div
const wrapperDiv = document.createElement("div");
wrapperDiv.className = "oh-switch";
wrapperDiv.style.width = "30px";
// Append the checkbox input to the div
wrapperDiv.appendChild(element);
$(element).change();
element = wrapperDiv;
break;
case "Textarea":
element = document.createElement("textarea");
element.style = `
case "Select":
case "SelectMultiple":
element = document.createElement("select");
if (fieldItem.type === "SelectMultiple") {
element.multiple = true;
}
element.onchange = function (event) {
addSelectedAttr(event);
};
fieldItem.options.forEach((optionValue) => {
if (optionValue.value) {
const option = document.createElement("option");
option.value = optionValue.value;
option.textContent = optionValue.label;
element.appendChild(option);
}
});
break;
case "Textarea":
element = document.createElement("textarea");
element.style = `
height: 29px !important;
margin-top: 5px;
`;
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).html($(this).val());
};
break;
case "TextInput":
element = document.createElement("input");
element.type = "text";
element.style = `
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).html($(this).val());
};
break;
case "TextInput":
element = document.createElement("input");
element.type = "text";
element.style = `
height: 30px !important;
`;
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).attr("value", $(this).val());
};
break;
case "EmailInput":
element = document.createElement("input");
element.type = "email";
element.style = `
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).attr("value", $(this).val());
};
break;
case "EmailInput":
element = document.createElement("input");
element.type = "email";
element.style = `
height: 30px !important;
`;
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).attr("value", $(this).val());
};
break;
case "NumberInput":
element = document.createElement("input");
element.type = "number";
element.style = `
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).attr("value", $(this).val());
};
break;
case "NumberInput":
element = document.createElement("input");
element.type = "number";
element.style = `
height: 30px !important;
`;
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).attr("value", $(this).val());
};
break;
default:
element = document.createElement("input");
element.type = "text";
element.style = `
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).attr("value", $(this).val());
};
break;
default:
element = document.createElement("input");
element.type = "text";
element.style = `
height: 30px !important;
`;
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).attr("value", $(this).val());
};
break;
}
if (element) {
element.name = "automation_multiple_condition";
if (fieldItem.required) {
element.required = true;
element.className = "oh-input w-100";
if (fieldItem.max_length) {
element.maxLength = fieldItem.max_length;
}
element.onchange = function (event) {
$(this).attr("value", $(this).val());
};
break;
}
if (element) {
element.name = "automation_multiple_condition";
if (fieldItem.required) {
element.required = true;
}
// Create label
const label = document.createElement("label");
label.textContent = fieldItem.label;
label.htmlFor = "automation_multiple_condition";
// Create label
const label = document.createElement("label");
label.textContent = fieldItem.label;
label.htmlFor = "automation_multiple_condition";
return $(element);
}
return $(element);
}
}
function addSelectedAttr(event) {
const options = Array.from(event.target.options);
options.forEach((option) => {
if (option.selected) {
option.setAttribute("selected", "selected");
} else {
option.removeAttribute("selected");
}
});
const options = Array.from(event.target.options);
options.forEach((option) => {
if (option.selected) {
option.setAttribute("selected", "selected");
} else {
option.removeAttribute("selected");
}
});
}

View File

@@ -8,16 +8,21 @@
$(this).closest('.oh-accordion').toggleClass('oh-accordion--show');
});
$("#{{view_id}} form button").click(function (e) {
const form = document.getElementById('multipleConditionForm');
const elements = form.elements;
const queryString = Array.from(elements)
.filter(element => element.name && !element.disabled)
.map(element => encodeURIComponent(element.name) + '=' + encodeURIComponent(element.value))
$(document).on('click', '#{{view_id}}Form button[type="submit"]', function () {
const $mainForm = $('#{{view_id}}Form');
const conditionFormEl = $('#multipleConditionForm')[0];
if (!conditionFormEl) return;
const queryString = Array.from(conditionFormEl.elements)
.filter(el => el.name && !el.disabled)
.map(el => encodeURIComponent(el.name) + '=' + encodeURIComponent(el.value))
.join('&');
$("#{{view_id}} form [name=condition_querystring]").val(queryString);
html = $(".note-editable #multipleConditionForm").html()
$("#{{view_id}} form [name=condition_html]").val(html);
$mainForm.find('[name="condition_querystring"]').val(queryString);
const html = $(".note-editable #multipleConditionForm").html();
$mainForm.find('[name="condition_html"]').val(html);
});
$("#dynamic_field_condition").parent().removeClass("col-md-6");