- ${app.icon}
+ ${app.Icon || 'apps'}
- ${app.name}
+ ${app.Name}
|
- ${app.type}
+ ${app.Type}
|
+ ${app.Description || '-'} |
+ ${(app.Url || app.url) ? `${app.Url || app.url}` : '-'} |
-
- ${app.status === 'online' ? 'Online' : 'Offline'}
+
+ ${(app.Status || app.status) === 'online' ? 'Online' : 'Offline'}
|
-
@@ -377,86 +417,228 @@ class AccountManager {
-
-
`;
}
setupAccountRowListeners() {
+ // View Account listeners
+ document.querySelectorAll('.view-account').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ const accountId = Number(btn.dataset.accountId);
+ const account = this.accounts.find(a => a.AccountId === accountId);
+ this.currentViewAccountId = accountId;
+ this.currentViewAccount = account;
+ document.getElementById('viewAccountService').textContent = account?.AppName || '-';
+ document.getElementById('viewAccountOwner').textContent = account?.Email || '-';
+ document.getElementById('viewAccountUsername').textContent = account?.AccountUsername || '-';
+ document.getElementById('viewAccountPassword').textContent = '••••••••';
+ document.getElementById('viewAccountPassword').dataset.visible = 'false';
+ document.getElementById('toggleIcon').textContent = 'visibility';
+ document.getElementById('viewAccountModal').classList.add('open');
+ });
+ });
+
+ // Delete Account listeners - show confirmation modal
document.querySelectorAll('.delete-account').forEach(btn => {
btn.addEventListener('click', (e) => {
- const accountId = btn.dataset.accountId;
- if (confirm('Delete this account?')) {
- this.accounts.splice(accountId, 1);
- this.saveToStorage('accounts', this.accounts);
- location.href = './accounts.html';
+ const accountId = Number(btn.dataset.accountId);
+ const account = this.accounts.find(a => a.AccountId === accountId);
+ this.pendingDeleteAccountId = accountId;
+ document.getElementById('deleteAccountUsername').textContent = account?.AccountUsername || '';
+ document.getElementById('deleteAccountModal').classList.add('open');
+ });
+ });
+
+ // Confirm Delete Account
+ document.querySelectorAll('.confirm-delete-account').forEach(btn => {
+ btn.addEventListener('click', () => {
+ if (this.pendingDeleteAccountId !== undefined) {
+ fetch(`${this.apiBase}/accounts/${this.pendingDeleteAccountId}`, { method: 'DELETE' })
+ .then(res => res.json())
+ .then(data => {
+ if (data.success) {
+ alert('Account deleted successfully');
+ this.closeModals();
+ location.href = './accounts.html';
+ } else {
+ alert(data.message || 'Delete account failed');
+ }
+ })
+ .catch(err => {
+ console.error(err);
+ alert('Delete account failed');
+ });
}
});
});
+ // Edit Account listeners
document.querySelectorAll('.edit-account').forEach(btn => {
btn.addEventListener('click', (e) => {
- const accountId = btn.dataset.accountId;
- const account = this.accounts[accountId];
+ const accountId = Number(btn.dataset.accountId);
+ const account = this.accounts.find(a => a.AccountId === accountId);
// Populate form with existing data
- document.getElementById('accountUsername').value = account.username;
- document.getElementById('accountPassword').value = account.password;
- document.getElementById('accountOwner').value = account.owner;
- document.getElementById('accountService').value = account.service;
- this.editingAccountId = accountId;
+ const form = document.getElementById('accountForm');
+ if (form) {
+ const userInput = form.querySelector('#accountUsername');
+ const passInput = form.querySelector('#accountPassword');
+ const ownerInput = form.querySelector('#accountOwner');
+ const serviceSelect = form.querySelector('#accountService');
+ if (userInput) userInput.value = account?.AccountUsername || '';
+ if (passInput) passInput.value = account?.AccountPassword || '';
+ if (ownerInput) ownerInput.value = this.currentUser?.Username || this.currentUser?.username || '';
+ if (serviceSelect) serviceSelect.value = account?.AppId || '';
+ }
+ this.editingAccountId = account?.AccountId;
+ this.closeModals();
this.openAccountModal();
});
});
- document.querySelectorAll('.delete-app').forEach(btn => {
- btn.addEventListener('click', (e) => {
- const appId = btn.dataset.appId;
- if (confirm('Delete this application?')) {
- this.applications.splice(appId, 1);
- this.saveToStorage('applications', this.applications);
- location.href = './applications.html';
+ // Edit from View modal
+ document.querySelectorAll('.edit-account-from-view').forEach(btn => {
+ btn.addEventListener('click', () => {
+ const account = this.currentViewAccount;
+ const form = document.getElementById('accountForm');
+ if (form) {
+ const userInput = form.querySelector('#accountUsername');
+ const passInput = form.querySelector('#accountPassword');
+ const ownerInput = form.querySelector('#accountOwner');
+ const serviceSelect = form.querySelector('#accountService');
+ if (userInput) userInput.value = account?.AccountUsername || '';
+ if (passInput) passInput.value = account?.AccountPassword || '';
+ if (ownerInput) ownerInput.value = this.currentUser?.Username || this.currentUser?.username || '';
+ if (serviceSelect) serviceSelect.value = account?.AppId || '';
+ }
+ this.editingAccountId = account?.AccountId;
+ this.closeModals();
+ this.openAccountModal();
+ });
+ });
+
+ // Toggle Password Visibility
+ document.querySelectorAll('.toggle-password').forEach(btn => {
+ btn.addEventListener('click', () => {
+ const passwordEl = document.getElementById('viewAccountPassword');
+ const toggleIcon = document.getElementById('toggleIcon');
+ const isVisible = passwordEl.dataset.visible === 'true';
+
+ if (isVisible) {
+ passwordEl.textContent = '••••••••';
+ passwordEl.dataset.visible = 'false';
+ toggleIcon.textContent = 'visibility';
+ } else {
+ passwordEl.textContent = this.currentViewAccount?.AccountPassword || '';
+ passwordEl.dataset.visible = 'true';
+ toggleIcon.textContent = 'visibility_off';
}
});
});
+ // View App listeners
+ document.querySelectorAll('.view-app').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ const appId = Number(btn.dataset.appId);
+ const app = this.applications.find(a => a.AppId === appId);
+ this.currentViewAppId = appId;
+ document.getElementById('viewAppName').textContent = app?.Name || '-';
+ document.getElementById('viewAppType').textContent = app?.Type || '-';
+ document.getElementById('viewAppDescription').textContent = app?.Description || '-';
+ const urlEl = document.getElementById('viewAppUrl');
+ const urlVal = app?.Url || app?.url;
+ if (urlEl) {
+ if (urlVal) {
+ urlEl.innerHTML = `${urlVal}`;
+ } else {
+ urlEl.textContent = '-';
+ }
+ }
+ const statusValue = app?.Status || app?.status;
+ document.getElementById('viewAppStatus').textContent = statusValue === 'online' ? 'Online' : 'Offline';
+ document.getElementById('viewAppModal').classList.add('open');
+ });
+ });
+
+ // Delete App listeners - show confirmation modal
+ document.querySelectorAll('.delete-app').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ const appId = Number(btn.dataset.appId);
+ const app = this.applications.find(a => a.AppId === appId);
+ this.pendingDeleteAppId = appId;
+ document.getElementById('deleteAppName').textContent = app?.Name || '';
+ document.getElementById('deleteAppModal').classList.add('open');
+ });
+ });
+
+ // Confirm Delete App
+ document.querySelectorAll('.confirm-delete-app').forEach(btn => {
+ btn.addEventListener('click', () => {
+ if (this.pendingDeleteAppId !== undefined) {
+ fetch(`${this.apiBase}/applications/${this.pendingDeleteAppId}`, { method: 'DELETE' })
+ .then(res => res.json())
+ .then(data => {
+ if (data.success) {
+ alert('Application deleted successfully');
+ this.closeModals();
+ location.href = './applications.html';
+ } else {
+ alert(data.message || 'Delete application failed');
+ }
+ })
+ .catch(err => {
+ console.error(err);
+ alert('Delete application failed');
+ });
+ }
+ });
+ });
+
+ // Edit App listeners
document.querySelectorAll('.edit-app').forEach(btn => {
btn.addEventListener('click', (e) => {
- const appId = btn.dataset.appId;
- const app = this.applications[appId];
- document.getElementById('appName').value = app.name;
- document.getElementById('appType').value = app.type;
- document.getElementById('appStatus').value = app.status;
- this.editingAppId = appId;
+ const appId = Number(btn.dataset.appId);
+ const app = this.applications.find(a => a.AppId === appId);
+ document.getElementById('appName').value = app?.Name || '';
+ document.getElementById('appType').value = app?.Type || '';
+ document.getElementById('appStatus').value = app?.Status || 'online';
+ document.getElementById('appDescription').value = app?.Description || '';
+ document.getElementById('appUrl').value = app?.Url || app?.url || '';
+ this.editingAppId = app?.AppId;
+ this.closeModals();
+ this.openAppModal();
+ });
+ });
+
+ // Edit App from View modal
+ document.querySelectorAll('.edit-app-from-view').forEach(btn => {
+ btn.addEventListener('click', () => {
+ const appId = this.currentViewAppId;
+ const app = this.applications.find(a => a.AppId === appId);
+ document.getElementById('appName').value = app?.Name || '';
+ document.getElementById('appType').value = app?.Type || '';
+ document.getElementById('appStatus').value = app?.Status || 'online';
+ document.getElementById('appDescription').value = app?.Description || '';
+ document.getElementById('appUrl').value = app?.Url || '';
+ this.editingAppId = app?.AppId;
+ this.closeModals();
+ this.openAppModal();
+ });
+ });
+ }
+
+ setupAddButtonListeners() {
+ // Add Account button
+ document.querySelectorAll('#addAccountBtn').forEach(btn => {
+ btn.addEventListener('click', () => {
+ this.editingAccountId = undefined;
+ this.openAccountModal();
+ });
+ });
+
+ // Add Application button
+ document.querySelectorAll('#addAppBtn').forEach(btn => {
+ btn.addEventListener('click', () => {
+ this.editingAppId = undefined;
this.openAppModal();
});
});
@@ -464,67 +646,139 @@ class AccountManager {
handleAccountSubmit(e) {
e.preventDefault();
- const newAccount = {
- service: document.getElementById('accountService').value,
- owner: document.getElementById('accountOwner').value,
- username: document.getElementById('accountUsername').value,
- password: document.getElementById('accountPassword').value,
- dateCreated: new Date().toLocaleDateString()
+ const accountForm = document.getElementById('accountForm');
+ const userId = this.getUserId();
+ const appId = Number(accountForm?.querySelector('#accountService')?.value || 0);
+ const accountUsername = (accountForm?.querySelector('#accountUsername')?.value || '').trim();
+ const accountPassword = (accountForm?.querySelector('#accountPassword')?.value || '').trim();
+ const accountEmail = ((accountForm?.querySelector('#accountOwner')?.value || '').trim()) || this.currentUser?.Username || this.currentUser?.username || '';
+ if (!accountForm) {
+ alert('Account form not found.');
+ return;
+ }
+ if (!userId) {
+ alert('User is not authenticated. Please login again.');
+ return;
+ }
+ if (!appId) {
+ alert('Please select a service.');
+ return;
+ }
+ if (!accountUsername) {
+ alert('Please enter a username.');
+ return;
+ }
+ if (!accountPassword) {
+ alert('Please enter a password.');
+ return;
+ }
+ const payload = {
+ userId,
+ appId,
+ accountUsername,
+ accountPassword,
+ email: accountEmail,
+ accessLevel: 'user',
+ notes: ''
};
- if (this.editingAccountId !== undefined) {
- this.accounts[this.editingAccountId] = newAccount;
- this.editingAccountId = undefined;
- } else {
- this.accounts.push(newAccount);
- }
+ const isEdit = this.editingAccountId !== undefined;
+ const url = isEdit ? `${this.apiBase}/accounts/${this.editingAccountId}` : `${this.apiBase}/accounts`;
+ const method = isEdit ? 'PUT' : 'POST';
- this.saveToStorage('accounts', this.accounts);
- this.closeModals();
- location.href = './accounts.html';
+ fetch(url, {
+ method,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(payload)
+ }).then(res => res.json()).then(data => {
+ if (data.success) {
+ this.editingAccountId = undefined;
+ alert(isEdit ? 'Account updated successfully' : 'Account created successfully');
+ this.closeModals();
+ location.href = './accounts.html';
+ } else {
+ alert(data.message || 'Save account failed');
+ }
+ }).catch(err => {
+ console.error(err);
+ alert('Save account failed');
+ });
}
handleAppSubmit(e) {
e.preventDefault();
- const newApp = {
+ const payload = {
name: document.getElementById('appName').value,
type: document.getElementById('appType').value,
status: document.getElementById('appStatus').value,
- icon: 'cloud'
+ icon: 'cloud',
+ description: document.getElementById('appDescription')?.value || '',
+ url: (document.getElementById('appUrl')?.value || '').trim()
};
- if (this.editingAppId !== undefined) {
- this.applications[this.editingAppId] = newApp;
- this.editingAppId = undefined;
- } else {
- this.applications.push(newApp);
- }
+ const isEdit = this.editingAppId !== undefined;
+ const url = isEdit ? `${this.apiBase}/applications/${this.editingAppId}` : `${this.apiBase}/applications`;
+ const method = isEdit ? 'PUT' : 'POST';
- this.saveToStorage('applications', this.applications);
- this.closeModals();
- location.href = './applications.html';
+ fetch(url, {
+ method,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(payload)
+ }).then(res => res.json()).then(data => {
+ if (data.success) {
+ this.editingAppId = undefined;
+ alert(isEdit ? 'Application updated successfully' : 'Application created successfully');
+ this.closeModals();
+ location.href = './applications.html';
+ } else {
+ alert(data.message || 'Save application failed');
+ }
+ }).catch(err => {
+ console.error(err);
+ alert('Save application failed');
+ });
}
openAccountModal() {
- this.editingAccountId = undefined;
- document.getElementById('accountService').value = '';
- document.getElementById('accountOwner').value = '';
- document.getElementById('accountUsername').value = '';
- document.getElementById('accountPassword').value = '';
- document.getElementById('accountModal').classList.remove('hidden');
+ // Refresh service options so newly added applications appear
+ const serviceSelect = document.getElementById('accountService');
+ if (serviceSelect) {
+ serviceSelect.innerHTML = `` +
+ this.applications.map(app => ``).join('');
+ }
+
+ if (this.editingAccountId === undefined) {
+ const form = document.getElementById('accountForm');
+ if (form) {
+ const serviceSelect = form.querySelector('#accountService');
+ const ownerInput = form.querySelector('#accountOwner');
+ const userInput = form.querySelector('#accountUsername');
+ const passInput = form.querySelector('#accountPassword');
+ if (serviceSelect) serviceSelect.value = '';
+ if (ownerInput) ownerInput.value = this.currentUser?.Username || this.currentUser?.username || '';
+ if (userInput) userInput.value = '';
+ if (passInput) passInput.value = '';
+ }
+ }
+ document.getElementById('accountModal').classList.add('open');
}
openAppModal() {
- this.editingAppId = undefined;
- document.getElementById('appName').value = '';
- document.getElementById('appType').value = '';
- document.getElementById('appStatus').value = 'online';
- document.getElementById('appModal').classList.remove('hidden');
+ if (this.editingAppId === undefined) {
+ document.getElementById('appName').value = '';
+ document.getElementById('appType').value = '';
+ document.getElementById('appStatus').value = 'online';
+ const desc = document.getElementById('appDescription');
+ const url = document.getElementById('appUrl');
+ if (desc) desc.value = '';
+ if (url) url.value = '';
+ }
+ document.getElementById('appModal').classList.add('open');
}
closeModals() {
document.querySelectorAll('.modal-backdrop').forEach(modal => {
- modal.classList.add('hidden');
+ modal.classList.remove('open');
});
}
@@ -538,6 +792,37 @@ class AccountManager {
}
}
+// Global modal close functions
+function closeAllModals() {
+ document.querySelectorAll('.modal-backdrop').forEach(modal => {
+ modal.classList.remove('open');
+ });
+}
+
+function closeAccountModal() {
+ document.getElementById('accountModal').classList.remove('open');
+}
+
+function closeViewAccountModal() {
+ document.getElementById('viewAccountModal').classList.remove('open');
+}
+
+function closeDeleteAccountModal() {
+ document.getElementById('deleteAccountModal').classList.remove('open');
+}
+
+function closeAppModal() {
+ document.getElementById('appModal').classList.remove('open');
+}
+
+function closeViewAppModal() {
+ document.getElementById('viewAppModal').classList.remove('open');
+}
+
+function closeDeleteAppModal() {
+ document.getElementById('deleteAppModal').classList.remove('open');
+}
+
// Initialize app when DOM is ready
let app;
document.addEventListener('DOMContentLoaded', () => {
diff --git a/modals.html b/modals.html
new file mode 100644
index 0000000..5359426
--- /dev/null
+++ b/modals.html
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
+
+
+ close
+
+
+
+
+
+
+
+
+
+ ••••••••
+
+ visibility
+
+
+
+
+ Close
+ Edit
+
+
+
+
+
+
+
+
+
+ warning
+
+
+
+ Are you sure you want to delete the account for -? This action cannot be undone.
+
+ Cancel
+ Delete
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ close
+
+
+
+
+
+
+
+
+
+ Close
+ Edit
+
+
+
+
+
+
+
+
+
+ warning
+
+
+
+ Are you sure you want to delete -? This action cannot be undone.
+
+ Cancel
+ Delete
+
+
+
+
diff --git a/pages/accounts.html b/pages/accounts.html
index 61cbf6a..40284df 100644
--- a/pages/accounts.html
+++ b/pages/accounts.html
@@ -135,15 +135,111 @@
+
+
+
+
+
+
+
+ close
+
+
+
+
+
+
+
+
+
+
+
+
+ close
+
+
+
+
+
+
+
+
+
+ ••••••••
+
+ visibility
+
+
+
+
+ Close
+ Edit
+
+
+
+
+
+
+
+
+
+ warning
+
+
+
+ Are you sure you want to delete the account for -? This action cannot be undone.
+
+ Cancel
+ Delete
+
+
+
+
+
|