Upload files to "/"
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
|||||||
|
FROM php:8.2-apache
|
||||||
|
|
||||||
|
RUN docker-php-ext-install mysqli pdo pdo_mysql
|
||||||
|
|
||||||
|
RUN a2enmod rewrite
|
||||||
|
|
||||||
|
COPY . /var/www/html/
|
||||||
|
|
||||||
|
RUN chown -R www-data:www-data /var/www/html
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Deploy Coolify - Tugas_SIG Tiara
|
||||||
|
|
||||||
|
Repo ini dijadikan satu landing page untuk Tugas 1 sampai Tugas 4.
|
||||||
|
|
||||||
|
## Struktur utama
|
||||||
|
|
||||||
|
- `/` -> Landing page tugas
|
||||||
|
- `/Tugas1/` -> Tugas 1
|
||||||
|
- `/Tugas2/` -> Tugas 2
|
||||||
|
- `/Tugas3/` -> Tugas 3
|
||||||
|
- `/Tugas4/` -> Tugas 4
|
||||||
|
|
||||||
|
## Coolify
|
||||||
|
|
||||||
|
Buat 1 database MySQL/MariaDB dengan Initial Database:
|
||||||
|
|
||||||
|
```text
|
||||||
|
db_poverty_mapping
|
||||||
|
```
|
||||||
|
|
||||||
|
Buat 1 aplikasi dari repo ini:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Build Pack: Dockerfile
|
||||||
|
Ports Exposes: 80
|
||||||
|
```
|
||||||
|
|
||||||
|
Production Environment Variables:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DB_HOST=host_database_internal
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_NAME=db_poverty_mapping
|
||||||
|
DB_USER=mysql
|
||||||
|
DB_PASS=password_normal_user_database
|
||||||
|
```
|
||||||
|
|
||||||
|
Setelah deploy, buka:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://URL-TUGAS/install_database.php
|
||||||
|
```
|
||||||
|
|
||||||
|
Jika database berhasil diimport, hapus `install_database.php` lalu redeploy.
|
||||||
+193
-286
@@ -1,316 +1,223 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="id">
|
<html lang="id">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Portal WebGIS & Poverty Mapping — Tiara Chontesa</title>
|
<title>Landing Page Tugas SIG - Tiara Chontesa</title>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--primary-color: #2b5c8f;
|
--bg: #f5f7fb;
|
||||||
--primary-dark: #1e3f63;
|
--card: #ffffff;
|
||||||
--secondary-color: #4a90e2;
|
--text: #172033;
|
||||||
--accent-color: #e28743;
|
--muted: #64748b;
|
||||||
--text-main: #2c3e50;
|
--primary: #2563eb;
|
||||||
--text-muted: #7f8c8d;
|
--primary-dark: #1d4ed8;
|
||||||
--bg-light: #f4f7f6;
|
--accent: #f97316;
|
||||||
--bg-card: #ffffff;
|
--border: #e5e7eb;
|
||||||
--border-color: #e2e8f0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
* { box-sizing: border-box; }
|
||||||
box-sizing: border-box;
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
}
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
header {
|
||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
background: linear-gradient(135deg, #0f172a, #1d4ed8);
|
||||||
background-color: var(--bg-light);
|
color: white;
|
||||||
color: var(--text-main);
|
padding: 56px 20px;
|
||||||
line-height: 1.6;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header h1 {
|
||||||
background: linear-gradient(135deg, var(--primary-dark) 0%, var(--primary-color) 100%);
|
margin: 0 0 10px;
|
||||||
color: #ffffff;
|
font-size: clamp(28px, 4vw, 44px);
|
||||||
padding: 60px 20px;
|
}
|
||||||
text-align: center;
|
|
||||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-container {
|
header p {
|
||||||
max-width: 1000px;
|
margin: 0 auto;
|
||||||
margin: 0 auto;
|
max-width: 760px;
|
||||||
}
|
color: #dbeafe;
|
||||||
|
}
|
||||||
|
|
||||||
header h1 {
|
.identity {
|
||||||
font-size: 2.5rem;
|
display: inline-flex;
|
||||||
margin-bottom: 10px;
|
gap: 14px;
|
||||||
font-weight: 700;
|
flex-wrap: wrap;
|
||||||
letter-spacing: -0.5px;
|
justify-content: center;
|
||||||
}
|
margin-top: 22px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
header p {
|
.identity span {
|
||||||
font-size: 1.1rem;
|
background: rgba(255,255,255,.12);
|
||||||
opacity: 0.9;
|
border: 1px solid rgba(255,255,255,.18);
|
||||||
margin-bottom: 25px;
|
padding: 8px 12px;
|
||||||
}
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
.meta-info {
|
main {
|
||||||
display: inline-flex;
|
max-width: 1120px;
|
||||||
gap: 20px;
|
margin: 0 auto;
|
||||||
background: rgba(255, 255, 255, 0.1);
|
padding: 34px 20px 56px;
|
||||||
padding: 10px 25px;
|
}
|
||||||
border-radius: 30px;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.meta-info span strong {
|
.note {
|
||||||
color: #ffeb3b;
|
background: #fff;
|
||||||
}
|
border: 1px solid var(--border);
|
||||||
|
border-left: 5px solid var(--primary);
|
||||||
|
border-radius: 14px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
box-shadow: 0 8px 24px rgba(15, 23, 42, .05);
|
||||||
|
}
|
||||||
|
|
||||||
main {
|
.grid {
|
||||||
max-width: 1200px;
|
display: grid;
|
||||||
margin: 40px auto;
|
grid-template-columns: repeat(auto-fit, minmax(245px, 1fr));
|
||||||
padding: 0 20px;
|
gap: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overview-section {
|
.card {
|
||||||
background: var(--bg-card);
|
background: var(--card);
|
||||||
border-radius: 12px;
|
border: 1px solid var(--border);
|
||||||
padding: 30px;
|
border-radius: 16px;
|
||||||
margin-bottom: 40px;
|
padding: 22px;
|
||||||
box-shadow: 0 4px 6px rgba(0,0,0,0.02);
|
min-height: 260px;
|
||||||
border-left: 5px solid var(--secondary-color);
|
display: flex;
|
||||||
}
|
flex-direction: column;
|
||||||
|
box-shadow: 0 8px 24px rgba(15, 23, 42, .05);
|
||||||
|
}
|
||||||
|
|
||||||
.overview-section h2 {
|
.badge {
|
||||||
margin-bottom: 15px;
|
display: inline-block;
|
||||||
color: var(--primary-color);
|
width: fit-content;
|
||||||
}
|
background: #dbeafe;
|
||||||
|
color: #1d4ed8;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
.grid-container {
|
.card h2 {
|
||||||
display: grid;
|
margin: 0 0 10px;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
font-size: 20px;
|
||||||
gap: 25px;
|
}
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
.card p {
|
||||||
background: var(--bg-card);
|
margin: 0 0 16px;
|
||||||
border-radius: 12px;
|
color: var(--muted);
|
||||||
border: 1px solid var(--border-color);
|
font-size: 14px;
|
||||||
overflow: hidden;
|
}
|
||||||
box-shadow: 0 4px 10px rgba(0,0,0,0.03);
|
|
||||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card:hover {
|
.card ul {
|
||||||
transform: translateY(-5px);
|
margin: 0 0 20px;
|
||||||
box-shadow: 0 10px 20px rgba(0,0,0,0.08);
|
padding-left: 18px;
|
||||||
}
|
color: var(--muted);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
.card-header {
|
.btn {
|
||||||
background: #f8fafc;
|
display: block;
|
||||||
padding: 20px;
|
margin-top: auto;
|
||||||
border-bottom: 1px solid var(--border-color);
|
padding: 11px 14px;
|
||||||
position: relative;
|
text-align: center;
|
||||||
}
|
border-radius: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
background: var(--primary);
|
||||||
|
color: white;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
.task-badge {
|
.btn:hover { background: var(--primary-dark); }
|
||||||
position: absolute;
|
.btn.accent { background: var(--accent); }
|
||||||
top: 20px;
|
.btn.accent:hover { background: #ea580c; }
|
||||||
right: 20px;
|
|
||||||
background: var(--primary-color);
|
|
||||||
color: white;
|
|
||||||
padding: 4px 12px;
|
|
||||||
border-radius: 20px;
|
|
||||||
font-size: 0.75rem;
|
|
||||||
font-weight: 600;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header h3 {
|
footer {
|
||||||
font-size: 1.25rem;
|
text-align: center;
|
||||||
color: var(--primary-dark);
|
color: var(--muted);
|
||||||
margin-top: 10px;
|
padding: 24px 20px;
|
||||||
}
|
border-top: 1px solid var(--border);
|
||||||
|
background: #fff;
|
||||||
.card-body {
|
font-size: 13px;
|
||||||
padding: 20px;
|
}
|
||||||
flex-grow: 1;
|
</style>
|
||||||
}
|
|
||||||
|
|
||||||
.card-body p {
|
|
||||||
font-size: 0.95rem;
|
|
||||||
color: var(--text-main);
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-list {
|
|
||||||
list-style: none;
|
|
||||||
margin-top: 10px;
|
|
||||||
padding-left: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-list li {
|
|
||||||
font-size: 0.85rem;
|
|
||||||
color: var(--text-muted);
|
|
||||||
padding: 4px 0;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-footer {
|
|
||||||
padding: 20px;
|
|
||||||
background: #f8fafc;
|
|
||||||
border-top: 1px solid var(--border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
display: block;
|
|
||||||
text-align: center;
|
|
||||||
background: var(--primary-color);
|
|
||||||
color: #ffffff;
|
|
||||||
padding: 10px 20px;
|
|
||||||
border-radius: 6px;
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
transition: background 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn:hover {
|
|
||||||
background: var(--primary-dark);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-accent {
|
|
||||||
background: var(--accent-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-accent:hover {
|
|
||||||
background: #d07431;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
text-align: center;
|
|
||||||
padding: 30px 20px;
|
|
||||||
color: var(--text-muted);
|
|
||||||
font-size: 0.9rem;
|
|
||||||
border-top: 1px solid var(--border-color);
|
|
||||||
margin-top: 60px;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
header h1 { font-size: 2rem; }
|
|
||||||
.meta-info { flex-direction: column; gap: 5px; border-radius: 15px; }
|
|
||||||
.grid-container { grid-template-columns: 1fr; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>Landing Page Tugas SIG</h1>
|
||||||
|
<p>Kumpulan tugas WebGIS dalam satu halaman utama agar mudah diakses melalui deployment Coolify.</p>
|
||||||
|
<div class="identity">
|
||||||
|
<span>Nama: <strong>Tiara Chontesa</strong></span>
|
||||||
|
<span>NIM: <strong>D1041231070</strong></span>
|
||||||
|
<span>Database: <strong>db_poverty_mapping</strong></span>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<header>
|
<main>
|
||||||
<div class="header-container">
|
<section class="note">
|
||||||
<h1>Sistem Pemetaan Spasial Terpadu</h1>
|
<strong>Daftar Project Tugas</strong>
|
||||||
<p>Integrasi WebGIS Geometri Sigma & Analisis Titik Kerawanan Kemiskinan (Poverty Mapping)</p>
|
<p style="margin: 8px 0 0; color: var(--muted);">Halaman ini hanya untuk tugas kelas. Project UAS tetap dideploy terpisah.</p>
|
||||||
<div class="meta-info">
|
</section>
|
||||||
<span>Nama: <strong>Tiara Chontesa</strong></span>
|
|
||||||
<span>NIM: <strong>D1041231070</strong></span>
|
|
||||||
<span>Database induk: <strong>db_poverty_mapping</strong></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
<section class="grid">
|
||||||
<section class="overview-section">
|
<article class="card">
|
||||||
<h2>Tentang Proyek Integrasi</h2>
|
<span class="badge">Tugas 1</span>
|
||||||
<p>Repositori ini dirancang khusus untuk mengonsolidasikan 4 tugas WebGIS ke dalam satu arsitektur terintegrasi. Dengan memanfaatkan satu database utama, seluruh modul kerja spasial mulai dari pengelolaan jaringan infrastruktur (jalan, persil, titik fasilitas umum) hingga penentuan zonasi Keluarga Penerima Manfaat (KPM) bantuan sosial dapat diakses secara langsung dan dinamis.</p>
|
<h2>WebGIS Data Jalan</h2>
|
||||||
</section>
|
<p>Modul pemetaan dan pengelolaan geometri polyline untuk jaringan jalan.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Polyline / LineString</li>
|
||||||
|
<li>Data jalan</li>
|
||||||
|
<li>Visualisasi Leaflet</li>
|
||||||
|
</ul>
|
||||||
|
<a class="btn" href="Tugas1/">Buka Tugas 1</a>
|
||||||
|
</article>
|
||||||
|
|
||||||
<div class="grid-container">
|
<article class="card">
|
||||||
|
<span class="badge">Tugas 2</span>
|
||||||
|
<h2>WebGIS Polygon & GeoJSON</h2>
|
||||||
|
<p>Modul pemetaan wilayah, kecamatan, batas administrasi, dan data spasial berbasis GeoJSON.</p>
|
||||||
|
<ul>
|
||||||
|
<li>Polygon wilayah</li>
|
||||||
|
<li>Layer GeoJSON</li>
|
||||||
|
<li>Data kecamatan</li>
|
||||||
|
</ul>
|
||||||
|
<a class="btn" href="Tugas2/">Buka Tugas 2</a>
|
||||||
|
</article>
|
||||||
|
|
||||||
<div class="card">
|
<article class="card">
|
||||||
<div class="card-header">
|
<span class="badge">Tugas 3</span>
|
||||||
<span class="task-badge">Tugas 1</span>
|
<h2>Layer Control & Data Point</h2>
|
||||||
<h3>Manajemen Geometri Polyline (Jaringan Jalan)</h3>
|
<p>Modul layer control untuk menampilkan data point dan layer tematik pada peta.</p>
|
||||||
</div>
|
<ul>
|
||||||
<div class="card-body">
|
<li>Marker / Point</li>
|
||||||
<p>Modul pemetaan spasial linear yang berfungsi untuk merekam, menghitung panjang secara otomatis menggunakan sistem koordinat Leaflet, serta memetakan data jaringan jalan berdasarkan klasifikasinya.</p>
|
<li>Layer control</li>
|
||||||
<ul class="table-list">
|
<li>Populasi kecamatan</li>
|
||||||
<li>• Tabel Database: <code>data_jalan</code></li>
|
</ul>
|
||||||
<li>• Format Spasial: GeoJSON LineString</li>
|
<a class="btn" href="Tugas3/">Buka Tugas 3</a>
|
||||||
<li>• Klasifikasi: Nasional, Provinsi, Kabupaten</li>
|
</article>
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<a href="Tugas1/" class="btn">Buka Modul Tugas 1</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
<article class="card">
|
||||||
<div class="card-header">
|
<span class="badge">Tugas 4</span>
|
||||||
<span class="task-badge">Tugas 2</span>
|
<h2>Poverty Mapping</h2>
|
||||||
<h3>Zonasi Wilayah Polygon (Data Parsil Lahan)</h3>
|
<p>Modul pemetaan kemiskinan dan bantuan sosial dengan data rumah miskin, rumah ibadah, dan bantuan tersalur.</p>
|
||||||
</div>
|
<ul>
|
||||||
<div class="card-body">
|
<li>Rumah miskin</li>
|
||||||
<p>Modul analisis area yang memetakan batas-batas persil wilayah lahan atau pemukiman warga, lengkap dengan kalkulasi luas otomatis dalam satuan meter persegi (m²).</p>
|
<li>Rumah ibadah</li>
|
||||||
<ul class="table-list">
|
<li>Bantuan tersalur</li>
|
||||||
<li>• Tabel Database: <code>data_parsil</code></li>
|
</ul>
|
||||||
<li>• Format Spasial: GeoJSON Polygon</li>
|
<a class="btn accent" href="Tugas4/">Buka Tugas 4</a>
|
||||||
<li>• Fungsi Utama: Batas administratif & tata guna lahan</li>
|
</article>
|
||||||
</ul>
|
</section>
|
||||||
</div>
|
</main>
|
||||||
<div class="card-footer">
|
|
||||||
<a href="Tugas2/" class="btn">Buka Modul Tugas 2</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">
|
|
||||||
<span class="task-badge">Tugas 3</span>
|
|
||||||
<h3>Peta Sebaran Titik (Marker Fasilitas Umum)</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p>Modul penanda objek vital yang mengelola persebaran koordinat fasilitas umum, infrastruktur kota, serta objek-objek spasial berformat point lainnya di dalam peta interaktif.</p>
|
|
||||||
<ul class="table-list">
|
|
||||||
<li>• Tabel Database: <code>data_point</code>, <code>geometri_sigma</code></li>
|
|
||||||
<li>• Format Spasial: GeoJSON Point / Marker</li>
|
|
||||||
<li>• Fungsi Utama: Manajemen marker & kustomisasi icon</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<a href="Tugas3/" class="btn">Buka Modul Tugas 3</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card" style="border: 1px solid var(--accent-color);">
|
|
||||||
<div class="card-header" style="background-color: #fffaf5;">
|
|
||||||
<span class="task-badge" style="background-color: var(--accent-color);">Tugas 4</span>
|
|
||||||
<h3>WebGIS Poverty Mapping (Bantuan Sosial)</h3>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<p>Sistem informasi geografis tingkat lanjut untuk penanggulangan kemiskinan. Menampilkan radius bantuan rumah ibadah (buffer), status sebaran KPM, manajemen logistik bencana, serta kontrol akses 4 role pengguna.</p>
|
|
||||||
<ul class="table-list">
|
|
||||||
<li>• Tabel Database: <code>users</code>, <code>rumah_miskin</code>, <code>rumah_ibadah</code>, <code>bantuan_tersalur</code></li>
|
|
||||||
<li>• Fitur Kunci: Buffer spasial, Manajemen 4 Role User</li>
|
|
||||||
<li>• Status Bantuan: Deteksi Blank Spot area otomatis</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer" style="background-color: #fffaf5;">
|
|
||||||
<a href="Tugas4/" class="btn btn-accent">Buka Aplikasi Utama</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer>
|
|
||||||
<p>© 2026 Proyek Terintegrasi WebGIS Spasial. Dirancang oleh Tiara Chontesa (D1041231070).</p>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
© 2026 Tiara Chontesa - Tugas SIG WebGIS
|
||||||
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
// install_database.php - installer sementara database Tugas_SIG Tiara
|
||||||
|
// HAPUS file ini setelah database berhasil diimport.
|
||||||
|
|
||||||
|
set_time_limit(300);
|
||||||
|
|
||||||
|
$host = getenv('DB_HOST') ?: 'localhost';
|
||||||
|
$user = getenv('DB_USER') ?: 'root';
|
||||||
|
$pass = getenv('DB_PASS') ?: (getenv('DB_PASSWORD') ?: '');
|
||||||
|
$db = getenv('DB_NAME') ?: 'db_poverty_mapping';
|
||||||
|
$port = (int)(getenv('DB_PORT') ?: 3306);
|
||||||
|
|
||||||
|
echo "<h2>Install Database Tugas SIG Tiara</h2>";
|
||||||
|
echo "<p>Target koneksi: <b>" . htmlspecialchars($host) . ":" . htmlspecialchars((string)$port) . "</b>, database: <b>" . htmlspecialchars($db) . "</b>, user: <b>" . htmlspecialchars($user) . "</b></p>";
|
||||||
|
|
||||||
|
$conn = new mysqli($host, $user, $pass, $db, $port);
|
||||||
|
|
||||||
|
if ($conn->connect_error) {
|
||||||
|
die("<p style='color:red'>Koneksi gagal: " . htmlspecialchars($conn->connect_error) . "</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
$sqlFile = __DIR__ . "/database.sql";
|
||||||
|
if (!file_exists($sqlFile)) {
|
||||||
|
die("<p style='color:red'>File SQL tidak ditemukan: " . htmlspecialchars($sqlFile) . "</p>");
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = file_get_contents($sqlFile);
|
||||||
|
|
||||||
|
// Coolify normal user biasanya tidak butuh/ tidak punya izin CREATE DATABASE.
|
||||||
|
// Database sudah dibuat dari field Initial Database, jadi baris CREATE DATABASE dan USE diabaikan.
|
||||||
|
$sql = preg_replace('/CREATE\\s+DATABASE\\s+IF\\s+NOT\\s+EXISTS\\s+`?[^`\\s;]+`?.*?;/is', '', $sql);
|
||||||
|
$sql = preg_replace('/USE\\s+`?[^`\\s;]+`?\\s*;/is', '', $sql);
|
||||||
|
|
||||||
|
// Jika dump hasil copy menjadi komentar seperti "-- 1.\nTABEL ... CREATE TABLE",
|
||||||
|
// buang label teks agar SQL tidak error.
|
||||||
|
$sql = preg_replace('/--\\s*\\d+\\.\\s*TABEL[^\\n]*\\n/is', '', $sql);
|
||||||
|
$sql = preg_replace('/\\bTABEL\\s+(PENGGUNA|RUMAH|BENCANA|DATA)[^;]*?(CREATE\\s+TABLE)/is', '$2', $sql);
|
||||||
|
|
||||||
|
if ($conn->multi_query($sql)) {
|
||||||
|
do {
|
||||||
|
if ($result = $conn->store_result()) {
|
||||||
|
$result->free();
|
||||||
|
}
|
||||||
|
} while ($conn->more_results() && $conn->next_result());
|
||||||
|
|
||||||
|
if ($conn->errno) {
|
||||||
|
echo "<p style='color:red'>Ada error saat import: " . htmlspecialchars($conn->error) . "</p>";
|
||||||
|
} else {
|
||||||
|
echo "<p style='color:green;font-weight:bold'>Database berhasil diimport.</p>";
|
||||||
|
echo "<p>Setelah ini, hapus file <code>install_database.php</code> dari repo lalu redeploy.</p>";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo "<p style='color:red'>Import gagal: " . htmlspecialchars($conn->error) . "</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$conn->close();
|
||||||
|
?>
|
||||||
+35
-52
@@ -1,73 +1,56 @@
|
|||||||
<?php
|
<?php
|
||||||
// ============================================================================
|
// koneksi.php - versi deploy Coolify untuk Tugas_SIG Tiara
|
||||||
// koneksi.php - KONEKSI UTAMA INTEGRATED (ANTI-ERROR FOLDER PATH)
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
// Sistem WebGIS Poverty Mapping & Geometri Sigma
|
session_start();
|
||||||
// Penyusun: Tiara Chontesa (D1041231070)
|
}
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
// 1. KREDENSIAL DATABASE LOCALHOST (XAMPP)
|
$host = getenv('DB_HOST') ?: 'localhost';
|
||||||
define('DB_HOST', 'localhost');
|
$user = getenv('DB_USER') ?: 'root';
|
||||||
define('DB_USER', 'root');
|
$pass = getenv('DB_PASS') ?: (getenv('DB_PASSWORD') ?: '');
|
||||||
define('DB_PASS', ''); // Kosongkan jika menggunakan XAMPP standar lokal
|
$db = getenv('DB_NAME') ?: 'db_poverty_mapping';
|
||||||
define('DB_NAME', 'db_poverty_mapping'); // Mengarah ke nama database gabungan baru
|
$port = (int)(getenv('DB_PORT') ?: 3306);
|
||||||
|
|
||||||
// Eksekusi Koneksi MySQLi
|
$conn = new mysqli($host, $user, $pass, $db, $port);
|
||||||
$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
|
|
||||||
|
|
||||||
// Validasi Kegagalan Koneksi
|
|
||||||
if ($conn->connect_error) {
|
if ($conn->connect_error) {
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
die(json_encode([
|
die(json_encode([
|
||||||
'status' => 'error',
|
'status' => 'error',
|
||||||
'message' => 'Koneksi database gagal: ' . $conn->connect_error
|
'message' => 'Koneksi database gagal: ' . $conn->connect_error
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set Charset ke UTF-8 agar aman membaca data koordinat spasial/GeoJSON
|
|
||||||
$conn->set_charset('utf8mb4');
|
$conn->set_charset('utf8mb4');
|
||||||
|
|
||||||
|
function getRedirectPath($targetFile) {
|
||||||
|
$currentDir = basename(dirname($_SERVER['SCRIPT_FILENAME']));
|
||||||
|
if (stripos($currentDir, 'Tugas') !== false || stripos($currentDir, 'tugas') !== false || $currentDir === 'includes') {
|
||||||
|
return '../' . $targetFile;
|
||||||
|
}
|
||||||
|
return $targetFile;
|
||||||
|
}
|
||||||
|
|
||||||
// 2. DETEKSI LOKASI PATH RELATIF (Cerdas mencegah error No Such File / Wrong Redirect)
|
function cekLogin() {
|
||||||
if (!function_exists('getRedirectPath')) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
function getRedirectPath($targetFile) {
|
session_start();
|
||||||
// Ambil nama folder tempat file PHP yang sedang berjalan berada
|
}
|
||||||
$currentDir = basename(dirname($_SERVER['SCRIPT_FILENAME']));
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: ' . getRedirectPath('login.php'));
|
||||||
// Jika file pengakses ada di dalam subfolder tugas (misal: tugas1_polyline, tugas2_polygon)
|
exit;
|
||||||
// atau berada di dalam folder 'includes', mundurkan path satu tingkat ke luar menggunakan '../'
|
|
||||||
if (strpos($currentDir, 'tugas') !== false || $currentDir === 'includes') {
|
|
||||||
return '../' . $targetFile;
|
|
||||||
}
|
|
||||||
return $targetFile;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cekRole($role_wajib) {
|
||||||
// 3. FUNGSI OTENTIKASI GLOBAL (Bisa langsung dipanggil di semua folder tugas Anda)
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
if (!function_exists('cekLogin')) {
|
session_start();
|
||||||
function cekLogin() {
|
}
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
if (!isset($_SESSION['role']) || $_SESSION['role'] !== $role_wajib) {
|
||||||
session_start();
|
header('Location: ' . getRedirectPath('dashboard.php?error=unauthorized'));
|
||||||
}
|
exit;
|
||||||
// Jika belum ada session user_id, tendang paksa ke halaman login.php dengan path yang benar
|
|
||||||
if (!isset($_SESSION['user_id'])) {
|
|
||||||
$loginPath = getRedirectPath('login.php');
|
|
||||||
header("Location: " . $loginPath);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!function_exists('cekRole')) {
|
function bersih($str, $conn) {
|
||||||
function cekRole($role_wajib) {
|
return $conn->real_escape_string(htmlspecialchars(strip_tags(trim($str))));
|
||||||
if (session_status() === PHP_SESSION_NONE) {
|
|
||||||
session_start();
|
|
||||||
}
|
|
||||||
// Jika role user tidak sesuai dengan kriteria halaman, tendang ke dashboard utama
|
|
||||||
if (!isset($_SESSION['role']) || $_SESSION['role'] !== $role_wajib) {
|
|
||||||
$dashboardPath = getRedirectPath('dashboard.php?error=unauthorized');
|
|
||||||
header("Location: " . $dashboardPath);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
?>
|
||||||
|
|||||||
Reference in New Issue
Block a user