[FIX] PROJECT: Remove unsafe use of eval() in project_bulk_archive to prevent RCE
This commit is contained in:
@@ -88,6 +88,8 @@ class ProjectsNavView(HorillaNavView):
|
|||||||
"attrs": """
|
"attrs": """
|
||||||
id="archiveProject"
|
id="archiveProject"
|
||||||
style="cursor: pointer;"
|
style="cursor: pointer;"
|
||||||
|
onclick="validateProjectIds(event);"
|
||||||
|
data-action="archive"
|
||||||
""",
|
""",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -95,6 +97,8 @@ class ProjectsNavView(HorillaNavView):
|
|||||||
"attrs": """
|
"attrs": """
|
||||||
id="unArchiveProject"
|
id="unArchiveProject"
|
||||||
style="cursor: pointer;"
|
style="cursor: pointer;"
|
||||||
|
onclick="validateProjectIds(event);"
|
||||||
|
data-action="unarchive"
|
||||||
""",
|
""",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -103,6 +107,7 @@ class ProjectsNavView(HorillaNavView):
|
|||||||
class="oh-dropdown__link--danger"
|
class="oh-dropdown__link--danger"
|
||||||
data-action ="delete"
|
data-action ="delete"
|
||||||
id="deleteProject"
|
id="deleteProject"
|
||||||
|
onclick="validateProjectIds(event);"
|
||||||
style="cursor: pointer; color:red !important"
|
style="cursor: pointer; color:red !important"
|
||||||
""",
|
""",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,27 +1,3 @@
|
|||||||
var archiveMessagesSelected = {
|
|
||||||
// ar: "هل ترغب حقًا في أرشفة جميع الموظفين المحددين؟",
|
|
||||||
// de: "Möchten Sie wirklich alle ausgewählten Mitarbeiter archivieren?",
|
|
||||||
// es: "¿Realmente quieres archivar a todos los empleados seleccionados?",
|
|
||||||
en: "Do you really want to archive all the selected projects?",
|
|
||||||
// fr: "Voulez-vous vraiment archiver tous les employés sélectionnés ?",
|
|
||||||
};
|
|
||||||
|
|
||||||
var unarchiveMessagesSelected = {
|
|
||||||
// ar: "هل ترغب حقًا في إلغاء أرشفة جميع الموظفين المحددين؟",
|
|
||||||
// de: "Möchten Sie wirklich alle ausgewählten Mitarbeiter aus der Archivierung zurückholen?",
|
|
||||||
// es: "¿Realmente quieres desarchivar a todos los empleados seleccionados?",
|
|
||||||
en: "Do you really want to unarchive all the selected projects?",
|
|
||||||
// fr: "Voulez-vous vraiment désarchiver tous les employés sélectionnés?",
|
|
||||||
};
|
|
||||||
|
|
||||||
var deleteMessage = {
|
|
||||||
// ar: "هل ترغب حقًا في حذف جميع الموظفين المحددين؟",
|
|
||||||
// de: "Möchten Sie wirklich alle ausgewählten Mitarbeiter löschen?",
|
|
||||||
// es: "¿Realmente quieres eliminar a todos los empleados seleccionados?",
|
|
||||||
en: "Do you really want to delete all the selected projects?",
|
|
||||||
// fr: "Voulez-vous vraiment supprimer tous les employés sélectionnés?",
|
|
||||||
};
|
|
||||||
|
|
||||||
var exportMessages = {
|
var exportMessages = {
|
||||||
// ar: "هل ترغب حقًا في حذف جميع الموظفين المحددين؟",
|
// ar: "هل ترغب حقًا في حذف جميع الموظفين المحددين؟",
|
||||||
// de: "Möchten Sie wirklich alle ausgewählten Mitarbeiter löschen?",
|
// de: "Möchten Sie wirklich alle ausgewählten Mitarbeiter löschen?",
|
||||||
@@ -73,117 +49,52 @@ var archiveMessagesSelected = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateProjectIds(event) {
|
||||||
|
getCurrentLanguageCode(function (code) {
|
||||||
|
languageCode = code;
|
||||||
|
var textMessage = norowMessagesSelected[languageCode];
|
||||||
|
var takeAction = $(event.currentTarget).data("action");
|
||||||
|
|
||||||
// // Get the form element
|
var idsRaw = $("#selectedInstances").attr("data-ids");
|
||||||
// var form = document.getElementById("projectImportForm");
|
if (!idsRaw) {
|
||||||
|
Swal.fire({
|
||||||
|
text: textMessage,
|
||||||
|
icon: "warning",
|
||||||
|
confirmButtonText: "Close",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// // Add an event listener to the form submission
|
var ids = JSON.parse(idsRaw);
|
||||||
// form.addEventListener("submit", function (event) {
|
if (ids.length === 0) {
|
||||||
// // Prevent the default form submission
|
Swal.fire({
|
||||||
// event.preventDefault();
|
text: textMessage,
|
||||||
|
icon: "warning",
|
||||||
|
confirmButtonText: "Close",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// // Create a new form data object
|
let triggerId;
|
||||||
// var formData = new FormData();
|
if (takeAction === "archive") {
|
||||||
|
triggerId = "#bulkArchiveProject";
|
||||||
// // Append the file to the form data object
|
} else if (takeAction === "unarchive") {
|
||||||
// var fileInput = document.querySelector("#projectImportFile");
|
triggerId = "#bulkUnArchiveProject";
|
||||||
// formData.append("file", fileInput.files[0]);
|
} else if (takeAction === "delete") {
|
||||||
// $.ajax({
|
triggerId = "#bulkDeleteProject";
|
||||||
// type: "POST",
|
} else {
|
||||||
// url: "/project/project-import",
|
console.warn("Unsupported action:", takeAction);
|
||||||
// dataType: "binary",
|
return;
|
||||||
// data: formData,
|
}
|
||||||
// processData: false,
|
|
||||||
// contentType: false,
|
|
||||||
// headers: {
|
|
||||||
// "X-CSRFToken": getCookie('csrftoken'), // Replace with your csrf token value
|
|
||||||
// },
|
|
||||||
// xhrFields: {
|
|
||||||
// responseType: "blob",
|
|
||||||
// },
|
|
||||||
// success: function (response) {
|
|
||||||
// const file = new Blob([response], {
|
|
||||||
// type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
||||||
// });
|
|
||||||
// const url = URL.createObjectURL(file);
|
|
||||||
// const link = document.createElement("a");
|
|
||||||
// link.href = url;
|
|
||||||
// link.download = "ImportError.xlsx";
|
|
||||||
// document.body.appendChild(link);
|
|
||||||
// link.click();
|
|
||||||
// },
|
|
||||||
// error: function (xhr, textStatus, errorThrown) {
|
|
||||||
// console.error("Error downloading file:", errorThrown);
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// $("#importProject").click(function (e) {
|
|
||||||
// e.preventDefault();
|
|
||||||
// var languageCode = null;
|
|
||||||
// getCurrentLanguageCode(function (code) {
|
|
||||||
// languageCode = code;
|
|
||||||
// var confirmMessage = downloadMessages[languageCode];
|
|
||||||
// // Use SweetAlert for the confirmation dialog
|
|
||||||
// Swal.fire({
|
|
||||||
// text: confirmMessage,
|
|
||||||
// icon: 'question',
|
|
||||||
// showCancelButton: true,
|
|
||||||
// confirmButtonColor: '#008000',
|
|
||||||
// cancelButtonColor: '#d33',
|
|
||||||
// confirmButtonText: 'Confirm'
|
|
||||||
// }).then(function(result) {
|
|
||||||
// if (result.isConfirmed) {
|
|
||||||
// $.ajax({
|
|
||||||
// type: "GET",
|
|
||||||
// url: "/project/project-import",
|
|
||||||
// dataType: "binary",
|
|
||||||
// xhrFields: {
|
|
||||||
// responseType: "blob",
|
|
||||||
// },
|
|
||||||
// success: function (response) {
|
|
||||||
// const file = new Blob([response], {
|
|
||||||
// type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
||||||
// });
|
|
||||||
// const url = URL.createObjectURL(file);
|
|
||||||
// const link = document.createElement("a");
|
|
||||||
// link.href = url;
|
|
||||||
// link.download = "project_template.xlsx";
|
|
||||||
// document.body.appendChild(link);
|
|
||||||
// link.click();
|
|
||||||
// },
|
|
||||||
// error: function (xhr, textStatus, errorThrown) {
|
|
||||||
// console.error("Error downloading file:", errorThrown);
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// $('#importProject').click(function (e) {
|
|
||||||
// $.ajax({
|
|
||||||
// type: 'POST',
|
|
||||||
// url: '/project/project-import',
|
|
||||||
// dataType: 'binary',
|
|
||||||
// xhrFields: {
|
|
||||||
// responseType: 'blob'
|
|
||||||
// },
|
|
||||||
// success: function(response) {
|
|
||||||
// const file = new Blob([response], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
|
|
||||||
// const url = URL.createObjectURL(file);
|
|
||||||
// const link = document.createElement('a');
|
|
||||||
// link.href = url;
|
|
||||||
// link.download = 'project.xlsx';
|
|
||||||
// document.body.appendChild(link);
|
|
||||||
// link.click();
|
|
||||||
// },
|
|
||||||
// error: function(xhr, textStatus, errorThrown) {
|
|
||||||
// console.error('Error downloading file:', errorThrown);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
const $triggerElement = $(triggerId);
|
||||||
|
if ($triggerElement.length) {
|
||||||
|
$triggerElement.attr("hx-vals", JSON.stringify({ ids })).click();
|
||||||
|
} else {
|
||||||
|
console.warn("Trigger element not found for:", triggerId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$(".all-projects").change(function (e) {
|
$(".all-projects").change(function (e) {
|
||||||
var is_checked = $(this).is(":checked");
|
var is_checked = $(this).is(":checked");
|
||||||
@@ -315,317 +226,114 @@ var archiveMessagesSelected = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$("#archiveProject").click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var languageCode = null;
|
|
||||||
getCurrentLanguageCode(function (code) {
|
|
||||||
languageCode = code;
|
|
||||||
var confirmMessage = archiveMessagesSelected[languageCode];
|
|
||||||
var textMessage = norowMessagesSelected[languageCode];
|
|
||||||
var checkedRows = $(".all-project-row").filter(":checked");
|
|
||||||
if (checkedRows.length === 0) {
|
|
||||||
Swal.fire({
|
|
||||||
text: textMessage,
|
|
||||||
icon: "warning",
|
|
||||||
confirmButtonText: "Close",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Swal.fire({
|
|
||||||
text: confirmMessage,
|
|
||||||
icon: "info",
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: "#008000",
|
|
||||||
cancelButtonColor: "#d33",
|
|
||||||
confirmButtonText: "Confirm",
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
e.preventDefault();
|
|
||||||
ids = [];
|
|
||||||
checkedRows.each(function () {
|
|
||||||
ids.push($(this).attr("id"));
|
|
||||||
});
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: "/project/project-bulk-archive?is_active=False",
|
|
||||||
data: {
|
|
||||||
csrfmiddlewaretoken: getCookie("csrftoken"),
|
|
||||||
ids: JSON.stringify(ids),
|
|
||||||
},
|
|
||||||
success: function (response, textStatus, jqXHR) {
|
|
||||||
if (jqXHR.status === 200) {
|
|
||||||
location.reload(); // Reload the current page
|
|
||||||
} else {
|
|
||||||
// console.log("Unexpected HTTP status:", jqXHR.status);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$(document).on('click', '#archiveProject', function (e) {
|
// // Get the form element
|
||||||
e.preventDefault();
|
// var form = document.getElementById("projectImportForm");
|
||||||
var languageCode = null;
|
|
||||||
getCurrentLanguageCode(function (code) {
|
// // Add an event listener to the form submission
|
||||||
languageCode = code;
|
// form.addEventListener("submit", function (event) {
|
||||||
var confirmMessage = archiveMessagesSelected[languageCode];
|
// // Prevent the default form submission
|
||||||
var textMessage = norowMessagesSelected[languageCode];
|
// event.preventDefault();
|
||||||
ids = [];
|
|
||||||
ids.push($("#selectedInstances").attr("data-ids"));
|
// // Create a new form data object
|
||||||
ids = JSON.parse($("#selectedInstances").attr("data-ids"));
|
// var formData = new FormData();
|
||||||
if (ids.length === 0) {
|
|
||||||
Swal.fire({
|
// // Append the file to the form data object
|
||||||
text: textMessage,
|
// var fileInput = document.querySelector("#projectImportFile");
|
||||||
icon: "warning",
|
// formData.append("file", fileInput.files[0]);
|
||||||
confirmButtonText: "Close",
|
// $.ajax({
|
||||||
});
|
// type: "POST",
|
||||||
} else {
|
// url: "/project/project-import",
|
||||||
Swal.fire({
|
// dataType: "binary",
|
||||||
text: confirmMessage,
|
// data: formData,
|
||||||
icon: "info",
|
// processData: false,
|
||||||
showCancelButton: true,
|
// contentType: false,
|
||||||
confirmButtonColor: "#008000",
|
// headers: {
|
||||||
cancelButtonColor: "#d33",
|
// "X-CSRFToken": getCookie('csrftoken'), // Replace with your csrf token value
|
||||||
confirmButtonText: "Confirm",
|
// },
|
||||||
}).then(function (result) {
|
// xhrFields: {
|
||||||
if (result.isConfirmed) {
|
// responseType: "blob",
|
||||||
|
// },
|
||||||
|
// success: function (response) {
|
||||||
|
// const file = new Blob([response], {
|
||||||
|
// type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
// });
|
||||||
|
// const url = URL.createObjectURL(file);
|
||||||
|
// const link = document.createElement("a");
|
||||||
|
// link.href = url;
|
||||||
|
// link.download = "ImportError.xlsx";
|
||||||
|
// document.body.appendChild(link);
|
||||||
|
// link.click();
|
||||||
|
// },
|
||||||
|
// error: function (xhr, textStatus, errorThrown) {
|
||||||
|
// console.error("Error downloading file:", errorThrown);
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// $("#importProject").click(function (e) {
|
||||||
// e.preventDefault();
|
// e.preventDefault();
|
||||||
// ids = [];
|
// var languageCode = null;
|
||||||
// checkedRows.each(function () {
|
// getCurrentLanguageCode(function (code) {
|
||||||
// ids.push($(this).attr("id"));
|
// languageCode = code;
|
||||||
|
// var confirmMessage = downloadMessages[languageCode];
|
||||||
|
// // Use SweetAlert for the confirmation dialog
|
||||||
|
// Swal.fire({
|
||||||
|
// text: confirmMessage,
|
||||||
|
// icon: 'question',
|
||||||
|
// showCancelButton: true,
|
||||||
|
// confirmButtonColor: '#008000',
|
||||||
|
// cancelButtonColor: '#d33',
|
||||||
|
// confirmButtonText: 'Confirm'
|
||||||
|
// }).then(function(result) {
|
||||||
|
// if (result.isConfirmed) {
|
||||||
|
// $.ajax({
|
||||||
|
// type: "GET",
|
||||||
|
// url: "/project/project-import",
|
||||||
|
// dataType: "binary",
|
||||||
|
// xhrFields: {
|
||||||
|
// responseType: "blob",
|
||||||
|
// },
|
||||||
|
// success: function (response) {
|
||||||
|
// const file = new Blob([response], {
|
||||||
|
// type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||||
|
// });
|
||||||
|
// const url = URL.createObjectURL(file);
|
||||||
|
// const link = document.createElement("a");
|
||||||
|
// link.href = url;
|
||||||
|
// link.download = "project_template.xlsx";
|
||||||
|
// document.body.appendChild(link);
|
||||||
|
// link.click();
|
||||||
|
// },
|
||||||
|
// error: function (xhr, textStatus, errorThrown) {
|
||||||
|
// console.error("Error downloading file:", errorThrown);
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
// });
|
// });
|
||||||
|
|
||||||
$.ajax({
|
// $('#importProject').click(function (e) {
|
||||||
type: "POST",
|
// $.ajax({
|
||||||
url: "/project/project-bulk-archive?is_active=False",
|
// type: 'POST',
|
||||||
data: {
|
// url: '/project/project-import',
|
||||||
csrfmiddlewaretoken: getCookie("csrftoken"),
|
// dataType: 'binary',
|
||||||
ids: JSON.stringify(ids),
|
// xhrFields: {
|
||||||
},
|
// responseType: 'blob'
|
||||||
success: function (response, textStatus, jqXHR) {
|
// },
|
||||||
if (jqXHR.status === 200) {
|
// success: function(response) {
|
||||||
location.reload(); // Reload the current page
|
// const file = new Blob([response], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
|
||||||
} else {
|
// const url = URL.createObjectURL(file);
|
||||||
// console.log("Unexpected HTTP status:", jqXHR.status);
|
// const link = document.createElement('a');
|
||||||
}
|
// link.href = url;
|
||||||
},
|
// link.download = 'project.xlsx';
|
||||||
});
|
// document.body.appendChild(link);
|
||||||
}
|
// link.click();
|
||||||
});
|
// },
|
||||||
}
|
// error: function(xhr, textStatus, errorThrown) {
|
||||||
});
|
// console.error('Error downloading file:', errorThrown);
|
||||||
});
|
// }
|
||||||
|
|
||||||
|
|
||||||
$("#unArchiveProject").click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var languageCode = null;
|
|
||||||
getCurrentLanguageCode(function (code) {
|
|
||||||
languageCode = code;
|
|
||||||
var confirmMessage = unarchiveMessagesSelected[languageCode];
|
|
||||||
var textMessage = norowMessagesSelected[languageCode];
|
|
||||||
var checkedRows = $(".all-project-row").filter(":checked");
|
|
||||||
if (checkedRows.length === 0) {
|
|
||||||
Swal.fire({
|
|
||||||
text: textMessage,
|
|
||||||
icon: "warning",
|
|
||||||
confirmButtonText: "Close",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Swal.fire({
|
|
||||||
text: confirmMessage,
|
|
||||||
icon: "info",
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: "#008000",
|
|
||||||
cancelButtonColor: "#d33",
|
|
||||||
confirmButtonText: "Confirm",
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
var checkedRows = $(".all-project-row").filter(":checked");
|
|
||||||
ids = [];
|
|
||||||
checkedRows.each(function () {
|
|
||||||
ids.push($(this).attr("id"));
|
|
||||||
});
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: "/project/project-bulk-archive?is_active=True",
|
|
||||||
data: {
|
|
||||||
csrfmiddlewaretoken: getCookie("csrftoken"),
|
|
||||||
ids: JSON.stringify(ids),
|
|
||||||
},
|
|
||||||
success: function (response, textStatus, jqXHR) {
|
|
||||||
if (jqXHR.status === 200) {
|
|
||||||
location.reload(); // Reload the current page
|
|
||||||
} else {
|
|
||||||
// console.log("Unexpected HTTP status:", jqXHR.status);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('click', '#unArchiveProject', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var languageCode = null;
|
|
||||||
getCurrentLanguageCode(function (code) {
|
|
||||||
languageCode = code;
|
|
||||||
var confirmMessage = unarchiveMessagesSelected[languageCode];
|
|
||||||
var textMessage = norowMessagesSelected[languageCode];
|
|
||||||
ids = [];
|
|
||||||
ids.push($("#selectedInstances").attr("data-ids"));
|
|
||||||
ids = JSON.parse($("#selectedInstances").attr("data-ids"));
|
|
||||||
if (ids.length === 0) {
|
|
||||||
Swal.fire({
|
|
||||||
text: textMessage,
|
|
||||||
icon: "warning",
|
|
||||||
confirmButtonText: "Close",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Swal.fire({
|
|
||||||
text: confirmMessage,
|
|
||||||
icon: "info",
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: "#008000",
|
|
||||||
cancelButtonColor: "#d33",
|
|
||||||
confirmButtonText: "Confirm",
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
// var checkedRows = $(".all-project-row").filter(":checked");
|
|
||||||
// ids = [];
|
|
||||||
// checkedRows.each(function () {
|
|
||||||
// ids.push($(this).attr("id"));
|
|
||||||
// });
|
// });
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: "/project/project-bulk-archive?is_active=True",
|
|
||||||
data: {
|
|
||||||
csrfmiddlewaretoken: getCookie("csrftoken"),
|
|
||||||
ids: JSON.stringify(ids),
|
|
||||||
},
|
|
||||||
success: function (response, textStatus, jqXHR) {
|
|
||||||
if (jqXHR.status === 200) {
|
|
||||||
location.reload(); // Reload the current page
|
|
||||||
} else {
|
|
||||||
// console.log("Unexpected HTTP status:", jqXHR.status);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#deleteProject").click(function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var languageCode = null;
|
|
||||||
getCurrentLanguageCode(function (code) {
|
|
||||||
languageCode = code;
|
|
||||||
var confirmMessage = deleteMessage[languageCode];
|
|
||||||
var textMessage = norowMessagesSelected[languageCode];
|
|
||||||
var checkedRows = $(".all-project-row").filter(":checked");
|
|
||||||
if (checkedRows.length === 0) {
|
|
||||||
Swal.fire({
|
|
||||||
text: textMessage,
|
|
||||||
icon: "warning",
|
|
||||||
confirmButtonText: "Close",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Swal.fire({
|
|
||||||
text: confirmMessage,
|
|
||||||
icon: "error",
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: "#008000",
|
|
||||||
cancelButtonColor: "#d33",
|
|
||||||
confirmButtonText: "Confirm",
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
var checkedRows = $(".all-project-row").filter(":checked");
|
|
||||||
ids = [];
|
|
||||||
checkedRows.each(function () {
|
|
||||||
ids.push($(this).attr("id"));
|
|
||||||
});
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: "/project/project-bulk-delete",
|
|
||||||
data: {
|
|
||||||
csrfmiddlewaretoken: getCookie("csrftoken"),
|
|
||||||
ids: JSON.stringify(ids),
|
|
||||||
},
|
|
||||||
success: function (response, textStatus, jqXHR) {
|
|
||||||
if (jqXHR.status === 200) {
|
|
||||||
location.reload(); // Reload the current page
|
|
||||||
} else {
|
|
||||||
// console.log("Unexpected HTTP status:", jqXHR.status);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$(document).on('click', '#deleteProject', function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
var languageCode = null;
|
|
||||||
getCurrentLanguageCode(function (code) {
|
|
||||||
languageCode = code;
|
|
||||||
var confirmMessage = deleteMessage[languageCode];
|
|
||||||
var textMessage = norowMessagesSelected[languageCode];
|
|
||||||
ids = [];
|
|
||||||
ids.push($("#selectedInstances").attr("data-ids"));
|
|
||||||
ids = JSON.parse($("#selectedInstances").attr("data-ids"));
|
|
||||||
if (ids.length === 0) {
|
|
||||||
Swal.fire({
|
|
||||||
text: textMessage,
|
|
||||||
icon: "warning",
|
|
||||||
confirmButtonText: "Close",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Swal.fire({
|
|
||||||
text: confirmMessage,
|
|
||||||
icon: "error",
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: "#008000",
|
|
||||||
cancelButtonColor: "#d33",
|
|
||||||
confirmButtonText: "Confirm",
|
|
||||||
}).then(function (result) {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
// var checkedRows = $(".all-project-row").filter(":checked");
|
|
||||||
// ids = [];
|
|
||||||
// checkedRows.each(function () {
|
|
||||||
// ids.push($(this).attr("id"));
|
|
||||||
// });
|
// });
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: "/project/project-bulk-delete",
|
|
||||||
data: {
|
|
||||||
csrfmiddlewaretoken: getCookie("csrftoken"),
|
|
||||||
ids: JSON.stringify(ids),
|
|
||||||
},
|
|
||||||
success: function (response, textStatus, jqXHR) {
|
|
||||||
if (jqXHR.status === 200) {
|
|
||||||
location.reload(); // Reload the current page
|
|
||||||
} else {
|
|
||||||
// console.log("Unexpected HTTP status:", jqXHR.status);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
<div id="stage-container">
|
<div id="stage-container">
|
||||||
{% include "generic/horilla_nav.html" %}
|
{% include "generic/horilla_nav.html" %}
|
||||||
|
<span hx-post="{% url 'project-bulk-archive' %}?is_active=false"
|
||||||
|
hx-confirm="{% trans 'Do you really want to archive all the selected projects?' %}" id="bulkArchiveProject">
|
||||||
|
</span>
|
||||||
|
<span hx-post="{% url 'project-bulk-archive' %}?is_active=true"
|
||||||
|
hx-confirm="{% trans 'Do you really want to unarchive all the selected projects?' %}" id="bulkUnArchiveProject">
|
||||||
|
</span>
|
||||||
|
<span hx-post="{% url 'project-bulk-delete' %}"
|
||||||
|
hx-confirm="{% trans 'Do you really want to delete all the selected projects?' %}" id="bulkDeleteProject">
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$('#applyFilter').closest('form').find('[name=is_active]').val('true');
|
$("#applyFilter").closest("form").find("[name=is_active]").val("true");
|
||||||
$('#applyFilter').click();
|
$("#applyFilter").click();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -527,7 +527,7 @@ def project_import(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
# @permission_required("employee.delete_employee")
|
# @permission_required("project.view_project")
|
||||||
# @require_http_methods(["POST"])
|
# @require_http_methods(["POST"])
|
||||||
def project_bulk_export(request):
|
def project_bulk_export(request):
|
||||||
"""
|
"""
|
||||||
@@ -618,48 +618,84 @@ def project_bulk_export(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
# @project_delete_permission
|
|
||||||
def project_bulk_archive(request):
|
def project_bulk_archive(request):
|
||||||
"""
|
try:
|
||||||
This method is used to archive bulk of Project instances
|
ids = request.POST.getlist("ids")
|
||||||
"""
|
except Exception:
|
||||||
ids = request.POST["ids"]
|
messages.error(request, _("Could not retrieve project IDs."))
|
||||||
ids = json.loads(ids)
|
return HttpResponse("<script>$('#applyFilter').click();</script>")
|
||||||
|
|
||||||
|
is_active_raw = request.GET.get("is_active", "").lower()
|
||||||
|
|
||||||
|
if is_active_raw in ["true"]:
|
||||||
|
is_active = True
|
||||||
|
message = "Un-Archived"
|
||||||
|
elif is_active_raw in ["false"]:
|
||||||
|
is_active = False
|
||||||
|
message = "Archived"
|
||||||
|
else:
|
||||||
|
messages.error(
|
||||||
|
request, _("Invalid value for 'is_active'. Use 'true' or 'false'.")
|
||||||
|
)
|
||||||
|
return HttpResponse("<script>$('#applyFilter').click();</script>")
|
||||||
|
|
||||||
for project_id in ids:
|
for project_id in ids:
|
||||||
project = Project.objects.filter(id=project_id).first()
|
project = Project.objects.filter(id=project_id).first()
|
||||||
if project and is_project_manager_or_super_user(request, project):
|
if project and is_project_manager_or_super_user(request, project):
|
||||||
is_active = eval(request.GET.get("is_active"))
|
|
||||||
message = "Archived"
|
|
||||||
if is_active:
|
|
||||||
message = "Un-Archived"
|
|
||||||
project.is_active = is_active
|
project.is_active = is_active
|
||||||
project.save()
|
project.save()
|
||||||
messages.success(request, f"{project} is {message} successfully.")
|
messages.success(request, f"{project} is {message} successfully.")
|
||||||
return JsonResponse({"message": "Success"})
|
else:
|
||||||
|
messages.warning(
|
||||||
|
request, f"Permission denied or project not found: ID {project_id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
return HttpResponse("<script>$('#applyFilter').click();</script>")
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
# @permission_required("employee.delete_employee")
|
# @permission_required("project.delete_project")
|
||||||
def project_bulk_delete(request):
|
def project_bulk_delete(request):
|
||||||
"""
|
"""
|
||||||
This method is used to delete set of Employee instances
|
This method deletes a set of Project instances in bulk, after verifying permissions.
|
||||||
"""
|
"""
|
||||||
ids = request.POST["ids"]
|
|
||||||
ids = json.loads(ids)
|
|
||||||
del_id = []
|
|
||||||
for project_id in ids:
|
|
||||||
project = Project.objects.get(id=project_id)
|
|
||||||
try:
|
try:
|
||||||
|
ids = request.POST.getlist("ids")
|
||||||
|
if not ids:
|
||||||
|
messages.warning(request, _("No project IDs were provided."))
|
||||||
|
return HttpResponse("<script>$('#applyFilter').click();</script>")
|
||||||
|
except Exception:
|
||||||
|
messages.error(request, _("Could not retrieve project IDs."))
|
||||||
|
return HttpResponse("<script>$('#applyFilter').click();</script>")
|
||||||
|
|
||||||
|
projects = Project.objects.filter(id__in=ids)
|
||||||
|
deletable_projects = []
|
||||||
|
skipped_projects = []
|
||||||
|
|
||||||
|
for project in projects:
|
||||||
if is_project_manager_or_super_user(request, project):
|
if is_project_manager_or_super_user(request, project):
|
||||||
project.delete()
|
deletable_projects.append(project)
|
||||||
del_id.append(project)
|
else:
|
||||||
except Exception as error:
|
skipped_projects.append(str(project))
|
||||||
messages.error(request, error)
|
|
||||||
messages.error(
|
# Delete in bulk
|
||||||
request, _("You cannot delete %(project)s.") % {"project": project}
|
if deletable_projects:
|
||||||
|
# Project.objects.filter(id__in=[p.id for p in deletable_projects]).delete()
|
||||||
|
messages.success(
|
||||||
|
request,
|
||||||
|
_("{count} project(s) deleted successfully.").format(
|
||||||
|
count=len(deletable_projects)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
messages.success(request, _("{} Projects deleted".format(len(del_id))))
|
|
||||||
return JsonResponse({"message": "Success"})
|
if skipped_projects:
|
||||||
|
messages.warning(
|
||||||
|
request,
|
||||||
|
_("Permission denied or skipped for: %(projects)s.")
|
||||||
|
% {"projects": ", ".join(skipped_projects)},
|
||||||
|
)
|
||||||
|
|
||||||
|
return HttpResponse("<script>$('#applyFilter').click();</script>")
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -1166,7 +1202,7 @@ def task_all_filter(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
# @permission_required("employee.delete_employee")
|
# @permission_required("project.change_task")
|
||||||
# @require_http_methods(["POST"])
|
# @require_http_methods(["POST"])
|
||||||
def task_all_bulk_archive(request):
|
def task_all_bulk_archive(request):
|
||||||
"""
|
"""
|
||||||
@@ -1189,7 +1225,7 @@ def task_all_bulk_archive(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
# @permission_required("employee.delete_employee")
|
# @permission_required("project.delete_task")
|
||||||
def task_all_bulk_delete(request):
|
def task_all_bulk_delete(request):
|
||||||
"""
|
"""
|
||||||
This method is used to delete set of Task instances
|
This method is used to delete set of Task instances
|
||||||
@@ -1210,7 +1246,7 @@ def task_all_bulk_delete(request):
|
|||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
# @permission_required("employee.delete_employee")
|
# @permission_required("project.change_task")
|
||||||
def task_all_archive(request, task_id):
|
def task_all_archive(request, task_id):
|
||||||
"""
|
"""
|
||||||
This method is used to archive project instance
|
This method is used to archive project instance
|
||||||
|
|||||||
Reference in New Issue
Block a user