Phase A — HTML removed from PHP files: - RateLimitMiddleware.php: heredoc moved to views/errors/429.php - public/index.php: inline HTML replaced with View::error() - AuthMiddleware.php: <script> redirect replaced with <meta refresh> Phase B — Inline CSS/JS extracted from views: - CSS: landing.css (459 lines), legal.css (shared by terms+privacy) - JS: 17 new files extracted from ~20 view files - main.js (layout sidebar + notifications) - dashboard-chart.js, server-show.js, server-services.js - nginx-manager.js, database-manager.js - terminal.js, team-show.js, team-index.js - server-list.js, server-permissions.js (shared by edit+create) - server-ssl.js, server-processes.js, system-users.js - admin-users.js, audit-log.js, admin-notifications.js, admin-security.js - notifications.js Total: -3264 lines from views, +288 lines in new assets
188 lines
5.9 KiB
JavaScript
188 lines
5.9 KiB
JavaScript
function getCsrfToken() {
|
|
return document.querySelector('meta[name="csrf-token"]')?.content || '';
|
|
}
|
|
|
|
function editTeam() {
|
|
const name = prompt('Team name:', teamName);
|
|
if (!name) return;
|
|
const desc = prompt('Description:', teamDescription);
|
|
|
|
const form = new FormData();
|
|
form.append('name', name);
|
|
form.append('description', desc || '');
|
|
form.append('_csrf_token', getCsrfToken());
|
|
|
|
fetch('/teams/' + teamId + '/update', {
|
|
method: 'POST',
|
|
headers: { 'X-CSRF-Token': getCsrfToken() },
|
|
body: form,
|
|
})
|
|
.then(r => r.json())
|
|
.then(res => {
|
|
if (res.success) { showToast('success', res.message); location.reload(); }
|
|
else { showToast('error', res.message); }
|
|
});
|
|
}
|
|
|
|
function deleteTeam() {
|
|
if (!confirm('Delete this team? Members will lose access to assigned servers.')) return;
|
|
document.getElementById('postForm').action = '/teams/' + teamId + '/delete';
|
|
document.getElementById('postForm').submit();
|
|
}
|
|
|
|
let searchTimeout = null;
|
|
let selectedUserId = null;
|
|
|
|
document.getElementById('addUserInput').addEventListener('input', function() {
|
|
clearTimeout(searchTimeout);
|
|
const q = this.value.trim();
|
|
selectedUserId = null;
|
|
|
|
if (q.length < 2) {
|
|
document.getElementById('userDropdown').classList.remove('active');
|
|
return;
|
|
}
|
|
|
|
searchTimeout = setTimeout(function() {
|
|
fetch('/teams/search-users?q=' + encodeURIComponent(q), {
|
|
headers: { 'X-CSRF-Token': getCsrfToken() }
|
|
})
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
const dropdown = document.getElementById('userDropdown');
|
|
dropdown.innerHTML = '';
|
|
if (data.users && data.users.length > 0) {
|
|
data.users.forEach(function(u) {
|
|
const item = document.createElement('div');
|
|
item.className = 'autocomplete-item';
|
|
item.innerHTML = '<strong>' + escapeHtml(u.username) + '</strong> <small>' + escapeHtml(u.email) + '</small>';
|
|
item.dataset.id = u.id;
|
|
item.dataset.username = u.username;
|
|
item.addEventListener('click', function() {
|
|
selectUser(u.id, u.username);
|
|
});
|
|
dropdown.appendChild(item);
|
|
});
|
|
dropdown.classList.add('active');
|
|
} else {
|
|
dropdown.innerHTML = '<div class="autocomplete-empty">No users found</div>';
|
|
dropdown.classList.add('active');
|
|
}
|
|
})
|
|
.catch(function() {
|
|
document.getElementById('userDropdown').classList.remove('active');
|
|
});
|
|
}, 300);
|
|
});
|
|
|
|
document.addEventListener('click', function(e) {
|
|
if (!e.target.closest('.autocomplete')) {
|
|
document.getElementById('userDropdown').classList.remove('active');
|
|
}
|
|
});
|
|
|
|
function selectUser(id, username) {
|
|
selectedUserId = id;
|
|
document.getElementById('addUserInput').value = username;
|
|
document.getElementById('userDropdown').classList.remove('active');
|
|
|
|
const form = new FormData();
|
|
form.append('user_id', id);
|
|
form.append('_csrf_token', getCsrfToken());
|
|
|
|
fetch('/teams/' + teamId + '/add-user', {
|
|
method: 'POST',
|
|
headers: { 'X-CSRF-Token': getCsrfToken() },
|
|
body: form,
|
|
})
|
|
.then(r => r.json())
|
|
.then(res => {
|
|
if (res.success) {
|
|
showToast('success', username + ' added to team');
|
|
location.reload();
|
|
} else {
|
|
showToast('error', res.message);
|
|
document.getElementById('addUserInput').value = '';
|
|
}
|
|
});
|
|
}
|
|
|
|
function removeMember(userId, username) {
|
|
if (!confirm('Remove "' + username + '" from this team?')) return;
|
|
|
|
const form = new FormData();
|
|
form.append('user_id', userId);
|
|
form.append('_csrf_token', getCsrfToken());
|
|
|
|
fetch('/teams/' + teamId + '/remove-user', {
|
|
method: 'POST',
|
|
headers: { 'X-CSRF-Token': getCsrfToken() },
|
|
body: form,
|
|
})
|
|
.then(r => r.json())
|
|
.then(res => {
|
|
if (res.success) { showToast('success', res.message); location.reload(); }
|
|
else { showToast('error', res.message); }
|
|
});
|
|
}
|
|
|
|
function addServer(e) {
|
|
e.preventDefault();
|
|
const serverId = document.getElementById('addServerId').value;
|
|
const role = document.getElementById('addServerRole').value;
|
|
if (!serverId) return;
|
|
|
|
const form = new FormData();
|
|
form.append('server_id', serverId);
|
|
form.append('role', role);
|
|
form.append('_csrf_token', getCsrfToken());
|
|
|
|
fetch('/teams/' + teamId + '/add-server', {
|
|
method: 'POST',
|
|
headers: { 'X-CSRF-Token': getCsrfToken() },
|
|
body: form,
|
|
})
|
|
.then(r => r.json())
|
|
.then(res => {
|
|
if (res.success) { showToast('success', res.message); location.reload(); }
|
|
else { showToast('error', res.message); }
|
|
});
|
|
}
|
|
|
|
function removeServer(serverId, name) {
|
|
if (!confirm('Remove "' + name + '" from this team?')) return;
|
|
|
|
const form = new FormData();
|
|
form.append('server_id', serverId);
|
|
form.append('_csrf_token', getCsrfToken());
|
|
|
|
fetch('/teams/' + teamId + '/remove-server', {
|
|
method: 'POST',
|
|
headers: { 'X-CSRF-Token': getCsrfToken() },
|
|
body: form,
|
|
})
|
|
.then(r => r.json())
|
|
.then(res => {
|
|
if (res.success) { showToast('success', res.message); location.reload(); }
|
|
else { showToast('error', res.message); }
|
|
});
|
|
}
|
|
|
|
function updateServerRole(serverId, role) {
|
|
const form = new FormData();
|
|
form.append('server_id', serverId);
|
|
form.append('role', role);
|
|
form.append('_csrf_token', getCsrfToken());
|
|
|
|
fetch('/teams/' + teamId + '/update-server-role', {
|
|
method: 'POST',
|
|
headers: { 'X-CSRF-Token': getCsrfToken() },
|
|
body: form,
|
|
})
|
|
.then(r => r.json())
|
|
.then(res => {
|
|
if (res.success) { showToast('success', 'Role updated to ' + role); }
|
|
else { showToast('error', res.message); }
|
|
});
|
|
}
|