Admin: KPI Config — set target, bobot metrik, periode laporan
1-2 hari
30
Export PDF/Excel — laporan KPI per periode untuk manajemen
1-2 hari
31
Push Notif KPI Alert — notif jika KPI di bawah target ke Manager/IT Admin
1 hari
Urutan pengerjaan: ① Content/Home Feed → ② Mailcow → ③ Zammad+Ticketing → ④ Push Notif → ⑤ Gitea → ⑥ Mail UI → ⑦ Infra → ⑧ KPI Dashboard
(Gitea Fase 5 bisa dikerjakan paralel dengan Fase 2-4 karena tidak ada dependency) (KPI Fase 8 dikerjakan terakhir — butuh Zammad + Gitea + Collector + Uptime Kuma semua sudah running)
ADR — Standar Dialog Preview / Edit (UI Pattern)
Aturan Wajib
Semua dialog preview/edit WAJIB menggunakan <Dialog> dari @/components/ui/dialog (bukan Sheet/Drawer)
Ukuran: sm:max-w-lg (detail lebar) atau sm:max-w-md (form pendek)
Struktur wajib:
Header berwarna (gradient) — berisi ikon, judul, sub-judul
Body dengan overflow-y-auto max-h-[65dvh] — scrollable
Footer sticky dengan border-t bg-muted/30 — tombol Batal + Simpan
Untuk dialog yang punya preview DAN edit, gunakan 2 tab (tab "Detail" + tab "Edit")
Tab menggunakan komponen <Tabs> dari @/components/ui/tabs
Info 2-kolom: grid grid-cols-[160px_1fr] untuk label–value
src/lib/push-client.ts — subscribe/unsubscribe, kirim VAPID public key ke browser
Service Worker handler push event (via @ducanh2912/next-pwa custom SW)
Permission request UI — tombol "Aktifkan Notifikasi" di halaman profile/settings
Notification payload: { title, body, icon, badge, url, tag }
Action button pada notif: "Lihat Tiket", "Lihat Asset"
Notif center di navbar — in-app list notifikasi (polling atau WebSocket)
Kategori Notifikasi
🎫Ticketing: tiket baru assigned, update status, komentar baru, SLA overdue
🖥️Asset Management: device offline > X menit, disk usage > 90%, tiket asset baru
📢Broadcast IT: pengumuman, maintenance, downtime
(Future)📊 Monitoring: alert Zabbix
Activity Tracking
Status
✅last_login_at super apps — sudah fix (Jun 2026): kolom ditambah ke ldap_user_meta, diset saat AuthController::login(), dikembalikan oleh MeController prioritas di atas lastlogontimestamp AD yang stale.
Kenapa Tidak Pakai lastlogontimestamp dari AD?
Active Directory lastlogontimestamp hanya direplikasi antar Domain Controller setiap 9-14 hari — by design Microsoft untuk mengurangi replikasi traffic. Jadi selalu stale. Solusi: simpan timestamp di DB sendiri saat login ke super apps.
1. Super Apps — Page Visit & Feature Usage
Backend (geonet-console)
Buat tabel user_activity_logs (username, feature, action, duration_seconds, metadata JSON, created_at)
POST /api/v1/activity — endpoint internal FE kirim activity event
GET /api/v1/admin/activity — admin query logs (filter: user, feature, date range)
Aggregation query: fitur paling banyak dikunjungi, avg durasi per fitur, DAU/WAU/MAU
Frontend (Next.js)
src/lib/activity-tracker.ts — hook usePageTracking(): catat page_enter + page_leave dengan durasi
Kirim event ke /api/v1/activity saat user leave page (via beforeunload + visibilitychange)
Flow: user klik "Hubungkan Gitea" → redirect OAuth → dapat access token → simpan di session/DB
Fallback: user input Personal Access Token manual di halaman Profile
API Endpoint yang Digunakan
Auth:
GET /user — info user yang login
GET /users/{username} — profil user
Issues:
GET /repos/{owner}/{repo}/issues — list issues (filter: state, label, assignee)
POST /repos/{owner}/{repo}/issues — buat issue baru
GET /repos/{owner}/{repo}/issues/{index} — detail issue
PATCH /repos/{owner}/{repo}/issues/{index} — update (close, assign, label)
GET /repos/{owner}/{repo}/issues/{index}/comments — komentar
POST /repos/{owner}/{repo}/issues/{index}/comments — tambah komentar
GET /repos/{owner}/{repo}/labels — label/kategori tersedia
Repositories:
GET /user/repos — semua repo milik user
GET /repos/{owner}/{repo} — detail repo (stars, forks, size, last push)
GET /repos/{owner}/{repo}/branches — daftar branch
GET /repos/{owner}/{repo}/commits — commit history
GET /repos/{owner}/{repo}/releases — releases / tags
GET /repos/search?q=&topic= — search repo
FE Tasks
Setup & Auth
Daftarkan OAuth2 App di Gitea admin panel
src/lib/gitea-client.ts — wrapper API dengan Bearer token
Route GET /api/gitea/callback — handle OAuth callback, simpan token
Profile page: tombol "Hubungkan Akun Gitea" + status connected
Tambah gitea_token ke user session/store
Halaman Issues (/gitea/issues)
List issues dari semua repo yang diikuti user (filter: open/closed, label, repo)
Form buat issue — pilih repo, judul, body (Markdown), label, assignee
Link ke Gitea web untuk operasi lebih lanjut (clone, PR, dll)
Permission (tambah ke group_permissions)
Permission
Fungsi
gitea.view
Lihat issue & repo (semua user yang punya akun Gitea)
gitea.create_issue
Buat issue baru
gitea.manage
Admin Gitea (close issue, assign, label)
Catatan
Issue dari super apps dan Gitea web sinkron sempurna — data disimpan di Gitea, super apps hanya read/write via API
Tidak perlu database tambahan di super apps untuk Gitea — semua state di Gitea
Bisa jadi alternatif/pelengkap Zammad untuk bug tracking development (Zammad = IT helpdesk, Gitea = dev issues)
Content / Posting Microservice (geonet-content)
Saran Profesional
Gunakan pola Headless CMS + custom API — bukan CMS full seperti WordPress.
Ini memberi kontrol penuh atas schema, permission berbasis LDAP group, dan integrasi ke push notification.
Stack yang Disarankan
Backend: FastAPI + PostgreSQL (konsisten dengan Collector)
Configure Mailcow Multi Domain (geonet.co.id, gegeo.my.id)
Configure Mailcow Docker
Configure Mailcow Enterprise
Configure Mailcow Nilai
Configure Mailcow LDAP (10.100.1.40)
Install Thunderbird
Install Thunderbird
Configure Thunderbird
Configure Thunderbird for geonet.co.id
Configure Thunderbird for gegeo.my.id
Move Inbox from main geonet.co.id to geonet for mail server
save imap and pop3 file Thunderbird di NAS : untuk meringankan vm dan memastikan file tidak hilang
KPI Dashboard (geonet-kpi)
Dependency (semua harus sudah running)
✅ geonet-collector (asset & device data)
🔴 Zammad (tiket metrics)
🔴 Gitea (issue & commit metrics)
🔶 Uptime Kuma API (service uptime)
🔶 Zabbix API (network alert)
Arsitektur
Backend: geonet-kpi — FastAPI aggregator, bukan BI tool besar
Cache: Redis atau SQLite — hasil agregasi disimpan agar FE tidak hit semua API setiap request
Scheduler: APScheduler (built-in FastAPI) — hitung KPI otomatis tiap malam / per jam
Domain: kpi.gisportal.id (internal) atau lewat console.gisportal.id/api/kpi
Metrik KPI Karyawan
Metrik
Sumber
Cara Hitung
Tiket IT diselesaikan
Zammad
Count closed by assignee per periode
Rata-rata waktu resolve
Zammad
Avg(closed_at − created_at) per assignee
SLA compliance (%)
Zammad
% tiket selesai sebelum SLA deadline
Issue dev diselesaikan
Gitea
Count closed issues by assignee
Jumlah commit
Gitea
Count commits by author
Asset yang dikelola
geonet-collector
Count asset by owner
Login activity
geonet-console
Count login per bulan
Metrik KPI IT/Operasional
Metrik
Sumber
Cara Hitung
Uptime layanan (%)
Uptime Kuma
monitors → uptime ratio per service
Asset online vs offline
geonet-collector
online_count / total_count
Asset disk > 90%
geonet-collector
Count disk pct_used > 90
Tiket masuk vs selesai
Zammad
Open/Close ratio per periode
Avg first response time
Zammad
Time to first agent reply
Network alert count
Zabbix
Problem count by severity
Repo aktif
Gitea
Repo dengan commit dalam 30 hari terakhir
API Endpoints (geonet-kpi)
GET /kpi/summary — ringkasan KPI semua kategori (untuk dashboard)
GET /kpi/employee/{username} — KPI individu karyawan
GET /kpi/it-ops — KPI operasional IT
GET /kpi/history?period=monthly&months=6 — trend historis
GET /kpi/export?format=pdf|excel&period= — export laporan
POST /admin/kpi/config — set target & bobot per metrik
POST /admin/kpi/refresh — trigger recalculate manual
🗺️ ROADMAP & PRIORITAS PENGERJAAN
✅ Sudah Selesai
Microservice & Infrastruktur yang Sudah Running di Server (10.100.1.24)
my.gisportal.idconsole.gisportal.idcollector.gisportal.id/agent.gisportal.idgrafana.gisportal.iduptime.gisportal.idn8n.gisportal.idnode-red.gisportal.iddockge.gisportal.idzabbix.gisportal.idgit.gisportal.idjira.gisportal.idfile.gisportal.id/obj.gisportal.idYang Sudah Dibangun di Super Apps (my.gisportal.id)
🔴 Fase 1 — Content & Home Feed (Mulai sekarang — tidak ada dependency)
geonet-content— FastAPI, Post, Like, Comment, thumbnail OSS/posts/:slug, rich text, komentar bersarang🔴 Fase 1.5 — Activity Tracking (Bisa mulai sekarang — tidak ada dependency)
last_login_atsuper apps — simpan ke DB saat login, tidak ambil dari ADgeonet-console/user/heatmap,/repos/events)🔴 Fase 2 — Mail Server (Prerequisite Ticketing & Mail UI)
🔴 Fase 3 — Ticketing (Butuh Mailcow untuk notif email)
🔴 Fase 4 — Push Notification (Butuh Zammad webhook sebagai sumber event)
geonet-push— FastAPI + VAPID, subscribe per user LDAP🔴 Fase 5 — Gitea Integration (Tidak ada dependency — bisa mulai kapanpun)
src/lib/gitea-client.ts— API client (issues, repos, user) dengan token/OAuth🔴 Fase 6 — Mail UI & Monitoring (Butuh Mailcow API)
🔴 Fase 7 — Infrastruktur (Bisa paralel kapanpun)
🔴 Fase 8 — KPI Dashboard (Setelah semua service siap: Zammad, Gitea, Collector, Uptime Kuma)
geonet-kpi— FastAPI aggregator, pull dari semua API, cache Redis/SQLiteADR — Standar Dialog Preview / Edit (UI Pattern)
Aturan Wajib
<Dialog>dari@/components/ui/dialog(bukan Sheet/Drawer)sm:max-w-lg(detail lebar) atausm:max-w-md(form pendek)overflow-y-auto max-h-[65dvh]— scrollableborder-t bg-muted/30— tombol Batal + Simpan<Tabs>dari@/components/ui/tabsgrid grid-cols-[160px_1fr]untuk label–valueReferensi Implementasi
src/app/(app)/profile/page.tsx—<Dialog>Edit Profil & Ganti Passwordsrc/components/asset-management/asset-detail-dialog.tsx— Dialog Asset (2 tab)Komponen yang Mengikuti Standar Ini
/profile)/profile)/asset-management)Ticketing Microservice
Platform: Zammad (Rekomendasi Production)
zammad.gisportal.id/ticketingSetup Zammad
Kategori Tiket
Alur Tiket (Workflow)
FE Integration (
/ticketingdi my.gisportal.id)Zammad API Client (
src/lib/zammad-client.ts)Push Notification Microservice
Arsitektur yang Disarankan: Web Push (VAPID) + ntfy / Superstream
Opsi Backend
Rekomendasi: Custom FastAPI Push Service + Web Push VAPID
pushevent sudah didukung@ducanh2912/next-pwaAlur Push Notification
Setup Push Service
geonet-pushservice (FastAPI + pywebpush)POST /subscribe— simpan push subscription per user LDAPPOST /unsubscribe— hapus subscriptionPOST /send— kirim notif ke user/group (internal, pakai API key)push.gisportal.id(internal)Sumber Event (Trigger)
FE Integration (Next.js PWA)
src/lib/push-client.ts— subscribe/unsubscribe, kirim VAPID public key ke browserpushevent (via@ducanh2912/next-pwacustom SW){ title, body, icon, badge, url, tag }Kategori Notifikasi
Activity Tracking
Status
last_login_atsuper apps — sudah fix (Jun 2026): kolom ditambah keldap_user_meta, diset saatAuthController::login(), dikembalikan olehMeControllerprioritas di ataslastlogontimestampAD yang stale.Kenapa Tidak Pakai
lastlogontimestampdari AD?Active Directory
lastlogontimestamphanya direplikasi antar Domain Controller setiap 9-14 hari — by design Microsoft untuk mengurangi replikasi traffic. Jadi selalu stale. Solusi: simpan timestamp di DB sendiri saat login ke super apps.1. Super Apps — Page Visit & Feature Usage
Backend (
geonet-console)user_activity_logs(username, feature, action, duration_seconds, metadata JSON, created_at)POST /api/v1/activity— endpoint internal FE kirim activity eventGET /api/v1/admin/activity— admin query logs (filter: user, feature, date range)Frontend (Next.js)
src/lib/activity-tracker.ts— hookusePageTracking(): catatpage_enter+page_leavedengan durasi/api/v1/activitysaat user leave page (viabeforeunload+visibilitychange){ feature: 'asset-management', action: 'view', duration_seconds: 45 }Fitur yang Dilacak
dashboard/dashboardprofile/profileasset_management/asset-managementadmin_users/admin/permissionsticketing/ticketinggitea_issues/gitea/issuesgitea_repos/gitea/reposmail/mailmonitoring/monitoringkpi/kpiAdmin Activity Dashboard (
/admin/activity)2. NAS (QNAP) Login Tracking
Pendekatan
QNAP tidak punya webhook login. Opsi terbaik: polling system log via SSH periodik.
ssh -i ~/.ssh/id_ed25519 admin@10.100.1.10/var/log/connection.logatau via APIGET /cgi-bin/authLogin.cgiGET /api/v2/system/log(QTS 5.x)Implementasi
/api/v2/system/loggeonet-console(ataugeonet-kpi) — pull NAS log setiap 15 menitexternal_login_logs(source: 'nas'|'gitea', username, logged_at, ip, metadata)3. Gitea Login & Activity Tracking
Pendekatan
Gitea punya Events API — tidak perlu parsing log.
external_login_logsImplementasi
GET /api/v1/admin/userstiap malam → updateexternal_login_logs(source: 'gitea')Permission
activity.view_ownactivity.view_allGitea Integration (
git.gisportal.id)Status
10.100.1.41:3000→ domaingit.gisportal.id/api/v1/) — tidak perlu install apapun, langsung integrasigit.gisportal.id/api/swaggerAuth Strategy
Pilihan: OAuth2 (rekomendasi)
https://my.gisportal.id/auth/gitea/callbackAPI Endpoint yang Digunakan
FE Tasks
Setup & Auth
src/lib/gitea-client.ts— wrapper API dengan Bearer tokenGET /api/gitea/callback— handle OAuth callback, simpan tokengitea_tokenke user session/storeHalaman Issues (
/gitea/issues)Halaman Repo Explorer (
/gitea/repos)Permission (tambah ke group_permissions)
gitea.viewgitea.create_issuegitea.manageCatatan
Content / Posting Microservice (
geonet-content)Saran Profesional
Gunakan pola Headless CMS + custom API — bukan CMS full seperti WordPress.
Ini memberi kontrol penuh atas schema, permission berbasis LDAP group, dan integrasi ke push notification.
Stack yang Disarankan
super-apps, pathcontent/)Pillowsaat upload (multi-resolusi: 400px, 800px)Model Data
Post
API Endpoints
GET /posts— list posting (filter: status, kategori, tag; sort: date/views/likes/comments/priority)GET /posts/:slug— detail + increment view_countPOST /posts— buat posting (butuh permissioncontent.create)PUT /posts/:id— edit posting (butuh permissioncontent.editatau own post)DELETE /posts/:id— hapus (butuh permissioncontent.manage)POST /posts/:id/like— toggle like (user LDAP)GET /posts/:id/comments— list komentar + replyPOST /posts/:id/comments— tambah komentarPUT /admin/posts/reorder— ubah urutan priority (butuh permissioncontent.manage)POST /admin/posts/:id/thumbnail— upload + resize thumbnail ke OSSPermission LDAP Group (tambah ke group_permissions)
content.viewcontent.createcontent.editcontent.manageKonfigurasi Tampilan (Admin Panel)
date_created|views|likes|comments|prioritypublished_atdi masa depan)Setup Backend
geonet-contentservice (FastAPI + SQLAlchemy + PostgreSQL)content/thumbnails/)UPDATE ... SET view_count = view_count + 1)content.gisportal.id(internal) atau lewatmy.gisportal.id/api/contentX-LDAP-Username+X-LDAP-Groups(diteruskan dari geonet-console)FE Integration (
/home &/posts)/posts/:slugdengan body rich text, komentar bersarangContent API Client (
src/lib/content-client.ts)getPosts(params)— list dengan filter & sortgetPost(slug)— detailcreatePost(body)/updatePost(id, body)toggleLike(postId)getComments(postId)/addComment(postId, body)reorderPosts(orderedIds)uploadThumbnail(postId, file)FE
my.gisportal.id
│
├─ Dashboard
├─ Profile (Action : Edit Profile, Ganti Password, Test Email)
├─ Ticketing
├─ Asset Management
├─ GeoNetAgent
├─ Monitoring
└─ Mail
│
├─ Inbox
├─ Sent
├─ Draft
├─ Contacts
├─ Calendar
├─ Tasks
└─ Rules
Microservices
Mailserver (Mailcow)
Setup
Install Thunderbird
KPI Dashboard (
geonet-kpi)Dependency (semua harus sudah running)
Arsitektur
geonet-kpi— FastAPI aggregator, bukan BI tool besarkpi.gisportal.id(internal) atau lewatconsole.gisportal.id/api/kpiMetrik KPI Karyawan
Metrik KPI IT/Operasional
API Endpoints (
geonet-kpi)Permission (tambah ke group_permissions)
kpi.view_ownkpi.view_teamkpi.manageFE Tasks
Dashboard KPI IT/Ops (
/kpi/ops)Dashboard KPI Karyawan (
/kpi/employee)Admin: KPI Config (
/admin/kpi)Notifikasi KPI
Mikrotik
Windows Server 2012 R2 Active Directory
ToDo
Zammad → integrasi feedback → halaman /ticket → baru Mailcow