Added pagination (#19)

* Added initial functionality for pagination

* Display of pagination now works for total page number greater than 8. Note that the actual pagination is not yet implemented

* Pagination is now functional and loads the requested sites

* Added cursor pointer to pagination

* page parameter is now set to 1 if not a number or smaller than 1

* page parameter is now checked with isset to prevent errors if it is not supplied

* Changed default number of domains per page to 15

* Added isset check to $input->page to prevent errors if it is not set
This commit is contained in:
Maurice Meyer 2016-06-07 19:00:35 +02:00 committed by Lukas Metzger
parent dc8fab4d42
commit 788c0d1d19
4 changed files with 167 additions and 43 deletions

View file

@ -28,39 +28,22 @@ if(!isset($input->csrfToken) || $input->csrfToken !== $_SESSION['csrfToken']) {
}
if(isset($input->action) && $input->action == "getDomains") {
// Check if the requested page is a number
if(!(isset($input->page) && is_int($input->page) && $input->page > 0)) {
echo "Requested page must be a positive number!";
exit();
}
// Here we get the number of matching records
$sql = "
SELECT D.id,D.name,D.type,count(R.domain_id) AS records
SELECT COUNT(*) AS anzahl
FROM domains D
LEFT OUTER JOIN records R ON D.id = R.domain_id
LEFT OUTER JOIN permissions P ON D.id = P.domain
WHERE (P.user=? OR ?)
GROUP BY D.id, D.name, D.type
HAVING
WHERE (P.user=? OR ?) AND
(D.name LIKE ? OR ?) AND
(D.type=? OR ?)
";
if(isset($input->sort->field) && $input->sort->field != "") {
if($input->sort->field == "id") {
$sql .= "ORDER BY id";
} else if($input->sort->field == "name") {
$sql .= "ORDER BY name";
} else if($input->sort->field == "type") {
$sql .= "ORDER BY type";
} else if($input->sort->field == "records") {
$sql .= "ORDER BY records";
}
if(isset($input->sort->order)) {
if($input->sort->order == 0) {
$sql .= " DESC";
} else if($input->sort->order == 1) {
$sql .= " ASC";
}
}
}
$stmt = $db->prepare($sql);
if(isset($input->name)) {
@ -91,10 +74,91 @@ if(isset($input->action) && $input->action == "getDomains") {
$result = $stmt->get_result();
// This is the object containing the number of rows
$obj = $result->fetch_object();
// Initialize the return value
$retval = Array();
$retval['pages']['current'] = $input->page;
$retval['pages']['total'] = ceil($obj->anzahl / $config['domain_rows']);
// Now the real search is done on the database
$sql = "
SELECT D.id,D.name,D.type,count(R.domain_id) AS records
FROM domains D
LEFT OUTER JOIN records R ON D.id = R.domain_id
LEFT OUTER JOIN permissions P ON D.id = P.domain
WHERE (P.user=? OR ?)
GROUP BY D.id, D.name, D.type
HAVING
(D.name LIKE ? OR ?) AND
(D.type=? OR ?)
";
if(isset($input->sort->field) && $input->sort->field != "") {
if($input->sort->field == "id") {
$sql .= "ORDER BY id";
} else if($input->sort->field == "name") {
$sql .= "ORDER BY name";
} else if($input->sort->field == "type") {
$sql .= "ORDER BY type";
} else if($input->sort->field == "records") {
$sql .= "ORDER BY records";
}
if(isset($input->sort->order)) {
if($input->sort->order == 0) {
$sql .= " DESC";
} else if($input->sort->order == 1) {
$sql .= " ASC";
}
}
}
/*
* Now the number of entries gets limited to the domainRows config value.
* SQL LIMIT is used for that:
* LIMIT lower, upper
* Note that LIMIT 0,4 returns the first five rows!
*/
$lower_limit = ($config['domain_rows'] * ($input->page - 1));
$sql .= " LIMIT " . $lower_limit . ", " . $config['domain_rows'];
$stmt = $db->prepare($sql);
if(isset($input->name)) {
$name_filter = "%" . $input->name . "%";
$name_filter_used = 0;
} else {
$name_filter = "";
$name_filter_used = 1;
}
$id_filter = $_SESSION['id'];
$id_filter_used = (int)($_SESSION['type'] == "admin" ? 1 : 0);
if(isset($input->type)) {
$type_filter = $input->type;
$type_filter_used = 0;
} else {
$type_filter = "";
$type_filter_used = 1;
}
$stmt->bind_param("sisiii",
$id_filter, $id_filter_used,
$name_filter, $name_filter_used,
$type_filter, $type_filter_used
);
$stmt->execute();
$result = $stmt->get_result();
while($obj = $result->fetch_object()) {
$retval[] = $obj;
$retval['data'][] = $obj;
}
}

View file

@ -26,4 +26,7 @@ $config['db_name'] = "pdnsmanager";
//Remote update
$config['nonce_lifetime'] = 15;
include 'config-user.php';
//Number of rows in domain overview
$config['domain_rows'] = 15;
include 'config-user.php';

View file

@ -50,7 +50,7 @@ limitations under the License.
</ul>
</div>
</nav>
<div class="container">
<table class="table table-hover" id="table-domains">
<thead>
@ -82,12 +82,16 @@ limitations under the License.
</thead>
<tbody class="cursor-pointer">
</tbody>
</table>
<nav id="pagination-wrapper" class="text-center defaulthidden">
<ul id="pagination" class="pagination cursor-pointer">
</ul>
</nav>
<?php
if($_SESSION['type'] == "admin") {
echo '<div class="row">';
echo '<div class="row text-center">';
echo '<a class="btn btn-success" href="add-domain.php#MASTER">Add MASTER</a>';
echo '<a class="btn btn-primary margin-left-20" href="add-domain.php#NATIVE">Add NATIVE</a>';
echo '</div>';
@ -108,6 +112,8 @@ limitations under the License.
</div>
</div>
</div>
<?php echo '<span class="hidden" id="csrfToken">' . $_SESSION['csrfToken'] . '</span>'; ?>
<?php echo '<span class="hidden" id="csrfToken">' . $_SESSION['csrfToken'] . '</span>'; ?>
</body>
</html>

View file

@ -39,49 +39,96 @@ $(document).ready(function() {
}
requestData();
});
$('#searchName').bind("paste keyup", function() {
requestData();
});
$('#searchType').change(function() {
requestData();
});
$('#searchType').select2({
minimumResultsForSearch: Infinity
});
});
function requestData() {
function requestData(page) {
if(typeof(page) !== 'number' || page <= 0) {
page = 1;
}
var restrictions = {
csrfToken: $('#csrfToken').text()
csrfToken: $('#csrfToken').text(),
};
restrictions.sort = sort;
var searchName = $('#searchName').val();
if(searchName.length > 0) {
restrictions.name = searchName;
}
var searchType = $('#searchType').val();
if(searchType != "none") {
restrictions.type = searchType;
}
restrictions.action = "getDomains";
restrictions.page = page;
$.post(
"api/domains.php",
JSON.stringify(restrictions),
function(data) {
recreateTable(data);
recreateTable(data.data);
recreatePagination(data.pages)
},
"json"
);
}
function recreatePagination(data) {
$('#pagination').empty();
if(data.total === 1) {
$('#pagination-wrapper').hide();
return;
}
if(data.current > 1) {
$('<li><a href="#"><span class="glyphicon glyphicon-chevron-left"></span></a></li>').appendTo('#pagination').data("page", data.current - 1).click(paginationClicked);
}
$('<li><span>1</span></li>').appendTo('#pagination').data("page", 1).click(paginationClicked);
if(data.current > 4) {
$('<li class="disabled"><span>&hellip;</span></li>').appendTo('#pagination');
}
for(var i = data.current - 2; i <= data.current + 2; i++) {
if(i > 1 && i < data.total) {
if(data.current === i) {
$('<li class="active"><span>' + i + '</span></li>').appendTo('#pagination');
} else {
$('<li><span>' + i + '</span></li>').appendTo('#pagination').data("page", i).click(paginationClicked);
}
}
}
if(data.current < data.total - 3) {
$('<li class="disabled"><span>&hellip;</span></li>').appendTo('#pagination');
}
$('<li><span>' + data.total + '</span></li>').appendTo('#pagination').data("page", data.total).click(paginationClicked);
if(data.current < data.total) {
$('<li><a href="#"><span class="glyphicon glyphicon-chevron-right"></span></a></li>').appendTo('#pagination').data("page", data.current + 1).click(paginationClicked);
}
$('#pagination-wrapper').show();
}
function recreateTable(data) {
$('#table-domains>tbody').empty();
@ -144,4 +191,8 @@ function deleteDomainWithId(id, callback) {
},
"json"
);
}
function paginationClicked() {
requestData($(this).data("page"));
}