Files
OBE-Mapping/app/templates/beranda.html
Power BI Dev a45b08b00e Tambah peran Dosen MK/RPS+MK, komponen penilaian baku, dan bantu isi RPS
- Peran dosen dipecah jadi dosen_mk (nilai & portofolio saja, RPS baca-only)
  dan dosen_rps_mk (bisa edit RPS juga); migrasi otomatis dari skema lama.
- Rekap Bobot Penilaian RPS pakai 6 komponen teknik asesmen baku prodi;
  total wajib tepat 100%, komponen individual boleh dikosongkan.
- Dropdown & daftar Sub-CPMK tak lagi terpotong teksnya.
- Bagian F (Rencana Mingguan): tombol "Isi Otomatis" per baris (termasuk
  usulan Bobot) yang muncul setelah Sub-CPMK dipilih, plus panel contoh
  teks bantu per kolom.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 08:45:56 +07:00

141 lines
6.5 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block isi %}
<div class="kpi-baris" title="Persentase dihitung dari MK pada semester terpilih — hijau ≥ 75 %, kuning 4074 %, merah < 40 %">
<div><b id="kpi-mk">{{ daftar|length }}</b> <span>mata kuliah</span></div>
<div><b id="kpi-rps">{{ n_selesai }}</b> <span>RPS selesai</span> <span class="kpi-pct" id="pct-rps"></span></div>
<div><b id="kpi-draft">{{ n_draft }}</b> <span>RPS draft</span></div>
<div><b id="kpi-nilai">{{ st_nilai|length }}</b> <span>MK setor nilai</span> <span class="kpi-pct" id="pct-nilai"></span></div>
<div><b id="kpi-porto">{{ st_porto.values()|selectattr('status', 'equalto', 'selesai')|list|length }}</b> <span>portofolio selesai</span> <span class="kpi-pct" id="pct-porto"></span></div>
</div>
{% if user.role != 'kaprodi' %}
{% if hanya_saya %}
<div class="info" style="margin-top:0">Menampilkan <b>{{ daftar|length }} MK yang Anda ampu</b>.
RPS mata kuliah lain tetap terbuka baca — <a href="/?semua=1">tampilkan seluruh {{ n_total }} MK</a>.</div>
{% elif mk_saya %}
<div class="info" style="margin-top:0">Menampilkan seluruh {{ n_total }} MK —
<a href="/">kembali ke MK yang Anda ampu saja</a>.</div>
{% else %}
<div class="peringatan" style="margin-top:0">Belum ada MK yang ditugaskan kepada
Anda — hubungi kaprodi agar menetapkan penugasan di halaman Kelola Akun.
Sementara itu seluruh MK ditampilkan (hanya-baca).</div>
{% endif %}
{% endif %}
<div class="filter-baris">
<label for="filter-smt">Tampilkan semester:</label>
<select id="filter-smt" style="width:auto">
<option value="">Semua</option>
<option value="ganjil">Ganjil (1, 3, 5, 7)</option>
<option value="genap">Genap (2, 4, 6, 8)</option>
{% for s in smt.values()|select|unique|sort %}
<option value="{{ s }}">Semester {{ s }}</option>
{% endfor %}
</select>
<span id="filter-info" class="keterangan" style="margin:0"></span>
</div>
{% macro stempel(st) -%}
{% if st and st.status == 'selesai' %}<span class="stamp stamp-ok">SELESAI</span>
{% elif st %}<span class="stamp stamp-draft">DRAFT</span>
{% else %}<span class="stamp stamp-no">BELUM</span>{% endif %}
{%- endmacro %}
<div class="gulir">
<table class="grid">
<thead>
<tr>
<th style="width:56px">No.</th>
<th style="width:112px">Kode</th>
<th class="tengah" style="width:52px">Smt</th>
<th>Mata Kuliah</th>
<th style="width:150px">Pengampu</th>
<th style="width:120px">CPL Dipikul</th>
<th class="tengah" style="width:104px">RPS</th>
<th class="tengah" style="width:104px">Nilai</th>
<th class="tengah" style="width:104px">Portofolio</th>
<th style="width:170px">Pemutakhiran Terakhir</th>
</tr>
</thead>
<tbody>
{% for mk in daftar %}
{% set st = status.get(mk.kode) %}
{% set sn = st_nilai.get(mk.kode) %}
{% set sp = st_porto.get(mk.kode) %}
<tr data-smt="{{ smt.get(mk.kode) or '' }}"
data-rps="{{ st.status if st else '' }}"
data-nilai="{{ sn.status if sn else '' }}"
data-porto="{{ sp.status if sp else '' }}">
<td class="tengah">{{ mk.no }}</td>
<td>{{ mk.kode }}</td>
<td class="tengah">{{ smt.get(mk.kode) or '—' }}</td>
<td>{{ mk.nama }}<br>
<span style="font-size:12px;color:var(--grey)">{{ mk.n_cpmk }} CPMK · {{ mk.n_sub }} Sub-CPMK</span>
</td>
<td style="font-size:13px">{{ pengampu.get(mk.kode, [])|join(', ') or '—' }}</td>
<td>{{ mk.cpls|map('replace','CPL-','')|join(', ') }}</td>
<td class="tengah"><a href="/rps/{{ mk.kode }}" style="text-decoration:none">{{ stempel(st) }}</a></td>
<td class="tengah"><a href="/nilai/{{ mk.kode }}" style="text-decoration:none">{{ stempel(sn) }}</a></td>
<td class="tengah"><a href="/portofolio/{{ mk.kode }}" style="text-decoration:none">{{ stempel(sp) }}</a></td>
<td style="font-size:12.5px">
{% set terakhir = [st, sn, sp]|select|sort(attribute='updated_at')|last %}
{% if terakhir %}{{ terakhir.updated_at }}{% if terakhir.updated_by %} — {{ terakhir.updated_by }}{% endif %}{% else %}—{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<script>
(function () {
var pilih = document.getElementById('filter-smt');
var info = document.getElementById('filter-info');
var baris = document.querySelectorAll('table.grid tbody tr');
function cocok(tr, v) {
var smt = tr.dataset.smt;
return v === '' ? true :
v === 'ganjil' ? smt !== '' && smt % 2 === 1 :
v === 'genap' ? smt !== '' && smt % 2 === 0 :
smt === v;
}
function isiPct(id, n, total) {
var el = document.getElementById(id);
if (!total) { el.textContent = ''; el.className = 'kpi-pct'; return; }
var p = Math.round(100 * n / total);
el.textContent = p + ' %';
el.className = 'kpi-pct ' +
(p >= 75 ? 'kpi-hijau' : p >= 40 ? 'kpi-kuning' : 'kpi-merah');
}
function perbarui() {
var v = pilih.value, n = 0, rSel = 0, rDraft = 0, nilai = 0, porto = 0;
baris.forEach(function (tr) {
var tampil = cocok(tr, v);
tr.style.display = tampil ? '' : 'none';
if (!tampil) return;
n++;
if (tr.dataset.rps === 'selesai') rSel++;
if (tr.dataset.rps === 'draft') rDraft++;
if (tr.dataset.nilai !== '') nilai++;
if (tr.dataset.porto === 'selesai') porto++;
});
document.getElementById('kpi-mk').textContent = n;
document.getElementById('kpi-rps').textContent = rSel;
document.getElementById('kpi-draft').textContent = rDraft;
document.getElementById('kpi-nilai').textContent = nilai;
document.getElementById('kpi-porto').textContent = porto;
isiPct('pct-rps', rSel, n);
isiPct('pct-nilai', nilai, n);
isiPct('pct-porto', porto, n);
info.textContent = v === '' ? '' : n + ' dari ' + baris.length + ' MK ditampilkan';
}
pilih.addEventListener('change', perbarui);
perbarui();
})();
</script>
<p class="keterangan" style="margin-top:10px">Klik stempel untuk membuka form terkait. Alur per MK: <b>RPS</b> (rencana &amp; bobot) → <b>Nilai</b> (unggah Excel / rata-rata) → <b>Portofolio</b> (refleksi &amp; dokumen akhir). Rekap prodi menggulung otomatis dari nilai yang masuk.</p>
{% endblock %}