add loader

This commit is contained in:
usmannasir
2025-04-08 22:58:11 +05:00
parent 0c4c5e54d9
commit bb7157d9f4
2 changed files with 474 additions and 552 deletions

View File

@@ -2589,12 +2589,14 @@ $("#listFail").hide();
app.controller('listWebsites', function ($scope, $http, $window) {
$scope.web = {};
$scope.WebSitesList = [];
$scope.loading = true; // Add loading state
$scope.currentPage = 1;
$scope.recordsToShow = 10;
// Initial fetch of websites
$scope.getFurtherWebsitesFromDB = function () {
$scope.loading = true; // Set loading to true when starting fetch
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
@@ -2617,9 +2619,11 @@ app.controller('listWebsites', function ($scope, $http, $window) {
$("#listFail").fadeIn();
$scope.errorMessage = response.data.error_message;
}
$scope.loading = false; // Set loading to false when done
}).catch(function(error) {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching websites';
$scope.loading = false; // Set loading to false on error
});
};
@@ -2635,58 +2639,43 @@ app.controller('listWebsites', function ($scope, $http, $window) {
return;
}
// Find the website in the list and set loading state
var site = $scope.WebSitesList.find(function(website) {
return website.domain === domain;
});
if (!site) {
console.error('Website not found:', domain);
return;
}
// Toggle visibility and handle loading state
site.showWPSites = !site.showWPSites;
var url = '/websites/fetchWPDetails';
var data = {
domain: domain
};
// Only fetch if we're showing and don't have data yet
if (site.showWPSites && (!site.wp_sites || !site.wp_sites.length)) {
// Set loading state
site.loadingWPSites = true;
var url = '/websites/fetchWPDetails';
var data = {
domain: domain
};
console.log('Making request to:', url, 'with data:', data);
$http({
method: 'POST',
url: url,
data: $.param(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken': getCookie('csrftoken')
}
}).then(function(response) {
console.log('Response received:', response);
if (response.data.status === 1 && response.data.fetchStatus === 1) {
site.wp_sites = response.data.sites;
$("#listFail").hide();
} else {
$("#listFail").fadeIn();
$scope.errorMessage = response.data.error_message || 'Failed to fetch WordPress sites';
console.error('Error in response:', response.data.error_message);
}
}).catch(function(error) {
console.log('Making request to:', url, 'with data:', data);
$http({
method: 'POST',
url: url,
data: $.param(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken': getCookie('csrftoken')
}
}).then(function(response) {
console.log('Response received:', response);
if (response.data.status === 1 && response.data.fetchStatus === 1) {
// Find the website in the list and update its properties
$scope.WebSitesList.forEach(function(website) {
if (website.domain === domain) {
website.wp_sites = response.data.sites;
website.showWPSites = true;
console.log('Updated website:', website);
}
});
$("#listFail").hide();
} else {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching WordPress sites';
console.error('Request failed:', error);
}).finally(function() {
// Clear loading state when done
site.loadingWPSites = false;
});
}
$scope.errorMessage = response.data.error_message || 'Failed to fetch WordPress sites';
console.error('Error in response:', response.data.error_message);
}
}).catch(function(error) {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching WordPress sites';
console.error('Request failed:', error);
});
};
$scope.visitSite = function(wp) {
@@ -3018,8 +3007,7 @@ app.controller('listWebsites', function ($scope, $http, $window) {
$scope.cyberPanelLoading = true;
$scope.searchWebsites = function () {
$scope.cyberPanelLoading = false;
$scope.loading = true; // Set loading to true when starting search
var config = {
headers: {
@@ -3033,13 +3021,8 @@ app.controller('listWebsites', function ($scope, $http, $window) {
dataurl = "/websites/searchWebsites";
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
function ListInitialData(response) {
$scope.cyberPanelLoading = true;
$http.post(dataurl, data, config).then(function(response) {
if (response.data.listWebSiteStatus === 1) {
var finalData = JSON.parse(response.data.data);
$scope.WebSitesList = finalData;
$("#listFail").hide();
@@ -3049,20 +3032,16 @@ app.controller('listWebsites', function ($scope, $http, $window) {
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialData(response) {
$scope.cyberPanelLoading = true;
$scope.loading = false; // Set loading to false when done
}).catch(function(error) {
new PNotify({
title: 'Operation Failed!',
text: 'Connect disrupted, refresh the page.',
type: 'error'
});
}
$scope.loading = false; // Set loading to false on error
});
};
$scope.ScanWordpressSite = function () {
@@ -5715,12 +5694,14 @@ $("#listFail").hide();
app.controller('listWebsites', function ($scope, $http, $window) {
$scope.web = {};
$scope.WebSitesList = [];
$scope.loading = true; // Add loading state
$scope.currentPage = 1;
$scope.recordsToShow = 10;
// Initial fetch of websites
$scope.getFurtherWebsitesFromDB = function () {
$scope.loading = true; // Set loading to true when starting fetch
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
@@ -5743,9 +5724,11 @@ app.controller('listWebsites', function ($scope, $http, $window) {
$("#listFail").fadeIn();
$scope.errorMessage = response.data.error_message;
}
$scope.loading = false; // Set loading to false when done
}).catch(function(error) {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching websites';
$scope.loading = false; // Set loading to false on error
});
};
@@ -5761,58 +5744,43 @@ app.controller('listWebsites', function ($scope, $http, $window) {
return;
}
// Find the website in the list and set loading state
var site = $scope.WebSitesList.find(function(website) {
return website.domain === domain;
});
if (!site) {
console.error('Website not found:', domain);
return;
}
// Toggle visibility and handle loading state
site.showWPSites = !site.showWPSites;
var url = '/websites/fetchWPDetails';
var data = {
domain: domain
};
// Only fetch if we're showing and don't have data yet
if (site.showWPSites && (!site.wp_sites || !site.wp_sites.length)) {
// Set loading state
site.loadingWPSites = true;
var url = '/websites/fetchWPDetails';
var data = {
domain: domain
};
console.log('Making request to:', url, 'with data:', data);
$http({
method: 'POST',
url: url,
data: $.param(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken': getCookie('csrftoken')
}
}).then(function(response) {
console.log('Response received:', response);
if (response.data.status === 1 && response.data.fetchStatus === 1) {
site.wp_sites = response.data.sites;
$("#listFail").hide();
} else {
$("#listFail").fadeIn();
$scope.errorMessage = response.data.error_message || 'Failed to fetch WordPress sites';
console.error('Error in response:', response.data.error_message);
}
}).catch(function(error) {
console.log('Making request to:', url, 'with data:', data);
$http({
method: 'POST',
url: url,
data: $.param(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken': getCookie('csrftoken')
}
}).then(function(response) {
console.log('Response received:', response);
if (response.data.status === 1 && response.data.fetchStatus === 1) {
// Find the website in the list and update its properties
$scope.WebSitesList.forEach(function(website) {
if (website.domain === domain) {
website.wp_sites = response.data.sites;
website.showWPSites = true;
console.log('Updated website:', website);
}
});
$("#listFail").hide();
} else {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching WordPress sites';
console.error('Request failed:', error);
}).finally(function() {
// Clear loading state when done
site.loadingWPSites = false;
});
}
$scope.errorMessage = response.data.error_message || 'Failed to fetch WordPress sites';
console.error('Error in response:', response.data.error_message);
}
}).catch(function(error) {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching WordPress sites';
console.error('Request failed:', error);
});
};
$scope.visitSite = function(wp) {
@@ -6145,8 +6113,7 @@ app.controller('listWebsites', function ($scope, $http, $window) {
$scope.cyberPanelLoading = true;
$scope.searchWebsites = function () {
$scope.cyberPanelLoading = false;
$scope.loading = true; // Set loading to true when starting search
var config = {
headers: {
@@ -6160,13 +6127,8 @@ app.controller('listWebsites', function ($scope, $http, $window) {
dataurl = "/websites/searchWebsites";
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
function ListInitialData(response) {
$scope.cyberPanelLoading = true;
$http.post(dataurl, data, config).then(function(response) {
if (response.data.listWebSiteStatus === 1) {
var finalData = JSON.parse(response.data.data);
$scope.WebSitesList = finalData;
$("#listFail").hide();
@@ -6176,20 +6138,16 @@ app.controller('listWebsites', function ($scope, $http, $window) {
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialData(response) {
$scope.cyberPanelLoading = true;
$scope.loading = false; // Set loading to false when done
}).catch(function(error) {
new PNotify({
title: 'Operation Failed!',
text: 'Connect disrupted, refresh the page.',
type: 'error'
});
}
$scope.loading = false; // Set loading to false on error
});
};
$scope.ScanWordpressSite = function () {
@@ -9415,12 +9373,14 @@ $("#listFail").hide();
app.controller('listWebsites', function ($scope, $http, $window) {
$scope.web = {};
$scope.WebSitesList = [];
$scope.loading = true; // Add loading state
$scope.currentPage = 1;
$scope.recordsToShow = 10;
// Initial fetch of websites
$scope.getFurtherWebsitesFromDB = function () {
$scope.loading = true; // Set loading to true when starting fetch
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
@@ -9443,9 +9403,11 @@ app.controller('listWebsites', function ($scope, $http, $window) {
$("#listFail").fadeIn();
$scope.errorMessage = response.data.error_message;
}
$scope.loading = false; // Set loading to false when done
}).catch(function(error) {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching websites';
$scope.loading = false; // Set loading to false on error
});
};
@@ -9461,58 +9423,43 @@ app.controller('listWebsites', function ($scope, $http, $window) {
return;
}
// Find the website in the list and set loading state
var site = $scope.WebSitesList.find(function(website) {
return website.domain === domain;
});
if (!site) {
console.error('Website not found:', domain);
return;
}
// Toggle visibility and handle loading state
site.showWPSites = !site.showWPSites;
var url = '/websites/fetchWPDetails';
var data = {
domain: domain
};
// Only fetch if we're showing and don't have data yet
if (site.showWPSites && (!site.wp_sites || !site.wp_sites.length)) {
// Set loading state
site.loadingWPSites = true;
var url = '/websites/fetchWPDetails';
var data = {
domain: domain
};
console.log('Making request to:', url, 'with data:', data);
$http({
method: 'POST',
url: url,
data: $.param(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken': getCookie('csrftoken')
}
}).then(function(response) {
console.log('Response received:', response);
if (response.data.status === 1 && response.data.fetchStatus === 1) {
site.wp_sites = response.data.sites;
$("#listFail").hide();
} else {
$("#listFail").fadeIn();
$scope.errorMessage = response.data.error_message || 'Failed to fetch WordPress sites';
console.error('Error in response:', response.data.error_message);
}
}).catch(function(error) {
console.log('Making request to:', url, 'with data:', data);
$http({
method: 'POST',
url: url,
data: $.param(data),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-CSRFToken': getCookie('csrftoken')
}
}).then(function(response) {
console.log('Response received:', response);
if (response.data.status === 1 && response.data.fetchStatus === 1) {
// Find the website in the list and update its properties
$scope.WebSitesList.forEach(function(website) {
if (website.domain === domain) {
website.wp_sites = response.data.sites;
website.showWPSites = true;
console.log('Updated website:', website);
}
});
$("#listFail").hide();
} else {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching WordPress sites';
console.error('Request failed:', error);
}).finally(function() {
// Clear loading state when done
site.loadingWPSites = false;
});
}
$scope.errorMessage = response.data.error_message || 'Failed to fetch WordPress sites';
console.error('Error in response:', response.data.error_message);
}
}).catch(function(error) {
$("#listFail").fadeIn();
$scope.errorMessage = error.message || 'An error occurred while fetching WordPress sites';
console.error('Request failed:', error);
});
};
$scope.visitSite = function(wp) {
@@ -9643,8 +9590,7 @@ app.controller('listWebsites', function ($scope, $http, $window) {
$scope.cyberPanelLoading = true;
$scope.searchWebsites = function () {
$scope.cyberPanelLoading = false;
$scope.loading = true; // Set loading to true when starting search
var config = {
headers: {
@@ -9658,13 +9604,8 @@ app.controller('listWebsites', function ($scope, $http, $window) {
dataurl = "/websites/searchWebsites";
$http.post(dataurl, data, config).then(ListInitialData, cantLoadInitialData);
function ListInitialData(response) {
$scope.cyberPanelLoading = true;
$http.post(dataurl, data, config).then(function(response) {
if (response.data.listWebSiteStatus === 1) {
var finalData = JSON.parse(response.data.data);
$scope.WebSitesList = finalData;
$("#listFail").hide();
@@ -9674,20 +9615,16 @@ app.controller('listWebsites', function ($scope, $http, $window) {
text: response.data.error_message,
type: 'error'
});
}
}
function cantLoadInitialData(response) {
$scope.cyberPanelLoading = true;
$scope.loading = false; // Set loading to false when done
}).catch(function(error) {
new PNotify({
title: 'Operation Failed!',
text: 'Connect disrupted, refresh the page.',
type: 'error'
});
}
$scope.loading = false; // Set loading to false on error
});
};
$scope.ScanWordpressSite = function () {

View File

@@ -17,243 +17,244 @@
</script>
<div ng-controller="listWebsites" class="container">
<!-- Password Protection Modal -->
<div class="modal fade" id="passwordProtectionModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Password Protection</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" ng-model="currentWP.PPUsername" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" ng-model="currentWP.PPPassword" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" ng-click="submitPasswordProtection()">Enable Protection</button>
<!-- Loading State -->
<div ng-show="loading" class="text-center" style="padding: 50px;">
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;">
<span class="sr-only">Loading...</span>
</div>
<h4 class="mt-3">{% trans "Loading websites..." %}</h4>
</div>
<!-- Main Content (hidden while loading) -->
<div ng-hide="loading">
<!-- Password Protection Modal -->
<div class="modal fade" id="passwordProtectionModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Password Protection</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" ng-model="currentWP.PPUsername" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" ng-model="currentWP.PPPassword" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" ng-click="submitPasswordProtection()">Enable Protection</button>
</div>
</div>
</div>
</div>
</div>
<div id="page-title">
<h2 id="domainNamePage">{% trans "List Websites" %}
<a class="pull-right btn btn-primary" href="{% url "createWebsite" %}">{% trans "Create Website" %}</a>
</h2>
<img ng-hide="cyberPanelLoading" src="{% static 'images/loading.gif' %}">
<p>{% trans "On this page you can launch, list, modify and delete websites 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 id="page-title">
<h2 id="domainNamePage">{% trans "List Websites" %}
<a class="pull-right btn btn-primary" href="{% url "createWebsite" %}">{% trans "Create Website" %}</a>
</h2>
<img ng-hide="cyberPanelLoading" src="{% static 'images/loading.gif' %}">
<p>{% trans "On this page you can launch, list, modify and delete websites from your server." %}</p>
</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 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 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="_self" href="/filemanager/{$ web.domain $}" title="Open File Manager"> --
{% trans "File Manager" %}</a>
</div>
<div class="col-md-2 content-box-header" style="text-transform: none;">
<a href="/websites/{$ web.domain $}" target="_self" title="Manage Website">
<i class="p fa fa-external-link btn-icon">&emsp;</i>
<span>{% trans "Manage" %}</span>
</a>
</div>
</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 class="col-md-12">
<div class="col-md-3 content-box-header">
<i class="p fa fa-sticky-note btn-icon text-muted" data-toggle="tooltip"
data-placement="right" title="State">&emsp;</i>
<span ng-bind="web.state" style="text-transform: none"></span>
</div>
<div class="col-md-3 content-box-header">
<i class="p fa fa-map-marker btn-icon text-muted" data-toggle="tooltip"
data-placement="right" title="IP Address">&emsp;</i>
<span ng-bind="web.ipAddress"></span>
</div>
<div class="col-md-3 content-box-header">
<i class="p fa fa-lock btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="SSL">&emsp;</i>
<span><a ng-click="issueSSL(web.domain)" href=""
style="text-transform: none">{% trans "Issue SSL" %}</a></span>
</div>
<div class="col-md-3 content-box-header">
<span ng-bind="web.phpVersion"></span>
</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 class="col-md-12">
<div class="col-md-3 content-box-header">
<i class="fa-solid fa-hard-drive btn-icon text-muted" data-toggle="tooltip"
data-placement="right"
title="Disk Usage">&emsp;</i>
<span ng-bind="web.diskUsed" style="text-transform: none"></span>
</div>
<div class="col-md-3 content-box-header">
<i class="fa-solid fa-cubes btn-icon text-muted" data-toggle="tooltip"
data-placement="right"
title="Packages">&emsp;</i>
<span ng-bind="web.package" style="text-transform: none"></span>
</div>
<div class="col-md-3 content-box-header">
<i class="fa-solid fa-user btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="Owner">&emsp;</i>
<span ng-bind="web.admin" style="text-transform: none"></span>
</div>
<div class="col-md-3 content-box-header">
<a href="javascript:void(0);" ng-click="showWPSites(web.domain)" style="cursor: pointer;">
<i class="fa-brands fa-wordpress btn-icon text-muted" data-toggle="tooltip"
data-placement="right" title="Show WordPress Sites">&emsp;</i>
<span ng-if="web.wp_sites && web.wp_sites.length > 0" style="text-transform: none">
{$ web.wp_sites.length $} WordPress Sites
</span>
<i ng-if="web.loadingWPSites" class="fa fa-spinner fa-spin" style="margin-left: 5px;"></i>
</a>
</div>
</div>
<!-- Loading State for WordPress Sites -->
<div class="col-md-12" ng-if="web.showWPSites && web.loadingWPSites" style="padding: 15px 30px;">
<div class="loading-state">
<div class="loading-spinner">
<i class="fa fa-spinner fa-spin fa-3x"></i>
<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="_self" href="/filemanager/{$ web.domain $}" title="Open File Manager"> --
{% trans "File Manager" %}</a>
</div>
<div class="col-md-2 content-box-header" style="text-transform: none;">
<a href="/websites/{$ web.domain $}" target="_self" title="Manage Website">
<i class="p fa fa-external-link btn-icon">&emsp;</i>
<span>{% trans "Manage" %}</span>
</a>
</div>
<div class="loading-text">Loading WordPress sites...</div>
</div>
</div>
<!-- WordPress Sites Section -->
<div class="col-md-12" ng-if="web.showWPSites && !web.loadingWPSites && web.wp_sites && web.wp_sites.length > 0" style="padding: 15px 30px;">
<div ng-repeat="wp in web.wp_sites" class="wp-site-item">
<div class="row">
<div class="col-sm-12">
<div class="wp-site-header">
<div class="row">
<div class="col-sm-8">
<h4><i class="fa-brands fa-wordpress" style="color: #00749C; margin-right: 8px;"></i>{$ wp.title $}</h4>
</div>
<div class="col-sm-4 text-right">
<button class="btn btn-outline-primary btn-sm wp-action-btn" ng-click="manageWP(wp.id)">
<i class="fa-solid fa-cog"></i> Manage
</button>
<button class="btn btn-outline-danger btn-sm wp-action-btn" ng-click="deleteWPSite(wp)">
<i class="fa-solid fa-trash"></i> Delete
</button>
<div class="col-md-12">
<div class="col-md-3 content-box-header">
<i class="p fa fa-sticky-note btn-icon text-muted" data-toggle="tooltip"
data-placement="right" title="State">&emsp;</i>
<span ng-bind="web.state" style="text-transform: none"></span>
</div>
<div class="col-md-3 content-box-header">
<i class="p fa fa-map-marker btn-icon text-muted" data-toggle="tooltip"
data-placement="right" title="IP Address">&emsp;</i>
<span ng-bind="web.ipAddress"></span>
</div>
<div class="col-md-3 content-box-header">
<i class="p fa fa-lock btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="SSL">&emsp;</i>
<span><a ng-click="issueSSL(web.domain)" href=""
style="text-transform: none">{% trans "Issue SSL" %}</a></span>
</div>
<div class="col-md-3 content-box-header">
<span ng-bind="web.phpVersion"></span>
</div>
</div>
<div class="col-md-12">
<div class="col-md-3 content-box-header">
<i class="fa-solid fa-hard-drive btn-icon text-muted" data-toggle="tooltip"
data-placement="right"
title="Disk Usage">&emsp;</i>
<span ng-bind="web.diskUsed" style="text-transform: none"></span>
</div>
<div class="col-md-3 content-box-header">
<i class="fa-solid fa-cubes btn-icon text-muted" data-toggle="tooltip"
data-placement="right"
title="Packages">&emsp;</i>
<span ng-bind="web.package" style="text-transform: none"></span>
</div>
<div class="col-md-3 content-box-header">
<i class="fa-solid fa-user btn-icon text-muted" data-toggle="tooltip" data-placement="right"
title="Owner">&emsp;</i>
<span ng-bind="web.admin" style="text-transform: none"></span>
</div>
<div class="col-md-3 content-box-header">
<a href="javascript:void(0);" ng-click="showWPSites(web.domain)" style="cursor: pointer;">
<i class="fa-brands fa-wordpress btn-icon text-muted" data-toggle="tooltip"
data-placement="right" title="Show WordPress Sites">&emsp;</i>
<span ng-if="web.wp_sites && web.wp_sites.length > 0" style="text-transform: none">
{$ web.wp_sites.length $} WordPress Sites
</span>
<i ng-if="web.loadingWPSites" class="fa fa-spinner fa-spin" style="margin-left: 5px;"></i>
</a>
</div>
</div>
<!-- WordPress Sites Section -->
<div class="col-md-12" ng-if="web.showWPSites && web.wp_sites && web.wp_sites.length > 0" style="padding: 15px 30px;">
<div ng-repeat="wp in web.wp_sites" class="wp-site-item">
<div class="row">
<div class="col-sm-12">
<div class="wp-site-header">
<div class="row">
<div class="col-sm-8">
<h4><i class="fa-brands fa-wordpress" style="color: #00749C; margin-right: 8px;"></i>{$ wp.title $}</h4>
</div>
<div class="col-sm-4 text-right">
<button class="btn btn-outline-primary btn-sm wp-action-btn" ng-click="manageWP(wp.id)">
<i class="fa-solid fa-cog"></i> Manage
</button>
<button class="btn btn-outline-danger btn-sm wp-action-btn" ng-click="deleteWPSite(wp)">
<i class="fa-solid fa-trash"></i> Delete
</button>
</div>
</div>
</div>
</div>
<div class="wp-site-content">
<div class="row">
<div class="col-sm-3">
<img ng-src="{$ wp.screenshot $}"
alt="{$ wp.title $}"
class="img-responsive"
style="max-width: 100%; margin-bottom: 10px; min-height: 150px; background: #f5f5f5;"
onerror="this.onerror=null; this.src='https://s.wordpress.org/style/images/about/WordPress-logotype-standard.png';">
<div class="text-center wp-action-buttons">
<a href="javascript:void(0);" ng-click="visitSite(wp)" class="btn btn-outline-secondary btn-sm wp-action-btn">
<i class="fa-solid fa-external-link"></i> Visit Site
</a>
<a href="{% url 'AutoLogin' %}?id={$ wp.id $}" target="_blank" class="btn btn-outline-primary btn-sm wp-action-btn">
<i class="fa-brands fa-wordpress"></i> WP Login
</a>
</div>
</div>
<div class="col-sm-9">
<div class="row">
<div class="col-sm-3">
<div class="info-box">
<label>WordPress</label>
<span>{$ wp.version || 'Unknown' $}</span>
</div>
</div>
<div class="col-sm-3">
<div class="info-box">
<label>PHP Version</label>
<span>{$ wp.phpVersion || 'Loading...' $}</span>
</div>
</div>
<div class="col-sm-3">
<div class="info-box">
<label>Theme</label>
<span>{$ wp.theme || 'twentytwentyfive' $}</span>
</div>
</div>
<div class="col-sm-3">
<div class="info-box">
<label>Plugins</label>
<span>{$ wp.activePlugins || '0' $} active</span>
</div>
<div class="wp-site-content">
<div class="row">
<div class="col-sm-3">
<img ng-src="{$ wp.screenshot $}"
alt="{$ wp.title $}"
class="img-responsive"
style="max-width: 100%; margin-bottom: 10px; min-height: 150px; background: #f5f5f5;"
onerror="this.onerror=null; this.src='https://s.wordpress.org/style/images/about/WordPress-logotype-standard.png';">
<div class="text-center wp-action-buttons">
<a href="javascript:void(0);" ng-click="visitSite(wp)" class="btn btn-outline-secondary btn-sm wp-action-btn">
<i class="fa-solid fa-external-link"></i> Visit Site
</a>
<a href="{% url 'AutoLogin' %}?id={$ wp.id $}" target="_blank" class="btn btn-outline-primary btn-sm wp-action-btn">
<i class="fa-brands fa-wordpress"></i> WP Login
</a>
</div>
</div>
<div class="row mt-3">
<div class="col-sm-6">
<div class="checkbox">
<label>
<input type="checkbox"
ng-click="updateSetting(wp, 'search-indexing')"
ng-checked="wp.searchIndex == 1">
Search engine indexing
</label>
<div class="col-sm-9">
<div class="row">
<div class="col-sm-3">
<div class="info-box">
<label>WordPress</label>
<span>{$ wp.version || 'Unknown' $}</span>
</div>
</div>
<div class="checkbox">
<label>
<input type="checkbox"
ng-click="updateSetting(wp, 'debugging')"
ng-checked="wp.debugging == 1">
Debugging
</label>
<div class="col-sm-3">
<div class="info-box">
<label>PHP Version</label>
<span>{$ wp.phpVersion || 'Loading...' $}</span>
</div>
</div>
<div class="col-sm-3">
<div class="info-box">
<label>Theme</label>
<span>{$ wp.theme || 'twentytwentyfive' $}</span>
</div>
</div>
<div class="col-sm-3">
<div class="info-box">
<label>Plugins</label>
<span>{$ wp.activePlugins || '0' $} active</span>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="checkbox">
<label>
<input type="checkbox"
ng-model="wp.passwordProtection"
ng-init="wp.passwordProtection = wp.passwordProtection || false"
ng-change="togglePasswordProtection(wp)">
Password protection
</label>
<div class="row mt-3">
<div class="col-sm-6">
<div class="checkbox">
<label>
<input type="checkbox"
ng-click="updateSetting(wp, 'search-indexing')"
ng-checked="wp.searchIndex == 1">
Search engine indexing
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox"
ng-click="updateSetting(wp, 'debugging')"
ng-checked="wp.debugging == 1">
Debugging
</label>
</div>
</div>
<div class="checkbox">
<label>
<input type="checkbox"
ng-click="updateSetting(wp, 'maintenance-mode')"
ng-checked="wp.maintenanceMode == 1">
Maintenance mode
</label>
<div class="col-sm-6">
<div class="checkbox">
<label>
<input type="checkbox"
ng-model="wp.passwordProtection"
ng-init="wp.passwordProtection = wp.passwordProtection || false"
ng-change="togglePasswordProtection(wp)">
Password protection
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox"
ng-click="updateSetting(wp, 'maintenance-mode')"
ng-checked="wp.maintenanceMode == 1">
Maintenance mode
</label>
</div>
</div>
</div>
</div>
@@ -263,149 +264,133 @@
</div>
</div>
</div>
</div>
<style>
.wp-site-item {
border: 1px solid #e0e0e0;
margin-bottom: 20px;
border-radius: 8px;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.wp-site-header {
padding: 15px 20px;
border-bottom: 1px solid #e0e0e0;
background: #f8f9fa;
border-radius: 8px 8px 0 0;
}
.wp-site-header h4 {
margin: 0;
font-size: 18px;
line-height: 34px;
color: #2c3338;
font-weight: 500;
}
.wp-site-content {
padding: 20px;
}
.info-box {
margin-bottom: 15px;
background: #f8f9fa;
padding: 10px;
border-radius: 6px;
}
.info-box label {
display: block;
font-size: 12px;
color: #646970;
margin-bottom: 5px;
font-weight: 500;
}
.info-box span {
font-size: 14px;
font-weight: 600;
color: #2c3338;
}
.checkbox {
margin-bottom: 10px;
}
.mt-3 {
margin-top: 1rem;
}
/* Updated button styles */
.wp-action-btn {
margin: 0 4px;
padding: 6px 12px;
font-size: 13px;
font-weight: 500;
transition: all 0.2s ease;
border-width: 1.5px;
line-height: 1.5;
display: inline-flex;
align-items: center;
justify-content: center;
vertical-align: middle;
height: 32px;
}
.wp-action-btn i {
margin-right: 6px;
font-size: 14px;
display: inline-flex;
align-items: center;
}
.wp-action-buttons {
margin-top: 12px;
display: flex;
gap: 8px;
justify-content: center;
}
.wp-action-buttons .wp-action-btn {
min-width: 110px;
flex: 0 1 auto;
}
.btn-outline-primary {
color: #0073aa;
border-color: #0073aa;
}
.btn-outline-primary:hover {
background-color: #0073aa;
color: white;
}
.btn-outline-secondary {
color: #50575e;
border-color: #50575e;
}
.btn-outline-secondary:hover {
background-color: #50575e;
color: white;
}
.btn-outline-danger {
color: #dc3545;
border-color: #dc3545;
}
.btn-outline-danger:hover {
background-color: #dc3545;
color: white;
}
.loading-state {
text-align: center;
padding: 30px;
background: #f8f9fa;
border-radius: 8px;
margin: 20px 0;
}
.loading-spinner {
margin-bottom: 15px;
color: #0073aa;
}
.loading-text {
color: #646970;
font-size: 14px;
font-weight: 500;
}
</style>
<style>
.wp-site-item {
border: 1px solid #e0e0e0;
margin-bottom: 20px;
border-radius: 8px;
background: white;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.wp-site-header {
padding: 15px 20px;
border-bottom: 1px solid #e0e0e0;
background: #f8f9fa;
border-radius: 8px 8px 0 0;
}
.wp-site-header h4 {
margin: 0;
font-size: 18px;
line-height: 34px;
color: #2c3338;
font-weight: 500;
}
.wp-site-content {
padding: 20px;
}
.info-box {
margin-bottom: 15px;
background: #f8f9fa;
padding: 10px;
border-radius: 6px;
}
.info-box label {
display: block;
font-size: 12px;
color: #646970;
margin-bottom: 5px;
font-weight: 500;
}
.info-box span {
font-size: 14px;
font-weight: 600;
color: #2c3338;
}
.checkbox {
margin-bottom: 10px;
}
.mt-3 {
margin-top: 1rem;
}
/* Updated button styles */
.wp-action-btn {
margin: 0 4px;
padding: 6px 12px;
font-size: 13px;
font-weight: 500;
transition: all 0.2s ease;
border-width: 1.5px;
line-height: 1.5;
display: inline-flex;
align-items: center;
justify-content: center;
vertical-align: middle;
height: 32px;
}
.wp-action-btn i {
margin-right: 6px;
font-size: 14px;
display: inline-flex;
align-items: center;
}
.wp-action-buttons {
margin-top: 12px;
display: flex;
gap: 8px;
justify-content: center;
}
.wp-action-buttons .wp-action-btn {
min-width: 110px;
flex: 0 1 auto;
}
.btn-outline-primary {
color: #0073aa;
border-color: #0073aa;
}
.btn-outline-primary:hover {
background-color: #0073aa;
color: white;
}
.btn-outline-secondary {
color: #50575e;
border-color: #50575e;
}
.btn-outline-secondary:hover {
background-color: #50575e;
color: white;
}
.btn-outline-danger {
color: #dc3545;
border-color: #dc3545;
}
.btn-outline-danger:hover {
background-color: #dc3545;
color: white;
}
</style>
<div id="listFail" class="alert alert-danger">
<p>{% trans "Cannot list websites. Error message:" %} {$ errorMessage $}</p>
<div id="listFail" class="alert alert-danger">
<p>{% trans "Cannot list websites. Error message:" %} {$ errorMessage $}</p>
</div>
</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 style="margin-top: 2%" class="row">
<div class="col-md-12">
<div class="row">
<div class="col-md-9">
</div>
</div>
</div> <!-- end row -->
<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>
</div>
</div>