working up to proker update

This commit is contained in:
nugroho 2025-06-24 15:41:43 +07:00
parent 30e4477d2f
commit 5a73046112
10 changed files with 456 additions and 47 deletions

View File

@ -44,7 +44,7 @@ thead
background-color: var(--primary-accent);
color: var(--primary-background);
position: sticky;
top: 1px;
top: 0;
z-index: 1;
}
button
@ -99,18 +99,23 @@ button:disabled
table
{
isolation: isolate;
table-layout: fixed;
width: 100%;
}
table td
{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
table, table th, table td {
border-collapse: collapse;
padding: .2ch .25ch .2ch .25ch;
padding: .35ch .25ch;
margin: auto;
}
table.bordered, table.bordered th , table.bordered td {
border: 1px solid var(--primary-background);
}
table.fullwidth{
width: calc(100% - 2ch);
}
table.selectable tr:not(thead tr){
user-select: none;
-webkit-user-select: none;

View File

@ -51,3 +51,39 @@ async function postText(url,data = {},headers={}) {
});
}
}
monthName =
[
"#Inv#",
"Januari",
"Februari",
"Maret",
"April",
"Mei",
"Juni",
"Juli",
"Agustus",
"September",
"Oktober",
"November",
"Desember"
];
monthShort =
[
"###",
"Jan",
"Feb",
"Mar",
"Apr",
"Mei",
"Jun",
"Jul",
"Ags",
"Sep",
"Okt",
"Nov",
"Des"
]
function gen16BytesID()
{
return Date.now().toString(36)+Math.random().toString(36).substring(2,10);
}

View File

@ -10,9 +10,13 @@ class molybdenum{
_loads = [];
_dialogs = [];
lastDialog()
{
if(this._dialogs.length > 0)
{
return this._dialogs.at(-1);
}
return null;
}
lastLoadScreenId()
{
if(this._loads.length > 0)
@ -459,7 +463,7 @@ class molybdenum{
}
FileInput = class extends HTMLElement
{
static observedAttributes = ["disabled", "accept", "multiple"];
static observedAttributes = ["disabled", "accept", "multiple", "label"];
constructor() {
super();
this.attachShadow({ mode: "open" }); // Attach Shadow DOM
@ -513,7 +517,13 @@ class molybdenum{
{
this._input.setAttribute("multiple", "");
this.multiple = this.hasAttribute("multiple");
this._label.innerText = "Click to select files.";
this._label.innerText = this.hasAttribute("label") ? this.getAttribute("label") : "Click to select files.";
}
else
{
this._input.removeAttribute("multiple");
this.multiple = this.hasAttribute("multiple");
this._label.innerText = this.hasAttribute("label") ? this.getAttribute("label") : "Click to select a file.";
}
}
disconnectedCallback() {
@ -531,7 +541,7 @@ class molybdenum{
}
else if (this.hasAttribute("multiple"))
{
this._label.innerText = "Click to select files.";
this._label.innerText = this.hasAttribute("label") ? this.getAttribute("label") : "Click to select files.";
}
else if (this._input.files.length == 1)
{
@ -539,7 +549,7 @@ class molybdenum{
}
else
{
this._label.innerText = "Click to select a file.";
this._label.innerText = this.hasAttribute("label") ? this.getAttribute("label") : "Click to select a file.";
}
this.dispatchEvent(new CustomEvent("change", {bubble: true, composed: true, detail: this.files}));
}
@ -576,6 +586,21 @@ class molybdenum{
return this._input.accept;
}
get label()
{
return this.getAttribute("label");
}
set label(value)
{
if (value)
{
this._label.innerText = this.getAttribute("label");
}
else
{
this._label.innerText = this.hasAttribute("multiple") ? "Click to select files." : "Click to select a file.";
}
}
set multiple(value) {
if (value) {
this._input.setAttribute("multiple", "");

View File

@ -202,7 +202,7 @@ nav
moly.alert.show("Koneksi Gagal","Gagal menyambung ke server. Harap periksa koneksi jaringan.");
return {data: []};
})).data;
const userDetails = detail.data;
window.userDetails = detail.data;
const loggedInAgent = agents.find(a=>a.agentID == userDetails.agentID)
// if (!window.evtSource) window.evtSource = new EventSource("/events");
window.addEventListener("viewChange", async ()=>{

View File

@ -1,5 +1,5 @@
<div style="display: grid; grid-template-columns: auto auto 1fr; column-gap:.5ch;">
<span>Username*</span>
<span>Username</span>
<span>:</span>
<input type="text" id="unme" disabled>
<span>Password*</span>
@ -8,13 +8,15 @@
<span>Password Konfirmasi*</span>
<span>:</span>
<input type="password" id="cPwd">
<span>Level*</span>
<span>Level</span>
<span>:</span>
<select id="lvel" disabled>
<option value="2">Agen Perubahan</option>
<option value="1">Evaluator</option>
<option value="0">Super Admin</option>
</select>
<div style="text-align: right;">
<hr style="grid-column: span 3; width: 100%; margin: .5ch 0;">
<div>
<a-button id="toggle">
</a-button>

View File

@ -1,4 +1,5 @@
<group-el label="Manajemen Agen Perubahan" style="padding: 3ch 1ch;">
<div style="max-height: 8em; overflow-y: scroll; margin: 1em 0" id="agentWrapper">
<table id="agents" class="fullwidth bordered selectable">
<thead>
<tr>
@ -14,9 +15,11 @@
</tr>
</tbody>
</table>
</div>
<a-button id="newAgent">Tambah Agen</a-button>
</group-el>
<group-el label="Manajemen Akun Pengguna" style="padding: 3ch 1ch;">
<div style="max-height: 8em; overflow-y: scroll; margin: 1em 0" id="accountWrapper">
<table id="users" class="fullwidth bordered selectable">
<thead>
<tr>
@ -32,6 +35,8 @@
</tr>
</tbody>
</table>
</div>
</group-el>
<script type="module">
let agents = {};
@ -39,7 +44,7 @@
let users = {};
async function populateAgents()
{
const loadid = moly.loadScreen.show("","bar","#agents");
const loadid = moly.loadScreen.show("Memuat Daftar Agen...","bar","#agentWrapper");
units = await getJson('/api/getunits');
if (units.status != 200) {
moly.loadScreen.close(loadid);
@ -94,7 +99,7 @@
}
async function populateUsers()
{
const loadid = moly.loadScreen.show("","bar","#users");
const loadid = moly.loadScreen.show("Memuat Daftar Akun...","bar","#accountWrapper");
users = await getJson('/api/getusers');
if (users.status != 200) {
moly.loadScreen.close(loadid);

View File

@ -0,0 +1,103 @@
<div style="display: grid; grid-template-columns: auto auto 1fr; column-gap: 1ch;">
<span>Kegiatan</span>
&nbsp;
<select id="kegiatan" style="width: max-content;">
<option value="-1" selected disabled>-Pilih Kegiatan-</option>
<option value="0">Sebagai Katalis</option>
<option value="1">Sebagai Penggerak Perubahan</option>
<option value="2">Sebagai Pemberi Solusi</option>
<option value="3">Sebagai Mediator</option>
<option value="4">Sebagai Penghubung</option>
</select>
<span>Target Waktu</span>
&nbsp;
<div>
<input type="number" id="target" min="1" style="width: 7ch;" value="1">
&nbsp;
<select id="targetUnit" style="width: max-content;">
<option value="0">Hari</option>
<option value="1" selected>Bulan</option>
</select>
</div>
<span class="forDay" hidden>Tgl Mulai</span>
<span class="forDay" hidden></span>
<input class="forDay" type="date" id="startDate" style="max-width: max-content;" hidden>
<span class="forMonth">Bulan Mulai</span>
<span class="forMonth"></span>
<input class="forMonth" type="month" id="startMonth" style="max-width: max-content;">
<div style="grid-column: span 3;">
<span>Sasaran Kegiatan:</span><br>
<textarea id="sasaran" style="resize: none; width: 100%; height: 4.6em;" maxlength="510" placeholder="Contoh: Mengenakan seragam sesuai aturan."></textarea>
</div>
<div style="grid-column: span 3;">
<span>Sasaran Entitas:</span><br>
<textarea id="enttarget" style="resize: none; width: 100%; height: 4.6em;" maxlength="510" placeholder="Contoh: Seluruh pegawai Kanwil BPN Provinsi Riau."></textarea>
</div>
<div style="grid-column: span 3;">
<span>Indikator:</span><br>
<textarea id="indikator" style="resize: none; width: 100%; height: 4.6em;" maxlength="510" placeholder="Contoh: Persentase pegawai taat aturan berpakaian."></textarea>
</div>
<div style="grid-column: span 3;">
<span>Rencana Aksi:</span><br>
<textarea id="aksi" style="resize: none; width: 100%; height: 4.6em;" maxlength="510" placeholder="Contoh: Sosialisasi aturan berpakaian."></textarea>
</div>
<span></span>
<span></span>
<div style="text-align: right;">
<a-button id="submit">Simpan</a-button>
</div>
</div>
<script type="module">
const thisDialog = moly.lastDialog();
const data = thisDialog.data;
function µ(selector)
{
if (selector) return $(thisDialog.box).find(selector);
return $(thisDialog.box);
}
µ('#targetUnit').change(()=>{
µ('.forDay').prop("hidden", µ('#targetUnit').val() != "0");
µ('.forMonth').prop("hidden", µ('#targetUnit').val() != "1");
µ('#startDay').val("");
µ('#startMonth').val("");
});
µ('#submit').click(async()=>{
const loadid = moly.loadScreen.show("Menambahkan Program Kerja...","sonar","#"+µ('[id^="db"]')[0].id);
const startDay = µ('#targetUnit').val() == "0" ? (new Date(µ('#startDate').val())).getDate() : null;
const startMonth = µ('#targetUnit').val() == "0" ? (new Date(µ('#startDate').val())).getMonth() +1 : (new Date(µ('#startMonth').val())).getMonth() +1;
const year = µ('#targetUnit').val() == "0" ? (new Date(µ('#startDate').val())).getFullYear() : (new Date(µ('#startMonth').val())).getFullYear();
const proker =
{
prokerid: gen16BytesID(),
agentID: data.agentID,
kegiatan: Number(µ('#kegiatan').val()),
sasaran: µ('#sasaran').val(),
startDay,
startMonth,
year,
timeTarget: Number(µ('#target').val()),
targetUnit: Number(µ('#targetUnit').val()),
entTarget: µ('#enttarget').val(),
indicator: µ('#indikator').val(),
action: µ('#aksi').val()
}
if(!µ('#kegiatan').val() || proker.sasaran.length <1 || (startDay != null && isNaN(startDay)) || isNaN(startMonth) || isNaN(year)
|| proker.entTarget.length < 1 || proker.indicator.length < 1 || proker.action.length < 1)
{
moly.alert.show("Data Belum Lengkap","Harap isi data dengan lengkap. Setiap kolom yang ditampilkan wajib diisi.");
console.log(proker);
moly.loadScreen.close(loadid);
return;
}
const mkproker = await postJson('/api/mkproker',proker);
console.log(mkproker)
if (mkproker.status != 201)
{
moly.alert.show("Simpan Program Kerja Gagal","Program kerja tidak dapat disimpan. Silakan coba kembali beberapa saat lagi.");
moly.loadScreen.close(loadid);
return;
}
thisDialog.resolve(proker);
moly.loadScreen.close(loadid);
})
</script>

View File

@ -0,0 +1,121 @@
<div style="display: grid; grid-template-columns: auto auto 1fr; column-gap: 1ch;">
<span>Kegiatan</span>
&nbsp;
<select id="kegiatan" style="width: max-content;">
<option value="-1" selected disabled>-Pilih Kegiatan-</option>
<option value="0">Sebagai Katalis</option>
<option value="1">Sebagai Penggerak Perubahan</option>
<option value="2">Sebagai Pemberi Solusi</option>
<option value="3">Sebagai Mediator</option>
<option value="4">Sebagai Penghubung</option>
</select>
<span>Target Waktu</span>
&nbsp;
<div>
<input type="number" id="target" min="1" style="width: 7ch;" value="1">
&nbsp;
<select id="targetUnit" style="width: max-content;">
<option value="0">Hari</option>
<option value="1" selected>Bulan</option>
</select>
</div>
<span class="forDay" hidden>Tgl Mulai</span>
<span class="forDay" hidden></span>
<input class="forDay" type="date" id="startDate" style="max-width: max-content;" hidden>
<span class="forMonth">Bulan Mulai</span>
<span class="forMonth"></span>
<input class="forMonth" type="month" id="startMonth" style="max-width: max-content;">
<div style="grid-column: span 3;">
<span>Sasaran Kegiatan:</span><br>
<textarea id="sasaran" style="resize: none; width: 100%; height: 4.6em;" maxlength="510" placeholder="Contoh: Mengenakan seragam sesuai aturan."></textarea>
</div>
<div style="grid-column: span 3;">
<span>Sasaran Entitas:</span><br>
<textarea id="enttarget" style="resize: none; width: 100%; height: 4.6em;" maxlength="510" placeholder="Contoh: Seluruh pegawai Kanwil BPN Provinsi Riau."></textarea>
</div>
<div style="grid-column: span 3;">
<span>Indikator:</span><br>
<textarea id="indikator" style="resize: none; width: 100%; height: 4.6em;" maxlength="510" placeholder="Contoh: Persentase pegawai taat aturan berpakaian."></textarea>
</div>
<div style="grid-column: span 3;">
<span>Rencana Aksi:</span><br>
<textarea id="aksi" style="resize: none; width: 100%; height: 4.6em;" maxlength="510" placeholder="Contoh: Sosialisasi aturan berpakaian."></textarea>
</div>
<span></span>
<span></span>
<div style="text-align: right;">
<a-button id="submit">Update</a-button>
</div>
</div>
<script type="module">
const thisDialog = moly.lastDialog();
const data = thisDialog.data;
function µ(selector)
{
if (selector) return $(thisDialog.box).find(selector);
return $(thisDialog.box);
}
$(document).ready(async()=>{
µ('#aksi').val(data.actions);
µ('#enttarget').val(data.entityTarget);
µ('#indikator').val(data.indicators);
µ('#targetUnit').val(data.isInMonth ? 1 : 0);
µ('#kegiatan').val(data.kegiatan);
µ('#sasaran').val(data.sasaran);
let DateTime = data.year + "-" + data.startMonth.toString().padStart(2,"0");
DateTime += data.isInMonth ? "" : "-" + data.startDay.toString().padStart(2,"0");
µ('#target').val(data.timeTarget);
if(data.isInMonth)
{
µ('#startMonth').val(DateTime);
}
else
{
µ('#startDate').val(DateTime);
}
})
µ('#targetUnit').change(()=>{
µ('.forDay').prop("hidden", µ('#targetUnit').val() != "0");
µ('.forMonth').prop("hidden", µ('#targetUnit').val() != "1");
µ('#startDay').val("");
µ('#startMonth').val("");
});
µ('#submit').click(async()=>{
const loadid = moly.loadScreen.show("Menambahkan Program Kerja...","sonar","#"+µ('[id^="db"]')[0].id);
const startDay = µ('#targetUnit').val() == "0" ? (new Date(µ('#startDate').val())).getDate() : null;
const startMonth = µ('#targetUnit').val() == "0" ? (new Date(µ('#startDate').val())).getMonth() +1 : (new Date(µ('#startMonth').val())).getMonth() +1;
const year = µ('#targetUnit').val() == "0" ? (new Date(µ('#startDate').val())).getFullYear() : (new Date(µ('#startMonth').val())).getFullYear();
const proker =
{
prokerid: data.prokerID,
kegiatan: Number(µ('#kegiatan').val()),
sasaran: µ('#sasaran').val(),
startDay,
startMonth,
year,
timeTarget: Number(µ('#target').val()),
targetUnit: Number(µ('#targetUnit').val()),
entTarget: µ('#enttarget').val(),
indicator: µ('#indikator').val(),
action: µ('#aksi').val()
}
if(!µ('#kegiatan').val() || proker.sasaran.length <1 || (startDay != null && isNaN(startDay)) || isNaN(startMonth) || isNaN(year)
|| proker.entTarget.length < 1 || proker.indicator.length < 1 || proker.action.length < 1)
{
moly.alert.show("Data Belum Lengkap","Harap isi data dengan lengkap. Setiap kolom yang ditampilkan wajib diisi.");
console.log(proker);
moly.loadScreen.close(loadid);
return;
}
const mkproker = await postJson('/api/updateproker',proker);
if (mkproker.status != 202)
{
moly.alert.show("Simpan Program Kerja Gagal","Program kerja tidak dapat disimpan. Silakan coba kembali beberapa saat lagi.");
moly.loadScreen.close(loadid);
return;
}
thisDialog.resolve(proker);
moly.loadScreen.close(loadid);
})
</script>

View File

@ -0,0 +1,99 @@
<style>
</style><group-el label="Program Kerja">
<div style="text-align: right;">
<a-button id="newProker">Tambah Kegiatan</a-button>
</div>
<div style="max-height: calc(50vh - 6em); overflow-y: scroll; margin: 1em 0" id="pkWrapper">
<table id="proker" class="bordered selectable">
<colgroup>
<col style="width: 4ch;">
<col style="width: 19ch;">
<col>
<col style="width: 8ch;">
<col style="width: 17ch;">
<col style="width: 14ch;">
</colgroup>
<thead>
<tr>
<th>No</th>
<th>Kegiatan</th>
<th>Sasaran</th>
<th>Target Waktu</th>
<th>Waktu Mulai</th>
<th>Status</th>
</tr>
</thead>
<tbody id="empty">
<tr>
<td colspan="6" style="text-align: center;">Data Kosong</td>
</tr>
</tbody>
<tbody id="pkContent" hidden>
</tbody>
</table>
</div>
</group-el>
<script type="module">
let prokers = [];
async function populateProker()
{
const loadid = moly.loadScreen.show("Memuat Daftar Program Kerja...","bar","#pkWrapper");
const kegiatanName = [
"Sebagai Katalis",
"Sebagai Penggerak Perubahan",
"Sebagai Pemberi Solusi",
"Sebagai Mediator",
"Sebagai Penghubung"
]
prokers = await getJson('/api/getprokers');
if (prokers.status != 200 || prokers.length < 1)
{
moly.loadScreen.close(loadid);
return;
}
prokers = prokers.data;
$('#proker #empty').prop("hidden", true);
$('#proker #pkContent').prop("hidden", false);
$('#proker #pkContent').empty();
$.each(prokers,(i,v)=>{
const ro = moly.newElement("tr");
const no = moly.newElement("td");
const kg = moly.newElement("td");
const ss = moly.newElement("td");
const tw = moly.newElement("td");
const wm = moly.newElement("td");
const st = moly.newElement("td");
ro.append(no);
ro.append(kg);
ro.append(ss);
ro.append(tw);
ro.append(wm);
ro.append(st);
no.append((i+1)+".");
no.style.textAlign = "right";
kg.append(kegiatanName[v.kegiatan]);
ss.append(v.sasaran);
tw.append(`${v.timeTarget} ${v.isInMonth ? "Bulan" : "Hari"}`);
tw.style.textAlign = "center";
wm.append(((v.startDay == null ? "" : v.startDay.toString().padStart(2,"0") + " ") + monthName[v.startMonth] + " " + v.year));
wm.style.textAlign = "right";
st.append("Draft");
st.style.textAlign = "center";
$(ro).click(async()=>{
const data = v;
const vw = await moly.dialog.show({title: "Detil Program Kerja", content: "/modules/kegiatan-proker-view.html", fetching: true, data});
if(vw) populateProker();
})
$('#proker #pkContent').append(ro);
});
moly.loadScreen.close(loadid);
}
$(document).ready(async()=>{
populateProker();
$('#newProker').click(async ()=>{
const data = userDetails;
const np = await moly.dialog.show({title: "Entri Program Kerja dan Rencana Aksi", content: "/modules/kegiatan-proker-new.html", fetching: true, data});
if(np) populateProker();
});
})
</script>

View File

@ -0,0 +1,13 @@
<iframe id="previewer" style="width: 80vw; height: 80vh;">
</iframe>
<script type="module">
const thisDialog = moly.lastDialog();
const data = thisDialog.data;
function µ(selector)
{
if (selector) return $(thisDialog.box).find(selector);
return $(thisDialog.box);
}
µ('#previewer')[0].src = "data:application/pdf;base64,"+data.data;
</script>