diff --git a/DATABASE_SETUP.md b/DATABASE_SETUP.md deleted file mode 100644 index 1eb927a..0000000 --- a/DATABASE_SETUP.md +++ /dev/null @@ -1,291 +0,0 @@ -# AccManager Backend Setup Guide - -## 📋 Database Information - -**Server:** 172.20.235.176 -**Database:** AccManager -**User:** sa -**Password:** robotics@2020 - -## 📊 Database Structure - -### Tables Created - -#### 1. **Users** - Quản lý người dùng -- `UserId` (INT) - Primary Key -- `Username` (NVARCHAR) - Unique -- `Password` (NVARCHAR) -- `Email` (NVARCHAR) -- `FullName` (NVARCHAR) -- `Role` (NVARCHAR) - admin, user, viewer -- `Status` (NVARCHAR) - Active/Inactive -- `CreatedDate` (DATETIME) -- `LastLogin` (DATETIME) -- `IsActive` (BIT) - -#### 2. **Applications** - Danh sách ứng dụng -- `AppId` (INT) - Primary Key -- `Name` (NVARCHAR) -- `Type` (NVARCHAR) - Cloud, VCS, Collaboration, Infra -- `Status` (NVARCHAR) - online/offline -- `Icon` (NVARCHAR) -- `Description` (NVARCHAR) -- `CreatedDate` (DATETIME) -- `UpdatedDate` (DATETIME) - -#### 3. **Accounts** - Tài khoản ứng dụng -- `AccountId` (INT) - Primary Key -- `UserId` (INT) - Foreign Key -- `AppId` (INT) - Foreign Key -- `AccountUsername` (NVARCHAR) -- `AccountPassword` (NVARCHAR) -- `Email` (NVARCHAR) -- `AccessLevel` (NVARCHAR) -- `Status` (NVARCHAR) -- `Notes` (NVARCHAR) -- `CreatedDate` (DATETIME) -- `UpdatedDate` (DATETIME) - -#### 4. **AuditLog** - Nhật ký hoạt động -- `LogId` (INT) - Primary Key -- `UserId` (INT) - Foreign Key -- `Action` (NVARCHAR) - INSERT, UPDATE, DELETE -- `TableName` (NVARCHAR) -- `RecordId` (INT) -- `OldValue` (NVARCHAR) -- `NewValue` (NVARCHAR) -- `Timestamp` (DATETIME) - -## 🔐 Default Admin Account - -**Username:** admin -**Password:** admin -**Role:** admin -**Status:** Active - -## 🚀 Installation & Setup - -### 1. Install Node.js Dependencies - -```bash -npm install -``` - -### 2. Run Backend Server - -```bash -npm start -``` - -Server sẽ chạy tại: **http://localhost:3000** - -### 3. Kiểm tra Database Connection - -```bash -curl http://localhost:3000/api/health -``` - -Response: -```json -{ - "status": "OK", - "database": "Connected" -} -``` - -## 📡 API Endpoints - -### Authentication - -#### Login -```bash -POST /api/auth/login -Content-Type: application/json - -{ - "username": "admin", - "password": "admin" -} -``` - -### Users - -#### Get All Users -```bash -GET /api/users -``` - -#### Get User Details -```bash -GET /api/users/:id -``` - -#### Create New User -```bash -POST /api/users -Content-Type: application/json - -{ - "username": "newuser", - "password": "password123", - "email": "user@example.com", - "fullname": "Full Name", - "role": "user" -} -``` - -### Applications - -#### Get All Applications -```bash -GET /api/applications -``` - -#### Create Application -```bash -POST /api/applications -Content-Type: application/json - -{ - "name": "New App", - "type": "Cloud", - "status": "online", - "icon": "cloud", - "description": "Application description" -} -``` - -### Accounts - -#### Get User Accounts -```bash -GET /api/accounts/user/:userId -``` - -#### Create Account -```bash -POST /api/accounts -Content-Type: application/json - -{ - "userId": 1, - "appId": 1, - "accountUsername": "account_user", - "accountPassword": "account_pass", - "email": "account@example.com", - "accessLevel": "Admin", - "notes": "Account notes" -} -``` - -### Database Info - -#### Get Database Statistics -```bash -GET /api/database/info -``` - -Response: -```json -{ - "success": true, - "database": "AccManager", - "server": "172.20.235.176", - "tables": [ - { - "TableName": "Accounts", - "ColumnCount": 11 - }, - { - "TableName": "Applications", - "ColumnCount": 7 - }, - { - "TableName": "AuditLog", - "ColumnCount": 8 - }, - { - "TableName": "Users", - "ColumnCount": 10 - } - ], - "statistics": { - "users": 1, - "applications": 4, - "accounts": 0 - } -} -``` - -## 🔧 Frontend Integration - -Update frontend API calls to use the backend server: - -```javascript -// Change from localStorage to API calls -const API_URL = 'http://localhost:3000/api'; - -// Example: Login -async function login(username, password) { - const response = await fetch(`${API_URL}/auth/login`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, password }) - }); - return response.json(); -} - -// Example: Get user accounts -async function getAccounts(userId) { - const response = await fetch(`${API_URL}/accounts/user/${userId}`); - return response.json(); -} -``` - -## 📝 Initial Data Created - -### Users -- **admin** (admin role) - -### Applications -- AWS (Cloud) - online -- GitHub (VCS) - online -- Google Workspace (Collaboration) - online -- Nginx Proxy (Infra) - offline - -## 🐛 Troubleshooting - -### Connection Error -``` -Database connection failed: Error -``` -**Solution:** -- Kiểm tra SQL Server đang chạy -- Kiểm tra network connectivity đến 172.20.235.176 -- Kiểm tra username/password đúng -- Kiểm tra SQL Server Authentication được enable - -### Port Already in Use -``` -listen EADDRINUSE: address already in use :::3000 -``` -**Solution:** -```bash -# Change port in .env -PORT=3001 -``` - -### MSSQL Module Not Found -```bash -npm install mssql -``` - -## 📚 References - -- [ExpressJS Documentation](https://expressjs.com/) -- [MSSQL Package](https://github.com/tediousjs/node-mssql) -- [SQL Server Documentation](https://docs.microsoft.com/en-us/sql/) - ---- - -**Status:** ✓ Database created, ✓ Tables created, ✓ Admin user created, ✓ Backend ready diff --git a/RUN_COMMANDS.md b/RUN_COMMANDS.md deleted file mode 100644 index 560ceeb..0000000 --- a/RUN_COMMANDS.md +++ /dev/null @@ -1,220 +0,0 @@ -# 🚀 Hướng Dẫn Chạy AccManager - Dành cho Người Dùng Mới - -## 📋 Bước 1: Kiểm Tra Node.js - -Mở **PowerShell** và chạy: - -```powershell -node --version -npm --version -``` - -**Kết quả mong đợi:** -``` -v18.16.0 (hoặc version cao hơn) -9.6.7 (hoặc version khác) -``` - -Nếu thấy version → **OK, tiếp tục bước 2** - ---- - -## 📋 Bước 2: Vào Thư Mục Dự Án - -Copy-paste lệnh này vào PowerShell: - -```powershell -cd d:\RoboticsSource\AccManager -``` - ---- - -## 📋 Bước 3: Cài Đặt Dependencies - -Copy-paste lệnh này vào PowerShell: - -```powershell -npm install -``` - -**Chờ cho tới khi thấy:** -``` -added XXX packages in XXs -``` - -(Sẽ mất 1-3 phút tùy tốc độ mạng) - ---- - -## 📋 Bước 4: Chạy Backend Server - -Copy-paste lệnh này vào PowerShell: - -```powershell -npm start -``` - -**Khi thành công, bạn sẽ thấy:** -``` -======================================== -AccManager Backend Server -======================================== -✓ Server running on http://localhost:3000 -✓ Database: AccManager -✓ Default admin: admin / admin - -API Endpoints: - POST /api/auth/login - GET /api/database/info - GET /api/users - GET /api/applications - GET /api/accounts/user/:userId -======================================== -``` - -**👉 ĐỪNG ĐÓNG TERMINAL NÀY - Server đang chạy!** - ---- - -## 🌐 Bước 5: Mở Ứng Dụng - -**Mở trình duyệt** (Chrome, Firefox, Edge...) copy-paste URL này: - -``` -http://localhost:3000/pages/login.html -``` - ---- - -## 🔐 Bước 6: Đăng Nhập - -**Nhập thông tin:** -- Username: `admin` -- Password: `admin` - -Nhấp **Login** - ---- - -## ✅ Nếu Thành Công - -Bạn sẽ thấy: -- ✓ Trang Dashboard -- ✓ Quản lý Accounts -- ✓ Quản lý Applications -- ✓ Thông tin Database - ---- - -## ❌ Nếu Có Lỗi - -### Lỗi 1: "npm: The term 'npm' is not recognized" -**Giải pháp:** -- Đóng PowerShell hiện tại -- Mở PowerShell **mới** -- Chạy lại `npm --version` - -### Lỗi 2: "Cannot find module 'express'" -**Giải pháp:** -```powershell -npm install -npm start -``` - -### Lỗi 3: "Port 3000 already in use" -**Giải pháp:** Có chương trình khác dùng port 3000 -```powershell -# Dừng server cũ (Ctrl+C) -# Rồi chạy lại: npm start -``` - -### Lỗi 4: "Cannot connect to database" -**Giải pháp:** Kiểm tra SQL Server -- Đảm bảo SQL Server đang chạy -- IP: 172.20.235.176 có reach được không - -```powershell -ping 172.20.235.176 -``` - ---- - -## 💡 Full Workflow - Copy Toàn Bộ Lệnh - -Nếu bạn muốn copy toàn bộ một lần: - -```powershell -# Kiểm tra Node.js -node --version - -# Vào thư mục -cd d:\RoboticsSource\AccManager - -# Cài packages -npm install - -# Chạy server -npm start -``` - ---- - -## 🎯 Các Lệnh Hữu Ích Khác - -### Dừng Server -Nhấp **Ctrl + C** trong PowerShell - -### Chạy Server Ở Chế Độ Development (auto-restart) -```powershell -npm run dev -``` - -### Kiểm Tra API Health -Mở browser khác nhập: -``` -http://localhost:3000/api/health -``` - -### Xem Tất Cả Users -``` -http://localhost:3000/api/users -``` - -### Xem Tất Cả Applications -``` -http://localhost:3000/api/applications -``` - -### Database Info -``` -http://localhost:3000/api/database/info -``` - ---- - -## 📊 Sơ Đồ Port - -| URL | Port | Mục đích | -|-----|------|---------| -| http://localhost:3000/pages/login.html | 3000 | Frontend | -| http://localhost:3000/api/health | 3000 | Backend API | -| 172.20.235.176 | 1433 | SQL Server | - ---- - -## 🎯 Tóm Tắt - 4 Bước Chính - -1. **Mở PowerShell** -2. **Chạy:** - ```powershell - cd d:\RoboticsSource\AccManager - npm install - npm start - ``` -3. **Chờ thấy "Server running on http://localhost:3000"** -4. **Mở browser vào: http://localhost:3000/pages/login.html** -5. **Đăng nhập: admin / admin** - ---- - -**Chúc bạn thành công! 🚀** diff --git a/SETUP_GUIDE.md b/SETUP_GUIDE.md deleted file mode 100644 index 5471692..0000000 --- a/SETUP_GUIDE.md +++ /dev/null @@ -1,294 +0,0 @@ -# 🚀 AccManager Backend - Complete Setup Guide - -## ⚠️ Pre-requisites - -### 1. Install Node.js & npm - -**Download từ:** https://nodejs.org/ -**Khuyến khích:** LTS version (v18 hoặc mới hơn) - -#### Kiểm tra installation: -```bash -node --version -npm --version -``` - -Expected output: -``` -v18.* (or newer) -9.* (or newer) -``` - -### 2. Verify SQL Server Connection - -Trước khi chạy backend, kiểm tra SQL Server: - -```bash -ping 172.20.235.176 -``` - -Nếu không ping được, kiểm tra: -- SQL Server đang chạy -- Firewall cho phép port 1433 -- Network connectivity - ---- - -## 📥 Setup Steps - -### Step 1: Install Node Packages - -```bash -cd d:\RoboticsSource\AccManager -npm install -``` - -Wait cho tới khi mô tả xuất hiện `added X packages` - -### Step 2: Run Backend Server - -```bash -npm start -``` - -**Expected Output:** -``` -======================================== -AccManager Backend Server -======================================== -✓ Server running on http://localhost:3000 -✓ Database: AccManager -✓ Default admin: admin / admin - -API Endpoints: - POST /api/auth/login - GET /api/database/info - GET /api/users - GET /api/applications - GET /api/accounts/user/:userId -======================================== -``` - -### Step 3: Test Connection - -Mở terminal mới, chạy: - -```bash -curl http://localhost:3000/api/health -``` - -**Response:** -```json -{ - "status": "OK", - "database": "Connected" -} -``` - -### Step 4: Test Database Info - -```bash -curl http://localhost:3000/api/database/info -``` - ---- - -## 📝 Database Structure - -### Database Name: `AccManager` - -#### Tables: -1. **Users** (1 admin account) - - Username: admin - - Password: admin - - Role: admin - -2. **Applications** (4 sample apps) - - AWS - - GitHub - - Google Workspace - - Nginx Proxy - -3. **Accounts** (empty, ready to use) - -4. **AuditLog** (empty, for logging) - ---- - -## 🧪 Test API Endpoints - -### Test 1: Login -```bash -curl -X POST http://localhost:3000/api/auth/login \ - -H "Content-Type: application/json" \ - -d "{\"username\":\"admin\",\"password\":\"admin\"}" -``` - -### Test 2: Get Users -```bash -curl http://localhost:3000/api/users -``` - -### Test 3: Get Applications -```bash -curl http://localhost:3000/api/applications -``` - -### Test 4: View Database Info -```bash -curl http://localhost:3000/api/database/info -``` - ---- - -## 🔌 Frontend Integration - -Update your frontend to connect to the backend: - -### Option 1: Update app.js - -```javascript -const API_URL = 'http://localhost:3000/api'; - -// Update login function -async function login(username, password) { - const response = await fetch(`${API_URL}/auth/login`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, password }) - }); - const data = await response.json(); - - if (data.success) { - localStorage.setItem('currentUser', JSON.stringify(data.user)); - window.location.href = './pages/accounts.html'; - } else { - alert('Login failed: ' + data.message); - } -} - -// Update get accounts function -async function getAccounts(userId) { - const response = await fetch(`${API_URL}/accounts/user/${userId}`); - const data = await response.json(); - return data.data || []; -} -``` - ---- - -## 📦 Project Structure - -``` -d:\RoboticsSource\AccManager\ -├── server.js # Backend server (Node.js) -├── package.json # Dependencies -├── .env # Configuration -├── DATABASE_SETUP.md # This file -├── database/ -│ └── setup.sql # SQL setup script -├── index.html # Frontend entry -├── pages/ -│ ├── login.html -│ ├── accounts.html -│ ├── applications.html -│ └── index.html -└── js/ - └── app.js # Frontend logic -``` - ---- - -## 🔒 Security Notes - -⚠️ **For Development Only:** -- Admin password is hardcoded as "admin" -- SQL credentials in code (not recommended for production) -- CORS enabled for all origins - -### For Production: -1. Use environment variables -2. Hash passwords with bcrypt -3. Implement JWT authentication -4. Use firewalls and VPNs -5. Enable SSL/TLS - ---- - -## 🐛 Troubleshooting - -### Error: "Cannot find module 'express'" -```bash -npm install -``` - -### Error: "Connection failed" -Check: -- SQL Server running -- IP address correct: 172.20.235.176 -- Port 1433 accessible -- Username/password correct - -### Error: "Port 3000 already in use" -```bash -# Change port in .env -PORT=3001 - -# Then restart server -npm start -``` - -### Error: "CORS error in browser" -This is normal during development. The backend already has CORS enabled. - ---- - -## 📊 Database Credentials - -``` -Server: 172.20.235.176 -Database: AccManager -User: sa -Password: robotics@2020 -``` - ---- - -## ✅ Verification Checklist - -- [ ] Node.js installed -- [ ] npm packages installed (`npm install`) -- [ ] Backend server running (`npm start`) -- [ ] Can access http://localhost:3000/api/health -- [ ] Can login with admin/admin -- [ ] Database shows tables and statistics -- [ ] Frontend connects to backend - ---- - -## 📚 Additional Commands - -### Install Development Tools -```bash -npm install -D nodemon -npm run dev # Auto-restart on code changes -``` - -### Check npm packages -```bash -npm list -``` - -### Update packages -```bash -npm update -``` - -### Clear npm cache -```bash -npm cache clean --force -``` - ---- - -**For Support:** Check server logs for error messages diff --git a/server.js b/backend/server.js similarity index 98% rename from server.js rename to backend/server.js index ee257e1..a503383 100644 --- a/server.js +++ b/backend/server.js @@ -10,15 +10,14 @@ const app = express(); app.use(cors()); app.use(express.json()); -// Serve static files +// Serve static files from /public const path = require('path'); -app.use(express.static(path.join(__dirname, 'pages'))); -app.use(express.static(path.join(__dirname, 'js'))); -app.use(express.static(path.join(__dirname))); +const publicDir = path.join(__dirname, '..', 'public'); +app.use(express.static(publicDir)); // Root route app.get('/', (req, res) => { - res.sendFile(path.join(__dirname, 'pages', 'login.html')); + res.sendFile(path.join(publicDir, 'pages', 'login.html')); }); // SQL Server Configuration diff --git a/codedialog.html b/codedialog.html deleted file mode 100644 index 3bcddcf..0000000 --- a/codedialog.html +++ /dev/null @@ -1,270 +0,0 @@ - - - - -
- - -| ${acc.Email || '-'} | ${acc.AccountUsername || '-'} | @@ -315,6 +383,7 @@ class AccountManager { } getApplicationsContent() { + const filteredApps = this.getFilteredApplications(); return `
|
@@ -457,16 +530,16 @@ class AccountManager {
.then(res => res.json())
.then(data => {
if (data.success) {
- alert('Account deleted successfully');
+ this.notifySuccess('Account deleted successfully');
this.closeModals();
- location.href = './accounts.html';
+ this.refreshAccountsUI();
} else {
- alert(data.message || 'Delete account failed');
+ this.notifyFailure(data.message || 'Delete account failed');
}
})
.catch(err => {
console.error(err);
- alert('Delete account failed');
+ this.notifyFailure('Delete account failed');
});
}
});
@@ -489,6 +562,7 @@ class AccountManager {
if (ownerInput) ownerInput.value = this.currentUser?.Username || this.currentUser?.username || '';
if (serviceSelect) serviceSelect.value = account?.AppId || '';
}
+ this.pendingAccountAppId = account?.AppId;
this.editingAccountId = account?.AccountId;
this.closeModals();
this.openAccountModal();
@@ -510,6 +584,7 @@ class AccountManager {
if (ownerInput) ownerInput.value = this.currentUser?.Username || this.currentUser?.username || '';
if (serviceSelect) serviceSelect.value = account?.AppId || '';
}
+ this.pendingAccountAppId = account?.AppId;
this.editingAccountId = account?.AccountId;
this.closeModals();
this.openAccountModal();
@@ -543,6 +618,11 @@ class AccountManager {
this.currentViewAppId = appId;
document.getElementById('viewAppName').textContent = app?.Name || '-';
document.getElementById('viewAppType').textContent = app?.Type || '-';
+ const iconVal = app?.Icon || app?.icon || 'apps';
+ const iconSymbolEl = document.getElementById('viewAppIconSymbol');
+ const iconNameEl = document.getElementById('viewAppIconName');
+ if (iconSymbolEl) iconSymbolEl.textContent = iconVal;
+ if (iconNameEl) iconNameEl.textContent = iconVal;
document.getElementById('viewAppDescription').textContent = app?.Description || '-';
const urlEl = document.getElementById('viewAppUrl');
const urlVal = app?.Url || app?.url;
@@ -578,16 +658,16 @@ class AccountManager {
.then(res => res.json())
.then(data => {
if (data.success) {
- alert('Application deleted successfully');
+ this.notifySuccess('Application deleted successfully');
this.closeModals();
- location.href = './applications.html';
+ this.refreshApplicationsUI();
} else {
- alert(data.message || 'Delete application failed');
+ this.notifyFailure(data.message || 'Delete application failed');
}
})
.catch(err => {
console.error(err);
- alert('Delete application failed');
+ this.notifyFailure('Delete application failed');
});
}
});
@@ -602,6 +682,7 @@ class AccountManager {
document.getElementById('appType').value = app?.Type || '';
document.getElementById('appStatus').value = app?.Status || 'online';
document.getElementById('appDescription').value = app?.Description || '';
+ document.getElementById('appIcon').value = app?.Icon || app?.icon || '';
document.getElementById('appUrl').value = app?.Url || app?.url || '';
this.editingAppId = app?.AppId;
this.closeModals();
@@ -618,6 +699,7 @@ class AccountManager {
document.getElementById('appType').value = app?.Type || '';
document.getElementById('appStatus').value = app?.Status || 'online';
document.getElementById('appDescription').value = app?.Description || '';
+ document.getElementById('appIcon').value = app?.Icon || app?.icon || '';
document.getElementById('appUrl').value = app?.Url || '';
this.editingAppId = app?.AppId;
this.closeModals();
@@ -631,6 +713,7 @@ class AccountManager {
document.querySelectorAll('#addAccountBtn').forEach(btn => {
btn.addEventListener('click', () => {
this.editingAccountId = undefined;
+ this.pendingAccountAppId = undefined;
this.openAccountModal();
});
});
@@ -644,7 +727,36 @@ class AccountManager {
});
}
- handleAccountSubmit(e) {
+ setupFilters() {
+ const serviceFilter = document.getElementById('serviceFilter');
+ if (serviceFilter) {
+ serviceFilter.value = this.accountServiceFilter || '';
+ serviceFilter.addEventListener('change', (e) => {
+ this.accountServiceFilter = e.target.value;
+ this.refreshAccountsUI();
+ });
+ }
+
+ const accountSearch = document.getElementById('accountSearch');
+ if (accountSearch) {
+ accountSearch.value = this.accountSearchTerm;
+ accountSearch.addEventListener('input', (e) => {
+ this.accountSearchTerm = e.target.value.toLowerCase();
+ this.refreshAccountsUI();
+ });
+ }
+
+ const appSearch = document.getElementById('appSearch');
+ if (appSearch) {
+ appSearch.value = this.applicationSearchTerm;
+ appSearch.addEventListener('input', (e) => {
+ this.applicationSearchTerm = e.target.value.toLowerCase();
+ this.refreshApplicationsUI();
+ });
+ }
+ }
+
+ async handleAccountSubmit(e) {
e.preventDefault();
const accountForm = document.getElementById('accountForm');
const userId = this.getUserId();
@@ -653,23 +765,23 @@ class AccountManager {
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.');
+ this.notifyFailure('Account form not found.');
return;
}
if (!userId) {
- alert('User is not authenticated. Please login again.');
+ this.notifyFailure('User is not authenticated. Please login again.');
return;
}
if (!appId) {
- alert('Please select a service.');
+ this.notifyWarning('Please select a service.');
return;
}
if (!accountUsername) {
- alert('Please enter a username.');
+ this.notifyWarning('Please enter a username.');
return;
}
if (!accountPassword) {
- alert('Please enter a password.');
+ this.notifyWarning('Please enter a password.');
return;
}
const payload = {
@@ -693,25 +805,37 @@ class AccountManager {
}).then(res => res.json()).then(data => {
if (data.success) {
this.editingAccountId = undefined;
- alert(isEdit ? 'Account updated successfully' : 'Account created successfully');
+ this.pendingAccountAppId = undefined;
+ this.notifySuccess(isEdit ? 'Account updated successfully' : 'Account created successfully');
this.closeModals();
- location.href = './accounts.html';
+ this.refreshAccountsUI();
} else {
- alert(data.message || 'Save account failed');
+ this.notifyFailure(data.message || 'Save account failed');
}
}).catch(err => {
console.error(err);
- alert('Save account failed');
+ this.notifyFailure('Save account failed');
});
}
- handleAppSubmit(e) {
+ async refreshAccountsUI() {
+ await this.fetchAccounts();
+ const mainContent = document.getElementById('mainContent');
+ if (mainContent) {
+ mainContent.innerHTML = this.getAccountsContent();
+ this.setupAccountRowListeners();
+ this.setupAddButtonListeners();
+ this.setupFilters();
+ }
+ }
+
+ async handleAppSubmit(e) {
e.preventDefault();
const payload = {
name: document.getElementById('appName').value,
type: document.getElementById('appType').value,
status: document.getElementById('appStatus').value,
- icon: 'cloud',
+ icon: (document.getElementById('appIcon')?.value || 'apps').trim() || 'apps',
description: document.getElementById('appDescription')?.value || '',
url: (document.getElementById('appUrl')?.value || '').trim()
};
@@ -727,24 +851,38 @@ class AccountManager {
}).then(res => res.json()).then(data => {
if (data.success) {
this.editingAppId = undefined;
- alert(isEdit ? 'Application updated successfully' : 'Application created successfully');
+ this.notifySuccess(isEdit ? 'Application updated successfully' : 'Application created successfully');
this.closeModals();
- location.href = './applications.html';
+ this.refreshApplicationsUI();
} else {
- alert(data.message || 'Save application failed');
+ this.notifyFailure(data.message || 'Save application failed');
}
}).catch(err => {
console.error(err);
- alert('Save application failed');
+ this.notifyFailure('Save application failed');
});
}
+ async refreshApplicationsUI() {
+ await this.fetchApplications();
+ const mainContent = document.getElementById('mainContent');
+ if (mainContent) {
+ mainContent.innerHTML = this.getApplicationsContent();
+ this.setupAccountRowListeners();
+ this.setupAddButtonListeners();
+ this.setupFilters();
+ }
+ }
+
openAccountModal() {
// 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 && this.pendingAccountAppId) {
+ serviceSelect.value = this.pendingAccountAppId;
+ }
}
if (this.editingAccountId === undefined) {
@@ -768,8 +906,10 @@ class AccountManager {
document.getElementById('appName').value = '';
document.getElementById('appType').value = '';
document.getElementById('appStatus').value = 'online';
+ const iconInput = document.getElementById('appIcon');
const desc = document.getElementById('appDescription');
const url = document.getElementById('appUrl');
+ if (iconInput) iconInput.value = '';
if (desc) desc.value = '';
if (url) url.value = '';
}
diff --git a/modals.html b/public/modals.html
similarity index 92%
rename from modals.html
rename to public/modals.html
index 5359426..74fe02c 100644
--- a/modals.html
+++ b/public/modals.html
@@ -108,6 +108,11 @@
+
+
+
+
Nhập tên icon từ https://fonts.google.com/icons (ví dụ: cloud, apps, security). +
@@ -149,6 +154,13 @@
+ -
+
+
+ apps
+ apps
+
+ -
diff --git a/pages/accounts.html b/public/pages/accounts.html
similarity index 98%
rename from pages/accounts.html
rename to public/pages/accounts.html
index 40284df..bf67bc5 100644
--- a/pages/accounts.html
+++ b/public/pages/accounts.html
@@ -3,12 +3,15 @@
- |