first commit
This commit is contained in:
83
resources/js/app.js
Normal file
83
resources/js/app.js
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Deshabilita o pone en modo de solo lectura los campos del formulario.
|
||||
* @param {string} formSelector - Selector del formulario a deshabilitar.
|
||||
*/
|
||||
const disableStoreForm = (formSelector) => {
|
||||
const form = document.querySelector(formSelector);
|
||||
if (!form) {
|
||||
console.warn(`Formulario no encontrado con el selector: ${formSelector}`);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Habilita o deshabilita un select con Select2.
|
||||
* @param {HTMLElement} selectElement - El select afectado.
|
||||
* @param {boolean} disabled - Si debe ser deshabilitado.
|
||||
*/
|
||||
const toggleSelect2Disabled = (selectElement, disabled) => {
|
||||
selectElement.disabled = disabled;
|
||||
selectElement.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
};
|
||||
|
||||
/**
|
||||
* Aplica modo solo lectura a un select estándar o Select2.
|
||||
* @param {HTMLElement} select - El select a modificar.
|
||||
* @param {boolean} readonly - Si debe estar en modo solo lectura.
|
||||
*/
|
||||
const setSelectReadonly = (select, readonly) => {
|
||||
select.setAttribute('readonly-mode', readonly);
|
||||
select.style.pointerEvents = readonly ? 'none' : '';
|
||||
select.tabIndex = readonly ? -1 : '';
|
||||
|
||||
if (select.classList.contains('select2-hidden-accessible')) {
|
||||
toggleSelect2Disabled(select, readonly);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Aplica modo solo lectura a un checkbox o radio.
|
||||
* @param {HTMLElement} checkbox - El input a modificar.
|
||||
* @param {boolean} readonly - Si debe ser solo lectura.
|
||||
*/
|
||||
const setCheckboxReadonly = (checkbox, readonly) => {
|
||||
checkbox.setAttribute('readonly-mode', readonly);
|
||||
checkbox.style.pointerEvents = readonly ? 'none' : '';
|
||||
checkbox[readonly ? 'addEventListener' : 'removeEventListener']('click', preventInteraction);
|
||||
};
|
||||
|
||||
/**
|
||||
* Previene interacción con el elemento.
|
||||
* @param {Event} event - El evento de clic.
|
||||
*/
|
||||
const preventInteraction = (event) => event.preventDefault();
|
||||
|
||||
// Obtener todos los inputs del formulario
|
||||
const inputs = form.querySelectorAll('input, textarea, select');
|
||||
|
||||
inputs.forEach((el) => {
|
||||
if (!el.classList.contains('data-always-enabled')) {
|
||||
switch (el.tagName) {
|
||||
case 'SELECT':
|
||||
if (el.classList.contains('select2')) {
|
||||
toggleSelect2Disabled(el, true);
|
||||
} else {
|
||||
setSelectReadonly(el, true);
|
||||
}
|
||||
break;
|
||||
case 'INPUT':
|
||||
if (['checkbox', 'radio'].includes(el.type)) {
|
||||
setCheckboxReadonly(el, true);
|
||||
} else {
|
||||
el.readOnly = true;
|
||||
}
|
||||
break;
|
||||
case 'TEXTAREA':
|
||||
el.readOnly = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Hacer la función accesible globalmente
|
||||
window.disableStoreForm = disableStoreForm;
|
206
resources/js/auth/app-access-permission.js
Normal file
206
resources/js/auth/app-access-permission.js
Normal file
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* App user list (jquery)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
$(function () {
|
||||
var dataTablePermissions = $('.datatables-permissions'),
|
||||
dt_permission,
|
||||
userList = baseUrl + 'app/user/list';
|
||||
// Users List datatable
|
||||
if (dataTablePermissions.length) {
|
||||
dt_permission = dataTablePermissions.DataTable({
|
||||
ajax: assetsPath + 'json/permissions-list.json', // JSON file to add data
|
||||
columns: [
|
||||
// columns according to JSON
|
||||
{ data: '' },
|
||||
{ data: 'id' },
|
||||
{ data: 'name' },
|
||||
{ data: 'assigned_to' },
|
||||
{ data: 'created_date' },
|
||||
{ data: '' }
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
// For Responsive
|
||||
className: 'control',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
responsivePriority: 2,
|
||||
targets: 0,
|
||||
render: function (data, type, full, meta) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 1,
|
||||
searchable: false,
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
// Name
|
||||
targets: 2,
|
||||
render: function (data, type, full, meta) {
|
||||
var $name = full['name'];
|
||||
return '<span class="text-nowrap text-heading">' + $name + '</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
// User Role
|
||||
targets: 3,
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
var $assignedTo = full['assigned_to'],
|
||||
$output = '';
|
||||
var roleBadgeObj = {
|
||||
Admin: '<a href="' + userList + '"><span class="badge me-4 bg-label-primary">Administrator</span></a>',
|
||||
Manager: '<a href="' + userList + '"><span class="badge me-4 bg-label-warning">Manager</span></a>',
|
||||
Users: '<a href="' + userList + '"><span class="badge me-4 bg-label-success">Users</span></a>',
|
||||
Support: '<a href="' + userList + '"><span class="badge me-4 bg-label-info">Support</span></a>',
|
||||
Restricted:
|
||||
'<a href="' + userList + '"><span class="badge me-4 bg-label-danger">Restricted User</span></a>'
|
||||
};
|
||||
for (var i = 0; i < $assignedTo.length; i++) {
|
||||
var val = $assignedTo[i];
|
||||
$output += roleBadgeObj[val];
|
||||
}
|
||||
return '<span class="text-nowrap">' + $output + '</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
// remove ordering from Name
|
||||
targets: 4,
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
var $date = full['created_date'];
|
||||
return '<span class="text-nowrap">' + $date + '</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
// Actions
|
||||
targets: -1,
|
||||
searchable: false,
|
||||
title: 'Actions',
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
return (
|
||||
'<div class="d-flex align-items-center">' +
|
||||
'<span class="text-nowrap"><button class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill me-1" data-bs-target="#editPermissionModal" data-bs-toggle="modal" data-bs-dismiss="modal"><i class="ti ti-edit ti-md"></i></button>' +
|
||||
'<a href="javascript:;" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill dropdown-toggle hide-arrow" data-bs-toggle="dropdown"><i class="ti ti-dots-vertical ti-md mx-1"></i></a>' +
|
||||
'<div class="dropdown-menu dropdown-menu-end m-0">' +
|
||||
'<a href="javascript:;"" class="dropdown-item">Edit</a>' +
|
||||
'<a href="javascript:;" class="dropdown-item">Suspend</a>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
order: [[1, 'asc']],
|
||||
dom:
|
||||
'<"row mx-1"' +
|
||||
'<"col-sm-12 col-md-3" l>' +
|
||||
'<"col-sm-12 col-md-9"<"dt-action-buttons text-xl-end text-lg-start text-md-end text-start d-flex align-items-center justify-content-md-end justify-content-center flex-wrap"<"me-4 mt-n6 mt-md-0"f>B>>' +
|
||||
'>t' +
|
||||
'<"row"' +
|
||||
'<"col-sm-12 col-md-6"i>' +
|
||||
'<"col-sm-12 col-md-6"p>' +
|
||||
'>',
|
||||
language: {
|
||||
sLengthMenu: 'Show _MENU_',
|
||||
search: '',
|
||||
searchPlaceholder: 'Search Permissions',
|
||||
paginate: {
|
||||
next: '<i class="ti ti-chevron-right ti-sm"></i>',
|
||||
previous: '<i class="ti ti-chevron-left ti-sm"></i>'
|
||||
}
|
||||
},
|
||||
// Buttons with Dropdown
|
||||
buttons: [
|
||||
{
|
||||
text: '<i class="ti ti-plus ti-xs me-0 me-sm-2"></i><span class="d-none d-sm-inline-block">Add Permission</span>',
|
||||
className: 'add-new btn btn-primary mb-6 mb-md-0 waves-effect waves-light',
|
||||
attr: {
|
||||
'data-bs-toggle': 'modal',
|
||||
'data-bs-target': '#addPermissionModal'
|
||||
},
|
||||
init: function (api, node, config) {
|
||||
$(node).removeClass('btn-secondary');
|
||||
}
|
||||
}
|
||||
],
|
||||
// For responsive popup
|
||||
responsive: {
|
||||
details: {
|
||||
display: $.fn.dataTable.Responsive.display.modal({
|
||||
header: function (row) {
|
||||
var data = row.data();
|
||||
return 'Details of ' + data['name'];
|
||||
}
|
||||
}),
|
||||
type: 'column',
|
||||
renderer: function (api, rowIdx, columns) {
|
||||
var data = $.map(columns, function (col, i) {
|
||||
return col.title !== '' // ? Do not show row in modal popup if title is blank (for check box)
|
||||
? '<tr data-dt-row="' +
|
||||
col.rowIndex +
|
||||
'" data-dt-column="' +
|
||||
col.columnIndex +
|
||||
'">' +
|
||||
'<td>' +
|
||||
col.title +
|
||||
':' +
|
||||
'</td> ' +
|
||||
'<td>' +
|
||||
col.data +
|
||||
'</td>' +
|
||||
'</tr>'
|
||||
: '';
|
||||
}).join('');
|
||||
|
||||
return data ? $('<table class="table"/><tbody />').append(data) : false;
|
||||
}
|
||||
}
|
||||
},
|
||||
initComplete: function () {
|
||||
// Adding role filter once table initialized
|
||||
this.api()
|
||||
.columns(3)
|
||||
.every(function () {
|
||||
var column = this;
|
||||
var select = $(
|
||||
'<select id="UserRole" class="form-select text-capitalize"><option value=""> Select Role </option></select>'
|
||||
)
|
||||
.appendTo('.user_role')
|
||||
.on('change', function () {
|
||||
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
||||
column.search(val ? '^' + val + '$' : '', true, false).draw();
|
||||
});
|
||||
|
||||
column
|
||||
.data()
|
||||
.unique()
|
||||
.sort()
|
||||
.each(function (d, j) {
|
||||
select.append('<option value="' + d + '" class="text-capitalize">' + d + '</option>');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Delete Record
|
||||
$('.datatables-permissions tbody').on('click', '.delete-record', function () {
|
||||
dt_permission.row($(this).parents('tr')).remove().draw();
|
||||
});
|
||||
|
||||
// Filter form control to default size
|
||||
// ? setTimeout used for multilingual table initialization
|
||||
setTimeout(() => {
|
||||
$('.dataTables_filter .form-control').removeClass('form-control-sm');
|
||||
$('.dataTables_length .form-select').removeClass('form-select-sm');
|
||||
$('.dataTables_info').addClass('ms-n1');
|
||||
$('.dataTables_paginate').addClass('me-n1');
|
||||
}, 300);
|
||||
});
|
428
resources/js/auth/app-access-roles.js
Normal file
428
resources/js/auth/app-access-roles.js
Normal file
@ -0,0 +1,428 @@
|
||||
/**
|
||||
* App user list
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Datatable (jquery)
|
||||
$(function () {
|
||||
var dtUserTable = $('.datatables-users'),
|
||||
dt_User,
|
||||
statusObj = {
|
||||
1: { title: 'Pending', class: 'bg-label-warning' },
|
||||
2: { title: 'Active', class: 'bg-label-success' },
|
||||
3: { title: 'Inactive', class: 'bg-label-secondary' }
|
||||
};
|
||||
|
||||
var userView = baseUrl + 'app/user/view/account';
|
||||
|
||||
// Users List datatable
|
||||
if (dtUserTable.length) {
|
||||
var dtUser = dtUserTable.DataTable({
|
||||
ajax: assetsPath + 'json/user-list.json', // JSON file to add data
|
||||
columns: [
|
||||
// columns according to JSON
|
||||
{ data: 'id' },
|
||||
{ data: 'id' },
|
||||
{ data: 'full_name' },
|
||||
{ data: 'role' },
|
||||
{ data: 'current_plan' },
|
||||
{ data: 'billing' },
|
||||
{ data: 'status' },
|
||||
{ data: '' }
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
// For Responsive
|
||||
className: 'control',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
responsivePriority: 2,
|
||||
targets: 0,
|
||||
render: function (data, type, full, meta) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
{
|
||||
// For Checkboxes
|
||||
targets: 1,
|
||||
orderable: false,
|
||||
checkboxes: {
|
||||
selectAllRender: '<input type="checkbox" class="form-check-input">'
|
||||
},
|
||||
render: function () {
|
||||
return '<input type="checkbox" class="dt-checkboxes form-check-input" >';
|
||||
},
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
// User full name and email
|
||||
targets: 2,
|
||||
responsivePriority: 4,
|
||||
render: function (data, type, full, meta) {
|
||||
var $name = full['full_name'],
|
||||
$email = full['email'],
|
||||
$image = full['avatar'];
|
||||
if ($image) {
|
||||
// For Avatar image
|
||||
var $output =
|
||||
'<img src="' + assetsPath + 'img/avatars/' + $image + '" alt="Avatar" class="rounded-circle">';
|
||||
} else {
|
||||
// For Avatar badge
|
||||
var stateNum = Math.floor(Math.random() * 6);
|
||||
var states = ['success', 'danger', 'warning', 'info', 'primary', 'secondary'];
|
||||
var $state = states[stateNum],
|
||||
$name = full['full_name'],
|
||||
$initials = $name.match(/\b\w/g) || [];
|
||||
$initials = (($initials.shift() || '') + ($initials.pop() || '')).toUpperCase();
|
||||
$output = '<span class="avatar-initial rounded-circle bg-label-' + $state + '">' + $initials + '</span>';
|
||||
}
|
||||
// Creates full output for row
|
||||
var $row_output =
|
||||
'<div class="d-flex justify-content-left align-items-center">' +
|
||||
'<div class="avatar-wrapper">' +
|
||||
'<div class="avatar avatar-sm me-4">' +
|
||||
$output +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="d-flex flex-column">' +
|
||||
'<a href="' +
|
||||
userView +
|
||||
'" class="text-heading text-truncate"><span class="fw-medium">' +
|
||||
$name +
|
||||
'</span></a>' +
|
||||
'<small>@' +
|
||||
$email +
|
||||
'</small>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
return $row_output;
|
||||
}
|
||||
},
|
||||
{
|
||||
// User Role
|
||||
targets: 3,
|
||||
render: function (data, type, full, meta) {
|
||||
var $role = full['role'];
|
||||
var roleBadgeObj = {
|
||||
Subscriber: '<i class="ti ti-crown ti-md text-primary me-2"></i>',
|
||||
Author: '<i class="ti ti-edit ti-md text-warning me-2"></i>',
|
||||
Maintainer: '<i class="ti ti-user ti-md text-success me-2"></i>',
|
||||
Editor: '<i class="ti ti-chart-pie ti-md text-info me-2"></i>',
|
||||
Admin: '<i class="ti ti-device-desktop ti-md text-danger me-2"></i>'
|
||||
};
|
||||
return (
|
||||
"<span class='text-truncate d-flex align-items-center text-heading'>" +
|
||||
roleBadgeObj[$role] +
|
||||
$role +
|
||||
'</span>'
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
// Plans
|
||||
targets: 4,
|
||||
render: function (data, type, full, meta) {
|
||||
var $plan = full['current_plan'];
|
||||
|
||||
return '<span class="text-heading">' + $plan + '</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
// User Status
|
||||
targets: 6,
|
||||
render: function (data, type, full, meta) {
|
||||
var $status = full['status'];
|
||||
|
||||
return (
|
||||
'<span class="badge ' +
|
||||
statusObj[$status].class +
|
||||
'" text-capitalized>' +
|
||||
statusObj[$status].title +
|
||||
'</span>'
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
// Actions
|
||||
targets: -1,
|
||||
title: 'Actions',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
return (
|
||||
'<div class="d-flex align-items-center">' +
|
||||
'<a href="javascript:;" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill delete-record"><i class="ti ti-trash ti-md"></i></a>' +
|
||||
'<a href="' +
|
||||
userView +
|
||||
'" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill"><i class="ti ti-eye ti-md"></i></a>' +
|
||||
'<a href="javascript:;" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill dropdown-toggle hide-arrow" data-bs-toggle="dropdown"><i class="ti ti-dots-vertical ti-md"></i></a>' +
|
||||
'<div class="dropdown-menu dropdown-menu-end m-0">' +
|
||||
'<a href="javascript:;"" class="dropdown-item">Edit</a>' +
|
||||
'<a href="javascript:;" class="dropdown-item">Suspend</a>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
order: [[2, 'desc']],
|
||||
dom:
|
||||
'<"row"' +
|
||||
'<"col-md-2"<l>>' +
|
||||
'<"col-md-10"<"dt-action-buttons text-xl-end text-lg-start text-md-end text-start d-flex align-items-center justify-content-end flex-md-row flex-column mb-6 mb-md-0"fB>>' +
|
||||
'>t' +
|
||||
'<"row"' +
|
||||
'<"col-sm-12 col-md-6"i>' +
|
||||
'<"col-sm-12 col-md-6"p>' +
|
||||
'>',
|
||||
language: {
|
||||
sLengthMenu: 'Show _MENU_',
|
||||
search: '',
|
||||
searchPlaceholder: 'Search User',
|
||||
paginate: {
|
||||
next: '<i class="ti ti-chevron-right ti-sm"></i>',
|
||||
previous: '<i class="ti ti-chevron-left ti-sm"></i>'
|
||||
}
|
||||
},
|
||||
buttons: [
|
||||
{
|
||||
extend: 'collection',
|
||||
className:
|
||||
'btn btn-label-secondary dropdown-toggle me-4 waves-effect waves-light border-left-0 border-right-0 rounded',
|
||||
text: '<i class="ti ti-upload ti-xs me-sm-1 align-text-bottom"></i> <span class="d-none d-sm-inline-block">Export</span>',
|
||||
buttons: [
|
||||
{
|
||||
extend: 'print',
|
||||
text: '<i class="ti ti-printer me-1" ></i>Print',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [3, 4, 5, 6, 7],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
},
|
||||
customize: function (win) {
|
||||
//customize print view for dark
|
||||
$(win.document.body)
|
||||
.css('color', config.colors.headingColor)
|
||||
.css('border-color', config.colors.borderColor)
|
||||
.css('background-color', config.colors.bodyBg);
|
||||
$(win.document.body)
|
||||
.find('table')
|
||||
.addClass('compact')
|
||||
.css('color', 'inherit')
|
||||
.css('border-color', 'inherit')
|
||||
.css('background-color', 'inherit');
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'csv',
|
||||
text: '<i class="ti ti-file-text me-1" ></i>Csv',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [3, 4, 5, 6, 7],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'excel',
|
||||
text: '<i class="ti ti-file-spreadsheet me-1"></i>Excel',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [3, 4, 5, 6, 7],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'pdf',
|
||||
text: '<i class="ti ti-file-description me-1"></i>Pdf',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [3, 4, 5, 6, 7],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'copy',
|
||||
text: '<i class="ti ti-copy me-1" ></i>Copy',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [3, 4, 5, 6, 7],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '<i class="ti ti-plus ti-xs me-md-2"></i><span class="d-md-inline-block d-none">Add new role</span>',
|
||||
className: 'btn btn-primary waves-effect waves-light rounded border-left-0 border-right-0',
|
||||
attr: {
|
||||
'data-bs-toggle': 'modal',
|
||||
'data-bs-target': '#addRoleModal'
|
||||
}
|
||||
}
|
||||
],
|
||||
// For responsive popup
|
||||
responsive: {
|
||||
details: {
|
||||
display: $.fn.dataTable.Responsive.display.modal({
|
||||
header: function (row) {
|
||||
var data = row.data();
|
||||
return 'Details of ' + data['full_name'];
|
||||
}
|
||||
}),
|
||||
type: 'column',
|
||||
renderer: function (api, rowIdx, columns) {
|
||||
var data = $.map(columns, function (col, i) {
|
||||
return col.title !== '' // ? Do not show row in modal popup if title is blank (for check box)
|
||||
? '<tr data-dt-row="' +
|
||||
col.rowIndex +
|
||||
'" data-dt-column="' +
|
||||
col.columnIndex +
|
||||
'">' +
|
||||
'<td>' +
|
||||
col.title +
|
||||
':' +
|
||||
'</td> ' +
|
||||
'<td>' +
|
||||
col.data +
|
||||
'</td>' +
|
||||
'</tr>'
|
||||
: '';
|
||||
}).join('');
|
||||
|
||||
return data ? $('<table class="table"/><tbody />').append(data) : false;
|
||||
}
|
||||
}
|
||||
},
|
||||
initComplete: function () {
|
||||
// Adding role filter once table initialized
|
||||
this.api()
|
||||
.columns(3)
|
||||
.every(function () {
|
||||
var column = this;
|
||||
var select = $(
|
||||
'<select id="UserRole" class="form-select text-capitalize"><option value=""> Select Role </option></select>'
|
||||
)
|
||||
.appendTo('.user_role')
|
||||
.on('change', function () {
|
||||
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
||||
column.search(val ? '^' + val + '$' : '', true, false).draw();
|
||||
});
|
||||
|
||||
column
|
||||
.data()
|
||||
.unique()
|
||||
.sort()
|
||||
.each(function (d, j) {
|
||||
select.append('<option value="' + d + '" class="text-capitalize">' + d + '</option>');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// Delete Record
|
||||
$('.datatables-users tbody').on('click', '.delete-record', function () {
|
||||
dtUser.row($(this).parents('tr')).remove().draw();
|
||||
});
|
||||
|
||||
// Filter form control to default size
|
||||
// ? setTimeout used for multilingual table initialization
|
||||
setTimeout(() => {
|
||||
$('.dataTables_filter .form-control').removeClass('form-control-sm');
|
||||
$('.dataTables_length .form-select').removeClass('form-select-sm');
|
||||
}, 300);
|
||||
$('.dataTables_filter').addClass('ms-n4 me-4 mt-0 mt-md-6');
|
||||
});
|
||||
|
||||
(function () {
|
||||
// On edit role click, update text
|
||||
var roleEditList = document.querySelectorAll('.role-edit-modal'),
|
||||
roleAdd = document.querySelector('.add-new-role'),
|
||||
roleTitle = document.querySelector('.role-title');
|
||||
|
||||
roleAdd.onclick = function () {
|
||||
roleTitle.innerHTML = 'Add New Role'; // reset text
|
||||
};
|
||||
if (roleEditList) {
|
||||
roleEditList.forEach(function (roleEditEl) {
|
||||
roleEditEl.onclick = function () {
|
||||
roleTitle.innerHTML = 'Edit Role'; // reset text
|
||||
};
|
||||
});
|
||||
}
|
||||
})();
|
533
resources/js/auth/app-user-list.js
Normal file
533
resources/js/auth/app-user-list.js
Normal file
@ -0,0 +1,533 @@
|
||||
/**
|
||||
* Page User List
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Datatable (jquery)
|
||||
$(function () {
|
||||
let borderColor, bodyBg, headingColor;
|
||||
|
||||
if (isDarkStyle) {
|
||||
borderColor = config.colors_dark.borderColor;
|
||||
bodyBg = config.colors_dark.bodyBg;
|
||||
headingColor = config.colors_dark.headingColor;
|
||||
} else {
|
||||
borderColor = config.colors.borderColor;
|
||||
bodyBg = config.colors.bodyBg;
|
||||
headingColor = config.colors.headingColor;
|
||||
}
|
||||
|
||||
// Variable declaration for table
|
||||
var dt_user_table = $('.datatables-users'),
|
||||
select2 = $('.select2'),
|
||||
userView = baseUrl + 'app/user/view/account',
|
||||
statusObj = {
|
||||
1: { title: 'Pending', class: 'bg-label-warning' },
|
||||
2: { title: 'Active', class: 'bg-label-success' },
|
||||
3: { title: 'Inactive', class: 'bg-label-secondary' }
|
||||
};
|
||||
|
||||
if (select2.length) {
|
||||
var $this = select2;
|
||||
$this.wrap('<div class="position-relative"></div>').select2({
|
||||
placeholder: 'Select Country',
|
||||
dropdownParent: $this.parent()
|
||||
});
|
||||
}
|
||||
|
||||
// Users datatable
|
||||
if (dt_user_table.length) {
|
||||
var dt_user = dt_user_table.DataTable({
|
||||
ajax: assetsPath + 'json/user-list.json', // JSON file to add data
|
||||
columns: [
|
||||
// columns according to JSON
|
||||
{ data: 'id' },
|
||||
{ data: 'id' },
|
||||
{ data: 'full_name' },
|
||||
{ data: 'role' },
|
||||
{ data: 'current_plan' },
|
||||
{ data: 'billing' },
|
||||
{ data: 'status' },
|
||||
{ data: 'action' }
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
// For Responsive
|
||||
className: 'control',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
responsivePriority: 2,
|
||||
targets: 0,
|
||||
render: function (data, type, full, meta) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
{
|
||||
// For Checkboxes
|
||||
targets: 1,
|
||||
orderable: false,
|
||||
checkboxes: {
|
||||
selectAllRender: '<input type="checkbox" class="form-check-input">'
|
||||
},
|
||||
render: function () {
|
||||
return '<input type="checkbox" class="dt-checkboxes form-check-input" >';
|
||||
},
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
// User full name and email
|
||||
targets: 2,
|
||||
responsivePriority: 4,
|
||||
render: function (data, type, full, meta) {
|
||||
var $name = full['full_name'],
|
||||
$email = full['email'],
|
||||
$image = full['avatar'];
|
||||
if ($image) {
|
||||
// For Avatar image
|
||||
var $output =
|
||||
'<img src="' + assetsPath + 'img/avatars/' + $image + '" alt="Avatar" class="rounded-circle">';
|
||||
} else {
|
||||
// For Avatar badge
|
||||
var stateNum = Math.floor(Math.random() * 6);
|
||||
var states = ['success', 'danger', 'warning', 'info', 'primary', 'secondary'];
|
||||
var $state = states[stateNum],
|
||||
$name = full['full_name'],
|
||||
$initials = $name.match(/\b\w/g) || [];
|
||||
$initials = (($initials.shift() || '') + ($initials.pop() || '')).toUpperCase();
|
||||
$output = '<span class="avatar-initial rounded-circle bg-label-' + $state + '">' + $initials + '</span>';
|
||||
}
|
||||
// Creates full output for row
|
||||
var $row_output =
|
||||
'<div class="d-flex justify-content-start align-items-center user-name">' +
|
||||
'<div class="avatar-wrapper">' +
|
||||
'<div class="avatar avatar-sm me-4">' +
|
||||
$output +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div class="d-flex flex-column">' +
|
||||
'<a href="' +
|
||||
userView +
|
||||
'" class="text-heading text-truncate"><span class="fw-medium">' +
|
||||
$name +
|
||||
'</span></a>' +
|
||||
'<small>' +
|
||||
$email +
|
||||
'</small>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
return $row_output;
|
||||
}
|
||||
},
|
||||
{
|
||||
// User Role
|
||||
targets: 3,
|
||||
render: function (data, type, full, meta) {
|
||||
var $role = full['role'];
|
||||
var roleBadgeObj = {
|
||||
Subscriber: '<i class="ti ti-crown ti-md text-primary me-2"></i>',
|
||||
Author: '<i class="ti ti-edit ti-md text-warning me-2"></i>',
|
||||
Maintainer: '<i class="ti ti-user ti-md text-success me-2"></i>',
|
||||
Editor: '<i class="ti ti-chart-pie ti-md text-info me-2"></i>',
|
||||
Admin: '<i class="ti ti-device-desktop ti-md text-danger me-2"></i>'
|
||||
};
|
||||
return (
|
||||
"<span class='text-truncate d-flex align-items-center text-heading'>" +
|
||||
roleBadgeObj[$role] +
|
||||
$role +
|
||||
'</span>'
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
// Plans
|
||||
targets: 4,
|
||||
render: function (data, type, full, meta) {
|
||||
var $plan = full['current_plan'];
|
||||
|
||||
return '<span class="text-heading">' + $plan + '</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
// User Status
|
||||
targets: 6,
|
||||
render: function (data, type, full, meta) {
|
||||
var $status = full['status'];
|
||||
|
||||
return (
|
||||
'<span class="badge ' +
|
||||
statusObj[$status].class +
|
||||
'" text-capitalized>' +
|
||||
statusObj[$status].title +
|
||||
'</span>'
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
// Actions
|
||||
targets: -1,
|
||||
title: 'Actions',
|
||||
searchable: false,
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
return (
|
||||
'<div class="d-flex align-items-center">' +
|
||||
'<a href="javascript:;" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill delete-record"><i class="ti ti-trash ti-md"></i></a>' +
|
||||
'<a href="' +
|
||||
userView +
|
||||
'" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill"><i class="ti ti-eye ti-md"></i></a>' +
|
||||
'<a href="javascript:;" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill dropdown-toggle hide-arrow" data-bs-toggle="dropdown"><i class="ti ti-dots-vertical ti-md"></i></a>' +
|
||||
'<div class="dropdown-menu dropdown-menu-end m-0">' +
|
||||
'<a href="javascript:;"" class="dropdown-item">Edit</a>' +
|
||||
'<a href="javascript:;" class="dropdown-item">Suspend</a>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
order: [[2, 'desc']],
|
||||
dom:
|
||||
'<"row"' +
|
||||
'<"col-md-2"<"ms-n2"l>>' +
|
||||
'<"col-md-10"<"dt-action-buttons text-xl-end text-lg-start text-md-end text-start d-flex align-items-center justify-content-end flex-md-row flex-column mb-6 mb-md-0 mt-n6 mt-md-0"fB>>' +
|
||||
'>t' +
|
||||
'<"row"' +
|
||||
'<"col-sm-12 col-md-6"i>' +
|
||||
'<"col-sm-12 col-md-6"p>' +
|
||||
'>',
|
||||
language: {
|
||||
sLengthMenu: '_MENU_',
|
||||
search: '',
|
||||
searchPlaceholder: 'Search User',
|
||||
paginate: {
|
||||
next: '<i class="ti ti-chevron-right ti-sm"></i>',
|
||||
previous: '<i class="ti ti-chevron-left ti-sm"></i>'
|
||||
}
|
||||
},
|
||||
// Buttons with Dropdown
|
||||
buttons: [
|
||||
{
|
||||
extend: 'collection',
|
||||
className: 'btn btn-label-secondary dropdown-toggle mx-4 waves-effect waves-light',
|
||||
text: '<i class="ti ti-upload me-2 ti-xs"></i>Export',
|
||||
buttons: [
|
||||
{
|
||||
extend: 'print',
|
||||
text: '<i class="ti ti-printer me-2" ></i>Print',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [1, 2, 3, 4, 5],
|
||||
// prevent avatar to be print
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
},
|
||||
customize: function (win) {
|
||||
//customize print view for dark
|
||||
$(win.document.body)
|
||||
.css('color', headingColor)
|
||||
.css('border-color', borderColor)
|
||||
.css('background-color', bodyBg);
|
||||
$(win.document.body)
|
||||
.find('table')
|
||||
.addClass('compact')
|
||||
.css('color', 'inherit')
|
||||
.css('border-color', 'inherit')
|
||||
.css('background-color', 'inherit');
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'csv',
|
||||
text: '<i class="ti ti-file-text me-2" ></i>Csv',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [1, 2, 3, 4, 5],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'excel',
|
||||
text: '<i class="ti ti-file-spreadsheet me-2"></i>Excel',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [1, 2, 3, 4, 5],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'pdf',
|
||||
text: '<i class="ti ti-file-code-2 me-2"></i>Pdf',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [1, 2, 3, 4, 5],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'copy',
|
||||
text: '<i class="ti ti-copy me-2" ></i>Copy',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: {
|
||||
columns: [1, 2, 3, 4, 5],
|
||||
// prevent avatar to be display
|
||||
format: {
|
||||
body: function (inner, coldex, rowdex) {
|
||||
if (inner.length <= 0) return inner;
|
||||
var el = $.parseHTML(inner);
|
||||
var result = '';
|
||||
$.each(el, function (index, item) {
|
||||
if (item.classList !== undefined && item.classList.contains('user-name')) {
|
||||
result = result + item.lastChild.firstChild.textContent;
|
||||
} else if (item.innerText === undefined) {
|
||||
result = result + item.textContent;
|
||||
} else result = result + item.innerText;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
text: '<i class="ti ti-plus me-0 me-sm-1 ti-xs"></i><span class="d-none d-sm-inline-block">Add New User</span>',
|
||||
className: 'add-new btn btn-primary waves-effect waves-light',
|
||||
attr: {
|
||||
'data-bs-toggle': 'offcanvas',
|
||||
'data-bs-target': '#offcanvasAddUser'
|
||||
}
|
||||
}
|
||||
],
|
||||
// For responsive popup
|
||||
responsive: {
|
||||
details: {
|
||||
display: $.fn.dataTable.Responsive.display.modal({
|
||||
header: function (row) {
|
||||
var data = row.data();
|
||||
return 'Details of ' + data['full_name'];
|
||||
}
|
||||
}),
|
||||
type: 'column',
|
||||
renderer: function (api, rowIdx, columns) {
|
||||
var data = $.map(columns, function (col, i) {
|
||||
return col.title !== '' // ? Do not show row in modal popup if title is blank (for check box)
|
||||
? '<tr data-dt-row="' +
|
||||
col.rowIndex +
|
||||
'" data-dt-column="' +
|
||||
col.columnIndex +
|
||||
'">' +
|
||||
'<td>' +
|
||||
col.title +
|
||||
':' +
|
||||
'</td> ' +
|
||||
'<td>' +
|
||||
col.data +
|
||||
'</td>' +
|
||||
'</tr>'
|
||||
: '';
|
||||
}).join('');
|
||||
|
||||
return data ? $('<table class="table"/><tbody />').append(data) : false;
|
||||
}
|
||||
}
|
||||
},
|
||||
initComplete: function () {
|
||||
// Adding role filter once table initialized
|
||||
this.api()
|
||||
.columns(3)
|
||||
.every(function () {
|
||||
var column = this;
|
||||
var select = $(
|
||||
'<select id="UserRole" class="form-select text-capitalize"><option value=""> Select Role </option></select>'
|
||||
)
|
||||
.appendTo('.user_role')
|
||||
.on('change', function () {
|
||||
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
||||
column.search(val ? '^' + val + '$' : '', true, false).draw();
|
||||
});
|
||||
|
||||
column
|
||||
.data()
|
||||
.unique()
|
||||
.sort()
|
||||
.each(function (d, j) {
|
||||
select.append('<option value="' + d + '">' + d + '</option>');
|
||||
});
|
||||
});
|
||||
// Adding plan filter once table initialized
|
||||
this.api()
|
||||
.columns(4)
|
||||
.every(function () {
|
||||
var column = this;
|
||||
var select = $(
|
||||
'<select id="UserPlan" class="form-select text-capitalize"><option value=""> Select Plan </option></select>'
|
||||
)
|
||||
.appendTo('.user_plan')
|
||||
.on('change', function () {
|
||||
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
||||
column.search(val ? '^' + val + '$' : '', true, false).draw();
|
||||
});
|
||||
|
||||
column
|
||||
.data()
|
||||
.unique()
|
||||
.sort()
|
||||
.each(function (d, j) {
|
||||
select.append('<option value="' + d + '">' + d + '</option>');
|
||||
});
|
||||
});
|
||||
// Adding status filter once table initialized
|
||||
this.api()
|
||||
.columns(6)
|
||||
.every(function () {
|
||||
var column = this;
|
||||
var select = $(
|
||||
'<select id="FilterTransaction" class="form-select text-capitalize"><option value=""> Select Status </option></select>'
|
||||
)
|
||||
.appendTo('.user_status')
|
||||
.on('change', function () {
|
||||
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
||||
column.search(val ? '^' + val + '$' : '', true, false).draw();
|
||||
});
|
||||
|
||||
column
|
||||
.data()
|
||||
.unique()
|
||||
.sort()
|
||||
.each(function (d, j) {
|
||||
select.append(
|
||||
'<option value="' +
|
||||
statusObj[d].title +
|
||||
'" class="text-capitalize">' +
|
||||
statusObj[d].title +
|
||||
'</option>'
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Delete Record
|
||||
$('.datatables-users tbody').on('click', '.delete-record', function () {
|
||||
dt_user.row($(this).parents('tr')).remove().draw();
|
||||
});
|
||||
|
||||
// Filter form control to default size
|
||||
// ? setTimeout used for multilingual table initialization
|
||||
setTimeout(() => {
|
||||
$('.dataTables_filter .form-control').removeClass('form-control-sm');
|
||||
$('.dataTables_length .form-select').removeClass('form-select-sm');
|
||||
}, 300);
|
||||
});
|
||||
|
||||
// Validation & Phone mask
|
||||
(function () {
|
||||
const phoneMaskList = document.querySelectorAll('.phone-mask'),
|
||||
addNewUserForm = document.getElementById('addNewUserForm');
|
||||
|
||||
// Phone Number
|
||||
if (phoneMaskList) {
|
||||
phoneMaskList.forEach(function (phoneMask) {
|
||||
new Cleave(phoneMask, {
|
||||
phone: true,
|
||||
phoneRegionCode: 'US'
|
||||
});
|
||||
});
|
||||
}
|
||||
// Add New User Form Validation
|
||||
const fv = FormValidation.formValidation(addNewUserForm, {
|
||||
fields: {
|
||||
userFullname: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter fullname '
|
||||
}
|
||||
}
|
||||
},
|
||||
userEmail: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your email'
|
||||
},
|
||||
emailAddress: {
|
||||
message: 'The value is not a valid email address'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
eleValidClass: '',
|
||||
rowSelector: function (field, ele) {
|
||||
// field is the field name & ele is the field element
|
||||
return '.mb-6';
|
||||
}
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
});
|
||||
})();
|
222
resources/js/auth/app-user-view-account.js
Normal file
222
resources/js/auth/app-user-view-account.js
Normal file
@ -0,0 +1,222 @@
|
||||
/**
|
||||
* App User View - Account (jquery)
|
||||
*/
|
||||
|
||||
$(function () {
|
||||
'use strict';
|
||||
|
||||
// Variable declaration for table
|
||||
var dt_invoice_table = $('.datatable-invoice');
|
||||
|
||||
// Invoice datatable
|
||||
// --------------------------------------------------------------------
|
||||
if (dt_invoice_table.length) {
|
||||
var dt_invoice = dt_invoice_table.DataTable({
|
||||
ajax: assetsPath + 'json/invoice-list.json', // JSON file to add data
|
||||
columns: [
|
||||
// columns according to JSON
|
||||
{ data: '' },
|
||||
{ data: 'invoice_id' },
|
||||
{ data: 'invoice_status' },
|
||||
{ data: 'total' },
|
||||
{ data: 'issued_date' },
|
||||
{ data: 'action' }
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
// For Responsive
|
||||
className: 'control',
|
||||
responsivePriority: 2,
|
||||
targets: 0,
|
||||
render: function (data, type, full, meta) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
{
|
||||
// Invoice ID
|
||||
targets: 1,
|
||||
render: function (data, type, full, meta) {
|
||||
var $invoice_id = full['invoice_id'];
|
||||
// Creates full output for row
|
||||
var $row_output = '<a href="' + baseUrl + 'app/invoice/preview"><span>#' + $invoice_id + '</span></a>';
|
||||
return $row_output;
|
||||
}
|
||||
},
|
||||
{
|
||||
// Invoice status
|
||||
targets: 2,
|
||||
render: function (data, type, full, meta) {
|
||||
var $invoice_status = full['invoice_status'],
|
||||
$due_date = full['due_date'],
|
||||
$balance = full['balance'];
|
||||
var roleBadgeObj = {
|
||||
Sent: '<span class="badge badge-center d-flex align-items-center justify-content-center rounded-pill bg-label-secondary w-px-30 h-px-30"><i class="ti ti-circle-check ti-xs"></i></span>',
|
||||
Draft:
|
||||
'<span class="badge badge-center d-flex align-items-center justify-content-center rounded-pill bg-label-primary w-px-30 h-px-30"><i class="ti ti-device-floppy ti-xs"></i></span>',
|
||||
'Past Due':
|
||||
'<span class="badge badge-center d-flex align-items-center justify-content-center rounded-pill bg-label-danger w-px-30 h-px-30"><i class="ti ti-info-circle ti-xs"></i></span>',
|
||||
'Partial Payment':
|
||||
'<span class="badge badge-center d-flex align-items-center justify-content-center rounded-pill bg-label-success w-px-30 h-px-30"><i class="ti ti-circle-half-2 ti-xs"></i></span>',
|
||||
Paid: '<span class="badge badge-center d-flex align-items-center justify-content-center rounded-pill bg-label-warning w-px-30 h-px-30"><i class="ti ti-chart-pie ti-xs"></i></span>',
|
||||
Downloaded:
|
||||
'<span class="badge badge-center d-flex align-items-center justify-content-center rounded-pill bg-label-info w-px-30 h-px-30"><i class="ti ti-arrow-down-circle ti-xs"></i></span>'
|
||||
};
|
||||
return (
|
||||
"<span class='d-inline-block' data-bs-toggle='tooltip' data-bs-html='true' title='<span>" +
|
||||
$invoice_status +
|
||||
'<br> <span class="fw-medium">Balance:</span> ' +
|
||||
$balance +
|
||||
'<br> <span class="fw-medium">Due Date:</span> ' +
|
||||
$due_date +
|
||||
"</span>'>" +
|
||||
roleBadgeObj[$invoice_status] +
|
||||
'</span>'
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
// Total Invoice Amount
|
||||
targets: 3,
|
||||
render: function (data, type, full, meta) {
|
||||
var $total = full['total'];
|
||||
return '$' + $total;
|
||||
}
|
||||
},
|
||||
{
|
||||
// Actions
|
||||
targets: -1,
|
||||
title: 'Actions',
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
return (
|
||||
'<div class="d-flex align-items-center">' +
|
||||
'<a href="javascript:;" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill delete-record" data-bs-toggle="tooltip" title="Delete record"><i class="ti ti-trash ti-md"></i></a>' +
|
||||
'<a href="app-invoice-preview.html" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill" data-bs-toggle="tooltip" title="Preview"><i class="ti ti-eye ti-md"></i></a>' +
|
||||
'<div class="d-inline-block">' +
|
||||
'<a href="javascript:;" class="btn btn-sm btn-icon dropdown-toggle hide-arrow btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill" data-bs-toggle="dropdown"><i class="ti ti-dots-vertical ti-md"></i></a>' +
|
||||
'<ul class="dropdown-menu dropdown-menu-end m-0">' +
|
||||
'<li><a href="javascript:;" class="dropdown-item">Details</a></li>' +
|
||||
'<li><a href="javascript:;" class="dropdown-item">Archive</a></li>' +
|
||||
'</ul>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
order: [[1, 'desc']],
|
||||
dom:
|
||||
'<"row mx-6"' +
|
||||
'<"col-sm-6 col-12 d-flex align-items-center justify-content-center justify-content-sm-start mt-6 mt-sm-0"<"invoice-head-label">>' +
|
||||
'<"col-sm-6 col-12 d-flex justify-content-center justify-content-md-end align-items-baseline"<"dt-action-buttons d-flex justify-content-center flex-md-row align-items-baseline gap-2"lB>>' +
|
||||
'>t' +
|
||||
'<"row mx-4"' +
|
||||
'<"col-sm-12 col-xxl-6 text-center text-xxl-start pb-md-2 pb-xxl-0"i>' +
|
||||
'<"col-sm-12 col-xxl-6 d-md-flex justify-content-xxl-end justify-content-center"p>' +
|
||||
'>',
|
||||
language: {
|
||||
sLengthMenu: 'Show _MENU_',
|
||||
search: '',
|
||||
searchPlaceholder: 'Search Invoice',
|
||||
paginate: {
|
||||
next: '<i class="ti ti-chevron-right ti-sm"></i>',
|
||||
previous: '<i class="ti ti-chevron-left ti-sm"></i>'
|
||||
}
|
||||
},
|
||||
// Buttons with Dropdown
|
||||
buttons: [
|
||||
{
|
||||
extend: 'collection',
|
||||
className: 'btn btn-label-secondary dropdown-toggle float-sm-end mb-3 mb-sm-0 waves-effect waves-light',
|
||||
text: '<i class="ti ti-upload ti-xs me-2"></i>Export',
|
||||
buttons: [
|
||||
{
|
||||
extend: 'print',
|
||||
text: '<i class="ti ti-printer me-2" ></i>Print',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: { columns: [1, 2, 3, 4] }
|
||||
},
|
||||
{
|
||||
extend: 'csv',
|
||||
text: '<i class="ti ti-file-text me-2" ></i>Csv',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: { columns: [1, 2, 3, 4] }
|
||||
},
|
||||
{
|
||||
extend: 'excel',
|
||||
text: '<i class="ti ti-file-spreadsheet me-2"></i>Excel',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: { columns: [1, 2, 3, 4] }
|
||||
},
|
||||
{
|
||||
extend: 'pdf',
|
||||
text: '<i class="ti ti-file-description me-2"></i>Pdf',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: { columns: [1, 2, 3, 4] }
|
||||
},
|
||||
{
|
||||
extend: 'copy',
|
||||
text: '<i class="ti ti-copy me-2" ></i>Copy',
|
||||
className: 'dropdown-item',
|
||||
exportOptions: { columns: [1, 2, 3, 4] }
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
// For responsive popup
|
||||
responsive: {
|
||||
details: {
|
||||
display: $.fn.dataTable.Responsive.display.modal({
|
||||
header: function (row) {
|
||||
var data = row.data();
|
||||
return 'Details of ' + data['full_name'];
|
||||
}
|
||||
}),
|
||||
type: 'column',
|
||||
renderer: function (api, rowIdx, columns) {
|
||||
var data = $.map(columns, function (col, i) {
|
||||
return col.title !== '' // ? Do not show row in modal popup if title is blank (for check box)
|
||||
? '<tr data-dt-row="' +
|
||||
col.rowIndex +
|
||||
'" data-dt-column="' +
|
||||
col.columnIndex +
|
||||
'">' +
|
||||
'<td>' +
|
||||
col.title +
|
||||
':' +
|
||||
'</td> ' +
|
||||
'<td>' +
|
||||
col.data +
|
||||
'</td>' +
|
||||
'</tr>'
|
||||
: '';
|
||||
}).join('');
|
||||
|
||||
return data ? $('<table class="table"/><tbody />').append(data) : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
$('div.invoice-head-label').html('<h5 class="card-title mb-0">Invoice List</h5>');
|
||||
}
|
||||
// On each datatable draw, initialize tooltip
|
||||
dt_invoice_table.on('draw.dt', function () {
|
||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl, {
|
||||
boundary: document.body
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Delete Record
|
||||
$('.datatable-invoice tbody').on('click', '.delete-record', function () {
|
||||
dt_invoice.row($(this).parents('tr')).remove().draw();
|
||||
});
|
||||
// Filter form control to default size
|
||||
// ? setTimeout used for multilingual table initialization
|
||||
setTimeout(() => {
|
||||
$('.dataTables_filter .form-control').removeClass('form-control-sm');
|
||||
$('.dataTables_length .form-select').removeClass('form-select-sm');
|
||||
}, 300);
|
||||
});
|
57
resources/js/auth/app-user-view-billing.js
Normal file
57
resources/js/auth/app-user-view-billing.js
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* App User View - Billing
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
// Cancel Subscription alert
|
||||
const cancelSubscription = document.querySelector('.cancel-subscription');
|
||||
|
||||
// Alert With Functional Confirm Button
|
||||
if (cancelSubscription) {
|
||||
cancelSubscription.onclick = function () {
|
||||
Swal.fire({
|
||||
text: 'Are you sure you would like to cancel your subscription?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Yes',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-2 waves-effect waves-light',
|
||||
cancelButton: 'btn btn-label-secondary waves-effect waves-light'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (result.value) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Unsubscribed!',
|
||||
text: 'Your subscription cancelled successfully.',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
} else if (result.dismiss === Swal.DismissReason.cancel) {
|
||||
Swal.fire({
|
||||
title: 'Cancelled',
|
||||
text: 'Unsubscription Cancelled!!',
|
||||
icon: 'error',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// On edit address click, update text of add address modal
|
||||
const addressEdit = document.querySelector('.edit-address'),
|
||||
addressTitle = document.querySelector('.address-title'),
|
||||
addressSubTitle = document.querySelector('.address-subtitle');
|
||||
|
||||
addressEdit.onclick = function () {
|
||||
addressTitle.innerHTML = 'Edit Address'; // reset text
|
||||
addressSubTitle.innerHTML = 'Edit your current address';
|
||||
};
|
||||
})();
|
63
resources/js/auth/app-user-view-security.js
Normal file
63
resources/js/auth/app-user-view-security.js
Normal file
@ -0,0 +1,63 @@
|
||||
/**
|
||||
* App User View - Security
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
const formChangePass = document.querySelector('#formChangePassword');
|
||||
|
||||
// Form validation for Change password
|
||||
if (formChangePass) {
|
||||
const fv = FormValidation.formValidation(formChangePass, {
|
||||
fields: {
|
||||
newPassword: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter new password'
|
||||
},
|
||||
stringLength: {
|
||||
min: 8,
|
||||
message: 'Password must be more than 8 characters'
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmPassword: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please confirm new password'
|
||||
},
|
||||
identical: {
|
||||
compare: function () {
|
||||
return formChangePass.querySelector('[name="newPassword"]').value;
|
||||
},
|
||||
message: 'The password and its confirm are not the same'
|
||||
},
|
||||
stringLength: {
|
||||
min: 8,
|
||||
message: 'Password must be more than 8 characters'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: '',
|
||||
rowSelector: '.form-password-toggle'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
89
resources/js/auth/app-user-view.js
Normal file
89
resources/js/auth/app-user-view.js
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* App User View - Suspend User Script
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
const suspendUser = document.querySelector('.suspend-user');
|
||||
|
||||
// Suspend User javascript
|
||||
if (suspendUser) {
|
||||
suspendUser.onclick = function () {
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: "You won't be able to revert user!",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Yes, Suspend user!',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-2 waves-effect waves-light',
|
||||
cancelButton: 'btn btn-label-secondary waves-effect waves-light'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (result.value) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Suspended!',
|
||||
text: 'User has been suspended.',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
} else if (result.dismiss === Swal.DismissReason.cancel) {
|
||||
Swal.fire({
|
||||
title: 'Cancelled',
|
||||
text: 'Cancelled Suspension :)',
|
||||
icon: 'error',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
//? Billing page have multiple buttons
|
||||
// Cancel Subscription alert
|
||||
const cancelSubscription = document.querySelectorAll('.cancel-subscription');
|
||||
|
||||
// Alert With Functional Confirm Button
|
||||
if (cancelSubscription) {
|
||||
cancelSubscription.forEach(btnCancle => {
|
||||
btnCancle.onclick = function () {
|
||||
Swal.fire({
|
||||
text: 'Are you sure you would like to cancel your subscription?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Yes',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-2 waves-effect waves-light',
|
||||
cancelButton: 'btn btn-label-secondary waves-effect waves-light'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (result.value) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Unsubscribed!',
|
||||
text: 'Your subscription cancelled successfully.',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
} else if (result.dismiss === Swal.DismissReason.cancel) {
|
||||
Swal.fire({
|
||||
title: 'Cancelled',
|
||||
text: 'Unsubscription Cancelled!!',
|
||||
icon: 'error',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
})();
|
73
resources/js/auth/modal-add-new-address.js
Normal file
73
resources/js/auth/modal-add-new-address.js
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Add New Address
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Select2 (jquery)
|
||||
$(function () {
|
||||
const select2 = $('.select2');
|
||||
|
||||
// Select2 Country
|
||||
if (select2.length) {
|
||||
select2.each(function () {
|
||||
var $this = $(this);
|
||||
$this.wrap('<div class="position-relative"></div>').select2({
|
||||
placeholder: 'Select value',
|
||||
dropdownParent: $this.parent()
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Add New Address form validation
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
(function () {
|
||||
// initCustomOptionCheck on modal show to update the custom select
|
||||
let addNewAddress = document.getElementById('addNewAddress');
|
||||
addNewAddress.addEventListener('show.bs.modal', function (event) {
|
||||
// Init custom option check
|
||||
window.Helpers.initCustomOptionCheck();
|
||||
});
|
||||
|
||||
FormValidation.formValidation(document.getElementById('addNewAddressForm'), {
|
||||
fields: {
|
||||
modalAddressFirstName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your first name'
|
||||
},
|
||||
regexp: {
|
||||
regexp: /^[a-zA-Zs]+$/,
|
||||
message: 'The first name can only consist of alphabetical'
|
||||
}
|
||||
}
|
||||
},
|
||||
modalAddressLastName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your last name'
|
||||
},
|
||||
regexp: {
|
||||
regexp: /^[a-zA-Zs]+$/,
|
||||
message: 'The last name can only consist of alphabetical'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-12'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
});
|
||||
})();
|
||||
});
|
107
resources/js/auth/modal-add-new-cc.js
Normal file
107
resources/js/auth/modal-add-new-cc.js
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Add new credit card
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
// Variables
|
||||
const creditCardMask = document.querySelector('.credit-card-mask'),
|
||||
expiryDateMask = document.querySelector('.expiry-date-mask'),
|
||||
cvvMask = document.querySelector('.cvv-code-mask'),
|
||||
btnReset = document.querySelector('.btn-reset');
|
||||
let cleave;
|
||||
|
||||
// Credit Card
|
||||
function initCleave() {
|
||||
if (creditCardMask) {
|
||||
cleave = new Cleave(creditCardMask, {
|
||||
creditCard: true,
|
||||
onCreditCardTypeChanged: function (type) {
|
||||
if (type != '' && type != 'unknown') {
|
||||
document.querySelector('.card-type').innerHTML =
|
||||
'<img src="' +
|
||||
assetsPath +
|
||||
'img/icons/payments/' +
|
||||
type +
|
||||
'-cc.png" class="cc-icon-image" height="28"/>';
|
||||
} else {
|
||||
document.querySelector('.card-type').innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Init cleave on show modal (To fix the cc image issue)
|
||||
let addNewCCModal = document.getElementById('addNewCCModal');
|
||||
addNewCCModal.addEventListener('show.bs.modal', function (event) {
|
||||
initCleave();
|
||||
});
|
||||
|
||||
// Expiry Date Mask
|
||||
if (expiryDateMask) {
|
||||
new Cleave(expiryDateMask, {
|
||||
date: true,
|
||||
delimiter: '/',
|
||||
datePattern: ['m', 'y']
|
||||
});
|
||||
}
|
||||
|
||||
// CVV
|
||||
if (cvvMask) {
|
||||
new Cleave(cvvMask, {
|
||||
numeral: true,
|
||||
numeralPositiveOnly: true
|
||||
});
|
||||
}
|
||||
|
||||
// Credit card form validation
|
||||
FormValidation.formValidation(document.getElementById('addNewCCForm'), {
|
||||
fields: {
|
||||
modalAddCard: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your credit card number'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-12'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
//* Move the error message out of the `input-group` element
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).on('plugins.message.displayed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
//* Move the error message out of the `input-group` element
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement.parentElement);
|
||||
}
|
||||
});
|
||||
|
||||
// reset card image on click of cancel
|
||||
btnReset.addEventListener('click', function (e) {
|
||||
// blank '.card-type' innerHTML to remove image
|
||||
document.querySelector('.card-type').innerHTML = '';
|
||||
// destroy cleave and init again on modal open
|
||||
cleave.destroy();
|
||||
});
|
||||
})();
|
||||
});
|
35
resources/js/auth/modal-add-permission.js
Normal file
35
resources/js/auth/modal-add-permission.js
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Add Permission Modal JS
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Add permission form validation
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
FormValidation.formValidation(document.getElementById('addPermissionForm'), {
|
||||
fields: {
|
||||
modalPermissionName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter permission name'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-12'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
});
|
||||
})();
|
||||
});
|
44
resources/js/auth/modal-add-role.js
Normal file
44
resources/js/auth/modal-add-role.js
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Add new role Modal JS
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
// add role form validation
|
||||
FormValidation.formValidation(document.getElementById('addRoleForm'), {
|
||||
fields: {
|
||||
modalRoleName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter role name'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-12'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
});
|
||||
|
||||
// Select All checkbox click
|
||||
const selectAll = document.querySelector('#selectAll'),
|
||||
checkboxList = document.querySelectorAll('[type="checkbox"]');
|
||||
selectAll.addEventListener('change', t => {
|
||||
checkboxList.forEach(e => {
|
||||
e.checked = t.target.checked;
|
||||
});
|
||||
});
|
||||
})();
|
||||
});
|
79
resources/js/auth/modal-edit-cc.js
Normal file
79
resources/js/auth/modal-edit-cc.js
Normal file
@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Edit credit card
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
const editCreditCardMaskEdit = document.querySelector('.credit-card-mask-edit'),
|
||||
editExpiryDateMaskEdit = document.querySelector('.expiry-date-mask-edit'),
|
||||
editCVVMaskEdit = document.querySelector('.cvv-code-mask-edit');
|
||||
|
||||
// Credit Card
|
||||
if (editCreditCardMaskEdit) {
|
||||
new Cleave(editCreditCardMaskEdit, {
|
||||
creditCard: true,
|
||||
onCreditCardTypeChanged: function (type) {
|
||||
if (type != '' && type != 'unknown') {
|
||||
document.querySelector('.card-type-edit').innerHTML =
|
||||
'<img src="' + assetsPath + 'img/icons/payments/' + type + '-cc.png" height="28"/>';
|
||||
} else {
|
||||
document.querySelector('.card-type-edit').innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Expiry Date MaskEdit
|
||||
if (editExpiryDateMaskEdit) {
|
||||
new Cleave(editExpiryDateMaskEdit, {
|
||||
date: true,
|
||||
delimiter: '/',
|
||||
datePattern: ['m', 'y']
|
||||
});
|
||||
}
|
||||
|
||||
// CVV MaskEdit
|
||||
if (editCVVMaskEdit) {
|
||||
new Cleave(editCVVMaskEdit, {
|
||||
numeral: true,
|
||||
numeralPositiveOnly: true
|
||||
});
|
||||
}
|
||||
|
||||
// Credit card form validation
|
||||
FormValidation.formValidation(document.getElementById('editCCForm'), {
|
||||
fields: {
|
||||
modalEditCard: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your credit card number'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-12'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
//* Move the error message out of the `input-group` element
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
});
|
35
resources/js/auth/modal-edit-permission.js
Normal file
35
resources/js/auth/modal-edit-permission.js
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Edit Permission Modal JS
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Edit permission form validation
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
FormValidation.formValidation(document.getElementById('editPermissionForm'), {
|
||||
fields: {
|
||||
editPermissionName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter permission name'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-sm-9'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
});
|
||||
})();
|
||||
});
|
103
resources/js/auth/modal-edit-user.js
Normal file
103
resources/js/auth/modal-edit-user.js
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Edit User
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Select2 (jquery)
|
||||
$(function () {
|
||||
const select2 = $('.select2');
|
||||
|
||||
// Select2 Country
|
||||
if (select2.length) {
|
||||
select2.each(function () {
|
||||
var $this = $(this);
|
||||
$this.wrap('<div class="position-relative"></div>').select2({
|
||||
placeholder: 'Select value',
|
||||
dropdownParent: $this.parent()
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
// variables
|
||||
const modalEditUserTaxID = document.querySelector('.modal-edit-tax-id');
|
||||
const modalEditUserPhone = document.querySelector('.phone-number-mask');
|
||||
|
||||
// Prefix
|
||||
if (modalEditUserTaxID) {
|
||||
new Cleave(modalEditUserTaxID, {
|
||||
prefix: 'TIN',
|
||||
blocks: [3, 3, 3, 4],
|
||||
uppercase: true
|
||||
});
|
||||
}
|
||||
|
||||
// Phone Number Input Mask
|
||||
if (modalEditUserPhone) {
|
||||
new Cleave(modalEditUserPhone, {
|
||||
phone: true,
|
||||
phoneRegionCode: 'US'
|
||||
});
|
||||
}
|
||||
|
||||
// Edit user form validation
|
||||
FormValidation.formValidation(document.getElementById('editUserForm'), {
|
||||
fields: {
|
||||
modalEditUserFirstName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your first name'
|
||||
},
|
||||
regexp: {
|
||||
regexp: /^[a-zA-Zs]+$/,
|
||||
message: 'The first name can only consist of alphabetical'
|
||||
}
|
||||
}
|
||||
},
|
||||
modalEditUserLastName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your last name'
|
||||
},
|
||||
regexp: {
|
||||
regexp: /^[a-zA-Zs]+$/,
|
||||
message: 'The last name can only consist of alphabetical'
|
||||
}
|
||||
}
|
||||
},
|
||||
modalEditUserName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your username'
|
||||
},
|
||||
stringLength: {
|
||||
min: 6,
|
||||
max: 30,
|
||||
message: 'The name must be more than 6 and less than 30 characters long'
|
||||
},
|
||||
regexp: {
|
||||
regexp: /^[a-zA-Z0-9 ]+$/,
|
||||
message: 'The name can only consist of alphabetical, number and space'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-12'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
});
|
||||
})();
|
||||
});
|
53
resources/js/auth/modal-enable-otp.js
Normal file
53
resources/js/auth/modal-enable-otp.js
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Enable OTP
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
const phoneMask = document.querySelector('.phone-number-otp-mask');
|
||||
|
||||
// Phone Number Input Mask
|
||||
if (phoneMask) {
|
||||
new Cleave(phoneMask, {
|
||||
phone: true,
|
||||
phoneRegionCode: 'US'
|
||||
});
|
||||
}
|
||||
|
||||
// Enable OTP form validation
|
||||
FormValidation.formValidation(document.getElementById('enableOTPForm'), {
|
||||
fields: {
|
||||
modalEnableOTPPhone: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your mobile number'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-12'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
//* Move the error message out of the `input-group` element
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
});
|
189
resources/js/auth/pages-account-settings-account.js
Normal file
189
resources/js/auth/pages-account-settings-account.js
Normal file
@ -0,0 +1,189 @@
|
||||
/**
|
||||
* Account Settings - Account
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
const formAccSettings = document.querySelector('#formAccountSettings'),
|
||||
deactivateAcc = document.querySelector('#formAccountDeactivation'),
|
||||
deactivateButton = deactivateAcc.querySelector('.deactivate-account');
|
||||
|
||||
// Form validation for Add new record
|
||||
if (formAccSettings) {
|
||||
const fv = FormValidation.formValidation(formAccSettings, {
|
||||
fields: {
|
||||
firstName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter first name'
|
||||
}
|
||||
}
|
||||
},
|
||||
lastName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter last name'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-md-6'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (deactivateAcc) {
|
||||
const fv = FormValidation.formValidation(deactivateAcc, {
|
||||
fields: {
|
||||
accountActivation: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please confirm you want to delete account'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: ''
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
fieldStatus: new FormValidation.plugins.FieldStatus({
|
||||
onStatusChanged: function (areFieldsValid) {
|
||||
areFieldsValid
|
||||
? // Enable the submit button
|
||||
// so user has a chance to submit the form again
|
||||
deactivateButton.removeAttribute('disabled')
|
||||
: // Disable the submit button
|
||||
deactivateButton.setAttribute('disabled', 'disabled');
|
||||
}
|
||||
}),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Deactivate account alert
|
||||
const accountActivation = document.querySelector('#accountActivation');
|
||||
|
||||
// Alert With Functional Confirm Button
|
||||
if (deactivateButton) {
|
||||
deactivateButton.onclick = function () {
|
||||
if (accountActivation.checked == true) {
|
||||
Swal.fire({
|
||||
text: 'Are you sure you would like to deactivate your account?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Yes',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-2 waves-effect waves-light',
|
||||
cancelButton: 'btn btn-label-secondary waves-effect waves-light'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (result.value) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Deleted!',
|
||||
text: 'Your file has been deleted.',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
} else if (result.dismiss === Swal.DismissReason.cancel) {
|
||||
Swal.fire({
|
||||
title: 'Cancelled',
|
||||
text: 'Deactivation Cancelled!!',
|
||||
icon: 'error',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// CleaveJS validation
|
||||
|
||||
const phoneNumber = document.querySelector('#phoneNumber'),
|
||||
zipCode = document.querySelector('#zipCode');
|
||||
// Phone Mask
|
||||
if (phoneNumber) {
|
||||
new Cleave(phoneNumber, {
|
||||
phone: true,
|
||||
phoneRegionCode: 'US'
|
||||
});
|
||||
}
|
||||
|
||||
// Pincode
|
||||
if (zipCode) {
|
||||
new Cleave(zipCode, {
|
||||
delimiter: '',
|
||||
numeral: true
|
||||
});
|
||||
}
|
||||
|
||||
// Update/reset user image of account page
|
||||
let accountUserImage = document.getElementById('uploadedAvatar');
|
||||
const fileInput = document.querySelector('.account-file-input'),
|
||||
resetFileInput = document.querySelector('.account-image-reset');
|
||||
|
||||
if (accountUserImage) {
|
||||
const resetImage = accountUserImage.src;
|
||||
fileInput.onchange = () => {
|
||||
if (fileInput.files[0]) {
|
||||
accountUserImage.src = window.URL.createObjectURL(fileInput.files[0]);
|
||||
}
|
||||
};
|
||||
resetFileInput.onclick = () => {
|
||||
fileInput.value = '';
|
||||
accountUserImage.src = resetImage;
|
||||
};
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
// Select2 (jquery)
|
||||
$(function () {
|
||||
var select2 = $('.select2');
|
||||
// For all Select2
|
||||
if (select2.length) {
|
||||
select2.each(function () {
|
||||
var $this = $(this);
|
||||
$this.wrap('<div class="position-relative"></div>');
|
||||
$this.select2({
|
||||
dropdownParent: $this.parent()
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
194
resources/js/auth/pages-account-settings-billing.js
Normal file
194
resources/js/auth/pages-account-settings-billing.js
Normal file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* Account Settings - Billing & Plans
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
const creditCardMask = document.querySelector('.credit-card-mask'),
|
||||
expiryDateMask = document.querySelector('.expiry-date-mask'),
|
||||
CVVMask = document.querySelector('.cvv-code-mask');
|
||||
|
||||
// Credit Card
|
||||
if (creditCardMask) {
|
||||
new Cleave(creditCardMask, {
|
||||
creditCard: true,
|
||||
onCreditCardTypeChanged: function (type) {
|
||||
if (type != '' && type != 'unknown') {
|
||||
document.querySelector('.card-type').innerHTML =
|
||||
'<img src="' + assetsPath + 'img/icons/payments/' + type + '-cc.png" height="28"/>';
|
||||
} else {
|
||||
document.querySelector('.card-type').innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Expiry Date Mask
|
||||
if (expiryDateMask) {
|
||||
new Cleave(expiryDateMask, {
|
||||
date: true,
|
||||
delimiter: '/',
|
||||
datePattern: ['m', 'y']
|
||||
});
|
||||
}
|
||||
|
||||
// CVV Mask
|
||||
if (CVVMask) {
|
||||
new Cleave(CVVMask, {
|
||||
numeral: true,
|
||||
numeralPositiveOnly: true
|
||||
});
|
||||
}
|
||||
|
||||
const formAccSettings = document.getElementById('formAccountSettings'),
|
||||
mobileNumber = document.querySelector('.mobile-number'),
|
||||
zipCode = document.querySelector('.zip-code'),
|
||||
creditCardForm = document.getElementById('creditCardForm');
|
||||
|
||||
// Form validation
|
||||
if (formAccSettings) {
|
||||
const fv = FormValidation.formValidation(formAccSettings, {
|
||||
fields: {
|
||||
companyName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter company name'
|
||||
}
|
||||
}
|
||||
},
|
||||
billingEmail: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter billing email'
|
||||
},
|
||||
emailAddress: {
|
||||
message: 'Please enter valid email address'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-sm-6'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Credit card form validation
|
||||
if (creditCardForm) {
|
||||
FormValidation.formValidation(creditCardForm, {
|
||||
fields: {
|
||||
paymentCard: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your credit card number'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: ''
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
//* Move the error message out of the `input-group` element
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Cancel Subscription alert
|
||||
const cancelSubscription = document.querySelector('.cancel-subscription');
|
||||
|
||||
// Alert With Functional Confirm Button
|
||||
if (cancelSubscription) {
|
||||
cancelSubscription.onclick = function () {
|
||||
Swal.fire({
|
||||
text: 'Are you sure you would like to cancel your subscription?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Yes',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary me-2 waves-effect waves-light',
|
||||
cancelButton: 'btn btn-label-secondary waves-effect waves-light'
|
||||
},
|
||||
buttonsStyling: false
|
||||
}).then(function (result) {
|
||||
if (result.value) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Unsubscribed!',
|
||||
text: 'Your subscription cancelled successfully.',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
} else if (result.dismiss === Swal.DismissReason.cancel) {
|
||||
Swal.fire({
|
||||
title: 'Cancelled',
|
||||
text: 'Unsubscription Cancelled!!',
|
||||
icon: 'error',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-success waves-effect waves-light'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
// CleaveJS validation
|
||||
|
||||
// Phone Mask
|
||||
if (mobileNumber) {
|
||||
new Cleave(mobileNumber, {
|
||||
phone: true,
|
||||
phoneRegionCode: 'US'
|
||||
});
|
||||
}
|
||||
|
||||
// Pincode
|
||||
if (zipCode) {
|
||||
new Cleave(zipCode, {
|
||||
delimiter: '',
|
||||
numeral: true
|
||||
});
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
// Select2 (jquery)
|
||||
$(function () {
|
||||
var select2 = $('.select2');
|
||||
|
||||
// Select2
|
||||
if (select2.length) {
|
||||
select2.each(function () {
|
||||
var $this = $(this);
|
||||
$this.wrap('<div class="position-relative"></div>');
|
||||
$this.select2({
|
||||
dropdownParent: $this.parent()
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
125
resources/js/auth/pages-account-settings-security.js
Normal file
125
resources/js/auth/pages-account-settings-security.js
Normal file
@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Account Settings - Security
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
const formChangePass = document.querySelector('#formAccountSettings'),
|
||||
formApiKey = document.querySelector('#formAccountSettingsApiKey');
|
||||
|
||||
// Form validation for Change password
|
||||
if (formChangePass) {
|
||||
const fv = FormValidation.formValidation(formChangePass, {
|
||||
fields: {
|
||||
currentPassword: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please current password'
|
||||
},
|
||||
stringLength: {
|
||||
min: 8,
|
||||
message: 'Password must be more than 8 characters'
|
||||
}
|
||||
}
|
||||
},
|
||||
newPassword: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter new password'
|
||||
},
|
||||
stringLength: {
|
||||
min: 8,
|
||||
message: 'Password must be more than 8 characters'
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmPassword: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please confirm new password'
|
||||
},
|
||||
identical: {
|
||||
compare: function () {
|
||||
return formChangePass.querySelector('[name="newPassword"]').value;
|
||||
},
|
||||
message: 'The password and its confirm are not the same'
|
||||
},
|
||||
stringLength: {
|
||||
min: 8,
|
||||
message: 'Password must be more than 8 characters'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-md-6'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Form validation for API key
|
||||
if (formApiKey) {
|
||||
const fvApi = FormValidation.formValidation(formApiKey, {
|
||||
fields: {
|
||||
apiKey: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter API key name'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: ''
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
// Submit the form when all fields are valid
|
||||
// defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
// Select2 (jquery)
|
||||
$(function () {
|
||||
var select2 = $('.select2');
|
||||
|
||||
// Select2 API Key
|
||||
if (select2.length) {
|
||||
select2.each(function () {
|
||||
var $this = $(this);
|
||||
$this.wrap('<div class="position-relative"></div>');
|
||||
$this.select2({
|
||||
dropdownParent: $this.parent()
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
305
resources/js/auth/pages-auth-multisteps.js
Normal file
305
resources/js/auth/pages-auth-multisteps.js
Normal file
@ -0,0 +1,305 @@
|
||||
/**
|
||||
* Page auth register multi-steps
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// Select2 (jquery)
|
||||
$(function () {
|
||||
var select2 = $('.select2');
|
||||
|
||||
// select2
|
||||
if (select2.length) {
|
||||
select2.each(function () {
|
||||
var $this = $(this);
|
||||
$this.wrap('<div class="position-relative"></div>');
|
||||
$this.select2({
|
||||
placeholder: 'Select an country',
|
||||
dropdownParent: $this.parent()
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Multi Steps Validation
|
||||
// --------------------------------------------------------------------
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
const stepsValidation = document.querySelector('#multiStepsValidation');
|
||||
if (typeof stepsValidation !== undefined && stepsValidation !== null) {
|
||||
// Multi Steps form
|
||||
const stepsValidationForm = stepsValidation.querySelector('#multiStepsForm');
|
||||
// Form steps
|
||||
const stepsValidationFormStep1 = stepsValidationForm.querySelector('#accountDetailsValidation');
|
||||
const stepsValidationFormStep2 = stepsValidationForm.querySelector('#personalInfoValidation');
|
||||
const stepsValidationFormStep3 = stepsValidationForm.querySelector('#billingLinksValidation');
|
||||
// Multi steps next prev button
|
||||
const stepsValidationNext = [].slice.call(stepsValidationForm.querySelectorAll('.btn-next'));
|
||||
const stepsValidationPrev = [].slice.call(stepsValidationForm.querySelectorAll('.btn-prev'));
|
||||
|
||||
const multiStepsExDate = document.querySelector('.multi-steps-exp-date'),
|
||||
multiStepsCvv = document.querySelector('.multi-steps-cvv'),
|
||||
multiStepsMobile = document.querySelector('.multi-steps-mobile'),
|
||||
multiStepsPincode = document.querySelector('.multi-steps-pincode'),
|
||||
multiStepsCard = document.querySelector('.multi-steps-card');
|
||||
|
||||
// Expiry Date Mask
|
||||
if (multiStepsExDate) {
|
||||
new Cleave(multiStepsExDate, {
|
||||
date: true,
|
||||
delimiter: '/',
|
||||
datePattern: ['m', 'y']
|
||||
});
|
||||
}
|
||||
|
||||
// CVV
|
||||
if (multiStepsCvv) {
|
||||
new Cleave(multiStepsCvv, {
|
||||
numeral: true,
|
||||
numeralPositiveOnly: true
|
||||
});
|
||||
}
|
||||
|
||||
// Mobile
|
||||
if (multiStepsMobile) {
|
||||
new Cleave(multiStepsMobile, {
|
||||
phone: true,
|
||||
phoneRegionCode: 'US'
|
||||
});
|
||||
}
|
||||
|
||||
// Pincode
|
||||
if (multiStepsPincode) {
|
||||
new Cleave(multiStepsPincode, {
|
||||
delimiter: '',
|
||||
numeral: true
|
||||
});
|
||||
}
|
||||
|
||||
// Credit Card
|
||||
if (multiStepsCard) {
|
||||
new Cleave(multiStepsCard, {
|
||||
creditCard: true,
|
||||
onCreditCardTypeChanged: function (type) {
|
||||
if (type != '' && type != 'unknown') {
|
||||
document.querySelector('.card-type').innerHTML =
|
||||
'<img src="' + assetsPath + 'img/icons/payments/' + type + '-cc.png" height="28"/>';
|
||||
} else {
|
||||
document.querySelector('.card-type').innerHTML = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let validationStepper = new Stepper(stepsValidation, {
|
||||
linear: true
|
||||
});
|
||||
|
||||
// Account details
|
||||
const multiSteps1 = FormValidation.formValidation(stepsValidationFormStep1, {
|
||||
fields: {
|
||||
multiStepsUsername: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter username'
|
||||
},
|
||||
stringLength: {
|
||||
min: 6,
|
||||
max: 30,
|
||||
message: 'The name must be more than 6 and less than 30 characters long'
|
||||
},
|
||||
regexp: {
|
||||
regexp: /^[a-zA-Z0-9 ]+$/,
|
||||
message: 'The name can only consist of alphabetical, number and space'
|
||||
}
|
||||
}
|
||||
},
|
||||
multiStepsEmail: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter email address'
|
||||
},
|
||||
emailAddress: {
|
||||
message: 'The value is not a valid email address'
|
||||
}
|
||||
}
|
||||
},
|
||||
multiStepsPass: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter password'
|
||||
}
|
||||
}
|
||||
},
|
||||
multiStepsConfirmPass: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Confirm Password is required'
|
||||
},
|
||||
identical: {
|
||||
compare: function () {
|
||||
return stepsValidationFormStep1.querySelector('[name="multiStepsPass"]').value;
|
||||
},
|
||||
message: 'The password and its confirm are not the same'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: '.col-sm-6'
|
||||
}),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus(),
|
||||
submitButton: new FormValidation.plugins.SubmitButton()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).on('core.form.valid', function () {
|
||||
// Jump to the next step when all fields in the current step are valid
|
||||
validationStepper.next();
|
||||
});
|
||||
|
||||
// Personal info
|
||||
const multiSteps2 = FormValidation.formValidation(stepsValidationFormStep2, {
|
||||
fields: {
|
||||
multiStepsFirstName: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter first name'
|
||||
}
|
||||
}
|
||||
},
|
||||
multiStepsAddress: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter your address'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: function (field, ele) {
|
||||
// field is the field name
|
||||
// ele is the field element
|
||||
switch (field) {
|
||||
case 'multiStepsFirstName':
|
||||
return '.col-sm-6';
|
||||
case 'multiStepsAddress':
|
||||
return '.col-md-12';
|
||||
default:
|
||||
return '.row';
|
||||
}
|
||||
}
|
||||
}),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus(),
|
||||
submitButton: new FormValidation.plugins.SubmitButton()
|
||||
}
|
||||
}).on('core.form.valid', function () {
|
||||
// Jump to the next step when all fields in the current step are valid
|
||||
validationStepper.next();
|
||||
});
|
||||
|
||||
// Social links
|
||||
const multiSteps3 = FormValidation.formValidation(stepsValidationFormStep3, {
|
||||
fields: {
|
||||
multiStepsCard: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter card number'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
// Use this for enabling/changing valid/invalid class
|
||||
// eleInvalidClass: '',
|
||||
eleValidClass: '',
|
||||
rowSelector: function (field, ele) {
|
||||
// field is the field name
|
||||
// ele is the field element
|
||||
switch (field) {
|
||||
case 'multiStepsCard':
|
||||
return '.col-md-12';
|
||||
|
||||
default:
|
||||
return '.col-dm-6';
|
||||
}
|
||||
}
|
||||
}),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus(),
|
||||
submitButton: new FormValidation.plugins.SubmitButton()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).on('core.form.valid', function () {
|
||||
// You can submit the form
|
||||
// stepsValidationForm.submit()
|
||||
// or send the form data to server via an Ajax request
|
||||
// To make the demo simple, I just placed an alert
|
||||
alert('Submitted..!!');
|
||||
});
|
||||
|
||||
stepsValidationNext.forEach(item => {
|
||||
item.addEventListener('click', event => {
|
||||
// When click the Next button, we will validate the current step
|
||||
switch (validationStepper._currentIndex) {
|
||||
case 0:
|
||||
multiSteps1.validate();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
multiSteps2.validate();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
multiSteps3.validate();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
stepsValidationPrev.forEach(item => {
|
||||
item.addEventListener('click', event => {
|
||||
switch (validationStepper._currentIndex) {
|
||||
case 2:
|
||||
validationStepper.previous();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
validationStepper.previous();
|
||||
break;
|
||||
|
||||
case 0:
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
})();
|
||||
});
|
83
resources/js/auth/pages-auth-two-steps.js
Normal file
83
resources/js/auth/pages-auth-two-steps.js
Normal file
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Page auth two steps
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
let maskWrapper = document.querySelector('.numeral-mask-wrapper');
|
||||
|
||||
for (let pin of maskWrapper.children) {
|
||||
pin.onkeyup = function (e) {
|
||||
// Check if the key pressed is a number (0-9)
|
||||
if (/^\d$/.test(e.key)) {
|
||||
// While entering value, go to next
|
||||
if (pin.nextElementSibling) {
|
||||
if (this.value.length === parseInt(this.attributes['maxlength'].value)) {
|
||||
pin.nextElementSibling.focus();
|
||||
}
|
||||
}
|
||||
} else if (e.key === 'Backspace') {
|
||||
// While deleting entered value, go to previous
|
||||
if (pin.previousElementSibling) {
|
||||
pin.previousElementSibling.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
// Prevent the default behavior for the minus key
|
||||
pin.onkeypress = function (e) {
|
||||
if (e.key === '-') {
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const twoStepsForm = document.querySelector('#twoStepsForm');
|
||||
|
||||
// Form validation for Add new record
|
||||
if (twoStepsForm) {
|
||||
const fv = FormValidation.formValidation(twoStepsForm, {
|
||||
fields: {
|
||||
otp: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Please enter otp'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: '',
|
||||
rowSelector: '.mb-6'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
|
||||
defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
});
|
||||
|
||||
const numeralMaskList = twoStepsForm.querySelectorAll('.numeral-mask');
|
||||
const keyupHandler = function () {
|
||||
let otpFlag = true,
|
||||
otpVal = '';
|
||||
numeralMaskList.forEach(numeralMaskEl => {
|
||||
if (numeralMaskEl.value === '') {
|
||||
otpFlag = false;
|
||||
twoStepsForm.querySelector('[name="otp"]').value = '';
|
||||
}
|
||||
otpVal = otpVal + numeralMaskEl.value;
|
||||
});
|
||||
if (otpFlag) {
|
||||
twoStepsForm.querySelector('[name="otp"]').value = otpVal;
|
||||
}
|
||||
};
|
||||
numeralMaskList.forEach(numeralMaskEle => {
|
||||
numeralMaskEle.addEventListener('keyup', keyupHandler);
|
||||
});
|
||||
}
|
||||
})();
|
||||
});
|
112
resources/js/auth/pages-auth.js
Normal file
112
resources/js/auth/pages-auth.js
Normal file
@ -0,0 +1,112 @@
|
||||
('use strict');
|
||||
|
||||
const formAuthentication = document.querySelector('#formAuthentication');
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (e) {
|
||||
(function () {
|
||||
// Form validation for Add new record
|
||||
if (formAuthentication) {
|
||||
const fv = FormValidation.formValidation(formAuthentication, {
|
||||
fields: {
|
||||
username: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Por favor, introduzca su nombre de usuario'
|
||||
},
|
||||
stringLength: {
|
||||
min: 6,
|
||||
message: 'El nombre de usuario debe tener más de 6 caracteres'
|
||||
}
|
||||
}
|
||||
},
|
||||
email: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Por favor, introduzca su correo electrónico'
|
||||
},
|
||||
emailAddress: {
|
||||
message: 'Por favor, introduzca una dirección de correo electrónico válida'
|
||||
}
|
||||
}
|
||||
},
|
||||
'email-username': {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Por favor, introduzca su correo electrónico / nombre de usuario'
|
||||
},
|
||||
stringLength: {
|
||||
min: 6,
|
||||
message: 'El nombre de usuario debe tener más de 6 caracteres'
|
||||
}
|
||||
}
|
||||
},
|
||||
password: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Por favor, introduzca su contraseña'
|
||||
},
|
||||
stringLength: {
|
||||
min: 6,
|
||||
message: 'La contraseña debe tener más de 6 caracteres'
|
||||
}
|
||||
}
|
||||
},
|
||||
'confirm-password': {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Confirme la contraseña'
|
||||
},
|
||||
identical: {
|
||||
compare: function () {
|
||||
return formAuthentication.querySelector('[name="password"]').value;
|
||||
},
|
||||
message: 'La contraseña y su confirmación no son iguales'
|
||||
},
|
||||
stringLength: {
|
||||
min: 6,
|
||||
message: 'La contraseña debe tener más de 6 caracteres'
|
||||
}
|
||||
}
|
||||
},
|
||||
terms: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Acepte los términos y condiciones'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: '',
|
||||
rowSelector: '.fv-row'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
|
||||
defaultSubmit: new FormValidation.plugins.DefaultSubmit(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
},
|
||||
init: instance => {
|
||||
instance.on('plugins.message.placed', function (e) {
|
||||
if (e.element.parentElement.classList.contains('input-group')) {
|
||||
e.element.parentElement.insertAdjacentElement('afterend', e.messageElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Two Steps Verification
|
||||
const numeralMask = document.querySelectorAll('.numeral-mask');
|
||||
|
||||
// Verification masking
|
||||
if (numeralMask.length) {
|
||||
numeralMask.forEach(e => {
|
||||
new Cleave(e, {
|
||||
numeral: true
|
||||
});
|
||||
});
|
||||
}
|
||||
})();
|
||||
});
|
4
resources/js/bootstrap.js
vendored
Normal file
4
resources/js/bootstrap.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import axios from 'axios';
|
||||
window.axios = axios;
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
27
resources/js/pages/admin-settings-scripts.js
Normal file
27
resources/js/pages/admin-settings-scripts.js
Normal file
@ -0,0 +1,27 @@
|
||||
import '../../assets/js/notifications/LivewireNotification.js';
|
||||
import FormCustomListener from '../../assets/js/forms/formCustomListener';
|
||||
|
||||
new FormCustomListener({
|
||||
buttonSelectors: ['.btn-save', '.btn-cancel', '.btn-reset'] // Selectores para botones
|
||||
});
|
||||
|
||||
Livewire.on('clearLocalStoregeTemplateCustomizer', event => {
|
||||
const _deleteCookie = name => {
|
||||
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
||||
};
|
||||
|
||||
const pattern = 'templateCustomizer-';
|
||||
|
||||
// Iterar sobre todas las claves en localStorage
|
||||
Object.keys(localStorage).forEach(key => {
|
||||
if (key.startsWith(pattern)) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
});
|
||||
|
||||
_deleteCookie('admin-mode');
|
||||
_deleteCookie('admin-colorPref');
|
||||
_deleteCookie('colorPref');
|
||||
_deleteCookie('theme');
|
||||
_deleteCookie('direction');
|
||||
});
|
99
resources/js/pages/cache-manager-scripts.js
Normal file
99
resources/js/pages/cache-manager-scripts.js
Normal file
@ -0,0 +1,99 @@
|
||||
import '../../assets/js/notifications/LivewireNotification.js';
|
||||
import FormCustomListener from '../../assets/js/forms/formCustomListener';
|
||||
|
||||
// Inicializar listener para estadísticas de cache
|
||||
new FormCustomListener({
|
||||
buttonSelectors: ['.btn-clear-cache', '.btn-reload-cache-stats']
|
||||
});
|
||||
|
||||
// Inicializar listener para funciones de cache
|
||||
new FormCustomListener({
|
||||
formSelector: '#cache-functions-card',
|
||||
buttonSelectors: ['.btn', '.btn-config-cache', '.btn-cache-routes'],
|
||||
callbacks: [
|
||||
null, // Callback por defecto para .btn
|
||||
(form, button) => {
|
||||
// Emitir notificación de carga
|
||||
notification.emitNotification({
|
||||
target: '#cache-functions-card .notification-container',
|
||||
message: 'Generando cache de configuraciones de Laravel...',
|
||||
type: 'warning'
|
||||
});
|
||||
|
||||
// Generar cache de configuraciones mediante una petición AJAX
|
||||
fetch('/admin/cache/config/cache', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
},
|
||||
body: JSON.stringify({})
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Error al generar el cache de configuraciones');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(() => {
|
||||
// Emitir notificación de éxito con recarga diferida
|
||||
notification.emitNotification({
|
||||
target: '#cache-functions-card .notification-container',
|
||||
message: 'Se ha cacheado la configuración de Laravel...',
|
||||
type: 'success',
|
||||
deferReload: true
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
// Emitir notificación de error
|
||||
notification.emitNotification({
|
||||
target: '#cache-functions-card .notification-container',
|
||||
message: `Error: ${error.message}`,
|
||||
type: 'danger'
|
||||
});
|
||||
console.error('Error al generar el cache:', error);
|
||||
});
|
||||
},
|
||||
(form, button) => {
|
||||
// Emitir notificación de carga
|
||||
notification.emitNotification({
|
||||
target: '#cache-functions-card .notification-container',
|
||||
message: 'Generando cache de rutas de Laravel...',
|
||||
type: 'warning'
|
||||
});
|
||||
|
||||
// Recargar estadísticas de cache mediante una petición AJAX
|
||||
fetch('/admin/cache/route/cache', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Error al recargar las estadísticas de cache');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(() => {
|
||||
// Emitir notificación de éxito con recarga diferida
|
||||
notification.emitNotification({
|
||||
target: '#cache-functions-card .notification-container',
|
||||
message: 'Se han cacheado las rutas de Laravel...',
|
||||
type: 'success',
|
||||
deferReload: true
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
// Emitir notificación de error
|
||||
notification.emitNotification({
|
||||
target: '#cache-functions-card .notification-container',
|
||||
message: `Error: ${error.message}`,
|
||||
type: 'danger'
|
||||
});
|
||||
console.error('Error al recargar las estadísticas:', error);
|
||||
});
|
||||
}
|
||||
]
|
||||
});
|
197
resources/js/pages/permissions-scripts.js
Normal file
197
resources/js/pages/permissions-scripts.js
Normal file
@ -0,0 +1,197 @@
|
||||
/**
|
||||
* App user list (jquery)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
$(function () {
|
||||
var dataTablePermissions = $('.datatables-permissions'),
|
||||
dt_permission,
|
||||
userList = baseUrl + 'app/user/list';
|
||||
|
||||
// Users List datatable
|
||||
if (dataTablePermissions.length) {
|
||||
dt_permission = dataTablePermissions.DataTable({
|
||||
ajax: window.location.href,
|
||||
columns: [
|
||||
// columns according to JSON
|
||||
{ data: '' },
|
||||
{ data: 'id' },
|
||||
{ data: 'name' },
|
||||
{ data: 'assigned_to' },
|
||||
{ data: 'created_date' },
|
||||
{ data: '' }
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
// For Responsive
|
||||
className: 'control',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
responsivePriority: 2,
|
||||
targets: 0,
|
||||
render: function (data, type, full, meta) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 1,
|
||||
searchable: false,
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
// Name
|
||||
targets: 2,
|
||||
render: function (data, type, full, meta) {
|
||||
var $name = full['name'];
|
||||
return '<span class="text-nowrap text-heading">' + $name + '</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
// User Role
|
||||
targets: 3,
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
var $assignedTo = full['assigned_to'],
|
||||
$output = '';
|
||||
var roleBadgeObj = {
|
||||
Admin:
|
||||
'<a href="' +
|
||||
userList +
|
||||
'"><span class="badge me-4 bg-label-primary">Administrator</span></a>',
|
||||
Manager:
|
||||
'<a href="' +
|
||||
userList +
|
||||
'"><span class="badge me-4 bg-label-warning">Manager</span></a>',
|
||||
Users:
|
||||
'<a href="' + userList + '"><span class="badge me-4 bg-label-success">Users</span></a>',
|
||||
Support:
|
||||
'<a href="' + userList + '"><span class="badge me-4 bg-label-info">Support</span></a>',
|
||||
Restricted:
|
||||
'<a href="' +
|
||||
userList +
|
||||
'"><span class="badge me-4 bg-label-danger">Restricted User</span></a>'
|
||||
};
|
||||
for (var i = 0; i < $assignedTo.length; i++) {
|
||||
var val = $assignedTo[i];
|
||||
$output += roleBadgeObj[val];
|
||||
}
|
||||
return '<span class="text-nowrap">' + $output + '</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
// remove ordering from Name
|
||||
targets: 4,
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
var $date = full['created_date'];
|
||||
return '<span class="text-nowrap">' + $date + '</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
// Actions
|
||||
targets: -1,
|
||||
searchable: false,
|
||||
title: 'Actions',
|
||||
orderable: false,
|
||||
render: function (data, type, full, meta) {
|
||||
return (
|
||||
'<div class="d-flex align-items-center">' +
|
||||
'<span class="text-nowrap"><button class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill me-1" data-bs-target="#editPermissionModal" data-bs-toggle="modal" data-bs-dismiss="modal"><i class="ti ti-edit ti-md"></i></button>' +
|
||||
'<a href="javascript:;" class="btn btn-icon btn-text-secondary waves-effect waves-light rounded-pill dropdown-toggle hide-arrow" data-bs-toggle="dropdown"><i class="ti ti-dots-vertical ti-md mx-1"></i></a>' +
|
||||
'<div class="dropdown-menu dropdown-menu-end m-0">' +
|
||||
'<a href="javascript:;"" class="dropdown-item">Edit</a>' +
|
||||
'<a href="javascript:;" class="dropdown-item">Suspend</a>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
}
|
||||
],
|
||||
order: [[1, 'asc']],
|
||||
dom:
|
||||
'<"row mx-1"' +
|
||||
'<"col-sm-12 col-md-3" l>' +
|
||||
'<"col-sm-12 col-md-9"<"dt-action-buttons text-xl-end text-lg-start text-md-end text-start d-flex align-items-center justify-content-md-end justify-content-center flex-wrap"<"me-4 mt-n6 mt-md-0"f>B>>' +
|
||||
'>t' +
|
||||
'<"row"' +
|
||||
'<"col-sm-12 col-md-6"i>' +
|
||||
'<"col-sm-12 col-md-6"p>' +
|
||||
'>',
|
||||
language: $.fn.dataTable.ext.datatable_spanish_default,
|
||||
// Buttons with Dropdown
|
||||
buttons: [],
|
||||
// For responsive popup
|
||||
responsive: {
|
||||
details: {
|
||||
display: $.fn.dataTable.Responsive.display.modal({
|
||||
header: function (row) {
|
||||
var data = row.data();
|
||||
return 'Details of ' + data['name'];
|
||||
}
|
||||
}),
|
||||
type: 'column',
|
||||
renderer: function (api, rowIdx, columns) {
|
||||
var data = $.map(columns, function (col, i) {
|
||||
return col.title !== '' // ? Do not show row in modal popup if title is blank (for check box)
|
||||
? '<tr data-dt-row="' +
|
||||
col.rowIndex +
|
||||
'" data-dt-column="' +
|
||||
col.columnIndex +
|
||||
'">' +
|
||||
'<td>' +
|
||||
col.title +
|
||||
':' +
|
||||
'</td> ' +
|
||||
'<td>' +
|
||||
col.data +
|
||||
'</td>' +
|
||||
'</tr>'
|
||||
: '';
|
||||
}).join('');
|
||||
|
||||
return data ? $('<table class="table"/><tbody />').append(data) : false;
|
||||
}
|
||||
}
|
||||
},
|
||||
initComplete: function () {
|
||||
// Adding role filter once table initialized
|
||||
this.api()
|
||||
.columns(3)
|
||||
.every(function () {
|
||||
var column = this;
|
||||
var select = $(
|
||||
'<select id="UserRole" class="form-select text-capitalize"><option value=""> Select Role </option></select>'
|
||||
)
|
||||
.appendTo('.user_role')
|
||||
.on('change', function () {
|
||||
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
||||
column.search(val ? '^' + val + '$' : '', true, false).draw();
|
||||
});
|
||||
|
||||
column
|
||||
.data()
|
||||
.unique()
|
||||
.sort()
|
||||
.each(function (d, j) {
|
||||
select.append('<option value="' + d + '" class="text-capitalize">' + d + '</option>');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Delete Record
|
||||
$('.datatables-permissions tbody').on('click', '.delete-record', function () {
|
||||
dt_permission.row($(this).parents('tr')).remove().draw();
|
||||
});
|
||||
|
||||
// Filter form control to default size
|
||||
// ? setTimeout used for multilingual table initialization
|
||||
setTimeout(() => {
|
||||
$('.dataTables_filter .form-control').removeClass('form-control-sm');
|
||||
$('.dataTables_length .form-select').removeClass('form-select-sm');
|
||||
$('.dataTables_info').addClass('ms-n1');
|
||||
$('.dataTables_paginate').addClass('me-n1');
|
||||
}, 300);
|
||||
});
|
1
resources/js/pages/roles-scripts.js
Normal file
1
resources/js/pages/roles-scripts.js
Normal file
@ -0,0 +1 @@
|
||||
import '../../assets/js/notifications/LivewireNotification.js';
|
25
resources/js/pages/smtp-settings-scripts.js
Normal file
25
resources/js/pages/smtp-settings-scripts.js
Normal file
@ -0,0 +1,25 @@
|
||||
import '../../assets/js/notifications/LivewireNotification.js';
|
||||
import SmtpSettingsForm from '../../js/smtp-settings/SmtpSettingsForm';
|
||||
import SenderResponseForm from '../../js/smtp-settings/SenderResponseForm.js';
|
||||
|
||||
window.smtpSettingsForm = new SmtpSettingsForm();
|
||||
window.senderResponseForm = new SenderResponseForm();
|
||||
|
||||
Livewire.hook('morphed', ({ component }) => {
|
||||
switch (component.name) {
|
||||
case 'mail-smtp-settings':
|
||||
if (window.smtpSettingsForm) {
|
||||
window.smtpSettingsForm.reload(); // Recarga el formulario sin destruir la instancia
|
||||
}
|
||||
break;
|
||||
|
||||
case 'mail-sender-response-settings':
|
||||
if (window.senderResponseForm) {
|
||||
window.senderResponseForm.reload(); // Recarga el formulario sin destruir la instancia
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
220
resources/js/smtp-settings/SenderResponseForm.js
Normal file
220
resources/js/smtp-settings/SenderResponseForm.js
Normal file
@ -0,0 +1,220 @@
|
||||
export default class SenderResponseForm {
|
||||
constructor(config = {}) {
|
||||
const defaultConfig = {
|
||||
formSenderResponseId: 'mail-sender-response-settings-card',
|
||||
replyToMethodId: 'reply_to_method',
|
||||
saveSenderResponseButtonId: 'save_sender_response_button',
|
||||
cancelButtonId: 'cancel_sender_response_button'
|
||||
};
|
||||
|
||||
this.config = { ...defaultConfig, ...config };
|
||||
this.formSenderResponse = null;
|
||||
this.smtpReplyToMethod = null;
|
||||
this.saveButton = null;
|
||||
this.cancelButton = null;
|
||||
|
||||
this.init(); // Inicializa el formulario
|
||||
}
|
||||
|
||||
// Método para inicializar el formulario
|
||||
init() {
|
||||
try {
|
||||
// Obtener elementos esenciales
|
||||
this.formSenderResponse = document.getElementById(this.config.formSenderResponseId);
|
||||
this.smtpReplyToMethod = document.getElementById(this.config.replyToMethodId);
|
||||
this.saveButton = document.getElementById(this.config.saveSenderResponseButtonId);
|
||||
this.cancelButton = document.getElementById(this.config.cancelButtonId);
|
||||
|
||||
// Asignar eventos
|
||||
this.formSenderResponse.addEventListener('input', event => this.handleInput(event));
|
||||
this.smtpReplyToMethod.addEventListener('change', () => this.handleToggleReplyToMethod());
|
||||
this.cancelButton.addEventListener('click', () => this.handleCancel());
|
||||
|
||||
// Inicializar validación del formulario
|
||||
this.initializeFormValidation(this.formSenderResponse, this.senderResponsValidateConfig, () => {
|
||||
this.handleFormValid();
|
||||
});
|
||||
|
||||
// Disparar el evento 'change' en el método de respuesta
|
||||
setTimeout(() => this.smtpReplyToMethod.dispatchEvent(new Event('change')), 0);
|
||||
} catch (error) {
|
||||
console.error('Error al inicializar el formulario de respuesta:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Método de recarga parcial
|
||||
* Este método restablece la validación y los eventos sin destruir la instancia.
|
||||
*/
|
||||
reload() {
|
||||
try {
|
||||
// Vuelve a inicializar la validación del formulario
|
||||
this.initializeFormValidation(this.formSenderResponse, this.senderResponsValidateConfig, () => {
|
||||
this.handleFormValid();
|
||||
});
|
||||
|
||||
// Vuelve a agregar los eventos (si es necesario, depende de tu lógica)
|
||||
this.smtpReplyToMethod.dispatchEvent(new Event('change'));
|
||||
} catch (error) {
|
||||
console.error('Error al recargar el formulario:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maneja el evento de entrada en el formulario.
|
||||
* @param {Event} event - Evento de entrada.
|
||||
*/
|
||||
handleInput(event) {
|
||||
const target = event.target;
|
||||
|
||||
if (['INPUT', 'SELECT', 'TEXTAREA'].includes(target.tagName)) {
|
||||
this.toggleButtonsState(this.formSenderResponse, true); // Habilitar botones
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Muestra u oculta el campo de correo personalizado según el método de respuesta seleccionado.
|
||||
* @param {HTMLElement} smtpReplyToMethod - Elemento select del método de respuesta.
|
||||
*/
|
||||
handleToggleReplyToMethod() {
|
||||
const emailCustomDiv = document.querySelector('.email-custom-div');
|
||||
|
||||
if (emailCustomDiv) {
|
||||
emailCustomDiv.style.display = Number(this.smtpReplyToMethod.value) === 3 ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the sender response form submission.
|
||||
* This method disables the form buttons, disables all form fields,
|
||||
* and sets the cancel button to a loading state.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
handleCancel() {
|
||||
this.disableFormFields(this.formSenderResponse);
|
||||
this.toggleButtonsState(this.formSenderResponse, false);
|
||||
this.setButtonLoadingState(this.cancelButton, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inicializa la validación del formulario.
|
||||
* @param {HTMLElement} form - El formulario.
|
||||
* @param {Object} config - Configuración de validación.
|
||||
* @param {Function} onValidCallback - Callback cuando el formulario es válido.
|
||||
*/
|
||||
initializeFormValidation(form, config, onValidCallback) {
|
||||
return FormValidation.formValidation(form, config).on('core.form.valid', onValidCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maneja la acción cuando el formulario es válido.
|
||||
*/
|
||||
handleFormValid() {
|
||||
this.disableFormFields(this.formSenderResponse);
|
||||
this.toggleButtonsState(this.formSenderResponse, false);
|
||||
this.setButtonLoadingState(this.saveButton, true);
|
||||
|
||||
Livewire.dispatch('saveMailSenderResponseSettings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Deshabilita todos los campos del formulario.
|
||||
* @param {HTMLElement} form - El formulario.
|
||||
*/
|
||||
disableFormFields(form) {
|
||||
form.querySelectorAll('input, select, textarea').forEach(field => {
|
||||
field.disabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Habilita o deshabilita los botones dentro del formulario.
|
||||
* @param {HTMLElement} form - El formulario.
|
||||
* @param {boolean} state - Estado de habilitación.
|
||||
*/
|
||||
toggleButtonsState(form, state) {
|
||||
form.querySelectorAll('button').forEach(button => {
|
||||
button.disabled = !state;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configura el estado de carga de un botón.
|
||||
* @param {HTMLElement} button - El botón.
|
||||
* @param {boolean} isLoading - Si el botón está en estado de carga.
|
||||
*/
|
||||
setButtonLoadingState(button, isLoading) {
|
||||
const loadingText = button.getAttribute('data-loading-text');
|
||||
|
||||
if (loadingText && isLoading) {
|
||||
button.innerHTML = loadingText;
|
||||
} else {
|
||||
button.innerHTML = button.getAttribute('data-original-text') || button.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
senderResponsValidateConfig = {
|
||||
fields: {
|
||||
from_address: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'El correo electrónico de salida es obligatorio.'
|
||||
},
|
||||
emailAddress: {
|
||||
message: 'Por favor, introduce un correo electrónico válido.'
|
||||
}
|
||||
}
|
||||
},
|
||||
from_name: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'El nombre del remitente es obligatorio.'
|
||||
}
|
||||
}
|
||||
},
|
||||
reply_to_method: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'El método de respuesta es obligatorio.'
|
||||
}
|
||||
}
|
||||
},
|
||||
reply_to_email: {
|
||||
validators: {
|
||||
callback: {
|
||||
message: 'El correo electrónico de respuesta es obligatorio.',
|
||||
callback: function (input) {
|
||||
if (Number(document.getElementById('reply_to_method').value) === 3) {
|
||||
return input.value.trim() !== '' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input.value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
reply_to_name: {
|
||||
validators: {
|
||||
callback: {
|
||||
message: 'El nombre de respuesta es obligatorio.',
|
||||
callback: function (input) {
|
||||
if (Number(document.getElementById('reply_to_method').value) === 3) {
|
||||
return input.value.trim() !== '';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
eleValidClass: '',
|
||||
rowSelector: '.fv-row'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
};
|
||||
}
|
239
resources/js/smtp-settings/SmtpSettingsForm.js
Normal file
239
resources/js/smtp-settings/SmtpSettingsForm.js
Normal file
@ -0,0 +1,239 @@
|
||||
export default class SmtpSettingsForm {
|
||||
constructor(config = {}) {
|
||||
const defaultConfig = {
|
||||
formSmtpSettingsSelector: '#mail-smtp-settings-card',
|
||||
changeSmtpSettingsId: 'change_smtp_settings',
|
||||
testSmtpConnectionButtonId: 'test_smtp_connection_button',
|
||||
saveSmtpConnectionButtonId: 'save_smtp_connection_button',
|
||||
cancelSmtpConnectionButtonId: 'cancel_smtp_connection_button'
|
||||
};
|
||||
|
||||
this.config = { ...defaultConfig, ...config };
|
||||
this.formSmtpSettings = null;
|
||||
this.changeSmtpSettingsCheckbox = null;
|
||||
this.testButton = null;
|
||||
this.saveButton = null;
|
||||
this.cancelButton = null;
|
||||
this.validator = null;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inicializa el formulario de configuración SMTP.
|
||||
*/
|
||||
init() {
|
||||
try {
|
||||
// Obtener elementos esenciales
|
||||
this.formSmtpSettings = document.querySelector(this.config.formSmtpSettingsSelector);
|
||||
this.notificationArea = this.formSmtpSettings.querySelector(this.config.notificationAreaSelector);
|
||||
this.changeSmtpSettingsCheckbox = document.getElementById(this.config.changeSmtpSettingsId);
|
||||
this.testButton = document.getElementById(this.config.testSmtpConnectionButtonId);
|
||||
this.saveButton = document.getElementById(this.config.saveSmtpConnectionButtonId);
|
||||
this.cancelButton = document.getElementById(this.config.cancelSmtpConnectionButtonId);
|
||||
|
||||
// Asignar eventos
|
||||
this.changeSmtpSettingsCheckbox.addEventListener('change', event => this.handleCheckboxChange(event));
|
||||
this.testButton.addEventListener('click', event => this.handleTestConnection(event));
|
||||
this.cancelButton.addEventListener('click', () => this.handleCancel());
|
||||
|
||||
// Inicializar validación del formulario
|
||||
this.validator = FormValidation.formValidation(this.formSmtpSettings, this.smtpSettingsFormValidateConfig);
|
||||
} catch (error) {
|
||||
console.error('Error al inicializar el formulario SMTP:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Método de recarga parcial
|
||||
* Este método restablece la validación y los eventos sin destruir la instancia.
|
||||
*/
|
||||
reload() {
|
||||
try {
|
||||
// Inicializar validación del formulario
|
||||
this.validator = FormValidation.formValidation(this.formSmtpSettings, this.smtpSettingsFormValidateConfig);
|
||||
} catch (error) {
|
||||
console.error('Error al recargar el formulario:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maneja el cambio en la casilla "Cambiar configuración SMTP".
|
||||
* @param {Event} event - Evento de cambio.
|
||||
*/
|
||||
handleCheckboxChange(event) {
|
||||
const isEnabled = event.target.checked;
|
||||
|
||||
this.toggleFieldsState(['host', 'port', 'encryption', 'username', 'password'], isEnabled);
|
||||
|
||||
this.testButton.disabled = false;
|
||||
this.saveButton.disabled = true;
|
||||
this.cancelButton.disabled = false;
|
||||
|
||||
if (!isEnabled) {
|
||||
Livewire.dispatch('loadSettings');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maneja el clic en el botón "Probar conexión".
|
||||
* @param {Event} event - Evento de clic.
|
||||
*/
|
||||
handleTestConnection(event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.validator.resetForm();
|
||||
|
||||
this.validator.validate().then(status => {
|
||||
if (status === 'Valid') {
|
||||
this.disableFormFields(this.formSmtpSettings);
|
||||
this.toggleButtonsState(this.formSmtpSettings, false);
|
||||
this.setButtonLoadingState(this.testButton, true);
|
||||
|
||||
Livewire.dispatch('testSmtpConnection');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Maneja la cancelación de cambios en la configuración SMTP.
|
||||
*/
|
||||
handleCancel() {
|
||||
this.disableFormFields(this.formSmtpSettings);
|
||||
this.toggleButtonsState(this.formSmtpSettings, false);
|
||||
this.setButtonLoadingState(this.cancelButton, true);
|
||||
|
||||
Livewire.dispatch('loadSettings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Habilita o deshabilita los campos del formulario.
|
||||
* @param {Array} fields - IDs de los campos a actualizar.
|
||||
* @param {boolean} isEnabled - Estado de habilitación.
|
||||
*/
|
||||
toggleFieldsState(fields, isEnabled) {
|
||||
fields.forEach(id => {
|
||||
const field = document.getElementById(id);
|
||||
|
||||
if (field) field.disabled = !isEnabled;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deshabilita todos los campos del formulario.
|
||||
* @param {HTMLElement} form - El formulario.
|
||||
*/
|
||||
disableFormFields(form) {
|
||||
form.querySelectorAll('input, select, textarea').forEach(field => {
|
||||
field.disabled = true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Habilita o deshabilita los botones dentro del formulario.
|
||||
* @param {HTMLElement} form - El formulario.
|
||||
* @param {boolean} state - Estado de habilitación.
|
||||
*/
|
||||
toggleButtonsState(form, state) {
|
||||
form.querySelectorAll('button').forEach(button => {
|
||||
button.disabled = !state;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configura el estado de carga de un botón.
|
||||
* @param {HTMLElement} button - El botón.
|
||||
* @param {boolean} isLoading - Si el botón está en estado de carga.
|
||||
*/
|
||||
setButtonLoadingState(button, isLoading) {
|
||||
const loadingText = button.getAttribute('data-loading-text');
|
||||
|
||||
if (loadingText && isLoading) {
|
||||
button.innerHTML = loadingText;
|
||||
} else {
|
||||
button.innerHTML = button.getAttribute('data-original-text') || button.innerHTML;
|
||||
}
|
||||
}
|
||||
|
||||
smtpSettingsFormValidateConfig = {
|
||||
fields: {
|
||||
host: {
|
||||
validators: {
|
||||
callback: {
|
||||
message: 'El servidor SMTP es obligatorio.',
|
||||
callback: function (input) {
|
||||
// Ejecutar la validación solo si 'change_smtp_settings' está marcado
|
||||
if (document.getElementById('change_smtp_settings').checked) {
|
||||
return input.value.trim() !== '';
|
||||
}
|
||||
return true; // No validar si no está marcado
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
port: {
|
||||
validators: {
|
||||
callback: {
|
||||
message: 'El puerto SMTP es obligatorio.',
|
||||
callback: function (input) {
|
||||
if (document.getElementById('change_smtp_settings').checked) {
|
||||
return (
|
||||
input.value.trim() !== '' &&
|
||||
/^\d+$/.test(input.value) &&
|
||||
input.value >= 1 &&
|
||||
input.value <= 65535
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
encryption: {
|
||||
validators: {
|
||||
callback: {
|
||||
message: 'La encriptación es obligatoria.',
|
||||
callback: function (input) {
|
||||
if (document.getElementById('change_smtp_settings').checked) {
|
||||
return input.value.trim() !== '';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
username: {
|
||||
validators: {
|
||||
callback: {
|
||||
message: 'El usuario SMTP es obligatorio.',
|
||||
callback: function (input) {
|
||||
if (document.getElementById('change_smtp_settings').checked) {
|
||||
return input.value.trim().length >= 6;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
password: {
|
||||
validators: {
|
||||
callback: {
|
||||
message: 'Por favor, introduzca su contraseña.',
|
||||
callback: function (input) {
|
||||
if (document.getElementById('change_smtp_settings').checked) {
|
||||
return input.value.trim().length >= 5;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({ rowSelector: '.fv-row' }),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus()
|
||||
}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user