|
|
<!DOCTYPE html><html lang="en" dir=""><html xmlns:th="http://www.thymeleaf.org"><head th:replace="~{fragments/modules/base/head :: head}"></head><style>.required{ color: red;}
/* Custom CSS for SweetAlert2 */.swal-container { display: flex; align-items: center; justify-content: center;}
.swal-popup { width: 80% !important; /* Adjust width as needed */ max-width: 600px; /* Max width for larger screens */ border-radius: 8px; /* Optional: round the corners */ padding: 2rem; /* Optional: adjust padding */}
.swal-confirm-button { background-color: #dc3545; /* Example: red background for delete button */ border: none; color: #fff;}
.swal-cancel-button { background-color: #6c757d; /* Example: gray background for cancel button */ border: none; color: #fff;}
#addcategoryform .modal-body { max-height: 500px; /* Set max height */ overflow-y: auto; /* Enable vertical scrolling when content overflows */}
#editCategoryModal .modal-body { max-height: 500px; /* Set max height */ overflow-y: auto; /* Enable vertical scrolling when content overflows */}
</style> <body> <!--[if lt IE 8]>
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> <![endif]-->
<div class="wrapper"> <!-- header top menu Start --> <header th:replace="~{fragments/modules/base/header :: header}"></header> <!-- header top menu end -->
<div class="page-wrap"> <!--=============== Left Menu side Start ================--> <div th:replace="~{fragments/modules/base/menu :: menu}"></div> <!--=============== Left side End ================--> <div class="main-content"> <div class="container-fluid"> <div class="page-header mb-2"> <div class="row align-items-end"> <div class="col-lg-8"> <div class="page-header-title"> <i class="fas fa-th-large bg-blue"></i> <div class="d-inline"> <h5>Add Category</h5> <span>1913 Add Category</span> </div> </div> </div> <div class="col-lg-4"> <nav class="breadcrumb-container" aria-label="breadcrumb"> <ol class="breadcrumb"> <li class="breadcrumb-item"><a href="/gcc/index"><i class="ik ik-home"></i></a></li> <li class="breadcrumb-item" aria-current="page">1913 Campaign</li> <li class="breadcrumb-item active" aria-current="page">Add Category</li> </ol> </nav> </div> </div> </div> <h4 class="h4 text-right text-mute" style="font-size: 12px;"> Auot refresh in <font id="refresh-countdown">00</font> seconds </h4> <div class="row"> <div class="col-md-12"> <div class="card"> <div class="card-block"> <div class="page-header-title" > <h5 style="margin: 0;font-weight: bold;">Category List</h5><hr> </div> <div> <table id="categoryDatatable" class="table table-striped table-bordered table-hover dataTable" role="grid" width="100%"> <thead class="thead-dark"> <tr role="row"> <th class="text-center no-sort">S.No</th> <th class="text-center">Category</th> <th class="text-center no-sort">Action</th> </tr> </thead> <tbody> <tr th:each="category, iterStat : ${categories}"> <td class="text-center" th:text="${iterStat.index + 1}"></td> <td class="text-center" th:text="${category.category_name}"></td> <td class="text-center"> <a href="#" th:onclick="return callEdit([[${category.category_id}]])" data-animation="true" data-toggle="tooltip" data-placement="top" title="Edit" data-original-title="Edit"> <i class="ik ik-edit f-16 mr-15 text-green"></i> </a> <!-- Delete button --> <a href="javascript:void(0);" th:onclick="return openDeleteModal([[${category.category_id}]])" title="Delete"> <i class="ik ik-trash-2 f-16 text-red ml-4"></i> </a> </td> </tr> </tbody>
<tfoot class="thead-dark"> <tr> <th class="text-center no-sort">S.No</th> <th class="text-center">Category</th> <th class="text-center no-sort">Action</th> </tr> </tfoot> </table> </div> </div> </div> </div> </div> </div> </div>
<footer th:replace="~{fragments/modules/base/footer :: footer}"></footer> </div> </div> <!-- Category Modal Form --> <div class="modal fade" id="addcategoryform" tabindex="-1" role="dialog"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Category Form</h5> <button type="button" class="close" data-dismiss="modal">×</button> </div> <div class="modal-body"> <form id="addCategoryForm"> <div class="form-group"> <label>Category Name <span class="required">*</span></label> <input type="text" class="form-control" id="categoryname" name="categoryname" placeholder="Enter Category Name" required> </div> <div id="columnInputs"> <label>Column Name <span class="required">*</span></label> <div class="form-group row column-group"> <div class="col-sm-10"> <input type="text" class="form-control columnname" name="columns[]" placeholder="Column Name" required> </div> <div class="col-sm-2"> <button type="button" class="btn btn-danger remove-column">×</button> </div> </div> </div> <button type="button" class="btn btn-primary" id="addMoreColumn">+ Add Column</button> <button type="button" class="btn btn-success" id="createCategoryBtn">Save Category</button> </form> </div> </div> </div> </div>
<!-- Edit Category Modal --> <div class="modal fade" id="editCategoryModal" tabindex="-1" role="dialog" aria-labelledby="editCategoryModalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="editCategoryModalLabel">Edit Category</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form id="editCategoryForm"> <input type="hidden" id="categoryId" name="categoryId"> <div class="form-group"> <label for="showcategoryName">Category Name <span class="required">*</span></label> <input type="text" class="form-control" id="showcategoryName" name="showcategoryName" required readonly="readonly"> </div> <div id="editColumnInputs"></div> <div id="editaddColumnInputs"></div> <hr> <button type="button" class="btn btn-success" id="addMoreEditColumn">+ Add Column</button> <button type="button" class="btn btn-primary" id="updateCategoryButton">Save Changes</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </form> </div> </div> </div> </div>
<!-- Delete Confirmation Modal --> <div class="modal fade" id="deleteCategoryModal" tabindex="-1" role="dialog" aria-labelledby="deleteCategoryModalLabel" aria-hidden="true"> <div class="modal-dialog modal-lg" role="document"> <!-- Add modal-lg here --> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="deleteCategoryModalLabel">Confirm Deletion</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <p>Are you sure you want to delete this category?</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button> <button type="button" class="btn btn-danger" id="confirmDeleteButton">Delete</button> </div> </div> </div> </div>
<div th:replace="~{fragments/modules/base/app_module_menu_box :: div}"></div> <script th:replace="~{fragments/modules/base/script :: script}"></script> <script src="node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script> $(document).ready(function () { // Initialize DataTables with export buttons var buttons = [ { extend: 'pageLength', className: 'btn btn-warning' }, { title: 'Data export', extend: 'copyHtml5', text: 'Copy', className: 'btn btn-secondary' }, { extend: 'excelHtml5', text: 'Excel', className: 'btn btn-secondary' }, { extend: 'csvHtml5', text: 'CSV', className: 'btn btn-secondary' }, { extend: 'pdfHtml5', text: 'PDF', className: 'btn btn-secondary' }, { text: '<i class="far fa-plus-square"></i> Add New Category', className: 'btn btn-warning', action: function () { callAdd(); // Now it will work }
} ];
$('#categoryDatatable').DataTable({ dom: 'Bftip', columnDefs: [ { targets: 'no-sort', orderable: false } ], lengthMenu: [ [50, 100, 200, 500, -1], ['50 rows', '100 rows', '200 rows', '500 rows', 'Show all'] ], scrollY: '30vh', fixedColumns: { left: 1, right: 1 }, buttons: buttons, fixedHeader: true, autoWidth: true, responsive: true, searching: false, select: false, processing: false, });
// Show Modal function callAdd() { resetForm(); $('#addcategoryform').modal({ backdrop: 'static', keyboard: false }); $('#addcategoryform').modal('show'); }
// Reset Form function resetForm() { $('#addCategoryForm')[0].reset(); $("#columnInputs .column-group:not(:first)").remove(); $(".remove-column").hide(); } //validateColumns function validateColumns(columns) { let columnSet = new Set(); let regex = /^[A-Za-z0-9_ ]+$/; // Allow alphabets, numbers, underscores, and spaces let invalidRegex = /^[_ ]+$/; // Match column names with only underscores and/or spaces
for (let col of columns) { if (!regex.test(col)) { Swal.fire({ title: "Validation Error", text: "Column names must contain only alphabets (A-Z, a-z), numbers (0-9), underscores (_), and spaces.", icon: "warning", confirmButtonText: "OK" }); return false; } if (invalidRegex.test(col)) { Swal.fire({ title: "Validation Error", text: "Column names cannot contain only spaces and underscores (_).", icon: "warning", confirmButtonText: "OK" }); return false; } let trimmedCol = col.trim().toLowerCase(); // Trim spaces for uniqueness check if (columnSet.has(trimmedCol)) { Swal.fire({ title: "Validation Error", text: "Duplicate column names are not allowed.", icon: "warning", confirmButtonText: "OK" }); return false; } columnSet.add(trimmedCol); } return true;}
// Add default fields on page load /* var defaultFields = ` <div class="form-group row column-group"> <div class="col-sm-10"> <input type="text" class="form-control" name="columns[]" value="name" readonly> <input type="text" class="form-control" name="columns[]" value="mobilenumber" readonly> <input type="text" class="form-control" name="columns[]" value="address" readonly> </div> </div>`; $('#columnInputs').append(defaultFields); */ var defaultFields = ` <div class="form-group row column-group"> <div class="col-sm-10"> <input type="text" class="form-control" name="columns[]" value="Name" > </div> </div> <div class="form-group row column-group"> <div class="col-sm-10"> <input type="text" class="form-control" name="columns[]" value="Mobilenumber" > </div> </div>
</div>`;
$('#columnInputs').append(defaultFields);
$('#addcategoryform').on('shown.bs.modal', function () { $('#columnInputs').html(''); // Clear existing columns $('#columnInputs').append(defaultFields); // Append default values });
$('#addcategoryform').on('hidden.bs.modal', function () { $('#categoryname').val(""); // Reset category name $('#columnInputs').html(""); // Clear all columns }); $('#editCategoryModal').on('hidden.bs.modal', function () { $('#editColumnInputs').html(''); // Clear all columns when modal is closed $('#editaddColumnInputs').html(''); // Clear additional columns if applicable });
// Add More Column Fields $('#addMoreColumn').click(function () { var newColumnField = ` <div class="form-group row column-group"> <div class="col-sm-10"> <input type="text" class="form-control columnname" name="columns[]" placeholder="Column Name" required> </div> <div class="col-sm-2"> <button type="button" class="btn btn-danger remove-column">×</button> </div> </div>`; $('#columnInputs').append(newColumnField); $('.remove-column').show(); });
// Remove Column Field $(document).on('click', '.remove-column', function () { $(this).closest('.column-group').remove(); if ($('.column-group').length === 1) { $('.remove-column').hide(); } }); $('#createCategoryBtn').click(function () { var categoryName = $('#categoryname').val().trim(); //var columnNames = $('.columnname').map(function () { var columnNames = $('input[name="columns[]"]').map(function () { return $(this).val().trim(); }).get().filter(name => name !== "");
console.log("categoryName=", categoryName); console.log("columnNames=", columnNames);
if (categoryName === "") { Swal.fire({ title: "Validation Error", text: "Please enter a category name.", icon: "warning", confirmButtonText: "OK" }); return; }
if (columnNames.length < 2) { Swal.fire({ title: "Validation Error", text: "Please enter at least two column names.", icon: "warning", confirmButtonText: "OK" }); return; }
if (!validateColumns(columnNames)) { return; } $('#createCategoryBtn').prop('disabled', true).text('Processing...');
$.ajax({ url: '/gcc/api/category/save', type: 'POST', contentType: 'application/json', data: JSON.stringify({ categoryname: categoryName, columns: columnNames }), success: function (response) { $('#createCategoryBtn').prop('disabled', false).text('Save Category'); Swal.fire({ title: "Success", text: "Category saved successfully!", icon: "success", confirmButtonText: "OK" }).then(function () { $('#addcategoryform').modal('hide'); $('#createCategoryBtn').prop('disabled', false).text('Save Category'); location.reload(); }); }, error: function (error) { $('#createCategoryBtn').prop('disabled', false).text('Save Category'); Swal.fire({ title: "Error", text: error.responseText, icon: "error", confirmButtonText: "OK" }); } }); }); /* $('#createCategoryBtn').click(function () { var categoryName = $('#categoryname').val().trim(); var columnNames = $('.columnname').map(function () { return $(this).val().trim(); }).get().filter(name => name !== ""); console.log("categoryName=========="+categoryName); console.log("columnNames=========="+columnNames); // Validation: Ensure category name is not empty and at least two columns are provided if (categoryName === "") { Swal.fire({ title: 'Validation Error', text: 'Please enter a category name.', icon: 'warning', confirmButtonText: 'OK' }); return; }
if (columnNames.length < 2) { Swal.fire({ title: 'Validation Error', text: 'Please enter at least two column names.', icon: 'warning', confirmButtonText: 'OK' }); return; } // Proceed with AJAX request if validation passes $.ajax({ url: '/gcc/api/category/save', type: 'POST', contentType: 'application/json', data: JSON.stringify({ categoryname: categoryName, columns: columnNames }), success: function (response) { Swal.fire({ title: 'Success', text: 'Category saved successfully!', icon: 'success', confirmButtonText: 'OK' }).then(function () { $('#addcategoryform').modal('hide'); location.reload(); }); }, error: function (error) { Swal.fire({ title: 'Error', text: error.responseText, icon: 'error', confirmButtonText: 'OK' }); } }); }); */ // Function to fetch category details and populate the edit modal window.callEdit = function (categoryId) { fetchCategoryDetails(categoryId); return false; };
function fetchCategoryDetails(categoryId) { $.ajax({ url: '/gcc/api/category/showcategoryId', type: 'GET', data: { category_id: categoryId }, success: function (response) { if (response) { $('#categoryId').val(response.category_id); $('#showcategoryName').val(response.category_name);
$('#editColumnInputs').empty(); $('#editaddColumnInputs').empty(); if (response.columns && response.columns.length > 0) { response.columns.forEach(col => addEditColumnField(col.id, col.column_name)); } else { addEditColumnField(); }
$('#editCategoryModal').modal({ backdrop: 'static', keyboard: false }); } else { Swal.fire('Error', 'Category not found.', 'error'); } }, error: function (xhr) { Swal.fire('Error', 'Error fetching category details: ' + xhr.responseText, 'error'); } }); }
function addEditColumnField(id = "", value = "", containerId = "editColumnInputs") { let removeButton = containerId === "editColumnInputs" ? `<button type="button" class="btn btn-danger" onclick="removeColumn(this, '${id}')">×</button>` : `<button type="button" class="btn btn-danger remove-column">×</button>`;
let columnField = ` <div class="form-group row column-group"> <input type="hidden" class="showcolumnId" value="${id}"> <div class="col-sm-10"> <input type="text" class="form-control showcolumnname" name="columns[]" placeholder="Column Name" value="${value}" required> </div> <div class="col-sm-2"> ${removeButton} </div> </div>`; $('#' + containerId).append(columnField); }
$('#addMoreEditColumn').click(function () { addEditColumnField("", "", "editaddColumnInputs"); }); $(document).ready(function () { window.removeColumn = function (button, columnId) { if (columnId) { Swal.fire({ title: "Are you sure?", text: "This column will be permanently deleted!", icon: "warning", showCancelButton: true, confirmButtonColor: "#d33", cancelButtonColor: "#3085d6", confirmButtonText: "Yes, delete it!" }).then((result) => { if (result.isConfirmed) { $.ajax({ url: '/gcc/api/category/deleteColumnById', type: 'POST', data: { columnId: columnId }, success: function (response) { if (response.success) { $(button).closest('.column-group').remove(); Swal.fire({ title: "Deleted!", text: "Column has been removed.", icon: "success", timer: 2000, // Auto-close after 2 seconds showConfirmButton: false }); } else { Swal.fire({ title: "Error", text: "Unable to delete column. Try again.", icon: "error", timer: 2000, // Auto-close after 2 seconds showConfirmButton: false }); } }, error: function (xhr) { Swal.fire("Error", "Something went wrong: " + xhr.responseText, "error"); } }); } }); } else { console.log("columnId=" + columnId); Swal.fire("Error!", "Problem in columnId", "error"); } }; });
// Event to remove column input dynamically $(document).on('click', '.remove-column', function () { $(this).closest('.column-group').remove(); }); $('#updateCategoryButton').click(function () { let categoryId = parseInt($('#categoryId').val(), 10);
let existingColumns = []; $('#editColumnInputs .column-group').each(function () { let columnId = parseInt($(this).find('.showcolumnId').val(), 10); let columnName = $(this).find('.showcolumnname').val(); if (columnName.trim() !== "") { existingColumns.push({ id: columnId, name: columnName }); } });
let newColumns = []; $('#editaddColumnInputs .column-group').each(function () { let columnName = $(this).find('.showcolumnname').val(); if (columnName.trim() !== "") { newColumns.push({ name: columnName }); } });
console.log("Category ID:", categoryId); console.log("Existing Columns:", existingColumns); console.log("New Columns:", newColumns);
let allColumnNames = [...existingColumns.map(col => col.name), ...newColumns.map(col => col.name)];
console.log("allColumnNames="+allColumnNames); if ((existingColumns.length + newColumns.length) < 2) { Swal.fire({ title: "Info", text: "You must have at least 2 columns!", icon: "info", confirmButtonText: "OK" }); return; }
if (!validateColumns(allColumnNames)) { return; } $('#updateCategoryButton').prop('disabled', true).text('Processing');
$.ajax({ url: '/gcc/api/category/updateCategoryColumns', type: 'POST', contentType: 'application/json', data: JSON.stringify({ categoryId: categoryId, columns: existingColumns }), success: function (response) { $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); if (response.success) { Swal.fire({ title: "Success!", text: "Category updated successfully!", icon: "success", showConfirmButton: false, timer: 2000 }).then(() => { $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); location.reload(); }); } else { $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); Swal.fire({ title: "Error", text: "Unable to update column. Try again.", icon: "error", showConfirmButton: true }); } }, error: function (xhr) { $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); Swal.fire("Error", "Failed to update category: " + xhr.responseText, "error"); } });
if (newColumns.length > 0) { $('#updateCategoryButton').prop('disabled', true).text('Processing'); $.ajax({ url: '/gcc/api/category/addNewColumns', type: 'POST', contentType: 'application/json', data: JSON.stringify({ categoryId: categoryId, columns: newColumns }), success: function (response) { $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); if (response.success) { Swal.fire({ title: "Success!", text: "Category updated successfully!", icon: "success", showConfirmButton: false, timer: 2000 }).then(() => { $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); location.reload(); }); } else { $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); Swal.fire({ title: "Error", text: "Unable to update column. Try again.", icon: "error", showConfirmButton: true }); } }, error: function (xhr) { $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); Swal.fire("Error", "Failed to add new columns: " + xhr.responseText, "error"); } }); $('#updateCategoryButton').prop('disabled', false).text('Save Changes'); } }); /* $('#updateCategoryButton').click(function () { let categoryId = parseInt($('#categoryId').val(), 10); // Collect existing columns let existingColumns = []; $('#editColumnInputs .column-group').each(function () { let columnId = parseInt($(this).find('.showcolumnId').val(), 10); let columnName = $(this).find('.showcolumnname').val(); if (columnName.trim() !== "") { existingColumns.push({ id: columnId, name: columnName }); } });
// Collect new columns let newColumns = []; $('#editaddColumnInputs .column-group').each(function () { let columnName = $(this).find('.showcolumnname').val(); if (columnName.trim() !== "") { newColumns.push({ name: columnName }); } }); // Debugging: Log values before AJAX calls console.log("Category ID:", categoryId); console.log("Existing Columns:", existingColumns); console.log("New Columns:", newColumns);
if ((existingColumns.length + newColumns.length) < 2) { Swal.fire({ title: "Info", text: "You must have at least 2 columns!", icon: "info", confirmButtonText: "OK" }); return; // Stop execution if condition fails }
// 1️⃣ Send existing columns update AJAX $.ajax({ url: '/gcc/api/category/updateCategoryColumns', type: 'POST', contentType: 'application/json', data: JSON.stringify({ categoryId: categoryId, columns: existingColumns }), success: function (response) { if (response.success) { Swal.fire({ title: "Success!", text: "Category updated successfully!", icon: "success", showConfirmButton: false, timer: 2000 // Show message for 2 seconds }).then(() => { location.reload(); // Reload the page after SweetAlert closes }); } else { Swal.fire({ title: "Error", text: "Unable to update column. Try again.", icon: "error", showConfirmButton: true }); } }, error: function (xhr) { Swal.fire("Error", "Failed to update category: " + xhr.responseText, "error"); } });
// 2️⃣ Send new columns addition AJAX (only if there are new columns) if (newColumns.length > 0) { $.ajax({ url: '/gcc/api/category/addNewColumns', type: 'POST', contentType: 'application/json', data: JSON.stringify({ categoryId: categoryId, columns: newColumns }), success: function (response) { if (response.success) { Swal.fire({ title: "Success!", text: "Category updated successfully!", icon: "success", showConfirmButton: false, timer: 2000 // Show message for 2 seconds }).then(() => { location.reload(); // Reload the page after SweetAlert closes }); } else { Swal.fire({ title: "Error", text: "Unable to update column. Try again.", icon: "error", showConfirmButton: true }); } }, error: function (xhr) { Swal.fire("Error", "Failed to add new columns: " + xhr.responseText, "error"); } }); } }); */
window.openDeleteModal = function (categoryId) { $('#categoryId').val(categoryId); // Set the categoryId before showing the modal fetchDeleteCategoryDetails(); return false; // Prevent default anchor click behavior }; function fetchDeleteCategoryDetails() { Swal.fire({ title: 'Confirm Deletion', text: 'Are you sure you want to delete this category?', icon: 'warning', showCancelButton: true, confirmButtonText: 'Delete', cancelButtonText: 'Cancel', customClass: { container: 'swal-container', popup: 'swal-popup', confirmButton: 'swal-confirm-button', cancelButton: 'swal-cancel-button' }, width: '80%', padding: '3rem', heightAuto: false }).then((result) => { if (result.isConfirmed) { // Call the function to delete the category deleteCategory(); } }); }
function deleteCategory() { var categoryId = $('#categoryId').val(); // Ensure this is correctly set console.log("Deleting category with ID: " + categoryId); // Debugging line $.ajax({ url: '/gcc/api/category/delete/' + categoryId, type: 'DELETE', success: function (response) { Swal.fire({ title: 'Deleted!', text: 'Category has been deleted.', icon: 'success' }).then(() => { location.reload(); // Refresh the page or update the UI as needed }); }, error: function (xhr, status, error) { Swal.fire({ title: 'Error', text: 'Error deleting category: ' + xhr.responseText, icon: 'error' }); } }); }
});
</script> </body></html>
|