d5edbe2134
- Halaman Nilai: tabel "Nilai per Komponen" (rata-rata skor mentah tiap sesi, bisa diedit langsung) berdampingan dengan grid Sub-CPMK yang tetap presisi; kolom persentase ternilai di Hasil Ketercapaian. - Komponen Tugas: sesi bisa menyasar subset Sub-CPMK (RPS tetap batasannya), lengkap dengan field ala RTM (bentuk tugas, deskripsi, metode, luaran, indikator/bobot, jadwal) dan tombol isi-otomatis per bentuk tugas. - RPS: auto-save berkala sebagai draft, tombol ke atas, validasi total bobot komponen 100% saat ditandai selesai, komponen berbobot kosong disembunyikan dari halaman Nilai. - Admin: tampilkan kelas yang tersedia dari data mahasiswa saat mengatur penugasan dosen per kelas. - Perbaikan step="any" pada input nilai (mencegah validasi HTML5 menolak nilai desimal hasil roll-up). - Tambah METODOLOGI_ASESMEN_KOMPONEN.md: dokumentasi metodologi Sub-CPMK vs komponen, termasuk skenario tugas menyasar sebagian Sub-CPMK. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
195 lines
12 KiB
HTML
195 lines
12 KiB
HTML
{% extends "base.html" %}
|
||
{% block judul %}Nilai {{ komponen.nama }} — {{ peta.nama }} — Informatika UNTAN{% endblock %}
|
||
{% block isi %}
|
||
<div class="nav-baris">
|
||
<div>MK ini: <a href="/rps/{{ peta.kode }}">RPS</a> · <a href="/nilai/{{ peta.kode }}">Input Nilai</a> · <b>{{ komponen.nama }}</b> · <a href="/portofolio/{{ peta.kode }}">Portofolio</a></div>
|
||
</div>
|
||
|
||
<h1>Isi Nilai — {{ komponen.nama }} <span style="color:var(--grey)">({{ peta.nama }})</span></h1>
|
||
|
||
<p class="keterangan">
|
||
Nilai di sini digabung ke Sub-CPMK yang diukur komponen ini:
|
||
{% for s in komponen.subs %}<b>{{ s }}</b>{{ ', ' if not loop.last }}{% endfor %}
|
||
{% if komponen.bobot %}(bobot komponen {{ komponen.bobot }}%){% endif %}.
|
||
{% if komponen.ulang %}
|
||
Komponen ini <b>boleh diisi berkali-kali</b> (mis. beberapa kali kuis sepanjang
|
||
semester) — nilai tiap sesi dirata-rata otomatis per Sub-CPMK. Bila satu Sub-CPMK
|
||
juga diukur komponen lain, hasil akhirnya dirata tertimbang bobot antar-komponen.
|
||
{% else %}
|
||
Komponen ini <b>hanya satu sesi per semester</b> — menyimpan lagi memperbarui
|
||
(menimpa) sesi yang sudah ada, bukan menambah sesi baru.
|
||
{% endif %}
|
||
Jika mahasiswa perlu nilai berbeda antar Sub-CPMK dalam komponen yang sama
|
||
(mis. UTS dengan beberapa kelompok soal), isi lewat
|
||
<a href="/nilai/{{ peta.kode }}">grid per Sub-CPMK</a> di halaman utama nilai, bukan di sini.
|
||
</p>
|
||
|
||
{% if pesan %}<div class="info">{{ pesan }}</div>{% endif %}
|
||
|
||
{% if komponen.ulang and daftar_sesi %}
|
||
<h2 class="bagian">SESI TERSIMPAN</h2>
|
||
<table class="grid" style="max-width:{{ '900px' if komponen.tugas else '560px' }}">
|
||
<thead><tr><th>Sesi</th>{% if komponen.tugas %}<th>Sub-CPMK</th><th style="width:130px">Jadwal</th>{% endif %}<th class="tengah" style="width:120px">Mahasiswa Terisi</th><th style="width:60px"></th></tr></thead>
|
||
<tbody>
|
||
{% for s in daftar_sesi %}
|
||
<tr{% if loop.index0 == edit_id %} style="background:var(--blue-fill)"{% endif %}>
|
||
<td>{{ s.label }}{% if komponen.tugas and s.deskripsi %}<br><span style="font-size:12px;color:var(--grey);font-style:italic">{{ s.deskripsi }}</span>{% endif %}</td>
|
||
{% if komponen.tugas %}<td>{{ (s.subs or komponen.subs)|join(', ') }}</td><td>{{ s.jadwal or '—' }}</td>{% endif %}
|
||
<td class="tengah">{{ (s.nilai or {})|length }}</td>
|
||
<td><a href="/nilai/{{ peta.kode }}/komponen/{{ i }}?sesi_id={{ loop.index0 }}">Edit</a></td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% endif %}
|
||
|
||
<h2 class="bagian">{{ 'EDIT SESI' if edit_id < daftar_sesi|length else 'SESI BARU' }} — {{ label_awal }}</h2>
|
||
<form method="post" action="/nilai/{{ peta.kode }}/komponen/{{ i }}">
|
||
<input type="hidden" name="edit_id" value="{{ edit_id }}">
|
||
{% if komponen.ulang %}
|
||
<label style="display:block;margin-bottom:10px">{{ 'Judul Tugas' if komponen.tugas else 'Nama sesi' }}
|
||
<input type="text" name="label" value="{{ label_awal }}" style="display:block;margin-top:4px;max-width:480px">
|
||
</label>
|
||
{% else %}
|
||
<input type="hidden" name="label" value="{{ label_awal }}">
|
||
{% endif %}
|
||
{% if komponen.tugas %}
|
||
<div style="margin-bottom:10px">
|
||
<div>Sub Capaian Pembelajaran Mata Kuliah <span style="font-weight:normal;color:var(--grey)">(bawaan semua tercentang, sesuai yang ditentukan RPS untuk komponen ini — kurangi bila tugas lain akan menyasar sisanya; bobot komponen ini tetap {{ komponen.bobot }}%)</span></div>
|
||
<div class="pilih-sub">
|
||
{% for s in subs_pilihan %}
|
||
<label><input type="checkbox" name="subs" value="{{ s.kode }}" {% if s.kode in subs_terpilih %}checked{% endif %}>{{ s.kode }} — {{ s.uraian }}</label>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
<label style="display:block;margin-bottom:10px">Bentuk Tugas
|
||
<span style="display:flex;align-items:center;gap:8px;margin-top:4px">
|
||
<select name="bentuk_tugas" id="bentuk_tugas" onchange="toggleIsiOtomatis()" style="max-width:280px">
|
||
<option value="">— pilih —</option>
|
||
{% for opsi in ["Diskusi", "PjBL", "CBL", "Esai", "Tes"] %}
|
||
<option value="{{ opsi }}" {% if rtm.bentuk_tugas == opsi %}selected{% endif %}>{{ opsi }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
<button type="button" class="tombol garis" id="tombol_isi_otomatis" onclick="isiOtomatisTugas()" {% if not rtm.bentuk_tugas %}hidden{% endif %}>Isi Otomatis</button>
|
||
</span>
|
||
</label>
|
||
<label style="display:block;margin-bottom:10px">Deskripsi Tugas <span style="font-weight:normal;color:var(--grey)">(opsional — soal cerita, esai, kasus, atau proyek yang harus diselesaikan mahasiswa)</span>
|
||
<textarea name="deskripsi" id="rtm_deskripsi" rows="4" style="display:block;margin-top:4px;max-width:760px;width:100%">{{ rtm.deskripsi }}</textarea>
|
||
</label>
|
||
<label style="display:block;margin-bottom:10px">Metode Pengerjaan Tugas <span style="font-weight:normal;color:var(--grey)">(opsional — langkah-langkah pengerjaan)</span>
|
||
<textarea name="metode_pengerjaan" id="rtm_metode" rows="3" style="display:block;margin-top:4px;max-width:760px;width:100%">{{ rtm.metode_pengerjaan }}</textarea>
|
||
</label>
|
||
<label style="display:block;margin-bottom:10px">Bentuk dan Format Luaran <span style="font-weight:normal;color:var(--grey)">(opsional)</span>
|
||
<textarea name="luaran" id="rtm_luaran" rows="2" style="display:block;margin-top:4px;max-width:760px;width:100%">{{ rtm.luaran }}</textarea>
|
||
</label>
|
||
<label style="display:block;margin-bottom:10px">Indikator, Kriteria dan Bobot Penilaian <span style="font-weight:normal;color:var(--grey)">(opsional — dokumentasi rubrik; bobot komponen di aplikasi tetap {{ komponen.bobot }}%, tak dihitung dari sini)</span>
|
||
<textarea name="indikator_bobot" id="rtm_indikator" rows="4" style="display:block;margin-top:4px;max-width:760px;width:100%">{{ rtm.indikator_bobot }}</textarea>
|
||
</label>
|
||
<label style="display:block;margin-bottom:10px">Jadwal Pelaksanaan <span style="font-weight:normal;color:var(--grey)">(opsional)</span>
|
||
<input type="text" name="jadwal" id="rtm_jadwal" value="{{ rtm.jadwal }}" style="display:block;margin-top:4px;max-width:480px">
|
||
</label>
|
||
<label style="display:block;margin-bottom:10px">Lain-lain <span style="font-weight:normal;color:var(--grey)">(opsional)</span>
|
||
<textarea name="lain_lain" rows="2" style="display:block;margin-top:4px;max-width:760px;width:100%">{{ rtm.lain_lain }}</textarea>
|
||
</label>
|
||
<label style="display:block;margin-bottom:10px">Daftar Rujukan <span style="font-weight:normal;color:var(--grey)">(opsional)</span>
|
||
<textarea name="rujukan" rows="2" style="display:block;margin-top:4px;max-width:760px;width:100%">{{ rtm.rujukan }}</textarea>
|
||
</label>
|
||
{% endif %}
|
||
<h2 class="bagian">NILAI MAHASISWA</h2>
|
||
<div class="gulir" style="max-height:480px;overflow-y:auto">
|
||
<table class="grid">
|
||
<thead>
|
||
<tr>
|
||
<th style="width:44px" class="tengah">No.</th>
|
||
<th style="width:112px">NIM</th>
|
||
<th style="min-width:150px">Nama</th>
|
||
<th class="tengah" style="width:140px">Nilai (0–100)</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for m in grid %}
|
||
<tr>
|
||
<td class="tengah">{{ loop.index }}
|
||
<input type="hidden" name="nim_{{ loop.index0 }}" value="{{ m.nim }}">
|
||
<input type="hidden" name="nama_{{ loop.index0 }}" value="{{ m.nama }}"></td>
|
||
<td>{{ m.nim }}</td>
|
||
<td>{{ m.nama }}</td>
|
||
<td class="isian"><input type="number" name="nilai_{{ loop.index0 }}"
|
||
min="0" max="100" step="any"
|
||
value="{{ '%g'|format(m.nilai_awal) if m.nilai_awal is not none else '' }}"></td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="aksi-baris">
|
||
<span style="color:var(--grey);font-size:13px">Disimpan atas nama <b>{{ user.nama }}</b></span>
|
||
<span class="spacer"></span>
|
||
<button class="tombol" type="submit">Simpan Sesi Ini</button>
|
||
</div>
|
||
</form>
|
||
|
||
{% if komponen.tugas %}
|
||
<script>
|
||
const BENTUK_TEMPLATE = {
|
||
Diskusi: {
|
||
deskripsi: 'Diskusikan {SUBCPMK} melalui studi kasus/topik terkait materi ini. Kelompok kecil (3-5 orang) menganalisis permasalahan dan menyusun rekomendasi.',
|
||
metode: '1) Baca materi & bahan diskusi;\n2) Diskusi kelompok;\n3) Susun poin-poin kesimpulan;\n4) Presentasikan hasil diskusi.',
|
||
luaran: 'Notulen/rangkuman diskusi kelompok dalam bentuk dokumen tertulis (maks. 3 halaman).',
|
||
indikator: 'Ketepatan analisis (30%)\nKeaktifan berdiskusi (30%)\nKejelasan kesimpulan (20%)\nKerja sama kelompok (20%)\nBobot: 100%',
|
||
jadwal: '1 minggu',
|
||
},
|
||
PjBL: {
|
||
deskripsi: 'Kerjakan proyek yang menghasilkan solusi nyata terkait {SUBCPMK}, mulai dari perencanaan hingga penyerahan hasil akhir.',
|
||
metode: '1) Identifikasi masalah;\n2) Rencanakan solusi;\n3) Kerjakan proyek secara bertahap;\n4) Uji & perbaiki;\n5) Serahkan hasil akhir beserta laporan.',
|
||
luaran: 'Produk/prototipe beserta laporan tertulis yang menjelaskan proses pengerjaan.',
|
||
indikator: 'Perencanaan (20%)\nProses pengerjaan (30%)\nKualitas hasil akhir (30%)\nLaporan (20%)\nBobot: 100%',
|
||
jadwal: '2-3 minggu',
|
||
},
|
||
CBL: {
|
||
deskripsi: 'Analisis studi kasus terkait {SUBCPMK}; identifikasi permasalahan dan usulkan solusi berbasis konsep yang dipelajari.',
|
||
metode: '1) Baca & pahami kasus;\n2) Identifikasi masalah inti;\n3) Terapkan konsep untuk analisis;\n4) Rumuskan solusi;\n5) Tulis laporan.',
|
||
luaran: 'Laporan analisis kasus tertulis, memuat identifikasi masalah, analisis, dan solusi yang diusulkan.',
|
||
indikator: 'Ketepatan identifikasi masalah (25%)\nKedalaman analisis (35%)\nKetepatan solusi (25%)\nSistematika laporan (15%)\nBobot: 100%',
|
||
jadwal: '1-2 minggu',
|
||
},
|
||
Esai: {
|
||
deskripsi: 'Tulis esai mengenai {SUBCPMK} sepanjang 800-1200 kata, disertai argumen dan referensi yang relevan.',
|
||
metode: '1) Tentukan tesis/argumen utama;\n2) Kumpulkan referensi pendukung;\n3) Susun kerangka esai;\n4) Tulis draf;\n5) Revisi & finalisasi.',
|
||
luaran: 'Esai tertulis (800-1200 kata) dalam format dokumen (PDF/Word).',
|
||
indikator: 'Ketepatan argumen (30%)\nKedalaman analisis (30%)\nSistematika penulisan (20%)\nPenggunaan referensi (20%)\nBobot: 100%',
|
||
jadwal: '1 minggu',
|
||
},
|
||
Tes: {
|
||
deskripsi: 'Kerjakan soal-soal tes tertulis terkait {SUBCPMK} sesuai instruksi yang diberikan.',
|
||
metode: '1) Baca instruksi & soal dengan teliti;\n2) Kerjakan sesuai alokasi waktu;\n3) Periksa kembali jawaban sebelum dikumpulkan.',
|
||
luaran: 'Lembar jawaban tes (tertulis/daring).',
|
||
indikator: 'Ketepatan jawaban per butir soal, dijumlah sesuai bobot masing-masing.\nBobot: 100%',
|
||
jadwal: '1x pertemuan (sesuai jadwal tes)',
|
||
},
|
||
};
|
||
|
||
function isiOtomatisTugas() {
|
||
const bentuk = document.getElementById('bentuk_tugas').value;
|
||
const tmpl = BENTUK_TEMPLATE[bentuk];
|
||
if (!tmpl) return;
|
||
const checked = Array.from(document.querySelectorAll('.pilih-sub input[name="subs"]:checked')).map(cb => cb.value);
|
||
const subcpmk = checked.length ? checked.join(', ') : 'Sub-CPMK terkait';
|
||
const isi = (id, teks) => {
|
||
const el = document.getElementById(id);
|
||
if (el && !el.value.trim()) el.value = teks.replace('{SUBCPMK}', subcpmk);
|
||
};
|
||
isi('rtm_deskripsi', tmpl.deskripsi);
|
||
isi('rtm_metode', tmpl.metode);
|
||
isi('rtm_luaran', tmpl.luaran);
|
||
isi('rtm_indikator', tmpl.indikator);
|
||
isi('rtm_jadwal', tmpl.jadwal);
|
||
}
|
||
function toggleIsiOtomatis() {
|
||
const bentuk = document.getElementById('bentuk_tugas').value;
|
||
document.getElementById('tombol_isi_otomatis').hidden = !bentuk;
|
||
}
|
||
</script>
|
||
{% endif %}
|
||
{% endblock %}
|