Files
OBE-Mapping/app/static/tabel.js
T
Power BI Dev 5f615aa7e8 Rapikan tampilan nilai, ganti NPM->NIM, fitur ganti password, kunci RPS view-only
- Tampilan "Isi Per Komponen Penilaian" diganti dari tombol bertumpuk teks
  jadi tabel (Komponen/Sub-CPMK/Bobot/Status/Aksi) dengan status berupa
  stempel, lebih mudah dipindai.
- Filter pencarian MK (ketik kode/nama) di kotak penugasan dosen /admin.
- Istilah NPM diseragamkan jadi NIM di seluruh aplikasi (label, header,
  template Excel, dokumen portofolio), termasuk migrasi kolom database
  mahasiswa.npm -> nim yang aman (ALTER TABLE RENAME COLUMN, otomatis saat
  startup, tanpa kehilangan data; parser Excel tetap terima file lama
  berheader NPM).
- Fitur ganti password mandiri (/akun): verifikasi password lama, sesi lain
  otomatis keluar setelah berhasil, sesi yang dipakai tetap aktif.
- RPS: dosen RPS+MK kini bisa menyesuaikan redaksi kalimat Sub-CPMK (bagian
  D) untuk MK yang diampu -- kode & kaitan CPMK/CPL tetap dari kurikulum,
  hanya teksnya yang bisa disesuaikan. Penyesuaian otomatis konsisten di
  dropdown mingguan (F), checklist komponen (G), serta unduhan RPS &
  portofolio, tanpa menyentuh data kurikulum induk atau halaman nilai/
  dashboard prodi.
- Form RPS dibungkus <fieldset disabled> untuk dosen tanpa hak edit --
  seluruh field benar-benar terkunci (bukan cuma tombol simpan hilang).
2026-07-22 08:37:54 +07:00

76 lines
2.8 KiB
JavaScript

/* Urutkan tabel.grid dengan klik header (naik/turun).
Tabel di dalam <form> dilewati (baris berisi isian, urutan tak relevan);
baris .total selalu tetap di bawah. */
(function () {
"use strict";
function nilaiSel(tr, i) {
var td = tr.cells[i];
return td ? td.textContent.trim() : "";
}
function sebagaiAngka(t) {
// "76,2", "86 %", "18/49" → angka; "—"/kosong → null
var m = t.replace(",", ".").match(/-?\d+(\.\d+)?/);
return m ? parseFloat(m[0]) : null;
}
function pasang(tabel) {
var thead = tabel.tHead;
var tbody = tabel.tBodies[0];
if (!thead || !tbody || thead.rows.length !== 1) return;
Array.prototype.forEach.call(thead.rows[0].cells, function (th, i) {
th.classList.add("bisa-urut");
th.addEventListener("click", function () {
var naik = th.dataset.arah !== "asc";
Array.prototype.forEach.call(thead.rows[0].cells, function (h) {
delete h.dataset.arah;
h.removeAttribute("aria-sort");
});
th.dataset.arah = naik ? "asc" : "desc";
th.setAttribute("aria-sort", naik ? "ascending" : "descending");
var baris = Array.prototype.slice.call(tbody.rows);
var biasa = baris.filter(function (tr) { return !tr.classList.contains("total"); });
var total = baris.filter(function (tr) { return tr.classList.contains("total"); });
biasa.sort(function (a, b) {
var ta = nilaiSel(a, i), tb = nilaiSel(b, i);
var na = sebagaiAngka(ta), nb = sebagaiAngka(tb);
var hasil;
if (na !== null && nb !== null) hasil = na - nb;
else if (na === null && nb === null) hasil = ta.localeCompare(tb, "id");
else hasil = na === null ? 1 : -1; // sel kosong/— selalu di akhir
return naik ? hasil : -hasil;
});
biasa.concat(total).forEach(function (tr) { tbody.appendChild(tr); });
});
});
}
document.addEventListener("DOMContentLoaded", function () {
document.querySelectorAll("table.grid").forEach(function (t) {
if (!t.closest("form")) pasang(t);
});
});
/* Filter daftar MK saat penugasan dosen (/admin): ketik di .cari-mk
menyaring .baris-mk berdasarkan kode/nama MK (data-cari). */
document.addEventListener("input", function (ev) {
if (!ev.target.classList.contains("cari-mk")) return;
var kata = ev.target.value.trim().toLowerCase();
var wadah = ev.target.nextElementSibling; // .pilih-sub tepat setelah input cari
if (!wadah) return;
var ada = false;
wadah.querySelectorAll(".baris-mk").forEach(function (baris) {
var cocok = !kata || baris.dataset.cari.indexOf(kata) !== -1;
baris.style.display = cocok ? "" : "none";
if (cocok) ada = true;
});
var kosong = wadah.querySelector(".cari-kosong");
if (kosong) kosong.style.display = ada ? "none" : "";
});
})();