forked from izu/student-web-if-development-kit
Compare commits
4 Commits
48ff6250ab
..
rehan
| Author | SHA1 | Date | |
|---|---|---|---|
| 49cd290d5a | |||
| 4d828814da | |||
| 112447c6bc | |||
| 027bd25359 |
@@ -20,16 +20,6 @@ Buka URL dari Vite (default: `http://localhost:5173`) lalu akses launcher di `/`
|
||||
| `npm run build` | Build static output ke folder `dist` |
|
||||
| `npm run preview` | Preview hasil build |
|
||||
|
||||
## Deploy Netlify
|
||||
|
||||
Project ini sudah punya konfigurasi Netlify di `netlify.toml`.
|
||||
|
||||
Saat membuat site di Netlify:
|
||||
- Repository: `GuavaPopper/PPL_Staging`
|
||||
- Branch deploy: `Staging`
|
||||
- Build command: `npm run build`
|
||||
- Publish directory: `dist`
|
||||
|
||||
## Struktur Folder
|
||||
|
||||
```
|
||||
|
||||
+12
-154
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
|
||||
<head>
|
||||
@@ -430,142 +430,14 @@
|
||||
<div id="mega-overlay" class="fixed inset-0 bg-black/30 backdrop-blur-sm z-30"></div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<div id="mobile-menu"
|
||||
class="fixed inset-0 bg-slate-900 z-[60] transform -translate-x-full lg:hidden flex flex-col transition-transform duration-300"
|
||||
role="dialog" aria-modal="true" aria-label="Menu navigasi mobile">
|
||||
<div class="p-4 flex justify-between items-center border-b border-white/10 bg-untan-navy">
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="font-bold text-lg text-white font-serif">Menu Utama</span>
|
||||
<button id="lang-toggle-mobile"
|
||||
class="language-toggle-btn px-2 py-1 rounded-sm border border-white/20 text-xs text-white hover:bg-white/10 transition-colors flex items-center gap-2"
|
||||
onclick="setLanguage(currentLang === 'id' ? 'en' : 'id')"
|
||||
aria-label="Ganti bahasa">
|
||||
<span class="font-bold">ID</span> <span class="text-white/40" aria-hidden="true">|</span> EN
|
||||
</button>
|
||||
<button
|
||||
class="w-8 h-8 rounded-sm bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-colors"
|
||||
aria-label="Pengaturan aksesibilitas"
|
||||
onclick="const p=document.getElementById('access-panel'); if (p) { p.classList.toggle('hidden'); p.classList.toggle('flex'); }">
|
||||
<i class="fas fa-universal-access" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button id="close-mobile-menu"
|
||||
class="w-8 h-8 rounded-sm bg-white/10 flex items-center justify-center text-white"
|
||||
aria-label="Tutup menu navigasi">
|
||||
<i class="fas fa-times" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex-1 overflow-y-auto p-5 space-y-4 bg-slate-50">
|
||||
<a href="../../index.html" class="block text-base font-bold text-slate-800 py-1 border-b border-slate-200"
|
||||
data-i18n="nav_home">Beranda</a>
|
||||
|
||||
<!-- Tentang Kami -->
|
||||
<div class="pt-2">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase font-serif" data-i18n="nav_about">Tentang
|
||||
Kami</span>
|
||||
<div class="pl-2 border-l-2 border-slate-100 mt-1 space-y-1">
|
||||
<a href="content.html?type=berita" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_history">Sejarah & Tonggak</a>
|
||||
<a href="content.html?type=berita" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_org">Struktur Organisasi</a>
|
||||
<a href="profil.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_vision">Visi & Misi</a>
|
||||
<a href="content.html?type=berita" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_partnership">Kerjasama & MoU</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Program -->
|
||||
<div class="pt-2 border-t border-slate-200">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase font-serif"
|
||||
data-i18n="nav_program">Program</span>
|
||||
<div class="pl-2 border-l-2 border-slate-100 mt-1 space-y-1">
|
||||
<a href="subject-and-courses.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_academic">Akademik</a>
|
||||
<a href="content.html?type=berita" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_accreditation">Akreditasi</a>
|
||||
<a href="graduate-profile.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_graduate">Profil Lulusan</a>
|
||||
<a href="subject-and-courses.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_courses">Mata Kuliah</a>
|
||||
<a href="academic-guidelines.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_guideline">Panduan Akademik</a>
|
||||
<a href="content.html?type=berita" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_statistics">Pengumuman</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SDM -->
|
||||
<div class="pt-2 border-t border-slate-200">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase font-serif" data-i18n="nav_sdm">SDM</span>
|
||||
<div class="pl-2 border-l-2 border-slate-100 mt-1 space-y-1">
|
||||
<a href="people-based-on-kk.html"
|
||||
class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue font-medium"
|
||||
data-i18n="btn_all_lecturers">Semua Dosen</a>
|
||||
<a href="people-based-on-kk.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="kk_ai">Kecerdasan Buatan</a>
|
||||
<a href="people-based-on-kk.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="kk_se">Rekayasa Perangkat Lunak</a>
|
||||
<a href="people-based-on-kk.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="kk_network">Jaringan & Keamanan</a>
|
||||
<a href="people-based-on-kk.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="kk_is">Sistem Informasi</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Fasilitas -->
|
||||
<div class="pt-2 border-t border-slate-200">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase font-serif"
|
||||
data-i18n="nav_facilities">Fasilitas</span>
|
||||
<div class="pl-2 border-l-2 border-slate-100 mt-1 space-y-1">
|
||||
<a href="content.html?type=rubrik" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="mega_lab">Laboratorium</a>
|
||||
<a href="content.html?type=rubrik" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="mega_dc">Data Center</a>
|
||||
<a href="content.html?type=rubrik" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="mega_eresources">E-Resources</a>
|
||||
<a href="ifuntanhub.html"
|
||||
class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue">IFUNTANHUB</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Karya & Agenda -->
|
||||
<div class="pt-2 border-t border-slate-200">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase font-serif" data-i18n="nav_works">Karya &
|
||||
Agenda</span>
|
||||
<div class="pl-2 border-l-2 border-slate-100 mt-1 space-y-1">
|
||||
<a href="karya.html" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_all_karya">Semua Karya</a>
|
||||
<a href="karya.html?filter=penelitian"
|
||||
class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_research">Riset</a>
|
||||
<a href="karya.html?filter=pkm" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_community">Pengabdian Masyarakat</a>
|
||||
<a href="content.html?type=rubrik" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_achievements">Prestasi</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Kontak -->
|
||||
<div class="pt-2 border-t border-slate-200 pb-8">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase font-serif"
|
||||
data-i18n="nav_contact">Kontak</span>
|
||||
<div class="pl-2 border-l-2 border-slate-100 mt-1 space-y-1">
|
||||
<a href="content.html?type=berita" class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_official_contact">Kontak Resmi</a>
|
||||
<a href="mailto:info@informatika.untan.ac.id"
|
||||
class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue"
|
||||
data-i18n="link_feedback">Saran & Masukan</a>
|
||||
<a href="https://instagram.com/informatika.untan" target="_blank" rel="noopener noreferrer"
|
||||
class="block py-1.5 text-sm text-slate-700 hover:text-untan-blue flex items-center gap-2">
|
||||
<i class="fab fa-instagram text-pink-500"></i> Instagram
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Breadcrumb (Diubah menyesuaikan pepet kiri navbar) -->
|
||||
<div class="bg-white">
|
||||
<div class="w-full px-3 sm:px-4 md:px-6 lg:px-8 xl:px-10 py-3 sm:py-3 md:py-3.5 lg:py-3.5 xl:py-3.5 text-[10px] sm:text-[11px] md:text-xs lg:text-xs xl:text-xs font-medium text-gray-500 uppercase">
|
||||
<span data-i18n="home">BERANDA</span> <span class="mx-2">/</span> <span class="text-untan-blue font-bold"
|
||||
data-i18n="pageTitle">RISET & KBK</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Hero Section -->
|
||||
<header class="bg-untan-navy relative reveal">
|
||||
<div class="max-w-7xl mx-auto px-3 sm:px-4 md:px-6 lg:px-8 xl:px-10 relative z-10 py-8 sm:py-12 md:py-16 lg:py-20 xl:py-24">
|
||||
@@ -919,8 +791,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><span data-i18n="lastUpdatedText">This page was last updated on: </span><span id="last-updated"></span></p>
|
||||
|
||||
<div id="riset-count-info"
|
||||
class="mt-3 sm:mt-3.5 md:mt-4 lg:mt-3 xl:mt-4 text-[10px] sm:text-[10px] md:text-[11px] lg:text-[11px] xl:text-[11px] font-medium text-slate-400 uppercase tracking-widest">
|
||||
Menghitung data...
|
||||
@@ -968,7 +838,7 @@
|
||||
<div class="max-w-2xl">
|
||||
<h2 class="text-2xl sm:text-2.5xl md:text-3xl lg:text-4xl xl:text-5xl font-bold font-condensed text-untan-navy mb-5 sm:mb-6 md:mb-7 lg:mb-8 xl:mb-8 leading-tight"
|
||||
data-i18n="labTitle">Laboratorium Pendukung Riset</h2>
|
||||
<p class="text-slate-500 text-xs sm:text-sm md:text-base lg:text-base xl:text-lg leading-relaxed" data-i18n="labDesc">5 laboratorium modern dengan 93 unit PC All-in-One
|
||||
<p class="text-slate-500 text-xs sm:text-sm md:text-base lg:text-base xl:text-lg leading-relaxed">5 laboratorium modern dengan 93 unit PC All-in-One
|
||||
yang mendukung kegiatan riset strategis dan pengembangan teknologi dosen serta mahasiswa.
|
||||
</p>
|
||||
</div>
|
||||
@@ -1380,10 +1250,7 @@
|
||||
ctaBtn: 'Hubungi Kami',
|
||||
viewAll: 'Lihat Semua',
|
||||
facultyDirectory: 'Direktori Dosen',
|
||||
expertise: 'Keahlian',
|
||||
lastUpdatedText: 'Halaman ini terakhir diperbarui pada: ',
|
||||
showingPubs: 'Menampilkan {0} dari {1} publikasi',
|
||||
labDesc: '5 laboratorium modern dengan 93 unit PC All-in-One yang mendukung kegiatan riset strategis dan pengembangan teknologi dosen serta mahasiswa.'
|
||||
expertise: 'Keahlian'
|
||||
},
|
||||
en: {
|
||||
info: 'LATEST INFO',
|
||||
@@ -1439,10 +1306,7 @@
|
||||
ctaBtn: 'Contact Us',
|
||||
viewAll: 'View All',
|
||||
facultyDirectory: 'Faculty Directory',
|
||||
expertise: 'Expertise',
|
||||
lastUpdatedText: 'This page was last updated on: ',
|
||||
showingPubs: 'Showing {0} of {1} publications',
|
||||
labDesc: '5 modern laboratories with 93 All-in-One PCs supporting strategic research and technological development for faculty and students.'
|
||||
expertise: 'Expertise'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1704,8 +1568,7 @@
|
||||
// Update info jumlah data yang ditampilkan
|
||||
const countInfo = document.getElementById('riset-count-info');
|
||||
if (countInfo) {
|
||||
const template = translations[currentLang].showingPubs || `Menampilkan {0} dari {1} publikasi`;
|
||||
countInfo.innerText = template.replace('{0}', itemsToShow.length).replace('{1}', filteredItems.length);
|
||||
countInfo.innerText = `Menampilkan ${itemsToShow.length} dari ${filteredItems.length} publikasi`;
|
||||
}
|
||||
|
||||
// Tampilkan/Sembunyikan tombol "Lihat Semua" berdasarkan sisa data
|
||||
@@ -1764,7 +1627,7 @@
|
||||
const rank = currentLang === 'id' ? leader.badge_id : leader.badge_en;
|
||||
|
||||
return `
|
||||
<a href="https://informatika.untan.ac.id/people-based-on-kk.html" class="group block rounded-2xl sm:rounded-2.5xl md:rounded-3xl lg:rounded-3xl xl:rounded-3xl overflow-hidden border border-slate-100 bg-white shadow-soft hover:-translate-y-2 hover:shadow-soft-lg transition-all duration-500">
|
||||
<a href="dosen_kbk.html?kbk=${kbk}&lang=${currentLang}" class="group block rounded-2xl sm:rounded-2.5xl md:rounded-3xl lg:rounded-3xl xl:rounded-3xl overflow-hidden border border-slate-100 bg-white shadow-soft hover:-translate-y-2 hover:shadow-soft-lg transition-all duration-500">
|
||||
<div class="p-5 sm:p-6 md:p-7 lg:p-8 xl:p-8 bg-gradient-to-br ${meta.accent} border-b border-slate-100">
|
||||
<div class="flex items-start justify-between gap-3 sm:gap-4">
|
||||
<div>
|
||||
@@ -1929,11 +1792,6 @@
|
||||
renderKbkInsight();
|
||||
renderRisetCards();
|
||||
renderDosenCards();
|
||||
|
||||
const lastUpdatedEl = document.getElementById("last-updated");
|
||||
if (lastUpdatedEl) {
|
||||
lastUpdatedEl.innerHTML = new Date(document.lastModified).toLocaleString(lang === 'id' ? 'id-ID' : 'en-US');
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('error', (event) => {
|
||||
|
||||
Generated
+11
-11
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "roda",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "roda",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC"
|
||||
"name": "roda",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "roda",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-13
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "roda",
|
||||
"version": "1.0.0",
|
||||
"description": "Project website untuk menampilkan sorotan dan prestasi karya mahasiswa program studi Informatika Universitas Tanjungpura.",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node server.js",
|
||||
"dev": "node server.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
"name": "roda",
|
||||
"version": "1.0.0",
|
||||
"description": "Project website untuk menampilkan sorotan dan prestasi karya mahasiswa program studi Informatika Universitas Tanjungpura.",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node server.js",
|
||||
"dev": "node server.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
[build]
|
||||
command = "npm run build"
|
||||
publish = "dist"
|
||||
|
||||
[build.environment]
|
||||
NODE_VERSION = "22"
|
||||
+1
-2
@@ -6,8 +6,7 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"test:netlify-build": "node scripts/verify-netlify-build.mjs"
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^7.1.0"
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
import { existsSync, readdirSync, statSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const root = process.cwd();
|
||||
const dist = path.join(root, 'dist');
|
||||
const excludedDirs = new Set(['.git', 'dist', 'node_modules']);
|
||||
|
||||
function collectFiles(dir, predicate = () => true) {
|
||||
const entries = readdirSync(dir, { withFileTypes: true });
|
||||
const files = [];
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (!excludedDirs.has(entry.name)) {
|
||||
files.push(...collectFiles(fullPath, predicate));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.isFile() && predicate(fullPath)) {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
if (!existsSync(dist) || !statSync(dist).isDirectory()) {
|
||||
throw new Error('Missing dist directory. Run `npm run build` first.');
|
||||
}
|
||||
|
||||
const missingHtmlFiles = collectFiles(root, (file) => file.endsWith('.html'))
|
||||
.map((file) => path.relative(root, file))
|
||||
.filter((relativePath) => !existsSync(path.join(dist, relativePath)));
|
||||
|
||||
const missingAssetFiles = collectFiles(path.join(root, 'assets'))
|
||||
.map((file) => path.relative(root, file))
|
||||
.filter((relativePath) => !existsSync(path.join(dist, relativePath)));
|
||||
|
||||
const missingFiles = [...missingHtmlFiles, ...missingAssetFiles];
|
||||
|
||||
if (missingFiles.length > 0) {
|
||||
throw new Error(`Missing built files:\n${missingFiles.join('\n')}`);
|
||||
}
|
||||
|
||||
console.log('All source HTML and static asset files are present in dist.');
|
||||
@@ -1,57 +0,0 @@
|
||||
import { cpSync, existsSync, readdirSync } from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
const root = path.dirname(fileURLToPath(import.meta.url));
|
||||
const excludedDirs = new Set(['.git', 'dist', 'node_modules']);
|
||||
|
||||
function collectHtmlInputs(dir) {
|
||||
const inputs = {};
|
||||
const entries = readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (!excludedDirs.has(entry.name)) {
|
||||
Object.assign(inputs, collectHtmlInputs(fullPath));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.isFile() && entry.name.endsWith('.html')) {
|
||||
const relativePath = path.relative(root, fullPath);
|
||||
const inputName = relativePath
|
||||
.replace(/\.html$/, '')
|
||||
.replace(/[^a-zA-Z0-9_-]+/g, '_');
|
||||
|
||||
inputs[inputName] = fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
return inputs;
|
||||
}
|
||||
|
||||
function copyStaticAssets() {
|
||||
return {
|
||||
name: 'copy-static-assets',
|
||||
closeBundle() {
|
||||
const source = path.join(root, 'assets');
|
||||
const destination = path.join(root, 'dist', 'assets');
|
||||
|
||||
if (existsSync(source)) {
|
||||
cpSync(source, destination, { recursive: true });
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [copyStaticAssets()],
|
||||
build: {
|
||||
rollupOptions: {
|
||||
input: collectHtmlInputs(root),
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user