Source Code Aplikasi Guru Wali untuk Semua Guru dalam Satu Sekolah
Bagi sekolah yang ingin mendigitalkan laporan bimbingan konseling atau catatan wali kelas, aplikasi berbasis Google Apps Script ini adalah solusi yang sangat efisien. Aplikasi ini dirancang khusus untuk SMPN 3 Kerinci namun dapat diadaptasi untuk sekolah manapun.
Fitur Utama Update Terbaru:
- ✅ Multi-User Login: Guru hanya bisa melihat dan mengelola siswanya sendiri.
- ✅ Akses Admin (Kepala Sekolah): Admin dapat melihat seluruh laporan dari semua guru dan mencetaknya dalam satu rekapitulasi.
- ✅ CRUD Siswa: Guru dapat menambah, mengedit, dan menghapus data siswa langsung dari aplikasi.
- ✅ Cetak PDF: Tanda tangan otomatis menyesuaikan user login (Kepsek atau Guru Wali).
Langkah 1: Siapkan Google Spreadsheet
1 Buka Google Drive, buat Spreadsheet baru.
2 Beri nama, misalnya "Database E-Wali". Anda tidak perlu membuat nama sheet (tab) secara manual, kode akan membuatnya otomatis saat dijalankan.
Langkah 2: Salin Kode Back-End (Code.gs)
Buka menu Ekstensi > Apps Script. Hapus semua kode yang ada, dan salin kode di bawah ini:
function doGet() {
buatSheetJikaBelumAda();
return HtmlService.createTemplateFromFile('Index').evaluate()
.setTitle('Aplikasi Guru Wali SMPN 3 Kerinci')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
.addMetaTag('viewport', 'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no');
}
function getDaftarGuru() {
return ["Admin (Kepala Sekolah)", "Aneke Prastika", "Dedes Lindawati", "FELLA APRISI", "GEFFI DEDE CANDRA", "Gita Pertiwi", "Hayat", "JONI PRATAMA", "Lenny Marlina", "Linda Purwanti", "Marjoni", "NATASIA ASTRIANZAH", "NONONG WAZIR", "PUTRI SOZA DWITA", "Reni Emelisa", "SATRA MURKA", "Yefri Haryanto"];
}
function buatSheetJikaBelumAda() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
if (!ss.getSheetByName('DataSiswa')) ss.insertSheet('DataSiswa').appendRow(['Nama', 'Guru']);
if (!ss.getSheetByName('DataBimbingan')) ss.insertSheet('DataBimbingan').appendRow(['Tgl', 'Siswa', 'Jenis', 'Catatan', 'TL', 'Guru']);
}
function ambilSemuaData(namaUser) {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var bimbData = ss.getSheetByName('DataBimbingan').getDataRange().getDisplayValues();
var siswaData = ss.getSheetByName('DataSiswa').getDataRange().getDisplayValues();
var searchName = (namaUser || "").toLowerCase().trim();
var isAdmin = searchName.includes("admin");
var resLaporan = [];
if (bimbData.length > 1) {
for (var i = 1; i < bimbData.length; i++) {
var row = bimbData[i];
var guruInSheet = (row[5] || "").toLowerCase().trim();
if (isAdmin || guruInSheet === searchName) {
resLaporan.push({ tgl: row[0], siswa: row[1], jenis: row[2], cat: row[3], tl: row[4], guru: row[5] });
}
}
}
var resSiswa = [];
if (siswaData.length > 1) {
for (var j = 1; j < siswaData.length; j++) {
var rSiswa = siswaData[j];
// Hanya ambil siswa milik guru tersebut
if ((rSiswa[1] || "").toLowerCase().trim() === searchName) resSiswa.push(rSiswa[0]);
}
}
return { laporan: resLaporan.reverse(), siswa: resSiswa.sort() };
} catch (e) { return { error: e.toString() }; }
}
function simpanSiswa(n, g) {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('DataSiswa').appendRow([n.trim(), g.trim()]);
return "OK";
}
function simpanData(o) {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('DataBimbingan').appendRow([o.tgl, o.nama, o.jenis, o.cat.trim(), o.tl.trim(), o.guru]);
return "OK";
}
// --- FITUR BARU: HAPUS & EDIT ---
function hapusSiswaServer(nama, guru) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('DataSiswa');
var data = sheet.getDataRange().getValues();
// Loop dari bawah agar aman menghapus baris
for (var i = data.length - 1; i >= 0; i--) {
// Cek Nama dan Guru agar tidak salah hapus punya orang lain
if (data[i][0].toString() === nama && data[i][1].toString() === guru) {
sheet.deleteRow(i + 1);
return "OK";
}
}
return "Gagal";
}
function editSiswaServer(namaLama, namaBaru, guru) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('DataSiswa');
var data = sheet.getDataRange().getValues();
for (var i = 0; i < data.length; i++) {
if (data[i][0].toString() === namaLama && data[i][1].toString() === guru) {
sheet.getRange(i + 1, 1).setValue(namaBaru.trim());
return "OK";
}
}
return "Gagal";
}
Langkah 3: Salin Kode Front-End (Index.html)
Buat file baru di Apps Script dengan menekan tanda (+) lalu pilih HTML. Beri nama file Index. Hapus isinya dan tempel kode berikut:
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>E-Wali SMPN 3 Kerinci</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<style>
:root { --p-blue: #0f172a; --accent: #fbbf24; --grad: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); }
/* 1. KUNCI MATI OVERFLOW (HP Gak Bisa Geser) */
* { box-sizing: border-box; }
html, body {
margin: 0; padding: 0; width: 100%; overflow-x: hidden !important;
background: #f1f5f9; font-family: 'Segoe UI', sans-serif; font-size: 13px;
}
/* 2. WRAPPER HIBRIDA (HP Kecil, Desktop Lebar) */
.app-shell {
width: 100%;
max-width: 100%; /* Default Mobile Full */
margin: 0 auto; min-height: 100vh; background: #ffffff;
display: flex; flex-direction: column; position: relative;
}
/* JIKA DI LAPTOP/TABLET (Layar > 800px) */
@media (min-width: 800px) {
.app-shell { max-width: 900px; border-left: 1px solid #ddd; border-right: 1px solid #ddd; }
.menu-grid { grid-template-columns: repeat(2, 1fr) !important; } /* Desktop Menu Grid 2 Kolom */
}
/* 3. LOGIN PAGE (Selalu Kecil di Tengah) */
#loginPage {
height: 100dvh; width: 100%; display: flex; align-items: center; justify-content: center;
background: var(--grad); position: fixed; top: 0; left: 0; z-index: 5000; padding: 20px;
}
.login-card {
width: 100%; max-width: 300px; padding: 25px; border-radius: 20px;
background: #fff; text-align: center; box-shadow: 0 10px 40px rgba(0,0,0,0.5);
}
.text-3d { color: #1e293b; font-weight: 900; text-shadow: 1px 1px 0 #cbd5e1; letter-spacing: 0.5px; }
/* 4. HEADER */
.top-header {
background: var(--grad); color: white; padding: 10px;
border-bottom: 4px solid var(--accent); display: flex; align-items: center;
justify-content: center; gap: 8px; position: sticky; top: 0; z-index: 1000;
}
.header-logo { width: 32px; height: auto; flex-shrink: 0; }
.header-title { font-size: 0.75rem; font-weight: 800; text-align: center; margin: 0; line-height: 1.2; text-transform: uppercase; }
@media (min-width: 800px) { .header-title { font-size: 1.1rem; } .header-logo { width: 45px; } }
/* 5. DASHBOARD & MENU */
.welcome-area { padding: 15px; background: white; border-bottom: 1px solid #eee; margin-bottom: 10px; }
.menu-grid {
display: flex; flex-direction: column; gap: 10px; padding: 0 15px;
}
.menu-card {
border: none; border-radius: 12px; padding: 12px 15px;
display: flex; align-items: center; justify-content: space-between;
color: white; cursor: pointer; box-shadow: 0 2px 5px rgba(0,0,0,0.1);
text-decoration: none; font-size: 12px;
}
.bg-m-1 { background: linear-gradient(135deg, #2563eb, #1d4ed8); }
.bg-m-2 { background: linear-gradient(135deg, #059669, #047857); }
.bg-m-3 { background: linear-gradient(135deg, #d97706, #b45309); }
.bg-m-4 { background: linear-gradient(135deg, #7c3aed, #6d28d9); }
/* 6. ELEMEN HALAMAN (Kecil di Mobile, Rapi di Desktop) */
.page { display: none; padding: 15px; padding-bottom: 90px; }
.page.active { display: block; animation: fadeIn 0.3s; }
.btn-center { display: flex; justify-content: center; margin-bottom: 15px; }
.btn-small { padding: 5px 20px; font-size: 11px; border-radius: 50px; }
/* List Siswa */
.siswa-item {
background: white; padding: 8px 12px; border-radius: 8px; margin-bottom: 5px;
border: 1px solid #e2e8f0; font-size: 12px; font-weight: 600; color: #334155;
display: flex; align-items: center; justify-content: space-between; /* Ubah ke space-between */
}
.siswa-name::before { content: '\f111'; font-family: "Font Awesome 6 Free"; font-size: 6px; margin-right: 10px; color: #cbd5e1; }
/* Input Form */
.form-box { background: white; padding: 15px; border-radius: 12px; border: 1px solid #e2e8f0; max-width: 600px; margin: 0 auto; }
.form-control, .form-select { font-size: 12px; padding: 8px; }
/* Laporan Card */
.report-card {
background: white; border-radius: 10px; padding: 10px; margin-bottom: 8px;
border-left: 3px solid var(--p-blue); box-shadow: 0 1px 3px rgba(0,0,0,0.05);
}
.r-name { font-size: 12px; font-weight: 800; color: var(--p-blue); }
.r-type { font-size: 10px; color: #d97706; font-weight: 700; display: block; margin-top: 2px; text-transform: uppercase; }
.r-body { font-size: 11px; margin-top: 5px; font-style: italic; }
/* 7. NAVIGASI BAWAH BERWARNA */
.bottom-nav {
position: fixed; bottom: 0; left: 0; right: 0; margin: 0 auto;
width: 100%; max-width: 900px; /* Ikuti lebar desktop */
background: var(--grad); /* Warna Biru Gelap */
display: flex; border-top: 2px solid var(--accent);
z-index: 2000; height: 60px; padding-bottom: env(safe-area-inset-bottom);
}
.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; color: rgba(255,255,255,0.5); text-decoration: none; font-size: 9px; font-weight: 600; }
.tab-item.active { color: var(--accent); background: rgba(255,255,255,0.1); }
.tab-item i { font-size: 18px; margin-bottom: 2px; }
/* 8. PRINT SYSTEM */
#printArea { display: none; }
@media print {
body, .app-shell { background: white !important; width: 100% !important; max-width: 100% !important; overflow: visible !important; }
.no-print, .bottom-nav, .top-header, .page { display: none !important; }
#printArea { display: block !important; padding: 0; color: black; }
.kop { display: flex; align-items: center; justify-content: center; border-bottom: 3px double black; padding-bottom: 10px; margin-bottom: 15px; gap: 15px; }
.kop img { width: 55px; }
.kop-text { text-align: center; flex: 1; }
table { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 10px; }
th, td { border: 1px solid black !important; padding: 5px; text-align: left; vertical-align: top; }
.ttd-box { float: right; text-align: center; width: 200px; margin-top: 30px; font-size: 11px; }
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
</style>
</head>
<body>
<div id="printArea">
<div class="kop">
<img src="https://drive.google.com/thumbnail?id=1uZHh5ReKYrAL6ycC6nYXtnb6zhETXQlX">
<div class="kop-text">
<h4 style="margin:0">DINAS PENDIDIKAN KABUPATEN KERINCI</h4>
<h2 style="margin:0">SMP NEGERI 3 KERINCI</h2>
<p style="margin:0; font-size:10px">Jl. Lempur Tengah, Kec. Gunung Raya, Kab. Kerinci, Jambi</p>
</div>
<img src="https://drive.google.com/thumbnail?id=1QOvUSLtFM9-s0asnaZSCPXxsGOZnBUim">
</div>
<div style="text-align:center; margin-bottom:10px;">
<h5 style="text-decoration:underline; margin:0; font-size:12px;">LAPORAN BIMBINGAN SISWA</h5>
<p style="font-size:10px; margin:0;">Identitas: <span id="p-identitas"></span></p>
</div>
<table id="tableCetak">
<thead id="hCetak"></thead>
<tbody id="bCetak"></tbody>
</table>
<div class="ttd-box">
<p>Kerinci, <span id="p-date"></span></p>
<p id="label-ttd" style="margin-bottom:50px; font-weight:bold;">Guru Wali</p>
<p><strong id="nama-ttd">( ________________ )</strong></p>
</div>
</div>
<div id="loginPage" class="no-print">
<div class="login-card">
<img src="https://drive.google.com/thumbnail?id=1QOvUSLtFM9-s0asnaZSCPXxsGOZnBUim" width="60" class="mb-3">
<h5 class="text-3d mb-1" style="font-size:14px;">APLIKASI GURU WALI</h5>
<h6 class="text-3d mb-3" style="font-size:12px;">SMP NEGERI 3 KERINCI</h6>
<select id="userSelect" class="form-select mb-3 shadow-sm" style="font-size:12px;"></select>
<button onclick="login()" class="btn btn-primary w-100 py-2 rounded-pill shadow fw-bold" style="font-size:12px; background:var(--p-blue); border:none;">MASUK</button>
</div>
</div>
<div class="app-shell no-print" id="mainApp" style="display:none;">
<div class="top-header">
<img src="https://drive.google.com/thumbnail?id=1uZHh5ReKYrAL6ycC6nYXtnb6zhETXQlX" class="header-logo">
<div class="header-title">Aplikasi Guru Wali<br>SMP Negeri 3 Kerinci</div>
<img src="https://drive.google.com/thumbnail?id=1QOvUSLtFM9-s0asnaZSCPXxsGOZnBUim" class="header-logo">
</div>
<div id="p-dash" class="page active">
<div class="welcome-area">
<h6 class="fw-bold text-primary m-0" style="font-size:13px;">Selamat Datang, <span id="uDash">...</span></h6>
<div class="mt-2 p-2 bg-light rounded border text-muted" style="font-size:10px;">
<strong>Petunjuk:</strong> 1. Input Siswa di menu SISWA. 2. Catat kasus di menu INPUT. 3. Cetak di menu LAPORAN.
</div>
</div>
<div class="menu-grid mt-2">
<div class="menu-card bg-m-1" onclick="openPage('dash')"><span>BERANDA</span><i class="fas fa-home"></i></div>
<div class="menu-card bg-m-2 guru-only" onclick="openPage('siswa')"><span>DATA SISWA</span><i class="fas fa-user-graduate"></i></div>
<div class="menu-card bg-m-3 guru-only" onclick="openPage('input')"><span>INPUT BIMBINGAN</span><i class="fas fa-edit"></i></div>
<div class="menu-card bg-m-4" onclick="openPage('lapor')"><span>LAPORAN</span><i class="fas fa-file-pdf"></i></div>
</div>
</div>
<div id="p-siswa" class="page">
<h6 class="fw-bold text-center mb-2" style="font-size:12px;">DAFTAR SISWA</h6>
<div class="btn-center">
<button onclick="tambahSiswa()" class="btn btn-success btn-small shadow-sm">+ SISWA BARU</button>
</div>
<div id="listSiswa"></div>
</div>
<div id="p-input" class="page">
<div class="form-box shadow-sm">
<h6 class="fw-bold mb-3 text-warning text-center" style="font-size:12px;">FORM BIMBINGAN</h6>
<form id="fInput">
<label class="small fw-bold">Siswa</label>
<select id="selSiswa" class="form-select mb-2" required></select>
<label class="small fw-bold">Jenis</label>
<select id="selJenis" class="form-select mb-2" required>
<option value="Akademik">Akademik</option><option value="Karakter">Karakter</option><option value="Pengembangan Diri">Pengembangan Diri</option><option value="Lainnya">Lainnya</option>
</select>
<label class="small fw-bold">Catatan</label>
<textarea id="tCat" class="form-control mb-2" rows="2" required></textarea>
<label class="small fw-bold">Tindak Lanjut</label>
<input type="text" id="tTL" class="form-control mb-3" required>
<button type="submit" class="btn btn-primary w-100 py-1 rounded-pill shadow-sm" style="font-size:11px;">SIMPAN</button>
</form>
</div>
</div>
<div id="p-lapor" class="page">
<div class="btn-center">
<button onclick="persiapkanCetak()" class="btn btn-dark btn-small shadow-sm"><i class="fas fa-print me-1"></i>CETAK PDF</button>
</div>
<div id="listLapor"></div>
</div>
<div class="bottom-nav">
<div class="tab-item active" id="tab-dash" onclick="openPage('dash')"><i class="fas fa-th-large"></i>Menu</div>
<div id="tabGuruSiswa" class="tab-item guru-only" onclick="openPage('siswa')"><i class="fas fa-users"></i>Siswa</div>
<div id="tabGuruInput" class="tab-item guru-only" onclick="openPage('input')"><i class="fas fa-pen-nib"></i>Input</div>
<div class="tab-item" id="tab-lapor" onclick="openPage('lapor')"><i class="fas fa-file-alt"></i>Laporan</div>
</div>
</div>
<script>
var userAktif = "";
var dataGlobal = [];
window.onload = function() {
google.script.run.withSuccessHandler(function(list) {
var sel = document.getElementById('userSelect');
sel.innerHTML = '<option value="" disabled selected>-- Pilih Nama --</option>';
list.forEach(g => sel.add(new Option(g, g)));
}).getDaftarGuru();
};
function login() {
userAktif = document.getElementById('userSelect').value;
if (!userAktif) return;
document.getElementById('loginPage').style.display = 'none';
document.getElementById('mainApp').style.display = 'flex';
document.getElementById('uDash').innerText = userAktif;
if (userAktif.toLowerCase().includes("admin")) {
document.querySelectorAll('.guru-only').forEach(el => el.style.display = 'none');
}
refreshData();
}
function openPage(id) {
document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
document.querySelectorAll('.tab-item').forEach(t => t.classList.remove('active'));
document.getElementById('p-' + id).classList.add('active');
var t = document.getElementById('tab-' + id); if(t) t.classList.add('active');
if (id === 'lapor') refreshData();
window.scrollTo(0,0);
}
function refreshData() {
google.script.run.withSuccessHandler(function(res) {
dataGlobal = res.laporan;
var sCont = document.getElementById('listSiswa');
var lCont = document.getElementById('listLapor');
var selS = document.getElementById('selSiswa');
// RESET LIST SISWA
sCont.innerHTML = '';
selS.innerHTML = '<option value="" disabled selected>-- Pilih --</option>';
// RENDER LIST SISWA DENGAN TOMBOL EDIT/HAPUS
res.siswa.forEach(s => {
sCont.innerHTML += `
<div class="siswa-item">
<span class="siswa-name">${s}</span>
<div>
<button onclick="editSiswa('${s}')" class="btn btn-warning btn-sm py-0 px-2" style="font-size:10px; margin-right:3px;">
<i class="fas fa-pen"></i>
</button>
<button onclick="hapusSiswa('${s}')" class="btn btn-danger btn-sm py-0 px-2" style="font-size:10px;">
<i class="fas fa-trash"></i>
</button>
</div>
</div>`;
selS.add(new Option(s, s));
});
// RENDER LAPORAN
lCont.innerHTML = '';
res.laporan.forEach(d => {
lCont.innerHTML += `<div class="report-card">
<span class="r-name">${d.siswa}</span>
<span class="r-type">${d.jenis}</span>
<div class="r-body">"${d.cat}"</div>
<div style="font-size:10px; color:#059669; font-weight:bold; margin-top:3px;">TL: ${d.tl}</div>
${userAktif.toLowerCase().includes("admin") ? `<div style="font-size:9px; border-top:1px solid #eee; margin-top:4px;">GURU: ${d.guru}</div>` : ''}
</div>`;
});
}).ambilSemuaData(userAktif);
}
function persiapkanCetak() {
if (dataGlobal.length === 0) return;
var isAdmin = userAktif.toLowerCase().includes("admin");
document.getElementById('p-identitas').innerText = isAdmin ? "REKAPITULASI SELURUH GURU" : userAktif;
document.getElementById('p-date').innerText = new Date().toLocaleDateString('id-ID', {day:'numeric', month:'long', year:'numeric'});
if(isAdmin) {
document.getElementById('label-ttd').innerText = "Mengetahui, Kepala Sekolah";
document.getElementById('nama-ttd').innerText = "( ____________________ )";
} else {
document.getElementById('label-ttd').innerText = "Guru Wali";
document.getElementById('nama-ttd').innerText = "( " + userAktif + " )";
}
document.getElementById('hCetak').innerHTML = `<tr><th>No</th><th>Tgl</th><th>Siswa</th><th>Jenis</th><th>Catatan</th><th>TL</th>${isAdmin ? '<th>Guru</th>' : ''}</tr>`;
var b = '';
dataGlobal.forEach((d, i) => {
b += `<tr><td style="text-align:center">${i+1}</td><td>${d.tgl}</td><td>${d.siswa}</td><td>${d.jenis}</td><td>${d.cat}</td><td>${d.tl}</td>${isAdmin ? `<td>${d.guru}</td>` : ''}</tr>`;
});
document.getElementById('bCetak').innerHTML = b;
window.print();
}
function tambahSiswa() {
Swal.fire({ title: 'Nama Siswa', input: 'text', showCancelButton: true }).then(r => {
if (r.value) google.script.run.withSuccessHandler(refreshData).simpanSiswa(r.value, userAktif);
});
}
// --- FUNGSI HAPUS SISWA ---
function hapusSiswa(nama) {
Swal.fire({
title: 'Hapus Siswa?',
text: "Hapus " + nama + "? Data bimbingan tetap ada, tapi nama hilang dari daftar.",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
confirmButtonText: 'Ya, Hapus!'
}).then((result) => {
if (result.isConfirmed) {
Swal.fire({title: 'Menghapus...', didOpen: () => Swal.showLoading()});
google.script.run.withSuccessHandler(() => {
Swal.fire('Terhapus!', 'Siswa berhasil dihapus.', 'success');
refreshData();
}).hapusSiswaServer(nama, userAktif);
}
});
}
// --- FUNGSI EDIT SISWA ---
function editSiswa(namaLama) {
Swal.fire({
title: 'Edit Nama Siswa',
input: 'text',
inputValue: namaLama,
showCancelButton: true,
confirmButtonText: 'Simpan',
inputValidator: (value) => {
if (!value) { return 'Nama tidak boleh kosong!' }
}
}).then((result) => {
if (result.isConfirmed && result.value !== namaLama) {
Swal.fire({title: 'Menyimpan...', didOpen: () => Swal.showLoading()});
google.script.run.withSuccessHandler(() => {
Swal.fire('Berhasil', 'Nama berhasil diubah.', 'success');
refreshData();
}).editSiswaServer(namaLama, result.value, userAktif);
}
});
}
document.getElementById('fInput').onsubmit = function(e) {
e.preventDefault();
var obj = { tgl: new Date().toLocaleDateString('id-ID'), nama: document.getElementById('selSiswa').value, jenis: document.getElementById('selJenis').value, cat: document.getElementById('tCat').value, tl: document.getElementById('tTL').value, guru: userAktif };
Swal.fire({ title: 'Menyimpan...', didOpen: () => Swal.showLoading() });
google.script.run.withSuccessHandler(() => {
Swal.fire('Berhasil', 'Data Tersimpan', 'success');
document.getElementById('fInput').reset();
refreshData();
}).simpanData(obj);
}
</script>
</body>
</html>
Langkah 4: Deploy Aplikasi
Agar aplikasi bisa diakses, Anda harus melakukan deployment:
- Klik tombol Terapkan (Deploy) > Deployment Baru.
- Pilih jenis Aplikasi Web.
- Pada bagian Siapa yang memiliki akses, pilih Siapa saja (Anyone).
- Klik Terapkan.
- Salin URL Web App yang diberikan dan bagikan ke guru-guru.
