Gabungkan aplikasi RPS & Portofolio OBE (dashboard jadi bagian aplikasi)

Dashboard pemetaan statis kini dilayani aplikasi di /dashboard
(app/static/dashboard.html). Fitur lengkap Tahap 1-4 + dasbor monitoring,
menu global, filter semester, input nilai langsung, penggabungan nilai
team teaching, tabel bisa urut. Dockerfile berubah dari nginx statis ke
uvicorn/FastAPI: healthcheck, proxy-headers, volume /data (SQLite).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Power BI Dev
2026-07-18 12:05:28 +07:00
parent 3405dc21ff
commit 9be6bd03e3
42 changed files with 11366 additions and 53 deletions
+79
View File
@@ -0,0 +1,79 @@
{% extends "base.html" %}
{% block judul %}Rekap Ketercapaian CPL/CPMK — Informatika UNTAN{% endblock %}
{% block isi %}
<h1>Rekap Ketercapaian CPL &amp; CPMK — {{ hasil.tahun }}</h1>
<div class="kpi-baris">
<div><b>{{ hasil.n_mk_setor }}</b> <span>MK sudah setor nilai</span></div>
<div><b>{{ hasil.ambang|round(0)|int }}</b> <span>ambang ketercapaian</span></div>
<div><b>{{ 'SKS' if hasil.metode == 'sks' else 'Bagi rata' }}</b> <span>metode antar-MK</span></div>
<div><b>{{ cpl_urut|selectattr('tercapai')|list|length }}</b> <span>CPL tercapai</span></div>
<div><b>{{ cpl_urut|rejectattr('skor', 'none')|rejectattr('tercapai')|list|length }}</b> <span>CPL di bawah ambang</span></div>
</div>
{% if hasil.n_mk_setor == 0 %}
<div class="peringatan">Belum ada MK yang menyetor nilai — seluruh CPL berstatus "belum terukur". Mulai dari halaman <b>Input Nilai</b> tiap MK di beranda.</div>
{% endif %}
<h2 class="bagian">KETERCAPAIAN CPL</h2>
<p class="keterangan">Kelengkapan bukti = berapa dari seluruh titik ukur (MK × CPMK pemikul) yang sudah menyetor nilai. Skor dari bukti yang belum lengkap harus dibaca hati-hati.</p>
<div class="gulir">
<table class="grid">
<thead>
<tr>
<th style="width:80px">CPL</th><th>Deskripsi</th>
<th class="tengah" style="width:80px">Skor</th>
<th class="tengah" style="width:130px">Status</th>
<th class="tengah" style="width:120px">Kelengkapan Bukti</th>
<th style="width:210px">Penyumbang Terlemah</th>
</tr>
</thead>
<tbody>
{% for c in cpl_urut %}
<tr>
<td class="tengah"><b>{{ c.kode }}</b></td>
<td>{{ c.desk[:130] }}{% if c.desk|length > 130 %}…{% endif %}</td>
<td class="tengah">{% if c.skor is not none %}<b>{{ '%.2f'|format(c.skor) }}</b>{% else %}—{% endif %}</td>
<td class="tengah">
{% if c.skor is none %}<span class="stamp stamp-draft">BELUM TERUKUR</span>
{% elif c.tercapai %}<span class="stamp stamp-ok">TERCAPAI</span>
{% else %}<span class="stamp stamp-no">DI BAWAH AMBANG</span>{% endif %}
</td>
<td class="tengah">{{ c.n_mk_setor }}/{{ c.n_mk_pemikul }} titik ukur{% if c.ada_agregat %}<br><span style="color:var(--red);font-size:11px">ada bukti agregat</span>{% endif %}</td>
<td>
{% if c.mk_terlemah %}
{{ c.cpmk_terlemah }} — {{ nama_mk.get(c.mk_terlemah[0], c.mk_terlemah[0]) }}
({{ '%.1f'|format(c.mk_terlemah[1]) }})
{% else %}—{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<h2 class="bagian">KETERCAPAIAN CPMK (TINGKAT PRODI)</h2>
<div class="gulir">
<table class="grid">
<thead>
<tr>
<th style="width:110px">CPMK</th>
<th style="width:120px">CPL Didukung</th>
<th class="tengah" style="width:80px">Skor</th>
<th class="tengah" style="width:130px">MK Setor / Pemikul</th>
<th style="width:230px">MK Terlemah</th>
</tr>
</thead>
<tbody>
{% for c in cpmk_urut %}
<tr>
<td class="tengah">{{ c.kode }}</td>
<td class="tengah">{{ c.cpl|join(', ') }}</td>
<td class="tengah">{% if c.skor is not none %}<b>{{ '%.2f'|format(c.skor) }}</b>{% else %}—{% endif %}</td>
<td class="tengah">{{ c.n_setor }}/{{ c.n_pemikul }}</td>
<td>{% if c.mk_terlemah %}{{ nama_mk.get(c.mk_terlemah[0], c.mk_terlemah[0]) }} ({{ '%.1f'|format(c.mk_terlemah[1]) }}){% else %}—{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}