mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2025-11-06 21:35:55 +01:00
feature: list child domains
This commit is contained in:
@@ -410,6 +410,9 @@
|
|||||||
<li><a href="{% url 'listWebsites' %}"
|
<li><a href="{% url 'listWebsites' %}"
|
||||||
title="{% trans 'List Websites' %}"><span>{% trans "List Websites" %}</span></a>
|
title="{% trans 'List Websites' %}"><span>{% trans "List Websites" %}</span></a>
|
||||||
</li>
|
</li>
|
||||||
|
<li><a href="{% url 'listChildDomains' %}"
|
||||||
|
title="{% trans 'List Child Domains' %}"><span>{% trans "List Child Domains" %}</span></a>
|
||||||
|
</li>
|
||||||
<li class="modifyWebsite"><a href="{% url 'modifyWebsite' %}"
|
<li class="modifyWebsite"><a href="{% url 'modifyWebsite' %}"
|
||||||
title="{% trans 'Modify Website' %}"><span>{% trans "Modify Website" %}</span></a>
|
title="{% trans 'Modify Website' %}"><span>{% trans "Modify Website" %}</span></a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -376,6 +376,156 @@ app.controller('listWebsites', function ($scope, $http) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
app.controller('listChildDomainsMain', function ($scope, $http) {
|
||||||
|
|
||||||
|
|
||||||
|
$scope.currentPage = 1;
|
||||||
|
$scope.recordsToShow = 10;
|
||||||
|
|
||||||
|
$scope.getFurtherWebsitesFromDB = function () {
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': getCookie('csrftoken')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
page: $scope.currentPage,
|
||||||
|
recordsToShow: $scope.recordsToShow
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
dataurl = "/websites/fetchChildDomainsMain";
|
||||||
|
|
||||||
|
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
|
||||||
|
|
||||||
|
|
||||||
|
function ListInitialData(response) {
|
||||||
|
if (response.data.listWebSiteStatus === 1) {
|
||||||
|
|
||||||
|
$scope.WebSitesList = JSON.parse(response.data.data);
|
||||||
|
$scope.pagination = response.data.pagination;
|
||||||
|
$scope.clients = JSON.parse(response.data.data);
|
||||||
|
$("#listFail").hide();
|
||||||
|
} else {
|
||||||
|
$("#listFail").fadeIn();
|
||||||
|
$scope.errorMessage = response.data.error_message;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cantLoadInitialData(response) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
$scope.getFurtherWebsitesFromDB();
|
||||||
|
|
||||||
|
$scope.cyberPanelLoading = true;
|
||||||
|
|
||||||
|
$scope.issueSSL = function (virtualHost) {
|
||||||
|
$scope.cyberPanelLoading = false;
|
||||||
|
|
||||||
|
var url = "/manageSSL/issueSSL";
|
||||||
|
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
virtualHost: virtualHost
|
||||||
|
};
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': getCookie('csrftoken')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
|
||||||
|
|
||||||
|
|
||||||
|
function ListInitialDatas(response) {
|
||||||
|
$scope.cyberPanelLoading = true;
|
||||||
|
if (response.data.SSL === 1) {
|
||||||
|
new PNotify({
|
||||||
|
title: 'Success!',
|
||||||
|
text: 'SSL successfully issued.',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
new PNotify({
|
||||||
|
title: 'Operation Failed!',
|
||||||
|
text: response.data.error_message,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function cantLoadInitialDatas(response) {
|
||||||
|
$scope.cyberPanelLoading = true;
|
||||||
|
new PNotify({
|
||||||
|
title: 'Operation Failed!',
|
||||||
|
text: 'Could not connect to server, please refresh this page',
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cyberPanelLoading = true;
|
||||||
|
|
||||||
|
$scope.searchWebsites = function () {
|
||||||
|
|
||||||
|
$scope.cyberPanelLoading = false;
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
headers: {
|
||||||
|
'X-CSRFToken': getCookie('csrftoken')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
patternAdded: $scope.patternAdded
|
||||||
|
};
|
||||||
|
|
||||||
|
dataurl = "/websites/searchWebsites";
|
||||||
|
|
||||||
|
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
|
||||||
|
|
||||||
|
|
||||||
|
function ListInitialData(response) {
|
||||||
|
$scope.cyberPanelLoading = true;
|
||||||
|
if (response.data.listWebSiteStatus === 1) {
|
||||||
|
|
||||||
|
var finalData = JSON.parse(response.data.data);
|
||||||
|
$scope.WebSitesList = finalData;
|
||||||
|
$("#listFail").hide();
|
||||||
|
} else {
|
||||||
|
new PNotify({
|
||||||
|
title: 'Operation Failed!',
|
||||||
|
text: response.data.error_message,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cantLoadInitialData(response) {
|
||||||
|
$scope.cyberPanelLoading = true;
|
||||||
|
new PNotify({
|
||||||
|
title: 'Operation Failed!',
|
||||||
|
text: 'Connect disrupted, refresh the page.',
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Java script code to list accounts ends here */
|
/* Java script code to list accounts ends here */
|
||||||
|
|||||||
151
websiteFunctions/templates/websiteFunctions/listChildDomains.html
Executable file
151
websiteFunctions/templates/websiteFunctions/listChildDomains.html
Executable file
@@ -0,0 +1,151 @@
|
|||||||
|
{% extends "baseTemplate/index.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Child Domains - CyberPanel" %}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% load static %}
|
||||||
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
|
<!-- Current language: {{ LANGUAGE_CODE }} -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div ng-controller="listChildDomainsMain" class="container">
|
||||||
|
|
||||||
|
<div id="page-title">
|
||||||
|
<h2 id="domainNamePage">{% trans "List Child Domains" %}</h2> <img ng-hide="cyberPanelLoading"
|
||||||
|
src="{% static 'images/loading.gif' %}">
|
||||||
|
<p>{% trans "On this page you can launch, list, modify and delete child domains from your server." %}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-10" style="padding: 0px; box-shadow: 0px 0px 1px 0px #888888; margin-bottom: 2%">
|
||||||
|
<input ng-change="searchWebsites()" placeholder="Search..." ng-model="patternAdded" name="dom" type="text"
|
||||||
|
class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<div class="form-group">
|
||||||
|
<select ng-model="recordsToShow" ng-change="getFurtherWebsitesFromDB()"
|
||||||
|
class="form-control" id="example-select">
|
||||||
|
<option>10</option>
|
||||||
|
<option>50</option>
|
||||||
|
<option>100</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-repeat="web in WebSitesList track by $index" class="panel col-md-12"
|
||||||
|
style="padding: 0px; box-shadow: 0px 0px 1px 0px #888888;">
|
||||||
|
<div class="">
|
||||||
|
<div class="table-responsive no-gutter text-nowrap" style="overflow-x: hidden;">
|
||||||
|
<div style="background-image: url({% static 'images/not-available-preview.png' %});
|
||||||
|
height: 160px;
|
||||||
|
width: 200px;
|
||||||
|
background-position: top;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
position: relative;" class="col-lg-3 col-md-12">
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-9" style="text-transform: none">
|
||||||
|
<div style="border-bottom: 1px solid #888888" class="col-md-12">
|
||||||
|
<div class="col-lg-10 content-box-header" style="text-transform: none;">
|
||||||
|
<a href="http://{$ web.domain $}" target="_blank" title="Visit Site">
|
||||||
|
<h2 style="display: inline; color: #414C59;" ng-bind="web.domain"></h2>
|
||||||
|
</a>
|
||||||
|
<a target="_blank" href="/filemanager/{$ web.masterDomain $}" title="Open File Manager"> -- {$ web.path $}</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2 content-box-header" style="text-transform: none;">
|
||||||
|
<a href="/websites/{$ web.domain $}" target="_blank" title="Manage Website">
|
||||||
|
<i class="p fa fa-external-link btn-icon"> </i>
|
||||||
|
<span>Manage</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="col-md-4 content-box-header">
|
||||||
|
<i class="p fa fa-user-circle btn-icon text-muted" data-toggle="tooltip"
|
||||||
|
data-placement="right" title="Master Domain/Owner"> </i>
|
||||||
|
<span ng-bind="web.masterDomain" style="text-transform: none"></span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 content-box-header">
|
||||||
|
<i class="p fa fa-map-marker btn-icon text-muted" data-toggle="tooltip"
|
||||||
|
data-placement="right" title="IP Address"> </i>
|
||||||
|
<span ng-bind="web.ipAddress"></span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 content-box-header">
|
||||||
|
<i class="p fa fa-lock btn-icon text-muted" data-toggle="tooltip" data-placement="right"
|
||||||
|
title="SSL"> </i>
|
||||||
|
<span><a ng-click="issueSSL(web.domain)" href="" style="text-transform: none">Issue SSL</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-12">
|
||||||
|
|
||||||
|
<div class="col-md-4 content-box-header">
|
||||||
|
<i class="p fa fa-cubes btn-icon text-muted" data-toggle="tooltip" data-placement="right"
|
||||||
|
title="Packages"> </i>
|
||||||
|
<span ng-bind="web.package" style="text-transform: none"></span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 content-box-header">
|
||||||
|
<i class="p fa fa-user btn-icon text-muted" data-toggle="tooltip" data-placement="right"
|
||||||
|
title="Owner"> </i>
|
||||||
|
<span ng-bind="web.admin" style="text-transform: none"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4 content-box-header">
|
||||||
|
<i class="p fa fa-arrows-h btn-icon text-muted" data-toggle="tooltip" data-placement="right"
|
||||||
|
title="Convert to Website"> </i>
|
||||||
|
<span><a ng-click="issueSSL(web.domain)" href="" style="text-transform: none">Convert to Website</a></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!--table cellpadding="0" cellspacing="0" border="0" class="table" style="margin:0px 0px; id="datatable-example">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>IP Address</th>
|
||||||
|
<th>Package</th>
|
||||||
|
<th>Owner</th>
|
||||||
|
<th>State</th>
|
||||||
|
<th>Email</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td ng-bind="web.ipAddress"></td>
|
||||||
|
<td ng-bind="web.package"></td>
|
||||||
|
<td ng-bind="web.admin"></td>
|
||||||
|
<td ng-bind="web.state"></td>
|
||||||
|
<td ng-bind="web.adminEmail"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table-->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="listFail" class="alert alert-danger">
|
||||||
|
<p>{% trans "Cannot list websites. Error message:" %} {$ errorMessage $}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 2%" class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-9">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<select ng-model="currentPage" class="form-control"
|
||||||
|
ng-change="getFurtherWebsitesFromDB()">
|
||||||
|
<option ng-repeat="page in pagination">{$ $index + 1 $}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> <!-- end row -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -6,6 +6,7 @@ urlpatterns = [
|
|||||||
url(r'^$', views.loadWebsitesHome, name='loadWebsitesHome'),
|
url(r'^$', views.loadWebsitesHome, name='loadWebsitesHome'),
|
||||||
url(r'^createWebsite$', views.createWebsite, name='createWebsite'),
|
url(r'^createWebsite$', views.createWebsite, name='createWebsite'),
|
||||||
url(r'^listWebsites$', views.listWebsites, name='listWebsites'),
|
url(r'^listWebsites$', views.listWebsites, name='listWebsites'),
|
||||||
|
url(r'^listChildDomains$', views.listChildDomains, name='listChildDomains'),
|
||||||
url(r'^modifyWebsite$', views.modifyWebsite, name='modifyWebsite'),
|
url(r'^modifyWebsite$', views.modifyWebsite, name='modifyWebsite'),
|
||||||
url(r'^deleteWebsite$', views.deleteWebsite, name='deleteWebsite'),
|
url(r'^deleteWebsite$', views.deleteWebsite, name='deleteWebsite'),
|
||||||
url(r'^siteState$', views.siteState, name='siteState'),
|
url(r'^siteState$', views.siteState, name='siteState'),
|
||||||
@@ -18,6 +19,7 @@ urlpatterns = [
|
|||||||
url(r'^submitWebsiteDeletion$', views.submitWebsiteDeletion, name='submitWebsiteDeletion'),
|
url(r'^submitWebsiteDeletion$', views.submitWebsiteDeletion, name='submitWebsiteDeletion'),
|
||||||
url(r'^submitWebsiteListing$', views.getFurtherAccounts, name='submitWebsiteListing'),
|
url(r'^submitWebsiteListing$', views.getFurtherAccounts, name='submitWebsiteListing'),
|
||||||
url(r'^fetchWebsitesList$', views.fetchWebsitesList, name='fetchWebsitesList'),
|
url(r'^fetchWebsitesList$', views.fetchWebsitesList, name='fetchWebsitesList'),
|
||||||
|
url(r'^fetchChildDomainsMain$', views.fetchChildDomainsMain, name='fetchChildDomainsMain'),
|
||||||
url(r'^searchWebsites$', views.searchWebsites, name='searchWebsites'),
|
url(r'^searchWebsites$', views.searchWebsites, name='searchWebsites'),
|
||||||
url(r'^submitWebsiteModification$', views.deleteWebsite, name='submitWebsiteModification'),
|
url(r'^submitWebsiteModification$', views.deleteWebsite, name='submitWebsiteModification'),
|
||||||
url(r'^submitWebsiteStatus$', views.submitWebsiteStatus, name='submitWebsiteStatus'),
|
url(r'^submitWebsiteStatus$', views.submitWebsiteStatus, name='submitWebsiteStatus'),
|
||||||
|
|||||||
@@ -61,6 +61,14 @@ def listWebsites(request):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return redirect(loadLoginPage)
|
return redirect(loadLoginPage)
|
||||||
|
|
||||||
|
def listChildDomains(request):
|
||||||
|
try:
|
||||||
|
userID = request.session['userID']
|
||||||
|
wm = WebsiteManager()
|
||||||
|
return wm.listChildDomains(request, userID)
|
||||||
|
except KeyError:
|
||||||
|
return redirect(loadLoginPage)
|
||||||
|
|
||||||
def submitWebsiteCreation(request):
|
def submitWebsiteCreation(request):
|
||||||
try:
|
try:
|
||||||
userID = request.session['userID']
|
userID = request.session['userID']
|
||||||
@@ -133,6 +141,14 @@ def fetchWebsitesList(request):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return redirect(loadLoginPage)
|
return redirect(loadLoginPage)
|
||||||
|
|
||||||
|
def fetchChildDomainsMain(request):
|
||||||
|
try:
|
||||||
|
userID = request.session['userID']
|
||||||
|
wm = WebsiteManager()
|
||||||
|
return wm.fetchChildDomainsMain(userID, json.loads(request.body))
|
||||||
|
except KeyError:
|
||||||
|
return redirect(loadLoginPage)
|
||||||
|
|
||||||
def submitWebsiteDeletion(request):
|
def submitWebsiteDeletion(request):
|
||||||
try:
|
try:
|
||||||
userID = request.session['userID']
|
userID = request.session['userID']
|
||||||
|
|||||||
@@ -115,6 +115,15 @@ class WebsiteManager:
|
|||||||
except BaseException as msg:
|
except BaseException as msg:
|
||||||
return HttpResponse(str(msg))
|
return HttpResponse(str(msg))
|
||||||
|
|
||||||
|
def listChildDomains(self, request=None, userID=None, data=None):
|
||||||
|
try:
|
||||||
|
currentACL = ACLManager.loadedACL(userID)
|
||||||
|
pagination = self.websitePagination(currentACL, userID)
|
||||||
|
|
||||||
|
return render(request, 'websiteFunctions/listChildDomains.html', {"pagination": pagination})
|
||||||
|
except BaseException as msg:
|
||||||
|
return HttpResponse(str(msg))
|
||||||
|
|
||||||
def listCron(self, request=None, userID=None, data=None):
|
def listCron(self, request=None, userID=None, data=None):
|
||||||
try:
|
try:
|
||||||
currentACL = ACLManager.loadedACL(userID)
|
currentACL = ACLManager.loadedACL(userID)
|
||||||
@@ -355,6 +364,32 @@ class WebsiteManager:
|
|||||||
json_data = json.dumps(dic)
|
json_data = json.dumps(dic)
|
||||||
return HttpResponse(json_data)
|
return HttpResponse(json_data)
|
||||||
|
|
||||||
|
def fetchChildDomainsMain(self, userID=None, data=None):
|
||||||
|
try:
|
||||||
|
currentACL = ACLManager.loadedACL(userID)
|
||||||
|
pageNumber = int(data['page'])
|
||||||
|
recordsToShow = int(data['recordsToShow'])
|
||||||
|
|
||||||
|
endPageNumber, finalPageNumber = self.recordsPointer(pageNumber, recordsToShow)
|
||||||
|
websites = ACLManager.findWebsiteObjects(currentACL, userID)
|
||||||
|
childDomains = []
|
||||||
|
|
||||||
|
for web in websites:
|
||||||
|
for child in web.childdomains_set.all():
|
||||||
|
childDomains.append(child)
|
||||||
|
|
||||||
|
pagination = self.getPagination(len(childDomains), recordsToShow)
|
||||||
|
json_data = self.findChildsListJson(childDomains[finalPageNumber:endPageNumber])
|
||||||
|
|
||||||
|
final_dic = {'status': 1, 'listWebSiteStatus': 1, 'error_message': "None", "data": json_data,
|
||||||
|
'pagination': pagination}
|
||||||
|
final_json = json.dumps(final_dic)
|
||||||
|
return HttpResponse(final_json)
|
||||||
|
except BaseException as msg:
|
||||||
|
dic = {'status': 1, 'listWebSiteStatus': 0, 'error_message': str(msg)}
|
||||||
|
json_data = json.dumps(dic)
|
||||||
|
return HttpResponse(json_data)
|
||||||
|
|
||||||
def findWebsitesListJson(self, websites):
|
def findWebsitesListJson(self, websites):
|
||||||
|
|
||||||
json_data = "["
|
json_data = "["
|
||||||
@@ -390,6 +425,35 @@ class WebsiteManager:
|
|||||||
|
|
||||||
return json_data
|
return json_data
|
||||||
|
|
||||||
|
def findChildsListJson(self, childs):
|
||||||
|
|
||||||
|
json_data = "["
|
||||||
|
checker = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
ipFile = "/etc/cyberpanel/machineIP"
|
||||||
|
f = open(ipFile)
|
||||||
|
ipData = f.read()
|
||||||
|
ipAddress = ipData.split('\n', 1)[0]
|
||||||
|
except BaseException as msg:
|
||||||
|
logging.CyberCPLogFileWriter.writeToFile("Failed to read machine IP, error:" + str(msg))
|
||||||
|
ipAddress = "192.168.100.1"
|
||||||
|
|
||||||
|
for items in childs:
|
||||||
|
|
||||||
|
dic = {'domain': items.domain, 'masterDomain': items.master.domain, 'adminEmail': items.master.adminEmail, 'ipAddress': ipAddress,
|
||||||
|
'admin': items.master.admin.userName, 'package': items.master.package.packageName, 'path': items.path}
|
||||||
|
|
||||||
|
if checker == 0:
|
||||||
|
json_data = json_data + json.dumps(dic)
|
||||||
|
checker = 1
|
||||||
|
else:
|
||||||
|
json_data = json_data + ',' + json.dumps(dic)
|
||||||
|
|
||||||
|
json_data = json_data + ']'
|
||||||
|
|
||||||
|
return json_data
|
||||||
|
|
||||||
def recordsPointer(self, page, toShow):
|
def recordsPointer(self, page, toShow):
|
||||||
finalPageNumber = ((page * toShow)) - toShow
|
finalPageNumber = ((page * toShow)) - toShow
|
||||||
endPageNumber = finalPageNumber + toShow
|
endPageNumber = finalPageNumber + toShow
|
||||||
|
|||||||
Reference in New Issue
Block a user