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>
This commit is contained in:
Power BI Dev
2026-07-21 08:45:56 +07:00
parent 9be6bd03e3
commit a45b08b00e
7 changed files with 175 additions and 45 deletions
+63 -8
View File
@@ -16,8 +16,10 @@
{% if pesan %}<div class="info">{{ pesan }}</div>{% endif %}
{% if not boleh_edit %}
<div class="info">Anda bukan pengampu MK ini — form terbuka <b>hanya untuk dibaca</b>.
Hubungi kaprodi bila penugasan MK Anda perlu diubah.</div>
<div class="info">Anda tidak memiliki hak edit RPS untuk MK ini — form terbuka
<b>hanya untuk dibaca</b>. Ini karena Anda bukan pengampu MK ini, atau peran Anda
<b>Dosen MK</b> (hanya mengelola nilai &amp; portofolio). Hubungi kaprodi bila ini
perlu diubah.</div>
{% endif %}
{% if tahun_lain and boleh_edit %}
@@ -97,7 +99,23 @@
<textarea name="media" rows="2" placeholder="mis. LMS (e-learning UNTAN), LCD proyektor, perangkat lunak pendukung.">{{ f.media }}</textarea>
<h2 class="bagian">F. RENCANA MINGGUAN <span id="total-bobot-f" style="font-weight:normal">— total bobot: <b>0</b>%</span></h2>
<p class="keterangan">Minggu 8 = UTS, minggu 16 = UAS. Total bobot seluruh minggu harus 100 %.</p>
<p class="keterangan">Minggu 8 = UTS, minggu 16 = UAS. Total bobot seluruh minggu harus 100 %.
{% if boleh_edit %}Pilih Sub-CPMK lalu klik <b>Isi Otomatis</b> untuk mengisi kolom kosong dengan teks
bantu (termasuk usulan Bobot — UTS 20%, UAS 30%, minggu biasa 3,5% — sesuaikan lagi agar totalnya
pas 100%).{% endif %}</p>
{% if boleh_edit %}
<details style="margin:0 0 10px">
<summary style="cursor:pointer;color:var(--blue);font-size:13px">Lihat contoh teks bantu per kolom</summary>
<div class="info" style="margin-top:6px;line-height:1.7">
<b>Indikator</b> — turunan Sub-CPMK, mis. "Mahasiswa mampu menjelaskan …"; "Ketepatan dan kelengkapan dalam …"<br>
<b>Kriteria &amp; Teknik</b> — mis. "Rubrik holistik; tes tertulis" / "Ketepatan jawaban; unjuk kerja" / "Kelengkapan tugas; observasi"<br>
<b>Tatap Muka</b> — mis. "Ceramah, diskusi, tanya jawab [TM: 2x50 menit]" / "Studi kasus &amp; presentasi kelompok [TM: 2x50 menit]"<br>
<b>Daring</b> — mis. "Membaca modul &amp; kuis di LMS [BT+BM: 2x60 menit]" / "Diskusi forum LMS [BT+BM: 2x60 menit]"<br>
<b>Kegiatan Pembelajaran</b> — mis. "Mahasiswa menyimak paparan dosen, berdiskusi, dan mengerjakan latihan terkait materi minggu ini."<br>
<b>Materi [Pustaka]</b> — rujuk nomor pustaka di Bagian H, mis. "Bab 3 (Pustaka Utama #1)"
</div>
</details>
{% endif %}
<div class="gulir">
<table class="grid" id="tabel-f">
<thead>
@@ -122,14 +140,20 @@
<tr class="{% if m.ke == 8 %}uts{% elif m.ke == 16 %}uas{% endif %}">
<td class="tengah">{{ m.ke }}</td>
<td class="isian">
<select name="m{{ m.ke }}_sub">
<select name="m{{ m.ke }}_sub" {% if boleh_edit %}onchange="document.getElementById('btn-isi-m{{ m.ke }}').style.display = this.value ? '' : 'none'"{% endif %}>
<option value="">— pilih —</option>
{% for s in peta.subs %}
<option value="{{ s.kode }}" {% if m.sub == s.kode %}selected{% endif %}>{{ s.kode }} — {{ s.uraian[:60] }}{% if s.uraian|length > 60 %}…{% endif %}</option>
<option value="{{ s.kode }}" {% if m.sub == s.kode %}selected{% endif %}>{{ s.kode }} — {{ s.uraian }}</option>
<option disabled>──────────────────────</option>
{% endfor %}
<option value="__uts__" {% if m.sub == '__uts__' %}selected{% endif %}>Sub-CPMK minggu 17 (UTS)</option>
<option value="__uas__" {% if m.sub == '__uas__' %}selected{% endif %}>Sub-CPMK minggu 915 (UAS)</option>
</select>
{% if boleh_edit %}
<button type="button" id="btn-isi-m{{ m.ke }}" class="tombol garis"
style="padding:1px 6px;font-size:10px;margin-top:4px;{% if not m.sub %}display:none{% endif %}"
onclick="isiOtomatis({{ m.ke }})" title="Isi kolom kosong dengan teks bantu dari Sub-CPMK terpilih">Isi Otomatis</button>
{% endif %}
</td>
<td class="isian"><textarea name="m{{ m.ke }}_indikator" rows="2">{{ m.indikator }}</textarea></td>
<td class="isian"><textarea name="m{{ m.ke }}_kriteria" rows="2">{{ m.kriteria }}</textarea></td>
@@ -145,7 +169,10 @@
</div>
<h2 class="bagian">G. REKAP BOBOT PENILAIAN <span id="total-bobot-g" style="font-weight:normal">— total: <b>0</b>%</span></h2>
<p class="keterangan">Centang Sub-CPMK yang dinilai tiap komponen. Setiap Sub-CPMK harus tercakup minimal satu komponen agar CPMK/CPL-nya terukur.</p>
<p class="keterangan">Enam komponen teknik asesmen baku prodi. Bobot boleh dikosongkan untuk
komponen yang tidak dipakai MK ini (opsional), tapi total seluruh komponen yang diisi harus
tepat 100%. Centang Sub-CPMK yang dinilai tiap komponen; setiap Sub-CPMK harus tercakup minimal
satu komponen agar CPMK/CPL-nya terukur.</p>
<div class="gulir">
<table class="grid">
<thead>
@@ -155,11 +182,11 @@
{% for k in f.komponen %}
{% set ki = loop.index %}
<tr>
<td class="isian"><input type="text" name="k{{ ki }}_nama" value="{{ k.nama }}"></td>
<td>{{ k.nama }}</td>
<td>
<div class="pilih-sub">
{% for s in peta.subs %}
<label><input type="checkbox" class="sub-k" name="k{{ ki }}_subs" value="{{ s.kode }}" {% if s.kode in k.subs %}checked{% endif %}>{{ s.kode }} — {{ s.uraian[:70] }}{% if s.uraian|length > 70 %}…{% endif %}</label>
<label><input type="checkbox" class="sub-k" name="k{{ ki }}_subs" value="{{ s.kode }}" {% if s.kode in k.subs %}checked{% endif %}>{{ s.kode }} — {{ s.uraian }}</label>
{% endfor %}
</div>
</td>
@@ -194,6 +221,34 @@
</form>
<script>
const SUB_URAIAN = {{ sub_uraian | tojson | safe }};
function isiOtomatis(mg) {
const sel = document.querySelector(`select[name="m${mg}_sub"]`);
const nilai = sel ? sel.value : '';
const isi = (nama, teks) => {
const el = document.querySelector(`[name="m${mg}_${nama}"]`);
if (el && !el.value.trim()) el.value = teks;
};
if (SUB_URAIAN[nilai]) {
const uraian = SUB_URAIAN[nilai];
isi('indikator', 'Mahasiswa ' + uraian.charAt(0).toLowerCase() + uraian.slice(1));
} else if (nilai === '__uts__') {
isi('indikator', 'Mahasiswa menguasai capaian Sub-CPMK minggu 17.');
} else if (nilai === '__uas__') {
isi('indikator', 'Mahasiswa menguasai capaian Sub-CPMK minggu 915.');
} else {
return; // belum pilih Sub-CPMK — tak ada dasar untuk mengisi
}
isi('kriteria', 'Ketepatan dan kelengkapan jawaban/tugas sesuai rubrik penilaian.');
isi('metode', 'Ceramah, diskusi, dan tanya jawab [TM: 2x50 menit]');
isi('daring', 'Membaca materi & berdiskusi di LMS [BT+BM: 2x60 menit]');
isi('kegiatan', 'Mahasiswa menyimak penjelasan dosen, berdiskusi, dan mengerjakan latihan terkait materi minggu ini.');
// bobot: usulan awal (UTS/UAS lazim lebih besar) — total tetap harus disesuaikan ke 100%
isi('bobot', mg == 8 ? '20' : mg == 16 ? '30' : '3.5');
segarkan();
}
function hitungTotal(kelas, idLabel) {
let t = 0;
document.querySelectorAll(kelas).forEach(el => { t += parseFloat(el.value) || 0; });