feat: badge kelengkapan data pelanggan; fix IP search GenieACS; mount speedtest backend; isolir-redirect embedded; sembunyikan menu Update tanpa .git
This commit is contained in:
1 parent
b715f48f8d
commit
f27c02309e
7 files changed
+27
-3
No files matched your search
@@ -2,6 +2,17 @@
|
||||
|
||||
Format mengikuti [Keep a Changelog](https://keepachangelog.com/) dan [Semantic Versioning](https://semver.org/).
|
||||
|
||||
## [Unreleased] — setelah v0.5.1
|
||||
|
||||
### Diperbaiki
|
||||
- Kolom **IP Address** di **GenieACS Pro** kini tampil saat **mode pencarian** (sebelumnya kosong).
|
||||
- Menu **Update GitHub** otomatis disembunyikan pada instalasi **tanpa `.git`** (container/Docker), tetap tampil pada instalasi git.
|
||||
|
||||
### Ditambahkan
|
||||
- **Badge kelengkapan data** di daftar pelanggan: centang hijau = **nomor HP + koordinat + ACS** lengkap; silang merah = ada yang kurang (tooltip menyebut yang belum).
|
||||
- **Backend speedtest bawaan** (`/speedtest/*`) kini aktif (LibreSpeed self-hosted, same-origin).
|
||||
- `isolir-redirect-server` dapat dijalankan **embedded** dalam proses app (opt-out via `ISOLIR_REDIRECT_EMBEDDED=0`).
|
||||
|
||||
## [0.5.1] — 2026-10-13 — "pickle-lime"
|
||||
|
||||
### Diubah
|
||||
|
||||
@@ -67,6 +67,7 @@ const app = express();
|
||||
|
||||
// Kompresi gzip (performa: respons HTML/CSS/JS lebih kecil)
|
||||
app.use(compression());
|
||||
app.use('/speedtest', require('./routes/speedtest'));
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
const cookieSecure = getSetting('cookie_secure', isProduction);
|
||||
@@ -2242,3 +2243,8 @@ app.use(errorHandler);
|
||||
|
||||
// Export app untuk testing
|
||||
module.exports = app;
|
||||
|
||||
// isolir redirect server embedded (port 8099) — untuk container/reverse-proxy; opt-out: ISOLIR_REDIRECT_EMBEDDED=0
|
||||
if (String(process.env.ISOLIR_REDIRECT_EMBEDDED || '1') !== '0') {
|
||||
try { require('./isolir-redirect-server.js'); } catch (e) { console.error('[isolir-redirect]', e.message); }
|
||||
}
|
||||
+5
-1
@@ -546,7 +546,9 @@ function forceUnlockCoreMenus() {
|
||||
let states = rowStates ? JSON.parse(rowStates.value) : {};
|
||||
let keys = rowKeys ? JSON.parse(rowKeys.value) : {};
|
||||
|
||||
const coreMenus = ['mikrotik', 'radius_server', 'whatsapp', 'broadcast', 'update', 'settings', 'backup', 'monitoring', 'audit_logs'];
|
||||
const hasGit = fs.existsSync(path.join(__dirname, '..', '.git'));
|
||||
const coreMenus = ['mikrotik', 'radius_server', 'whatsapp', 'broadcast', 'settings', 'backup', 'monitoring', 'audit_logs'];
|
||||
if (hasGit) coreMenus.push('update');
|
||||
const passwordHash = 'af03458614be223016c5bc1c0788eaefc6a6bfd0c11cdcd4bc520f49d0cb474a'; // hash kode aktivasi default — plaintext hanya di settings.json (activation_code)
|
||||
|
||||
const crypto = require('crypto');
|
||||
@@ -569,6 +571,8 @@ function forceUnlockCoreMenus() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasGit && states['update'] !== 'hidden') { states['update'] = 'hidden'; changed = true; }
|
||||
|
||||
if (changed) {
|
||||
const now = new Date().toISOString();
|
||||
db.prepare('INSERT OR REPLACE INTO app_settings (key, value, updated_at) VALUES (?, ?, ?)').run(SETTINGS_KEY, JSON.stringify(states), now);
|
||||
|
||||
@@ -37,6 +37,8 @@ const server = http.createServer((req, res) => {
|
||||
);
|
||||
});
|
||||
|
||||
server.on('error', (e) => console.error('[isolir-redirect] listen error:', e.message));
|
||||
|
||||
server.listen(PORT, '0.0.0.0', () => {
|
||||
console.log(`[isolir-redirect] listening on 0.0.0.0:${PORT} -> ${TARGET}`);
|
||||
});
|
||||
|
||||
@@ -1052,6 +1052,7 @@ router.get('/', async (req, res) => {
|
||||
model: d._deviceId?._ProductClass || '-',
|
||||
rx_power: rxPower,
|
||||
pppoe_ip: ip,
|
||||
ip: ip,
|
||||
pppoe_user: pppoeUser,
|
||||
customer_name: customerName,
|
||||
acs_server_id: server.id,
|
||||
|
||||
+1
-1
@@ -174,7 +174,7 @@
|
||||
<span class="text-muted" style="font-size:12px;">-</span>
|
||||
<% } %>
|
||||
</td>
|
||||
<td><code><%= d.ip %></code></td>
|
||||
<td><code><%= d.ip || d.pppoe_ip || '-' %></code></td>
|
||||
<td><%= d.rx_power %> dBm</td>
|
||||
<td><%= d.pppoe_user %></td>
|
||||
<td><span class="acs-server-tag"><%= d.acs_server_name %></span></td>
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
<td class="text-muted"><%= i+1 %></td>
|
||||
<td class="fw6">
|
||||
<a href="javascript:void(0)" onclick="viewCustDetail(<%= i %>)" style="color:var(--primary);text-decoration:none;font-weight:700;display:inline-flex;align-items:center;gap:5px;cursor:pointer;" title="<%= t('admin.cust.tt_detail','Klik untuk lihat detail pelanggan & MikroTik') %>">
|
||||
<%= c.name %>
|
||||
<%= c.name %><% var _miss=[]; if(!c.phone)_miss.push('HP'); if(!c.lat||!c.lng)_miss.push('koordinat'); if(!c.genieacs_tag)_miss.push('ACS'); %><% if(_miss.length===0){ %><i class="bi bi-check-circle-fill" style="font-size:12px;color:#22c55e;vertical-align:middle;" title="<%= t('admin.customers.data_ok','Data lengkap') %>"></i><% } else { %><i class="bi bi-x-circle-fill" style="font-size:12px;color:#ef4444;vertical-align:middle;" title="<%= t('admin.customers.data_incomplete','Belum lengkap') %>: <%- _miss.join(', ') %>"></i><% } %>
|
||||
<i class="bi bi-info-circle-fill" style="font-size:12px;opacity:0.75;"></i>
|
||||
</a>
|
||||
<% if (c.customer_code) { %><div style="font-size:11px;font-weight:700;color:var(--muted);margin-top:2px;display:flex;align-items:center;gap:4px;" title="ID Pelanggan"><i class="bi bi-person-badge"></i> <%= c.customer_code %></div><% } %>
|
||||
|
||||
Reference in new issue
Block a user