574 lines
24 KiB
HTML
574 lines
24 KiB
HTML
{% extends 'base_structure/layout/base_template.html' %}
|
|
{% load static %}
|
|
{% block stylesheet %}
|
|
<!-- include required css cdn link through html here -->
|
|
|
|
{% include "cdn_through_html/datatable_cdn_css.html" %}
|
|
{% include "cdn_through_html/animate_cdn_css.html" %}
|
|
{% include "cdn_through_html/modal_cdn_css.html" %}
|
|
{% include "cdn_through_html/switches_cdn_css.html" %}
|
|
{% include "cdn_through_html/sweetalert2_cdn_css.html" %}
|
|
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<div class="row layout-top-spacing">
|
|
<div class="col-lg-12">
|
|
<div class="row mb-2">
|
|
<div class="col">
|
|
<h3>Manage Contact Us</h3>
|
|
</div>
|
|
<div class="col text-end">
|
|
{% comment %} <button class="btn btn-dark mb-2 me-4" onclick="history.back()">
|
|
<i class="fa fa-arrow-left"></i>
|
|
Back
|
|
</button> {% endcomment %}
|
|
{% comment %} <a class="btn btn-success mb-2 me-4" href="{% url 'module_cms:faq_category_add' %}">Add Category</a> {% endcomment %}
|
|
{% comment %} <a class="btn btn-primary mb-2 me-4" href="{% url 'module_cms:faq_add' %}">Add FAQ</a> {% endcomment %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row layout-spacing">
|
|
<div class="col-lg-12">
|
|
<div class="statbox widget box box-shadow">
|
|
<div class="widget-content widget-content-area">
|
|
<div id="table_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4 no-footer">
|
|
|
|
<div class="table-responsive">
|
|
<table id="table" class="table style-3 dt-table-hover dataTable" role="grid"
|
|
aria-describedby="style-3_info">
|
|
|
|
<thead>
|
|
<tr role="row">
|
|
<th class="checkbox-column text-center dt-no-sorting" tabindex="0"
|
|
aria-controls="style-3" aria-sort="ascending"
|
|
style="width: 50.2656px;">#</th>
|
|
<th class="sorting_asc text-center" tabindex="0"
|
|
aria-controls="style-3" aria-sort="ascending"
|
|
style="width: 50.2656px;">RecordId</th>
|
|
<th class="sorting text-center" tabindex="1" aria-controls="style-3"
|
|
colspan="1"
|
|
style="width: 44.2344px;">Email Address</th>
|
|
<th class="sorting text-center" tabindex="2" aria-controls="style-3"
|
|
colspan="1"
|
|
style="width: 44.2344px;">Subject</th>
|
|
<th class="sorting text-center" tabindex="3" aria-controls="style-3"
|
|
colspan="1"
|
|
style="width: 44.2344px;">Message</th>
|
|
<th class="sorting text-center" tabindex="4" aria-controls="style-3"
|
|
colspan="1"
|
|
style="width: 44.2344px;">Reply</th>
|
|
<th class="sorting text-center" tabindex="5" aria-controls="style-3"
|
|
style="width: 79.7969px;">Active</th>
|
|
<th class="sorting text-center dt-no-sorting" tabindex="4" aria-controls="style-3"
|
|
colspan="1"
|
|
style="width: 44.2344px;">Status</th>
|
|
<th class="text-center dt-no-sorting" tabindex="6" aria-controls="style-3"
|
|
style="width: 79.7969px;">Action</th>
|
|
</tr>
|
|
<tr>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Message/ reply modal -->
|
|
<div class="modal fade" id="tabsModalMessageReply" tabindex="-1" role="dialog" aria-labelledby="tabsModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content" >
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="tabsModalLabel">Message / Reply</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<p class="mt-3" id="emailData"></p>
|
|
<p class="mt-3" id="subjectData"></p>
|
|
</div>
|
|
<div class="simple-pill">
|
|
|
|
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link active" id="pills-message-tab" data-bs-toggle="pill" data-bs-target="#pills-message" type="button" role="tab" aria-controls="pills-message" aria-selected="true">Message</button>
|
|
</li>
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="pills-reply-tab" data-bs-toggle="pill" data-bs-target="#pills-reply" type="button" role="tab" aria-controls="pills-reply" aria-selected="false">Reply</button>
|
|
</li>
|
|
</ul>
|
|
<div class="tab-content" id="pills-tabContent" style="max-height: 200px; overflow-y: auto;">
|
|
<div class="tab-pane fade show active" id="pills-message" role="tabpanel" aria-labelledby="pills-message-tab" tabindex="0">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<p class="mt-3" id="messageData"></p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="tab-pane fade" id="pills-reply" role="tabpanel" aria-labelledby="pills-reply-tab" tabindex="0">
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<p class="mt-3" id="replyData"></p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn btn-light-dark" data-bs-dismiss="modal">Discard</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal fade" id="replyModal" tabindex="-1" role="dialog" aria-labelledby="replyModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="replyModalLabel">Message / Reply</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"> </button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<input type="hidden" id="replyId">
|
|
<div class="form-group mb-3">
|
|
<label for="recipient-name" class="form-label">Recipient:</label>
|
|
<p id="recipient-name"></p>
|
|
</div>
|
|
<div class="form-group mb-3">
|
|
<label for="message" class="form-label">Message:</label>
|
|
<p id="message"></p>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="reply-text" class="form-label">Reply:</label>
|
|
<textarea class="form-control" id="reply-text"></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-light-dark" data-bs-dismiss="modal">Discard</button>
|
|
<button type="button" class="btn btn-primary" id="submitReply">Submit</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock content %}
|
|
|
|
{% block javascript %}
|
|
|
|
<!-- include required css cdn link through html here -->
|
|
|
|
{% include "cdn_through_html/datatable_cdn_js.html" %}
|
|
{% include "cdn_through_html/datatable_button_cdn_js.html" %}
|
|
{% include "cdn_through_html/sweetalert2_cdn_js.html" %}
|
|
|
|
<script>
|
|
|
|
|
|
// Define DataTable instance
|
|
var dataTableInstance;
|
|
var mainUrl = "{% url 'module_support:contact_us_list' %}?deleted_flag=False"
|
|
var actionUrl = "{% url 'module_support:contact_us_action' %}"
|
|
var viewArchiveUrl = "{% url 'module_support:contact_us_archive' %}"
|
|
var replyUrl = "{% url 'module_support:contact_us_reply' id=0 %}"
|
|
|
|
// Entry point
|
|
$(document).ready(function() {
|
|
|
|
tableName = $('#table');
|
|
dataTableInstance = initializeDataTable(tableName, mainUrl);
|
|
viewClickEvent(dataTableInstance)
|
|
replyEvent(dataTableInstance)
|
|
activeSwitchEventListener()
|
|
});
|
|
|
|
// Function to initialize DataTable
|
|
function initializeDataTable(tableName, mainUrl) {
|
|
return tableName.DataTable({
|
|
processing: true,
|
|
serverSide: true,
|
|
ajax: {
|
|
url: mainUrl,
|
|
type: "GET",
|
|
},
|
|
columns: [
|
|
{ data: null, className: "text-center", render: renderCheckbox },
|
|
{ data: "id", className: "text-center" },
|
|
{ data: "email_address" },
|
|
{ data: "subject" },
|
|
{ data: "message" },
|
|
{ data: "reply" },
|
|
{ data: "active", className: "text-center", render: renderSwitch },
|
|
{
|
|
data: "reply",
|
|
className: "text-center",
|
|
render: function(data, type, row, meta) {
|
|
var badgeText = "";
|
|
if (data) {
|
|
badgeText = "Completed";
|
|
} else {
|
|
badgeText = "Pending";
|
|
// Change class name for pending badge
|
|
return '<span class="badge badge-danger">' + badgeText + '</span>';
|
|
}
|
|
|
|
// Return badge for completed items (optional)
|
|
return '<span class="badge badge-primary">' + badgeText + '</span>';
|
|
}
|
|
},
|
|
{ data: null, className: "text-center", render: renderActions }
|
|
],
|
|
debug: true,
|
|
columnDefs: [
|
|
{
|
|
"targets": [4, 5, 6],
|
|
"render": function (data, type, row) {
|
|
// Adjust the length of text you want to show before truncating
|
|
var maxLength = 40;
|
|
// Truncate the text if it exceeds the maxLength
|
|
var truncatedText = data.length > maxLength ? data.substr(0, maxLength) + '...' : data;
|
|
// Return the truncated text
|
|
return truncatedText;
|
|
}
|
|
},
|
|
{
|
|
targets: [1, 2, 3, 4, 5, 6],
|
|
searchable: true,
|
|
orderable: true
|
|
},
|
|
{
|
|
targets: [0,7,-1], // Targeting the first and last column (action column)
|
|
searchable: false,
|
|
orderable: false
|
|
},
|
|
],
|
|
orderCellsTop: true,
|
|
dom: "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'Bf>>>" +
|
|
"<'table-responsive'tr>" +
|
|
"<'dt--bottom-section d-sm-flex justify-content-sm-between text-center'<'dt--pages-count mb-sm-0 mb-3'i><'dt--pagination'p>>",
|
|
buttons: [
|
|
{
|
|
text: 'Archive',
|
|
className: "btn btn-dark buttons-archive",
|
|
action: archiveAction,
|
|
init: function(api, node, config){
|
|
$(node).hide();
|
|
}
|
|
},
|
|
{
|
|
text: 'View Archive List',
|
|
className: "btn btn-dark ",
|
|
action: function () {
|
|
// Add your action here, e.g., redirect to archive page
|
|
window.location.href = viewArchiveUrl;
|
|
}
|
|
}
|
|
],
|
|
oLanguage: {
|
|
oPaginate: { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
|
|
sInfo: "Showing page _PAGE_ of _PAGES_",
|
|
sSearch: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
|
|
sSearchPlaceholder: "Search...",
|
|
sLengthMenu: " _MENU_",
|
|
},
|
|
stripeClasses: [],
|
|
lengthMenu: [5, 10, 20, 50],
|
|
pageLength: 10,
|
|
initComplete: initCompleteCallback
|
|
});
|
|
}
|
|
|
|
// Callback function for DataTable initialization complete event
|
|
function initCompleteCallback() {
|
|
var table = this.api();
|
|
var tableId = this.api().table().node().id;
|
|
console.log(tableId);
|
|
|
|
// Specify the column indexes for individual searchable fields (adjust as needed)
|
|
var searchableColumns = [1, 2, 3, 4, 5];
|
|
// Specify the column indexes for select input fields (adjust as needed)
|
|
var selectDropdownInputColumns = [6]
|
|
|
|
table.columns(searchableColumns).every(function() {
|
|
var column = this;
|
|
var title = $(this.header()).text().trim(); // Get the column title
|
|
|
|
var input = $('<input type="text" class="form-control" placeholder="Search ' + title + '" />')
|
|
.appendTo($("thead tr:eq(1) th").eq(this.index()))
|
|
.on("keyup", function() {
|
|
if (column.search() !== this.value) {
|
|
column.search(this.value).draw();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Add event listener for checkbox change
|
|
$('body').on('change', 'input[type="checkbox"]', function () {
|
|
var checkedCount = $(`#${tableId} tbody input.archive-checkbox:checked`).length;
|
|
var archiveButton = $('.buttons-archive');
|
|
console.log("checkbox is checked", + checkedCount)
|
|
archiveButton.toggle(checkedCount > 0);
|
|
});
|
|
|
|
table.columns(selectDropdownInputColumns).every( function () {
|
|
var column = this;
|
|
console.log( column.index() );
|
|
var nodeBelow = $(column.header()).closest('tr').next().children().eq( column.index() );
|
|
var select = $('<select class="form-control"><option value="">All</option></select>')
|
|
.appendTo( $(nodeBelow).empty() )
|
|
.on( 'change', function () {
|
|
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
|
if (column.search() !== this.value) {
|
|
column.search(val).draw();
|
|
}
|
|
} );
|
|
column.data().unique().sort().each( function ( d, j ) {
|
|
console.log(`data is ${d}`)
|
|
select.append( '<option value="'+d+'">'+d+'</option>' )
|
|
} );
|
|
});
|
|
|
|
}
|
|
|
|
// Function to reload the DataTable
|
|
function reloadDataTable() {
|
|
dataTableInstance.ajax.reload();
|
|
}
|
|
|
|
// Render checkbox
|
|
function renderCheckbox(data, type, row) {
|
|
|
|
var checkboxHTML = '<div class="form-check form-check-danger">';
|
|
checkboxHTML += '<input class="form-check-input archive-checkbox" type="checkbox" value="' + row.id + '" data-id="'+ row.id +'" id="checkbox-' + row.id + '">';
|
|
checkboxHTML += '</div>';
|
|
return checkboxHTML;
|
|
}
|
|
|
|
// Render switch
|
|
function renderSwitch(data, type, row) {
|
|
var checkedAttribute = data.toLowerCase() === 'true' ? 'checked' : '';
|
|
var switchHTML = '<div class="switch form-switch-custom switch-inline form-switch-primary">';
|
|
switchHTML += '<input class="switch-input" type="checkbox" role="switch" data-id="'+ row.id +'" id="form-custom-switch-checked' + row.id + '" ' + checkedAttribute + '>';
|
|
switchHTML += '</div>';
|
|
return switchHTML;
|
|
}
|
|
|
|
// Render actions
|
|
function renderActions(data, type, row) {
|
|
return `
|
|
<a href="javascript:void(0);" role="button" data-id="${row.id}" class="bs-tooltip view" data-bs-toggle="tooltip" data-bs-placement="top" title="" data-original-title="View" data-bs-original-title="View" aria-label="View">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-eye"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>
|
|
</a>
|
|
|
|
<a href="javascript:void(0);" data-id="${row.id}" class="bs-tooltip reply" data-bs-toggle="tooltip" data-bs-placement="top" title="" data-original-title="Reply" data-bs-original-title="Reply" aria-label="Reply">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-send"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
|
|
</a>
|
|
|
|
`;
|
|
}
|
|
|
|
function HideButton(className) {
|
|
// Hide archive button
|
|
$(`.${className}`).hide();
|
|
}
|
|
|
|
|
|
// Function to handle archive action
|
|
function archiveAction() {
|
|
// Get all the checked checkboxes
|
|
var checkedCheckboxes = $('.archive-checkbox:checked');
|
|
// If no checkboxes are checked, show an error message
|
|
if (checkedCheckboxes.length === 0) {
|
|
Swal.fire({
|
|
title: 'No record selected',
|
|
text: 'Please select at least one record to archive.',
|
|
icon: 'error',
|
|
showConfirmButton: true
|
|
});
|
|
return;
|
|
}
|
|
// Get the IDs of the checked checkboxes
|
|
var ids = checkedCheckboxes.map(function() {
|
|
return $(this).val();
|
|
}).get();
|
|
// Perform archive action with the collected user IDs
|
|
Swal.fire({
|
|
title: 'Are you sure?',
|
|
text: 'Once archived, you will recover it from archive list!',
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#d33',
|
|
cancelButtonColor: '#3085d6',
|
|
confirmButtonText: 'Yes, archive it!'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// Perform archive action
|
|
$.ajax({
|
|
url: actionUrl, // Replace with your archive endpoint
|
|
type: 'POST',
|
|
data: {
|
|
action: "archive",
|
|
ids: ids,
|
|
csrfmiddlewaretoken: '{{csrf_token}}'
|
|
},
|
|
success: function(response) {
|
|
// Show success message
|
|
Swal.fire({
|
|
title: 'Done!',
|
|
text: response.msg,
|
|
icon: 'success',
|
|
showConfirmButton: true
|
|
});
|
|
HideButton("buttons-archive");
|
|
// Optionally, you can reload the DataTable after successful archive
|
|
reloadDataTable();
|
|
},
|
|
error: function(response) {
|
|
// Show error message
|
|
Swal.fire({
|
|
title: 'Error!',
|
|
text: response.message,
|
|
icon: 'error',
|
|
showConfirmButton: true
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
// Function to handle click event for view button
|
|
function viewClickEvent(dataTableInstance) {
|
|
$('body').on('click', '.view', function(){
|
|
var id = $(this).data('id');
|
|
var rowData = dataTableInstance.row($(this).closest('tr')).data();
|
|
|
|
// Populate the modal fields with the data
|
|
$('#messageData').text(rowData.message);
|
|
$('#emailData').text(rowData.email_address);
|
|
$('#subjectData').text(rowData.subject);
|
|
$('#replyData').text(rowData.reply);
|
|
|
|
// Show the modal
|
|
$('#tabsModalMessageReply').modal('show');
|
|
});
|
|
}
|
|
|
|
|
|
// Function to add event listener for switch
|
|
function activeSwitchEventListener() {
|
|
// Add event listener for switch change event
|
|
$('body').on('change', '.switch-input', function() {
|
|
var rowId = $(this).closest('tr').find('.switch-input').data('id');
|
|
var isActive = $(this).prop('checked');
|
|
console.log(rowId, isActive)
|
|
// Perform active toggle action for the current user
|
|
$.ajax({
|
|
url: actionUrl, // Replace with your active toggle endpoint
|
|
type: 'POST',
|
|
data: {
|
|
action: "active",
|
|
ids: [rowId],
|
|
active: isActive,
|
|
csrfmiddlewaretoken: '{{csrf_token}}'
|
|
},
|
|
success: function(response) {
|
|
// Show success message
|
|
Swal.fire({
|
|
title: 'Done!',
|
|
text: response.msg,
|
|
icon: 'success',
|
|
showConfirmButton: true
|
|
});
|
|
// Reload the DataTable after successful toggle
|
|
reloadDataTable();
|
|
},
|
|
error: function(response) {
|
|
// Show error message
|
|
Swal.fire({
|
|
title: 'Error!',
|
|
text: response.message,
|
|
icon: 'error',
|
|
showConfirmButton: true
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function replyEvent(dataTableInstance){
|
|
$('body').on('click', '.reply', function(){
|
|
var id = $(this).data('id');
|
|
var rowData = dataTableInstance.row($(this).closest('tr')).data();
|
|
$('#message').text(rowData.message);
|
|
$('#recipient-name').text(rowData.email_address);
|
|
$('#replyId').val(id);
|
|
$('#replyModal').modal('show');
|
|
});
|
|
}
|
|
|
|
$('#replyModal').on('click', '#submitReply', function(e) {
|
|
e.preventDefault();
|
|
var id = $('#replyId').val();
|
|
var replyMessage = $('#reply-text').val();
|
|
console.log(id, replyMessage)
|
|
|
|
// Call the AJAX request
|
|
$.ajax({
|
|
type: 'POST',
|
|
url: replyUrl.replace("0", id),
|
|
data: { message: replyMessage, csrfmiddlewaretoken: '{{csrf_token}}' },
|
|
success: function(response) {
|
|
console.log('Response from server:', response);
|
|
Swal.fire({
|
|
title: 'Done!',
|
|
text: response.msg,
|
|
icon: 'success',
|
|
showConfirmButton: true
|
|
});
|
|
// Close the modal
|
|
$('#replyModal').modal('hide');
|
|
|
|
// Empty the input fields
|
|
$('#reply-text').val('');
|
|
// Reload the DataTable after successful toggle
|
|
reloadDataTable();
|
|
},
|
|
error: function(error) {
|
|
console.error('Error:', error);
|
|
Swal.fire({
|
|
title: 'Error!',
|
|
text: response.message,
|
|
icon: 'error',
|
|
showConfirmButton: true
|
|
});
|
|
}
|
|
});
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
{% endblock %} |