diff --git a/deploy-createuser-fix.sh b/deploy-createuser-fix.sh new file mode 100755 index 000000000..a4bcc4fe7 --- /dev/null +++ b/deploy-createuser-fix.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Deploy Create User page fix (userCreationFailed / "Unknown error" on load) +# Run this on the CyberPanel server (e.g. after pulling repo or copying fixed files) +# Usage: sudo bash deploy-createuser-fix.sh + +set -e + +CYBERCP_ROOT="${CYBERCP_ROOT:-/usr/local/CyberCP}" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PYTHON="${CYBERCP_ROOT}/bin/python" +if [ ! -x "$PYTHON" ]; then + PYTHON="python3" +fi + +echo "[$(date +%Y-%m-%d\ %H:%M:%S)] Deploying Create User fix..." + +# If running from repo (this workspace), copy fixed JS into CyberCP +if [ -f "$SCRIPT_DIR/userManagment/static/userManagment/userManagment.js" ]; then + echo " Copying userManagment.js from repo app static..." + mkdir -p "$CYBERCP_ROOT/userManagment/static/userManagment" + cp -f "$SCRIPT_DIR/userManagment/static/userManagment/userManagment.js" \ + "$CYBERCP_ROOT/userManagment/static/userManagment/userManagment.js" +fi +if [ -f "$SCRIPT_DIR/static/userManagment/userManagment.js" ]; then + echo " Copying userManagment.js from repo static..." + mkdir -p "$CYBERCP_ROOT/static/userManagment" + cp -f "$SCRIPT_DIR/static/userManagment/userManagment.js" \ + "$CYBERCP_ROOT/static/userManagment/userManagment.js" +fi +if [ -f "$SCRIPT_DIR/public/static/userManagment/userManagment.js" ]; then + echo " Copying userManagment.js from repo public/static..." + mkdir -p "$CYBERCP_ROOT/public/static/userManagment" + cp -f "$SCRIPT_DIR/public/static/userManagment/userManagment.js" \ + "$CYBERCP_ROOT/public/static/userManagment/userManagment.js" +fi + +# Run collectstatic so served static gets the fix +if [ -f "$CYBERCP_ROOT/manage.py" ]; then + echo " Running collectstatic..." + cd "$CYBERCP_ROOT" + "$PYTHON" manage.py collectstatic --noinput --clear 2>&1 | tail -5 + echo " collectstatic done." +else + echo " No $CYBERCP_ROOT/manage.py found; skipping collectstatic." +fi + +echo "[$(date +%Y-%m-%d\ %H:%M:%S)] Create User fix deployed. Hard-refresh browser (Ctrl+F5) on the Create User page." diff --git a/public/static/userManagment/userManagment.js b/public/static/userManagment/userManagment.js index f706d487f..0f0b677af 100644 --- a/public/static/userManagment/userManagment.js +++ b/public/static/userManagment/userManagment.js @@ -9,7 +9,7 @@ app.controller('createUserCtr', function ($scope, $http) { $scope.acctsLimit = true; $scope.webLimits = true; $scope.userCreated = true; - $scope.userCreationFailed = true; + $scope.userCreationFailed = false; // false = don't show error alert on load $scope.couldNotConnect = true; $scope.userCreationLoading = true; $scope.combinedLength = true; @@ -18,7 +18,7 @@ app.controller('createUserCtr', function ($scope, $http) { $scope.webLimits = false; $scope.userCreated = true; - $scope.userCreationFailed = true; + $scope.userCreationFailed = false; // hide error until we know the result $scope.couldNotConnect = true; $scope.userCreationLoading = false; $scope.combinedLength = true; @@ -61,7 +61,7 @@ app.controller('createUserCtr', function ($scope, $http) { if (response.data.createStatus == 1) { $scope.userCreated = false; - $scope.userCreationFailed = true; + $scope.userCreationFailed = false; // hide error on success $scope.couldNotConnect = true; $scope.userCreationLoading = true; @@ -73,11 +73,11 @@ app.controller('createUserCtr', function ($scope, $http) { $scope.acctsLimit = false; $scope.webLimits = false; $scope.userCreated = true; - $scope.userCreationFailed = false; + $scope.userCreationFailed = true; // show error on failure $scope.couldNotConnect = true; $scope.userCreationLoading = true; - $scope.errorMessage = response.data.error_message; + $scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error'; } @@ -90,7 +90,7 @@ app.controller('createUserCtr', function ($scope, $http) { $scope.acctsLimit = false; $scope.webLimits = false; $scope.userCreated = true; - $scope.userCreationFailed = true; + $scope.userCreationFailed = false; // show "Could not connect" instead $scope.couldNotConnect = false; $scope.userCreationLoading = true; @@ -138,10 +138,10 @@ app.controller('modifyUser', function ($scope, $http) { $scope.acctDetailsFetched = true; $scope.userAccountsLimit = true; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // false = don't show error alert on load $scope.couldNotConnect = true; - $scope.canotFetchDetails = true; - $scope.detailsFetched = true; + $scope.canotFetchDetails = false; // false = don't show fetch error on load + $scope.detailsFetched = false; // false = don't show "details loaded" on load $scope.accountTypeView = true; $scope.websitesLimit = true; $scope.qrHidden = true; @@ -200,9 +200,9 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (we only fetched details) $scope.couldNotConnect = true; - $scope.canotFetchDetails = true; + $scope.canotFetchDetails = false; // hide fetch error on success $scope.detailsFetched = false; $scope.userAccountsLimit = true; $scope.websitesLimit = true; @@ -212,13 +212,13 @@ app.controller('modifyUser', function ($scope, $http) { $scope.acctDetailsFetched = true; $scope.userAccountsLimit = true; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (only fetch failed) $scope.couldNotConnect = true; - $scope.canotFetchDetails = false; - $scope.detailsFetched = true; + $scope.canotFetchDetails = true; // show fetch error + $scope.detailsFetched = false; - $scope.errorMessage = response.data.error_message; + $scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error'; } @@ -232,7 +232,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.acctDetailsFetched = true; $scope.userAccountsLimit = true; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (only connection/fetch failed) $scope.couldNotConnect = false; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -249,7 +249,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = false; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide error until we know result $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -295,7 +295,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = true; $scope.userModified = false; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error on success $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -312,13 +312,13 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = false; + $scope.canotModifyUser = true; // show modify error $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; - $scope.errorMessage = response.data.error_message; + $scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error'; } @@ -1489,6 +1489,42 @@ app.controller('apiAccessCTRL', function ($scope, $http) { /* Java script code to list table users */ +/* Show modal by id - works with Bootstrap 3 (jQuery) or Bootstrap 5 (native) */ +function showModalById(modalId) { + var el = document.getElementById(modalId); + if (!el) return; + if (typeof jQuery !== 'undefined' && jQuery(el).modal) { + jQuery(el).modal('show'); + } else if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { + var m = bootstrap.Modal.getOrCreateInstance(el); + if (m) m.show(); + } else { + el.style.display = 'block'; + el.classList.add('in'); + if (el.getAttribute('aria-hidden') !== null) el.setAttribute('aria-hidden', 'false'); + var backdrop = document.createElement('div'); + backdrop.className = 'modal-backdrop fade in'; + backdrop.setAttribute('data-modal-backdrop', modalId); + document.body.appendChild(backdrop); + } +} + +function hideModalById(modalId) { + var el = document.getElementById(modalId); + if (!el) return; + if (typeof jQuery !== 'undefined' && jQuery(el).modal) { + jQuery(el).modal('hide'); + } else if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { + var m = bootstrap.Modal.getInstance(el); + if (m) m.hide(); + } else { + el.style.display = 'none'; + el.classList.remove('in'); + if (el.getAttribute('aria-hidden') !== null) el.setAttribute('aria-hidden', 'true'); + var backdrops = document.querySelectorAll('[data-modal-backdrop="' + modalId + '"]'); + backdrops.forEach(function (b) { if (b.parentNode) b.parentNode.removeChild(b); }); + } +} app.controller('listTableUsers', function ($scope, $http) { @@ -1552,6 +1588,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.deleteUserInitial = function (name){ UserToDelete = name; $scope.UserToDelete = name; + showModalById('deleteModal'); }; $scope.deleteUserFinal = function () { @@ -1576,6 +1613,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.cyberpanelLoading = true; if (response.data.deleteStatus === 1) { $scope.populateCurrentRecords(); + hideModalById('deleteModal'); new PNotify({ title: 'Success!', text: 'Users successfully deleted!', @@ -1613,6 +1651,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.editInitial = function (name) { $scope.name = name; + showModalById('editModal'); }; @@ -1640,6 +1679,7 @@ app.controller('listTableUsers', function ($scope, $http) { if (response.data.status === 1) { $scope.populateCurrentRecords(); + hideModalById('editModal'); new PNotify({ title: 'Success!', text: 'Changes successfully applied!', @@ -1693,6 +1733,7 @@ app.controller('listTableUsers', function ($scope, $http) { if (response.data.status === 1) { $scope.populateCurrentRecords(); + hideModalById('editModal'); new PNotify({ title: 'Success!', text: 'ACL Successfully changed.', diff --git a/static/userManagment/userManagment.js b/static/userManagment/userManagment.js index fdf0e7878..071dcec34 100644 --- a/static/userManagment/userManagment.js +++ b/static/userManagment/userManagment.js @@ -2,14 +2,65 @@ * Created by usman on 8/5/17. */ +/* Safe notification - use PNotify if available, else fallback to alert */ +function safePNotify(opts) { + if (typeof PNotify !== 'undefined') { + new PNotify(opts); + } else { + var msg = (opts.title || '') + (opts.text ? ': ' + opts.text : ''); + alert(msg || JSON.stringify(opts)); + } +} /* Java script code to create account */ app.controller('createUserCtr', function ($scope, $http) { + // Home directory functionality + $scope.homeDirectories = []; + $scope.selectedHomeDirectory = ''; + $scope.selectedHomeDirectoryInfo = null; + + // Load home directories on page load + $scope.loadHomeDirectories = function() { + var url = '/users/getUserHomeDirectories'; + var config = { + headers: { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + $http.post(url, {}, config) + .then(function(response) { + if (response.data && response.data.status === 1) { + $scope.homeDirectories = response.data.directories || []; + } else { + console.error('Error loading home directories:', response.data); + $scope.homeDirectories = []; + } + }) + .catch(function(error) { + console.error('Error loading home directories:', error); + $scope.homeDirectories = []; + }); + }; + + // Update home directory info when selection changes + $scope.updateHomeDirectoryInfo = function() { + if ($scope.selectedHomeDirectory) { + $scope.selectedHomeDirectoryInfo = $scope.homeDirectories.find(function(dir) { + return dir.id == $scope.selectedHomeDirectory; + }); + } else { + $scope.selectedHomeDirectoryInfo = null; + } + }; + + // Initialize home directories + $scope.loadHomeDirectories(); + $scope.acctsLimit = true; $scope.webLimits = true; $scope.userCreated = true; - $scope.userCreationFailed = true; + $scope.userCreationFailed = false; // false = don't show error alert on load $scope.couldNotConnect = true; $scope.userCreationLoading = true; $scope.combinedLength = true; @@ -18,20 +69,24 @@ app.controller('createUserCtr', function ($scope, $http) { $scope.webLimits = false; $scope.userCreated = true; - $scope.userCreationFailed = true; + $scope.userCreationFailed = false; // hide error until we know the result $scope.couldNotConnect = true; $scope.userCreationLoading = false; $scope.combinedLength = true; - - var firstName = $scope.firstName; - var lastName = $scope.lastName; + var firstName = $scope.firstName || ''; + var lastName = $scope.lastName || ''; var email = $scope.email; var selectedACL = $scope.selectedACL; var websitesLimits = $scope.websitesLimits; var userName = $scope.userName; var password = $scope.password; + if (firstName.length + lastName.length > 20) { + $scope.combinedLength = false; + $scope.userCreationLoading = true; + return; + } var url = "/users/submitUserCreation"; @@ -43,12 +98,14 @@ app.controller('createUserCtr', function ($scope, $http) { websitesLimit: websitesLimits, userName: userName, password: password, - securityLevel: $scope.securityLevel + securityLevel: $scope.securityLevel, + selectedHomeDirectory: $scope.selectedHomeDirectory || '' }; var config = { headers: { - 'X-CSRFToken': getCookie('csrftoken') + 'X-CSRFToken': getCookie('csrftoken'), + 'Content-Type': 'application/json' } }; @@ -59,42 +116,31 @@ app.controller('createUserCtr', function ($scope, $http) { if (response.data.createStatus == 1) { - - $scope.userCreated = false; - $scope.userCreationFailed = true; + $scope.userCreated = false; // show success + $scope.userCreationFailed = false; // hide error $scope.couldNotConnect = true; $scope.userCreationLoading = true; - $scope.userName = userName; - - } else { - $scope.acctsLimit = false; $scope.webLimits = false; $scope.userCreated = true; - $scope.userCreationFailed = false; + $scope.userCreationFailed = true; // true = show error alert $scope.couldNotConnect = true; $scope.userCreationLoading = true; - - $scope.errorMessage = response.data.error_message; - - + $scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error'; } } function cantLoadInitialDatas(response) { - $scope.acctsLimit = false; $scope.webLimits = false; $scope.userCreated = true; - $scope.userCreationFailed = true; - $scope.couldNotConnect = false; + $scope.userCreationFailed = false; // hide server error, show connection error instead + $scope.couldNotConnect = false; // show "Could not connect" message $scope.userCreationLoading = true; - - } @@ -138,10 +184,10 @@ app.controller('modifyUser', function ($scope, $http) { $scope.acctDetailsFetched = true; $scope.userAccountsLimit = true; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // false = don't show error alert on load $scope.couldNotConnect = true; - $scope.canotFetchDetails = true; - $scope.detailsFetched = true; + $scope.canotFetchDetails = false; // false = don't show fetch error on load + $scope.detailsFetched = false; // false = don't show "details loaded" on load $scope.accountTypeView = true; $scope.websitesLimit = true; $scope.qrHidden = true; @@ -401,9 +447,9 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (we only fetched details) $scope.couldNotConnect = true; - $scope.canotFetchDetails = true; + $scope.canotFetchDetails = false; // hide fetch error on success $scope.detailsFetched = false; $scope.userAccountsLimit = true; $scope.websitesLimit = true; @@ -413,13 +459,13 @@ app.controller('modifyUser', function ($scope, $http) { $scope.acctDetailsFetched = true; $scope.userAccountsLimit = true; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (only fetch failed) $scope.couldNotConnect = true; - $scope.canotFetchDetails = false; - $scope.detailsFetched = true; + $scope.canotFetchDetails = true; // show fetch error on failure + $scope.detailsFetched = false; - $scope.errorMessage = response.data.error_message; + $scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error'; } @@ -433,7 +479,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.acctDetailsFetched = true; $scope.userAccountsLimit = true; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (only connection/fetch failed) $scope.couldNotConnect = false; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -450,7 +496,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = false; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error until we know result $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -506,7 +552,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = true; $scope.userModified = false; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error on success $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -523,13 +569,13 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = false; + $scope.canotModifyUser = true; // show modify error on failure $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; - $scope.errorMessage = response.data.error_message; + $scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error'; } @@ -673,7 +719,7 @@ app.controller('deleteUser', function ($scope, $http) { app.controller('createACLCTRL', function ($scope, $http) { $scope.aclCreated = true; - $scope.aclCreationFailed = true; + $scope.aclCreationFailed = false; // false = don't show error alert on load $scope.couldNotConnect = true; $scope.aclLoading = true; @@ -844,14 +890,14 @@ app.controller('createACLCTRL', function ($scope, $http) { $scope.aclLoading = true; if (response.data.status === 1) { - new PNotify({ + safePNotify({ title: 'Success!', text: 'ACL Successfully created.', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.errorMessage, type: 'error' @@ -866,7 +912,7 @@ app.controller('createACLCTRL', function ($scope, $http) { $scope.aclLoading = false; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1065,14 +1111,14 @@ app.controller('deleteACTCTRL', function ($scope, $http) { $scope.aclLoading = true; if (response.data.status === 1) { - new PNotify({ + safePNotify({ title: 'Success!', text: 'ACL Successfully deleted.', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.errorMessage, type: 'error' @@ -1084,7 +1130,7 @@ app.controller('deleteACTCTRL', function ($scope, $http) { function cantLoadInitialDatas(response) { $scope.aclLoading = true; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1128,7 +1174,7 @@ app.controller('modifyACLCtrl', function ($scope, $http) { if (response.data.status === 1) { - new PNotify({ + safePNotify({ title: 'Success!', text: 'Current settings successfully fetched', type: 'success' @@ -1208,7 +1254,7 @@ app.controller('modifyACLCtrl', function ($scope, $http) { $scope.mailServerSSL = Boolean(response.data.mailServerSSL); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.errorMessage, type: 'error' @@ -1221,7 +1267,7 @@ app.controller('modifyACLCtrl', function ($scope, $http) { $scope.aclLoading = false; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1323,14 +1369,14 @@ app.controller('modifyACLCtrl', function ($scope, $http) { $scope.aclLoading = true; if (response.data.status === 1) { - new PNotify({ + safePNotify({ title: 'Success!', text: 'ACL Successfully modified.', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.errorMessage, type: 'error' @@ -1345,7 +1391,7 @@ app.controller('modifyACLCtrl', function ($scope, $http) { $scope.aclLoading = false; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1537,14 +1583,14 @@ app.controller('changeUserACLCTRL', function ($scope, $http) { $scope.aclLoading = true; if (response.data.status === 1) { - new PNotify({ + safePNotify({ title: 'Success!', text: 'ACL Successfully changed.', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.errorMessage, type: 'error' @@ -1556,7 +1602,7 @@ app.controller('changeUserACLCTRL', function ($scope, $http) { function cantLoadInitialDatas(response) { $scope.aclLoading = true; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1599,14 +1645,14 @@ app.controller('resellerCenterCTRL', function ($scope, $http) { $scope.aclLoading = true; if (response.data.status === 1) { - new PNotify({ + safePNotify({ title: 'Success!', text: 'Changes successfully applied!', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.errorMessage, type: 'error' @@ -1618,7 +1664,7 @@ app.controller('resellerCenterCTRL', function ($scope, $http) { function cantLoadInitialDatas(response) { $scope.aclLoading = true; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1668,14 +1714,14 @@ app.controller('apiAccessCTRL', function ($scope, $http) { if (response.data.status === 1) { $scope.apiAccessDropDown = true; - new PNotify({ + safePNotify({ title: 'Success!', text: 'Changes successfully applied!', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.error_message, type: 'error' @@ -1687,7 +1733,7 @@ app.controller('apiAccessCTRL', function ($scope, $http) { function cantLoadInitialDatas(response) { $scope.cyberpanelLoading = true; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1728,13 +1774,13 @@ app.controller('apiUsersCTRL', function ($scope, $http) { $scope.apiUsers = response.data.users; $scope.filteredUsers = response.data.users; - new PNotify({ + safePNotify({ title: 'Success!', text: 'API users loaded successfully', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.error_message, type: 'error' @@ -1744,7 +1790,7 @@ app.controller('apiUsersCTRL', function ($scope, $http) { function loadAPIUsersError(response) { $scope.apiUsersLoading = true; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not load API users. Please refresh the page.', type: 'error' @@ -1773,7 +1819,7 @@ app.controller('apiUsersCTRL', function ($scope, $http) { }; $scope.viewUserDetails = function(user) { - new PNotify({ + safePNotify({ title: 'User Details', text: 'Username: ' + user.userName + '
' + 'Full Name: ' + user.firstName + ' ' + user.lastName + '
' + @@ -1816,13 +1862,13 @@ app.controller('apiUsersCTRL', function ($scope, $http) { }); $scope.filteredUsers = $scope.apiUsers; - new PNotify({ + safePNotify({ title: 'Success!', text: 'API access disabled for ' + response.data.accountUsername, type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.error_message, type: 'error' @@ -1832,7 +1878,7 @@ app.controller('apiUsersCTRL', function ($scope, $http) { function disableAPIError(response) { $scope.apiUsersLoading = true; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not disable API access. Please try again.', type: 'error' @@ -1845,6 +1891,42 @@ app.controller('apiUsersCTRL', function ($scope, $http) { /* Java script code to list table users */ +/* Show modal by id - works with Bootstrap 3 (jQuery) or Bootstrap 5 (native) */ +function showModalById(modalId) { + var el = document.getElementById(modalId); + if (!el) return; + if (typeof jQuery !== 'undefined' && jQuery(el).modal) { + jQuery(el).modal('show'); + } else if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { + var m = bootstrap.Modal.getOrCreateInstance(el); + if (m) m.show(); + } else { + el.style.display = 'block'; + el.classList.add('in'); + if (el.getAttribute('aria-hidden') !== null) el.setAttribute('aria-hidden', 'false'); + var backdrop = document.createElement('div'); + backdrop.className = 'modal-backdrop fade in'; + backdrop.setAttribute('data-modal-backdrop', modalId); + document.body.appendChild(backdrop); + } +} + +function hideModalById(modalId) { + var el = document.getElementById(modalId); + if (!el) return; + if (typeof jQuery !== 'undefined' && jQuery(el).modal) { + jQuery(el).modal('hide'); + } else if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { + var m = bootstrap.Modal.getInstance(el); + if (m) m.hide(); + } else { + el.style.display = 'none'; + el.classList.remove('in'); + if (el.getAttribute('aria-hidden') !== null) el.setAttribute('aria-hidden', 'true'); + var backdrops = document.querySelectorAll('[data-modal-backdrop="' + modalId + '"]'); + backdrops.forEach(function (b) { if (b.parentNode) b.parentNode.removeChild(b); }); + } +} app.controller('listTableUsers', function ($scope, $http) { @@ -1876,14 +1958,14 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.records = JSON.parse(response.data.data); - new PNotify({ + safePNotify({ title: 'Success!', text: 'Users successfully fetched!', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.error_message, type: 'error' @@ -1894,7 +1976,7 @@ app.controller('listTableUsers', function ($scope, $http) { function cantLoadInitialDatas(response) { $scope.cyberpanelLoading = true; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1908,7 +1990,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.deleteUserInitial = function (name){ UserToDelete = name; $scope.UserToDelete = name; - $('#deleteModal').modal('show'); + showModalById('deleteModal'); }; $scope.deleteUserFinal = function () { @@ -1933,8 +2015,8 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.cyberpanelLoading = true; if (response.data.deleteStatus === 1) { $scope.populateCurrentRecords(); - $('#deleteModal').modal('hide'); - new PNotify({ + hideModalById('deleteModal'); + safePNotify({ title: 'Success!', text: 'Users successfully deleted!', type: 'success' @@ -1942,7 +2024,7 @@ app.controller('listTableUsers', function ($scope, $http) { } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.error_message, type: 'error' @@ -1956,7 +2038,7 @@ app.controller('listTableUsers', function ($scope, $http) { function cantLoadInitialDatas(response) { $scope.cyberpanelLoading = false; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -1970,7 +2052,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.editInitial = function (name) { $scope.name = name; - $('#editModal').modal('show'); + showModalById('editModal'); }; $scope.saveResellerChanges = function () { @@ -1997,15 +2079,15 @@ app.controller('listTableUsers', function ($scope, $http) { if (response.data.status === 1) { $scope.populateCurrentRecords(); - $('#editModal').modal('hide'); - new PNotify({ + hideModalById('editModal'); + safePNotify({ title: 'Success!', text: 'Changes successfully applied!', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.errorMessage, type: 'error' @@ -2016,7 +2098,7 @@ app.controller('listTableUsers', function ($scope, $http) { } function cantLoadInitialDatas(response) { - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -2051,15 +2133,15 @@ app.controller('listTableUsers', function ($scope, $http) { if (response.data.status === 1) { $scope.populateCurrentRecords(); - $('#editModal').modal('hide'); - new PNotify({ + hideModalById('editModal'); + safePNotify({ title: 'Success!', text: 'ACL Successfully changed.', type: 'success' }); } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.errorMessage, type: 'error' @@ -2071,7 +2153,7 @@ app.controller('listTableUsers', function ($scope, $http) { function cantLoadInitialDatas(response) { $scope.aclLoading = true; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' @@ -2105,7 +2187,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.cyberpanelLoading = true; if (response.data.status === 1) { $scope.populateCurrentRecords(); - new PNotify({ + safePNotify({ title: 'Success!', text: 'Action successfully started.', type: 'success' @@ -2113,7 +2195,7 @@ app.controller('listTableUsers', function ($scope, $http) { } else { - new PNotify({ + safePNotify({ title: 'Error!', text: response.data.error_message, type: 'error' @@ -2127,7 +2209,7 @@ app.controller('listTableUsers', function ($scope, $http) { function cantLoadInitialDatas(response) { $scope.cyberpanelLoading = false; - new PNotify({ + safePNotify({ title: 'Error!', text: 'Could not connect to server, please refresh this page.', type: 'error' diff --git a/userManagment/static/userManagment/userManagment.js b/userManagment/static/userManagment/userManagment.js index dedfd2a14..071dcec34 100644 --- a/userManagment/static/userManagment/userManagment.js +++ b/userManagment/static/userManagment/userManagment.js @@ -447,9 +447,9 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (we only fetched details) $scope.couldNotConnect = true; - $scope.canotFetchDetails = true; + $scope.canotFetchDetails = false; // hide fetch error on success $scope.detailsFetched = false; $scope.userAccountsLimit = true; $scope.websitesLimit = true; @@ -459,13 +459,13 @@ app.controller('modifyUser', function ($scope, $http) { $scope.acctDetailsFetched = true; $scope.userAccountsLimit = true; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (only fetch failed) $scope.couldNotConnect = true; - $scope.canotFetchDetails = false; - $scope.detailsFetched = true; + $scope.canotFetchDetails = true; // show fetch error on failure + $scope.detailsFetched = false; - $scope.errorMessage = response.data.error_message; + $scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error'; } @@ -479,7 +479,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.acctDetailsFetched = true; $scope.userAccountsLimit = true; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error (only connection/fetch failed) $scope.couldNotConnect = false; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -496,7 +496,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = false; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error until we know result $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -552,7 +552,7 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = true; $scope.userModified = false; - $scope.canotModifyUser = true; + $scope.canotModifyUser = false; // hide modify error on success $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; @@ -569,13 +569,13 @@ app.controller('modifyUser', function ($scope, $http) { $scope.userModificationLoading = true; $scope.acctDetailsFetched = false; $scope.userModified = true; - $scope.canotModifyUser = false; + $scope.canotModifyUser = true; // show modify error on failure $scope.couldNotConnect = true; $scope.canotFetchDetails = true; $scope.detailsFetched = true; - $scope.errorMessage = response.data.error_message; + $scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error'; } @@ -1891,6 +1891,42 @@ app.controller('apiUsersCTRL', function ($scope, $http) { /* Java script code to list table users */ +/* Show modal by id - works with Bootstrap 3 (jQuery) or Bootstrap 5 (native) */ +function showModalById(modalId) { + var el = document.getElementById(modalId); + if (!el) return; + if (typeof jQuery !== 'undefined' && jQuery(el).modal) { + jQuery(el).modal('show'); + } else if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { + var m = bootstrap.Modal.getOrCreateInstance(el); + if (m) m.show(); + } else { + el.style.display = 'block'; + el.classList.add('in'); + if (el.getAttribute('aria-hidden') !== null) el.setAttribute('aria-hidden', 'false'); + var backdrop = document.createElement('div'); + backdrop.className = 'modal-backdrop fade in'; + backdrop.setAttribute('data-modal-backdrop', modalId); + document.body.appendChild(backdrop); + } +} + +function hideModalById(modalId) { + var el = document.getElementById(modalId); + if (!el) return; + if (typeof jQuery !== 'undefined' && jQuery(el).modal) { + jQuery(el).modal('hide'); + } else if (typeof bootstrap !== 'undefined' && bootstrap.Modal) { + var m = bootstrap.Modal.getInstance(el); + if (m) m.hide(); + } else { + el.style.display = 'none'; + el.classList.remove('in'); + if (el.getAttribute('aria-hidden') !== null) el.setAttribute('aria-hidden', 'true'); + var backdrops = document.querySelectorAll('[data-modal-backdrop="' + modalId + '"]'); + backdrops.forEach(function (b) { if (b.parentNode) b.parentNode.removeChild(b); }); + } +} app.controller('listTableUsers', function ($scope, $http) { @@ -1954,7 +1990,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.deleteUserInitial = function (name){ UserToDelete = name; $scope.UserToDelete = name; - $('#deleteModal').modal('show'); + showModalById('deleteModal'); }; $scope.deleteUserFinal = function () { @@ -1979,7 +2015,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.cyberpanelLoading = true; if (response.data.deleteStatus === 1) { $scope.populateCurrentRecords(); - $('#deleteModal').modal('hide'); + hideModalById('deleteModal'); safePNotify({ title: 'Success!', text: 'Users successfully deleted!', @@ -2016,7 +2052,7 @@ app.controller('listTableUsers', function ($scope, $http) { $scope.editInitial = function (name) { $scope.name = name; - $('#editModal').modal('show'); + showModalById('editModal'); }; $scope.saveResellerChanges = function () { @@ -2043,7 +2079,7 @@ app.controller('listTableUsers', function ($scope, $http) { if (response.data.status === 1) { $scope.populateCurrentRecords(); - $('#editModal').modal('hide'); + hideModalById('editModal'); safePNotify({ title: 'Success!', text: 'Changes successfully applied!', @@ -2097,7 +2133,7 @@ app.controller('listTableUsers', function ($scope, $http) { if (response.data.status === 1) { $scope.populateCurrentRecords(); - $('#editModal').modal('hide'); + hideModalById('editModal'); safePNotify({ title: 'Success!', text: 'ACL Successfully changed.', diff --git a/userManagment/templates/userManagment/listUsers.html b/userManagment/templates/userManagment/listUsers.html index 8443ab182..5d6579264 100644 --- a/userManagment/templates/userManagment/listUsers.html +++ b/userManagment/templates/userManagment/listUsers.html @@ -330,28 +330,28 @@ - - {% trans "Suspend" %} - - - {% trans "Activate" %} - - - {% trans "Edit" %} - - - {% trans "Delete" %} - + + + +