mirror of
https://github.com/getnamingo/registry.git
synced 2025-05-15 09:07:00 +02:00
More work on issue 192
This commit is contained in:
parent
79eca91eb1
commit
ea88b14234
4 changed files with 349 additions and 36 deletions
|
@ -366,4 +366,290 @@ class DapiController extends Controller
|
||||||
$response->getBody()->write(json_encode($payload, JSON_UNESCAPED_UNICODE));
|
$response->getBody()->write(json_encode($payload, JSON_UNESCAPED_UNICODE));
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function listPayments(Request $request, Response $response): Response
|
||||||
|
{
|
||||||
|
$params = $request->getQueryParams();
|
||||||
|
$db = $this->container->get('db');
|
||||||
|
|
||||||
|
// Map fields to fully qualified columns for filtering/sorting
|
||||||
|
// Adjust field names if needed
|
||||||
|
$allowedFieldsMap = [
|
||||||
|
'date' => 'ph.date',
|
||||||
|
'registrar_id' => 'ph.registrar_id',
|
||||||
|
'description' => 'ph.description',
|
||||||
|
'amount' => 'ph.amount',
|
||||||
|
'registrar_name' => 'r.name'
|
||||||
|
];
|
||||||
|
|
||||||
|
// --- SORTING ---
|
||||||
|
$sortField = 'ph.date'; // default sort by date
|
||||||
|
$sortDir = 'desc';
|
||||||
|
if (!empty($params['order'])) {
|
||||||
|
$orderParts = explode(',', $params['order']);
|
||||||
|
if (count($orderParts) === 2) {
|
||||||
|
$fieldCandidate = preg_replace('/[^a-zA-Z0-9_]/', '', $orderParts[0]);
|
||||||
|
if (array_key_exists($fieldCandidate, $allowedFieldsMap)) {
|
||||||
|
$sortField = $allowedFieldsMap[$fieldCandidate];
|
||||||
|
}
|
||||||
|
$sortDir = strtolower($orderParts[1]) === 'asc' ? 'asc' : 'desc';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- PAGINATION ---
|
||||||
|
$page = 1;
|
||||||
|
$size = 10;
|
||||||
|
if (!empty($params['page'])) {
|
||||||
|
$pageParts = explode(',', $params['page']);
|
||||||
|
if (count($pageParts) === 2) {
|
||||||
|
$pageNum = (int)$pageParts[0];
|
||||||
|
$pageSize = (int)$pageParts[1];
|
||||||
|
if ($pageNum > 0) {
|
||||||
|
$page = $pageNum;
|
||||||
|
}
|
||||||
|
if ($pageSize > 0) {
|
||||||
|
$size = $pageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$offset = ($page - 1) * $size;
|
||||||
|
|
||||||
|
// --- FILTERING ---
|
||||||
|
$whereClauses = [];
|
||||||
|
$bindParams = [];
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
if (preg_match('/^filter\d+$/', $key)) {
|
||||||
|
$fParts = explode(',', $value);
|
||||||
|
if (count($fParts) === 3) {
|
||||||
|
list($fField, $fOp, $fVal) = $fParts;
|
||||||
|
$fField = preg_replace('/[^a-zA-Z0-9_]/', '', $fField);
|
||||||
|
|
||||||
|
// Ensure the field is allowed and fully qualify it
|
||||||
|
if (!array_key_exists($fField, $allowedFieldsMap)) {
|
||||||
|
// Skip unknown fields
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$column = $allowedFieldsMap[$fField];
|
||||||
|
|
||||||
|
switch ($fOp) {
|
||||||
|
case 'eq':
|
||||||
|
$whereClauses[] = "$column = :f_{$key}";
|
||||||
|
$bindParams["f_{$key}"] = $fVal;
|
||||||
|
break;
|
||||||
|
case 'cs':
|
||||||
|
$whereClauses[] = "$column LIKE :f_{$key}";
|
||||||
|
$bindParams["f_{$key}"] = "%$fVal%";
|
||||||
|
break;
|
||||||
|
case 'sw':
|
||||||
|
$whereClauses[] = "$column LIKE :f_{$key}";
|
||||||
|
$bindParams["f_{$key}"] = "$fVal%";
|
||||||
|
break;
|
||||||
|
case 'ew':
|
||||||
|
$whereClauses[] = "$column LIKE :f_{$key}";
|
||||||
|
$bindParams["f_{$key}"] = "%$fVal";
|
||||||
|
break;
|
||||||
|
// Add other cases if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base SQL
|
||||||
|
$sqlBase = "
|
||||||
|
FROM payment_history ph
|
||||||
|
LEFT JOIN registrar r ON ph.registrar_id = r.id
|
||||||
|
";
|
||||||
|
|
||||||
|
// If you want all filters combined with OR, keep " OR ".
|
||||||
|
// If you want AND logic for multiple filters, change to "AND".
|
||||||
|
$sqlWhere = '';
|
||||||
|
if (!empty($whereClauses)) {
|
||||||
|
$sqlWhere = "WHERE " . implode(" OR ", $whereClauses);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count total results
|
||||||
|
$totalSql = "SELECT COUNT(DISTINCT ph.id) AS total $sqlBase $sqlWhere";
|
||||||
|
$totalCount = $db->selectValue($totalSql, $bindParams);
|
||||||
|
|
||||||
|
// Data query
|
||||||
|
$selectFields = "
|
||||||
|
ph.id,
|
||||||
|
ph.registrar_id,
|
||||||
|
ph.date,
|
||||||
|
ph.description,
|
||||||
|
ph.amount,
|
||||||
|
r.name AS registrar_name
|
||||||
|
";
|
||||||
|
|
||||||
|
$dataSql = "
|
||||||
|
SELECT $selectFields
|
||||||
|
$sqlBase
|
||||||
|
$sqlWhere
|
||||||
|
ORDER BY $sortField $sortDir
|
||||||
|
LIMIT $offset, $size
|
||||||
|
";
|
||||||
|
|
||||||
|
$records = $db->select($dataSql, $bindParams);
|
||||||
|
|
||||||
|
// Ensure records is always an array
|
||||||
|
if (!$records) {
|
||||||
|
$records = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'records' => $records,
|
||||||
|
'results' => $totalCount
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $response->withHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||||
|
$response->getBody()->write(json_encode($payload, JSON_UNESCAPED_UNICODE));
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listStatements(Request $request, Response $response): Response
|
||||||
|
{
|
||||||
|
$params = $request->getQueryParams();
|
||||||
|
$db = $this->container->get('db');
|
||||||
|
|
||||||
|
// Map fields to fully qualified columns for filtering/sorting
|
||||||
|
$allowedFieldsMap = [
|
||||||
|
'date' => 'st.date',
|
||||||
|
'registrar_id' => 'st.registrar_id',
|
||||||
|
'command' => 'st.command',
|
||||||
|
'domain_name' => 'st.domain_name',
|
||||||
|
'length_in_months' => 'st.length_in_months',
|
||||||
|
'fromS' => 'st.fromS',
|
||||||
|
'toS' => 'st.toS',
|
||||||
|
'amount' => 'st.amount',
|
||||||
|
'registrar_name' => 'r.name'
|
||||||
|
];
|
||||||
|
|
||||||
|
// --- SORTING ---
|
||||||
|
$sortField = 'st.date'; // default sort by date
|
||||||
|
$sortDir = 'desc';
|
||||||
|
if (!empty($params['order'])) {
|
||||||
|
$orderParts = explode(',', $params['order']);
|
||||||
|
if (count($orderParts) === 2) {
|
||||||
|
$fieldCandidate = preg_replace('/[^a-zA-Z0-9_]/', '', $orderParts[0]);
|
||||||
|
if (array_key_exists($fieldCandidate, $allowedFieldsMap)) {
|
||||||
|
$sortField = $allowedFieldsMap[$fieldCandidate];
|
||||||
|
}
|
||||||
|
$sortDir = strtolower($orderParts[1]) === 'asc' ? 'asc' : 'desc';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- PAGINATION ---
|
||||||
|
$page = 1;
|
||||||
|
$size = 10;
|
||||||
|
if (!empty($params['page'])) {
|
||||||
|
$pageParts = explode(',', $params['page']);
|
||||||
|
if (count($pageParts) === 2) {
|
||||||
|
$pageNum = (int)$pageParts[0];
|
||||||
|
$pageSize = (int)$pageParts[1];
|
||||||
|
if ($pageNum > 0) {
|
||||||
|
$page = $pageNum;
|
||||||
|
}
|
||||||
|
if ($pageSize > 0) {
|
||||||
|
$size = $pageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$offset = ($page - 1) * $size;
|
||||||
|
|
||||||
|
// --- FILTERING ---
|
||||||
|
$whereClauses = [];
|
||||||
|
$bindParams = [];
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
if (preg_match('/^filter\d+$/', $key)) {
|
||||||
|
$fParts = explode(',', $value);
|
||||||
|
if (count($fParts) === 3) {
|
||||||
|
list($fField, $fOp, $fVal) = $fParts;
|
||||||
|
$fField = preg_replace('/[^a-zA-Z0-9_]/', '', $fField);
|
||||||
|
|
||||||
|
// Ensure the field is allowed and fully qualify it
|
||||||
|
if (!array_key_exists($fField, $allowedFieldsMap)) {
|
||||||
|
// Skip unknown fields
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$column = $allowedFieldsMap[$fField];
|
||||||
|
|
||||||
|
switch ($fOp) {
|
||||||
|
case 'eq':
|
||||||
|
$whereClauses[] = "$column = :f_{$key}";
|
||||||
|
$bindParams["f_{$key}"] = $fVal;
|
||||||
|
break;
|
||||||
|
case 'cs':
|
||||||
|
$whereClauses[] = "$column LIKE :f_{$key}";
|
||||||
|
$bindParams["f_{$key}"] = "%$fVal%";
|
||||||
|
break;
|
||||||
|
case 'sw':
|
||||||
|
$whereClauses[] = "$column LIKE :f_{$key}";
|
||||||
|
$bindParams["f_{$key}"] = "$fVal%";
|
||||||
|
break;
|
||||||
|
case 'ew':
|
||||||
|
$whereClauses[] = "$column LIKE :f_{$key}";
|
||||||
|
$bindParams["f_{$key}"] = "%$fVal";
|
||||||
|
break;
|
||||||
|
// Add other cases if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base SQL
|
||||||
|
$sqlBase = "
|
||||||
|
FROM statement st
|
||||||
|
LEFT JOIN registrar r ON st.registrar_id = r.id
|
||||||
|
";
|
||||||
|
|
||||||
|
// Combine filters with OR (common approach)
|
||||||
|
$sqlWhere = '';
|
||||||
|
if (!empty($whereClauses)) {
|
||||||
|
$sqlWhere = "WHERE " . implode(" OR ", $whereClauses);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count total results
|
||||||
|
$totalSql = "SELECT COUNT(DISTINCT st.id) AS total $sqlBase $sqlWhere";
|
||||||
|
$totalCount = $db->selectValue($totalSql, $bindParams);
|
||||||
|
|
||||||
|
// Data query
|
||||||
|
$selectFields = "
|
||||||
|
st.id,
|
||||||
|
st.registrar_id,
|
||||||
|
st.date,
|
||||||
|
st.command,
|
||||||
|
st.domain_name,
|
||||||
|
st.length_in_months,
|
||||||
|
st.fromS,
|
||||||
|
st.toS,
|
||||||
|
st.amount,
|
||||||
|
r.name AS registrar_name
|
||||||
|
";
|
||||||
|
|
||||||
|
$dataSql = "
|
||||||
|
SELECT $selectFields
|
||||||
|
$sqlBase
|
||||||
|
$sqlWhere
|
||||||
|
ORDER BY $sortField $sortDir
|
||||||
|
LIMIT $offset, $size
|
||||||
|
";
|
||||||
|
|
||||||
|
$records = $db->select($dataSql, $bindParams);
|
||||||
|
|
||||||
|
// Ensure records is always an array
|
||||||
|
if (!$records) {
|
||||||
|
$records = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'records' => $records,
|
||||||
|
'results' => $totalCount
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $response->withHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||||
|
$response->getBody()->write(json_encode($payload, JSON_UNESCAPED_UNICODE));
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
document.addEventListener("DOMContentLoaded", function(){
|
document.addEventListener("DOMContentLoaded", function(){
|
||||||
|
|
||||||
currency = "{{ currency }} ";
|
currency = "{{ currency }} ";
|
||||||
|
|
||||||
var searchTerm = ""; // global variable to hold the search term
|
var searchTerm = ""; // global variable to hold the search term
|
||||||
|
|
||||||
function updateSearchTerm(term) {
|
function updateSearchTerm(term) {
|
||||||
|
@ -19,20 +20,29 @@
|
||||||
pagination: true,
|
pagination: true,
|
||||||
paginationMode: "remote",
|
paginationMode: "remote",
|
||||||
paginationSize: 10,
|
paginationSize: 10,
|
||||||
ajaxURL: "/api/records/payment_history",
|
sortMode: "remote",
|
||||||
ajaxParams: {
|
ajaxURL: "/dapi/payments",
|
||||||
join: "registrar"
|
|
||||||
},
|
|
||||||
ajaxURLGenerator: function(url, config, params) {
|
ajaxURLGenerator: function(url, config, params) {
|
||||||
var queryParts = ["join=registrar"];
|
var queryParts = [];
|
||||||
|
|
||||||
// Handle search term
|
// Handle search term
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
queryParts.push("filter1=date,cs," + encodeURIComponent(searchTerm));
|
queryParts.push("filter1=registrar_name,cs," + encodeURIComponent(searchTerm));
|
||||||
queryParts.push("filter2=description,cs," + encodeURIComponent(searchTerm));
|
queryParts.push("filter2=date,cs," + encodeURIComponent(searchTerm));
|
||||||
|
queryParts.push("filter3=description,cs," + encodeURIComponent(searchTerm));
|
||||||
|
queryParts.push("filter4=amount,cs," + encodeURIComponent(searchTerm));
|
||||||
}
|
}
|
||||||
|
|
||||||
queryParts.push("order=date,desc");
|
// Handle sorting from Tabulator
|
||||||
|
if (params.sort && params.sort.length > 0) {
|
||||||
|
var sorter = params.sort[0]; // single-column sorting
|
||||||
|
var sortField = encodeURIComponent(sorter.field);
|
||||||
|
var sortDir = (sorter.dir === "asc" ? "asc" : "desc");
|
||||||
|
queryParts.push("order=" + sortField + "," + sortDir);
|
||||||
|
} else {
|
||||||
|
// fallback default order if no sorters
|
||||||
|
queryParts.push("order=date,desc");
|
||||||
|
}
|
||||||
|
|
||||||
// Include pagination parameters
|
// Include pagination parameters
|
||||||
if (params.page) {
|
if (params.page) {
|
||||||
|
@ -53,9 +63,6 @@
|
||||||
return { last_page: 1, data: [] };
|
return { last_page: 1, data: [] };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dataReceiveParams: {
|
|
||||||
"last_page": "results", // Mapping 'results' to 'last_page'
|
|
||||||
},
|
|
||||||
layout:"fitDataFill",
|
layout:"fitDataFill",
|
||||||
responsiveLayout: "collapse",
|
responsiveLayout: "collapse",
|
||||||
responsiveLayoutCollapseStartOpen:false,
|
responsiveLayoutCollapseStartOpen:false,
|
||||||
|
@ -63,10 +70,10 @@
|
||||||
placeholder: "{{ __('No Data') }}",
|
placeholder: "{{ __('No Data') }}",
|
||||||
columns:[
|
columns:[
|
||||||
{formatter:"responsiveCollapse", width:30, minWidth:30, hozAlign:"center", resizable:false, headerSort:false, responsive:0},
|
{formatter:"responsiveCollapse", width:30, minWidth:30, hozAlign:"center", resizable:false, headerSort:false, responsive:0},
|
||||||
{title:"{{ __('Registrar') }}", field:"registrar_id.name", resizable:false, headerSort:false, responsive:0},
|
{title:"{{ __('Registrar') }}", field:"registrar_name", resizable:false, headerSort:true, responsive:0},
|
||||||
{title:"{{ __('Date') }}", field:"date", resizable:false, headerSort:false, responsive:2},
|
{title:"{{ __('Date') }}", field:"date", resizable:false, headerSort:true, responsive:2},
|
||||||
{title:"{{ __('Description') }}", field:"description", resizable:false, headerSort:false, responsive:2},
|
{title:"{{ __('Description') }}", field:"description", resizable:false, headerSort:true, responsive:2, formatter:cell => (cell.getElement().setAttribute("title", cell.getValue() || ""), cell.getValue()?.length > 80 ? cell.getValue().substring(0, 80) + "..." : cell.getValue())},
|
||||||
{title:"{{ __('Amount') }}", field:"amount", resizable:false, headerSort:false, download:false, responsive:0, formatter:"money", formatterParams:{
|
{title:"{{ __('Amount') }}", field:"amount", resizable:false, headerSort:true, width:200, minWidth:100, responsive:0, formatter:"money", formatterParams:{
|
||||||
decimal:".",
|
decimal:".",
|
||||||
thousand:" ",
|
thousand:" ",
|
||||||
symbol:currency,
|
symbol:currency,
|
||||||
|
@ -75,8 +82,13 @@
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
var searchInput = document.getElementById("search-input");
|
var searchInput = document.getElementById("search-input");
|
||||||
|
let searchTimeout;
|
||||||
|
|
||||||
searchInput.addEventListener("input", function () {
|
searchInput.addEventListener("input", function () {
|
||||||
|
clearTimeout(searchTimeout);
|
||||||
|
searchTimeout = setTimeout(() => {
|
||||||
updateSearchTerm(searchInput.value);
|
updateSearchTerm(searchInput.value);
|
||||||
|
}, 300); // 300ms delay
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -19,22 +19,33 @@
|
||||||
pagination: true,
|
pagination: true,
|
||||||
paginationMode: "remote",
|
paginationMode: "remote",
|
||||||
paginationSize: 10,
|
paginationSize: 10,
|
||||||
ajaxURL: "/api/records/statement",
|
sortMode: "remote",
|
||||||
ajaxParams: {
|
ajaxURL: "/dapi/statements",
|
||||||
join: "registrar"
|
|
||||||
},
|
|
||||||
ajaxURLGenerator: function(url, config, params) {
|
ajaxURLGenerator: function(url, config, params) {
|
||||||
var queryParts = ["join=registrar"];
|
var queryParts = [];
|
||||||
|
|
||||||
// Handle search term
|
// Handle search term
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
queryParts.push("filter1=command,cs," + encodeURIComponent(searchTerm));
|
queryParts.push("filter1=registrar_name,cs," + encodeURIComponent(searchTerm));
|
||||||
queryParts.push("filter2=domain_name,cs," + encodeURIComponent(searchTerm));
|
queryParts.push("filter2=date,cs," + encodeURIComponent(searchTerm));
|
||||||
queryParts.push("filter3=fromS,cs," + encodeURIComponent(searchTerm));
|
queryParts.push("filter3=command,cs," + encodeURIComponent(searchTerm));
|
||||||
queryParts.push("filter4=toS,cs," + encodeURIComponent(searchTerm));
|
queryParts.push("filter4=domain_name,cs," + encodeURIComponent(searchTerm));
|
||||||
|
queryParts.push("filter5=length_in_months,cs," + encodeURIComponent(searchTerm));
|
||||||
|
queryParts.push("filter6=fromS,cs," + encodeURIComponent(searchTerm));
|
||||||
|
queryParts.push("filter7=toS,cs," + encodeURIComponent(searchTerm));
|
||||||
|
queryParts.push("filter8=amount,cs," + encodeURIComponent(searchTerm));
|
||||||
}
|
}
|
||||||
|
|
||||||
queryParts.push("order=date,desc");
|
// Handle sorting from Tabulator
|
||||||
|
if (params.sort && params.sort.length > 0) {
|
||||||
|
var sorter = params.sort[0]; // single-column sorting
|
||||||
|
var sortField = encodeURIComponent(sorter.field);
|
||||||
|
var sortDir = (sorter.dir === "asc" ? "asc" : "desc");
|
||||||
|
queryParts.push("order=" + sortField + "," + sortDir);
|
||||||
|
} else {
|
||||||
|
// fallback default order if no sorters
|
||||||
|
queryParts.push("order=date,desc");
|
||||||
|
}
|
||||||
|
|
||||||
// Include pagination parameters
|
// Include pagination parameters
|
||||||
if (params.page) {
|
if (params.page) {
|
||||||
|
@ -55,9 +66,6 @@
|
||||||
return { last_page: 1, data: [] };
|
return { last_page: 1, data: [] };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dataReceiveParams: {
|
|
||||||
"last_page": "results", // Mapping 'results' to 'last_page'
|
|
||||||
},
|
|
||||||
layout:"fitDataFill",
|
layout:"fitDataFill",
|
||||||
responsiveLayout: "collapse",
|
responsiveLayout: "collapse",
|
||||||
responsiveLayoutCollapseStartOpen:false,
|
responsiveLayoutCollapseStartOpen:false,
|
||||||
|
@ -65,14 +73,14 @@
|
||||||
placeholder: "{{ __('No Data') }}",
|
placeholder: "{{ __('No Data') }}",
|
||||||
columns:[
|
columns:[
|
||||||
{formatter:"responsiveCollapse", width:30, minWidth:30, hozAlign:"center", resizable:false, headerSort:false, responsive:0},
|
{formatter:"responsiveCollapse", width:30, minWidth:30, hozAlign:"center", resizable:false, headerSort:false, responsive:0},
|
||||||
{title:"{{ __('Registrar') }}", field:"registrar_id.name", resizable:false, headerSort:false, responsive:0},
|
{title:"{{ __('Registrar') }}", field:"registrar_name", resizable:false, headerSort:true, responsive:0},
|
||||||
{title:"{{ __('Date') }}", field:"date", resizable:false, headerSort:false, responsive:2},
|
{title:"{{ __('Date') }}", field:"date", resizable:false, headerSort:true, responsive:2},
|
||||||
{title:"{{ __('Command') }}", field:"command", resizable:false, headerSort:false, responsive:2},
|
{title:"{{ __('Command') }}", field:"command", resizable:false, headerSort:true, responsive:2},
|
||||||
{title:"{{ __('Domain') }}", field:"domain_name", resizable:false, headerSort:false, download:false, responsive:0},
|
{title:"{{ __('Domain') }}", field:"domain_name", resizable:false, headerSort:true, download:false, responsive:0},
|
||||||
{title:"{{ __('Length') }}", field:"length_in_months", resizable:false, headerSort:false, responsive:2},
|
{title:"{{ __('Length') }}", field:"length_in_months", resizable:false, download:false, headerSort:true, responsive:2},
|
||||||
{title:"{{ __('From') }}", field:"fromS", resizable:false, headerSort:false, responsive:2},
|
{title:"{{ __('From') }}", field:"fromS", resizable:false, headerSort:true, download:false, responsive:2},
|
||||||
{title:"{{ __('To') }}", field:"toS", resizable:false, headerSort:false, responsive:2},
|
{title:"{{ __('To') }}", field:"toS", resizable:false, headerSort:true, download:false, responsive:2},
|
||||||
{title:"{{ __('Amount') }}", field:"amount", resizable:false, headerSort:false, download:false, responsive:2, formatter:"money", formatterParams:{
|
{title:"{{ __('Amount') }}", field:"amount", resizable:false, headerSort:true, responsive:0, formatter:"money", formatterParams:{
|
||||||
decimal:".",
|
decimal:".",
|
||||||
thousand:" ",
|
thousand:" ",
|
||||||
symbol:currency,
|
symbol:currency,
|
||||||
|
@ -81,8 +89,13 @@
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
var searchInput = document.getElementById("search-input");
|
var searchInput = document.getElementById("search-input");
|
||||||
|
let searchTimeout;
|
||||||
|
|
||||||
searchInput.addEventListener("input", function () {
|
searchInput.addEventListener("input", function () {
|
||||||
|
clearTimeout(searchTimeout);
|
||||||
|
searchTimeout = setTimeout(() => {
|
||||||
updateSearchTerm(searchInput.value);
|
updateSearchTerm(searchInput.value);
|
||||||
|
}, 300); // 300ms delay
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,8 @@ $app->group('', function ($route) {
|
||||||
|
|
||||||
$route->get('/dapi/domains', [DapiController::class, 'listDomains']);
|
$route->get('/dapi/domains', [DapiController::class, 'listDomains']);
|
||||||
$route->get('/dapi/applications', [DapiController::class, 'listApplications']);
|
$route->get('/dapi/applications', [DapiController::class, 'listApplications']);
|
||||||
|
$route->get('/dapi/payments', [DapiController::class, 'listPayments']);
|
||||||
|
$route->get('/dapi/statements', [DapiController::class, 'listStatements']);
|
||||||
})->add(new AuthMiddleware($container));
|
})->add(new AuthMiddleware($container));
|
||||||
|
|
||||||
$app->any('/api[/{params:.*}]', function (
|
$app->any('/api[/{params:.*}]', function (
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue