diff --git a/.env.local.backup b/.env.local.backup new file mode 100644 index 0000000..9527dc3 --- /dev/null +++ b/.env.local.backup @@ -0,0 +1,76 @@ +APP_NAME=SIBEDAS-PBG +APP_ENV=local +APP_KEY=base64:xqCpwixWKqgu1Ca22gFizoOt44p7h+cgTOKuhS/P0Jw= +APP_DEBUG=true +APP_TIMEZONE=Asia/Jakarta +APP_URL=http://localhost:8000 + +API_URL=http://localhost:8000 + +APP_LOCALE=en +APP_FALLBACK_LOCALE=en +APP_FAKER_LOCALE=en_US + +APP_MAINTENANCE_DRIVER=file +# APP_MAINTENANCE_STORE=database + +PHP_CLI_SERVER_WORKERS=4 + +BCRYPT_ROUNDS=12 + +LOG_CHANNEL=stack +LOG_STACK=single +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=mariadb +DB_HOST=db +DB_PORT=3306 +DB_DATABASE=sibedas_db +DB_USERNAME=root +DB_PASSWORD=root + +SESSION_DRIVER=database +SESSION_LIFETIME=120 +SESSION_ENCRYPT=false +SESSION_PATH=/ +SESSION_DOMAIN=null + +BROADCAST_CONNECTION=log +FILESYSTEM_DISK=local +QUEUE_CONNECTION=database + +CACHE_STORE=database +CACHE_PREFIX= + +MEMCACHED_HOST=127.0.0.1 + +REDIS_CLIENT=phpredis +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=log +MAIL_HOST=127.0.0.1 +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +VITE_APP_NAME="${APP_NAME}" + +SIMBG_HOST="https://simbg.pu.go.id/" +SIMBG_EMAIL="dputr@bandungkab.go.id" +SIMBG_PASSWORD="Simbg123" + +API_KEY_GOOGLE="AIzaSyBxfEShFkKmykkc7RJR3lVzkQ_xGHK3qr0" +SPREAD_SHEET_ID="1QoXzuLdEX3MK70Yrfigz0Qj5rAt4T819jX85vubBNdY" +OPENAI_API_KEY="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" \ No newline at end of file diff --git a/BUILD_GUIDE.md b/BUILD_GUIDE.md deleted file mode 100644 index 2e2eb8b..0000000 --- a/BUILD_GUIDE.md +++ /dev/null @@ -1,180 +0,0 @@ -# πŸš€ Panduan Build untuk Production - -## πŸ“‹ Masalah yang Diselesaikan - -Aplikasi ini memiliki **banyak file JS dan CSS** yang harus dibangun semuanya karena: -- Setiap halaman memerlukan file JS/CSS yang spesifik -- Jika ada file yang hilang, halaman akan error (404 Not Found) -- Server dengan RAM terbatas sering mengalami "killed" saat build - -## 🎯 Solusi yang Tersedia - -### 1. **Build di Local (RECOMMENDED) πŸ†** -```bash -# Build di local computer Anda -npm run build:local - -# Upload ke server -./deploy.sh username server.com /path/to/project -``` - -**Kelebihan:** -- βœ… Tidak ada batasan memory -- βœ… Build lebih cepat -- βœ… Semua file terjamin ter-build - -### 2. **Build di Server dengan Optimasi** -```bash -# Option A: Build dengan memory optimization -npm run build:prod - -# Option B: Build dengan retry mechanism -npm run build:chunked - -# Option C: Build manual dengan script -./build-production.sh -``` - -### 3. **Setup Server untuk Build** -```bash -# Setup swap memory dan optimasi (run dengan sudo) -sudo ./server-setup.sh - -# Kemudian build -npm run build:prod -``` - -## πŸ“ File yang Akan Dibangun - -Semua file ini **WAJIB** ada karena dibutuhkan oleh halaman-halaman aplikasi: - -### CSS Files: -- `resources/scss/style.scss` - Main stylesheet -- `resources/scss/icons.scss` - Icons -- `resources/scss/components/_*.scss` - Components -- `resources/scss/dashboards/_*.scss` - Dashboard styles -- `resources/scss/pages/quick-search/*.scss` - Quick search pages -- Third-party CSS (Quill, Flatpickr, GridJS, dll) - -### JS Files: -- **Core:** `app.js`, `config.js`, `dashboard.js` -- **Pages:** `chart.js`, `form-*.js`, `table-*.js`, `maps-*.js` -- **Data:** `data-advertisements.js`, `data-umkm.js`, `data-tourisms.js` -- **Settings:** `syncronize.js`, `general-settings.js` -- **Dashboards:** `bigdata.js`, `pbg.js`, `potentials/*.js` -- **Users & Roles:** `users/*.js`, `roles/*.js`, `menus/*.js` -- **Reports:** `growth-report.js`, `tourisms/index.js` -- **Dan semua file lainnya sesuai kebutuhan halaman** - -## βš™οΈ Konfigurasi Build - -### Memory Optimization -```javascript -// vite.config.production.js -export default defineConfig({ - build: { - rollupOptions: { - output: { - manualChunks: { - vendor: ['bootstrap', 'moment', 'axios'], - charts: ['apexcharts'], - maps: ['leaflet', 'jsvectormap', 'gmaps'], - ui: ['sweetalert2', 'flatpickr', 'quill'] - } - }, - maxParallelFileOps: 1 // Untuk server dengan RAM terbatas - } - } -}) -``` - -### Memory Limits -```bash -# Untuk server dengan RAM 2GB+ -NODE_OPTIONS="--max-old-space-size=2048" - -# Untuk server dengan RAM 1GB -NODE_OPTIONS="--max-old-space-size=1024" -``` - -## πŸ”§ Troubleshooting - -### Build Terkill (Killed) -```bash -# Solusi 1: Build di local -npm run build:local -./deploy.sh - -# Solusi 2: Tambah swap memory -sudo ./server-setup.sh - -# Solusi 3: Gunakan build chunked -npm run build:chunked -``` - -### File JS/CSS Tidak Ditemukan -```bash -# Pastikan semua file ada di vite.config.production.js -# Jangan hapus file apapun dari daftar input! - -# Verifikasi build -find public/build -name "*.js" | wc -l -find public/build -name "*.css" | wc -l -``` - -### Server Kehabisan Memory -```bash -# Check memory usage -free -h - -# Add swap file -sudo fallocate -l 2G /swapfile -sudo chmod 600 /swapfile -sudo mkswap /swapfile -sudo swapon /swapfile -``` - -## πŸ“¦ Deployment Flow - -### Local Build β†’ Server Deploy -```bash -# 1. Di local -npm ci -npm run build:local - -# 2. Edit deploy.sh dengan info server -# 3. Deploy -./deploy.sh username server.com /path/to/project -``` - -### Server Build -```bash -# 1. Setup server -sudo ./server-setup.sh - -# 2. Install dependencies -npm ci --production=false - -# 3. Build -npm run build:chunked - -# 4. Optimize Laravel -php artisan config:cache -php artisan route:cache -php artisan view:cache -``` - -## ⚠️ Catatan Penting - -1. **JANGAN HAPUS FILE APAPUN** dari `vite.config.production.js` -2. **SEMUA FILE WAJIB ADA** karena dibutuhkan oleh halaman-halaman aplikasi -3. **BUILD DI LOCAL** adalah solusi terbaik untuk server dengan RAM terbatas -4. **BACKUP** selalu sebelum deploy ke production - -## πŸŽ‰ Success Indicators - -Build berhasil jika: -- βœ… File `public/build/manifest.json` ada -- βœ… Folder `public/build/assets/` berisi banyak file JS/CSS -- βœ… Tidak ada error 404 saat mengakses halaman -- βœ… Semua halaman dapat memuat JS/CSS yang dibutuhkan \ No newline at end of file diff --git a/app/Console/Commands/ScrapingLeaderData.php b/app/Console/Commands/ScrapingLeaderData.php new file mode 100644 index 0000000..04f8bc9 --- /dev/null +++ b/app/Console/Commands/ScrapingLeaderData.php @@ -0,0 +1,33 @@ +sync_leader_data(); + $this->info('Leader data synced successfully'); + } +} diff --git a/app/Http/Controllers/Dashboards/BigDataController.php b/app/Http/Controllers/Dashboards/BigDataController.php index 780c61d..42e8f14 100644 --- a/app/Http/Controllers/Dashboards/BigDataController.php +++ b/app/Http/Controllers/Dashboards/BigDataController.php @@ -21,4 +21,13 @@ class BigDataController extends Controller { return view('dashboards.pbg'); } + + public function leader() + { + $latest_import_datasource = ImportDatasource::latest()->first(); + $latest_created = $latest_import_datasource ? + $latest_import_datasource->created_at->format("j F Y H:i:s") : null; + $menus = Menu::all(); + return view('dashboards.leader', compact('latest_created', 'menus')); + } } diff --git a/app/Services/ServiceGoogleSheet.php b/app/Services/ServiceGoogleSheet.php index 6a046be..dcf1258 100644 --- a/app/Services/ServiceGoogleSheet.php +++ b/app/Services/ServiceGoogleSheet.php @@ -1,14 +1,16 @@ 'Processing leader data', + 'status' => 'processing', + 'start_time' => now(), + 'failed_uuid' => null + ]); + try { + $sections = [ + 'TARGET_PAD' => "TARGET PAD 2024", + 'KEKURANGAN_POTENSI' => "DEVIASI TARGET DENGAN POTENSI TOTAL BERKAS", + 'TOTAL_POTENSI_BERKAS' => "β€’TOTAL BERKAS 2025", + 'BELUM_TERVERIFIKASI' => "β€’BERKAS AKTUAL BELUM TERVERIFIKASI (POTENSI):", + 'TERVERIFIKASI' => "β€’BERKAS AKTUAL TERVERIFIKASI DINAS TEKNIS 2025:", + 'NON_USAHA' => "β€’NON USAHA: HUNIAN, SOSBUD, KEAGAMAAN", + 'USAHA' => "β€’USAHA: USAHA, CAMPURAN, KOLEKTIF, PRASARANA" + ]; + + $result = []; + + foreach ($sections as $key => $identifier) { + $values = $this->get_values_from_section(2, $identifier, [10, 11]); + + if (!empty($values)) { + $result[$key] = [ + 'identifier' => $identifier, + 'total' => $values[0] ?? null, // index 0 untuk total/jumlah + 'nominal' => $values[1] ?? null // index 1 untuk nominal + ]; + } + } + + Log::info("Leader data synced", ['result' => $result]); + + BigdataResume::create([ + 'import_datasource_id' => $import_datasource->id, + 'year' => now()->year, + // USAHA + 'business_count' => $this->convertToInteger($result['USAHA']['total'] ?? null) ?? 0, + 'business_sum' => $this->convertToDecimal($result['USAHA']['nominal'] ?? null) ?? 0, + // NON USAHA + 'non_business_count' => $this->convertToInteger($result['NON_USAHA']['total'] ?? null) ?? 0, + 'non_business_sum' => $this->convertToDecimal($result['NON_USAHA']['nominal'] ?? null) ?? 0, + // TERVERIFIKASI + 'verified_count' => $this->convertToInteger($result['TERVERIFIKASI']['total'] ?? null) ?? 0, + 'verified_sum' => $this->convertToDecimal($result['TERVERIFIKASI']['nominal'] ?? null) ?? 0, + // BELUM TERVERIFIKASI + 'non_verified_count' => $this->convertToInteger($result['BELUM_TERVERIFIKASI']['total'] ?? null) ?? 0, + 'non_verified_sum' => $this->convertToDecimal($result['BELUM_TERVERIFIKASI']['nominal'] ?? null) ?? 0, + // TOTAL POTENSI BERKAS + 'potention_count' => $this->convertToInteger($result['TOTAL_POTENSI_BERKAS']['total'] ?? null) ?? 0, + 'potention_sum' => $this->convertToDecimal($result['TOTAL_POTENSI_BERKAS']['nominal'] ?? null) ?? 0, + ]); + + $import_datasource->update([ + 'status' => 'success', + 'response_body' => json_encode($result), + 'message' => 'Leader data synced', + 'finish_time' => now() + ]); + return $result; + } catch (\Exception $e) { + Log::error("Error syncing leader data", ['error' => $e->getMessage()]); + $import_datasource->update([ + 'status' => 'failed', + 'message' => 'Leader data sync failed', + 'finish_time' => now() + ]); + throw $e; + } + } + public function get_big_resume_data(){ try { $sheet_big_data = $this->get_data_by_sheet(); @@ -261,9 +335,71 @@ class ServiceGoogleSheet return!empty($values)? $values : []; } + /** + * Get specific values from a row that contains a specific text/section identifier + * @param int $no_sheet Sheet number (0-based) + * @param string $section_identifier Text to search for in the row + * @param array $column_indices Array of column indices to extract values from + * @return array Array of values from specified columns, or empty array if section not found + */ + private function get_values_from_section($no_sheet = 1, $section_identifier, $column_indices = []) { + try { + $sheet_data = $this->get_data_by_sheet($no_sheet); + + if (empty($sheet_data)) { + Log::warning("No data found in sheet", ['sheet' => $no_sheet]); + return []; + } + + // Search for the row containing the section identifier + $target_row = null; + foreach ($sheet_data as $row_index => $row) { + if (is_array($row)) { + foreach ($row as $cell) { + if (is_string($cell) && strpos($cell, $section_identifier) !== false) { + $target_row = $row; + break 2; // Break out of both loops + } + } + } + } + + if ($target_row === null) { + Log::warning("Section not found", ['section_identifier' => $section_identifier]); + return []; + } + + // Extract values from specified column indices + $extracted_values = []; + foreach ($column_indices as $col_index) { + if (isset($target_row[$col_index])) { + $value = trim($target_row[$col_index]); + $extracted_values[] = $value !== '' ? $value : null; + } else { + $extracted_values[] = null; + } + } + + Log::info("Values extracted from section", [ + 'section_identifier' => $section_identifier, + 'column_indices' => $column_indices, + 'extracted_values' => $extracted_values + ]); + + return $extracted_values; + } catch (\Exception $e) { + Log::error("Error getting values from section", [ + 'error' => $e->getMessage(), + 'section_identifier' => $section_identifier, + 'sheet' => $no_sheet + ]); + return []; + } + } + private function convertToInteger($value) { - // Check if the value is an empty string, and return null if true - if (trim($value) === "") { + // Check if the value is null or empty string, and return null if true + if ($value === null || trim($value) === "") { return null; } diff --git a/build-chunked.sh b/build-chunked.sh deleted file mode 100644 index 69b4cad..0000000 --- a/build-chunked.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash - -# Build script bertahap untuk menghindari memory overload -# Tetap membangun SEMUA file yang diperlukan tapi secara bertahap - -echo "πŸ”¨ Starting chunked production build..." - -# Set memory limit -export NODE_OPTIONS="--max-old-space-size=1536" -export NODE_ENV=production - -# Clean previous build -echo "🧹 Cleaning previous build..." -rm -rf public/build/* - -# Fungsi untuk build dengan retry -build_with_retry() { - local config_file=$1 - local attempt=1 - local max_attempts=3 - - while [ $attempt -le $max_attempts ]; do - echo "πŸ”„ Build attempt $attempt of $max_attempts..." - - if vite build --config $config_file; then - echo "βœ… Build successful on attempt $attempt" - return 0 - else - echo "❌ Build failed on attempt $attempt" - if [ $attempt -lt $max_attempts ]; then - echo "⏳ Waiting 5 seconds before retry..." - sleep 5 - # Clear memory caches - sync && echo 3 > /proc/sys/vm/drop_caches 2>/dev/null || true - fi - attempt=$((attempt + 1)) - fi - done - - return 1 -} - -echo "πŸ“¦ Building all assets with memory optimization..." - -# Try building with production config first -if build_with_retry "vite.config.production.js"; then - echo "πŸŽ‰ Build completed successfully!" - echo "πŸ“Š Build summary:" - du -sh public/build/* 2>/dev/null || echo "Build files created" - - # Count generated files - echo "πŸ“ Generated files:" - find public/build -type f | wc -l | xargs echo "Total files:" - -else - echo "❌ Build failed after all attempts!" - echo "" - echo "πŸ’‘ Alternative solutions:" - echo " 1. ✨ Build locally: npm run build:local" - echo " 2. πŸ”§ Increase server memory/swap" - echo " 3. ☁️ Use GitHub Actions CI/CD" - echo " 4. πŸš€ Use deployment services (Vercel, Netlify)" - echo "" - echo "🏠 For local build and deploy:" - echo " npm run build:local" - echo " ./deploy.sh your-username your-server.com /path/to/project" - - exit 1 -fi - -echo "" -echo "πŸ” Verifying all essential files are built..." - -# Check for essential files -essential_files=( - "public/build/manifest.json" - "public/build/assets" -) - -missing_files=() -for file in "${essential_files[@]}"; do - if [ ! -e "$file" ]; then - missing_files+=("$file") - fi -done - -if [ ${#missing_files[@]} -eq 0 ]; then - echo "βœ… All essential files are present!" -else - echo "⚠️ Missing files:" - printf ' %s\n' "${missing_files[@]}" -fi \ No newline at end of file diff --git a/build-production.sh b/build-production.sh deleted file mode 100644 index a5a6914..0000000 --- a/build-production.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -# Production build script dengan optimasi memory -# Untuk server dengan resource terbatas - -echo "πŸ”¨ Starting production build with memory optimization..." - -# Set Node.js memory limit (adjust sesuai RAM server) -# Untuk server dengan banyak file, gunakan memory yang lebih besar -export NODE_OPTIONS="--max-old-space-size=2048 --max-semi-space-size=1024" - -# Use production vite config -export NODE_ENV=production - -# Clean previous build -echo "🧹 Cleaning previous build..." -rm -rf public/build/* - -# Build with limited resources -echo "πŸ“¦ Building assets with memory optimization..." - -# Option 1: Build with custom config -vite build --config vite.config.production.js - -# Option 2: Alternative - build in chunks (uncomment if needed) -# echo "Building CSS files first..." -# vite build --config vite.config.production.js --mode css-only -# -# echo "Building JS files..." -# vite build --config vite.config.production.js --mode js-only - -if [ $? -eq 0 ]; then - echo "βœ… Build completed successfully!" - echo "πŸ“Š Build summary:" - du -sh public/build/* -else - echo "❌ Build failed!" - echo "πŸ’‘ Try these solutions:" - echo " 1. Increase server memory" - echo " 2. Build locally and upload files" - echo " 3. Use swap memory (temporary solution)" - exit 1 -fi \ No newline at end of file diff --git a/build.zip b/build.zip deleted file mode 100644 index a928e1c..0000000 Binary files a/build.zip and /dev/null differ diff --git a/database/seeders/MenuSeeder.php b/database/seeders/MenuSeeder.php index e6baacd..b6c6406 100644 --- a/database/seeders/MenuSeeder.php +++ b/database/seeders/MenuSeeder.php @@ -30,7 +30,7 @@ class MenuSeeder extends Seeder "sort_order" => 2, "children" => [ [ - "name" => "Dashboard Pimpinan", + "name" => "Dashboard Pimpinan SIMBG", "url" => "dashboard.home", "icon" => null, "sort_order" => 1, @@ -67,6 +67,12 @@ class MenuSeeder extends Seeder "icon" => null, "sort_order" => 4, ], + [ + "name" => "Dashboard Pimpinan", + "url" => "dashboard.leader", + "icon" => null, + "sort_order" => 5, + ], ], ], [ diff --git a/debug-permissions.sh b/debug-permissions.sh deleted file mode 100644 index 930a975..0000000 --- a/debug-permissions.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# Debug script untuk diagnosa permission issues -# Jalankan di server untuk check masalah permission - -PROJECT_PATH=${1:-"/var/www/pupr"} - -echo "πŸ” Debugging permissions for: $PROJECT_PATH" -echo "=================================================" - -# Check if path exists -if [ ! -d "$PROJECT_PATH" ]; then - echo "❌ Project path not found: $PROJECT_PATH" - exit 1 -fi - -cd "$PROJECT_PATH" - -echo "πŸ“Š Current User & Groups:" -echo "Current user: $(whoami)" -echo "Web server user: $(ps aux | grep -E 'apache|nginx|httpd' | grep -v grep | head -1 | awk '{print $1}')" -echo "" - -echo "πŸ“ Directory Ownership & Permissions:" -echo "Project root:" -ls -la . | head -5 -echo "" -echo "Storage directory:" -ls -la storage/ -echo "" -echo "Storage/framework:" -ls -la storage/framework/ 2>/dev/null || echo "storage/framework/ not found" -echo "" -echo "Bootstrap/cache:" -ls -la bootstrap/cache/ 2>/dev/null || echo "bootstrap/cache/ not found" -echo "" - -echo "πŸ” Permission Analysis:" -# Check critical directories -directories=("storage" "storage/framework" "storage/framework/views" "storage/framework/cache" "storage/logs" "bootstrap/cache") - -for dir in "${directories[@]}"; do - if [ -d "$dir" ]; then - perm=$(stat -c "%a" "$dir") - owner=$(stat -c "%U:%G" "$dir") - echo "βœ… $dir: $perm ($owner)" - else - echo "❌ $dir: NOT FOUND" - fi -done - -echo "" -echo "πŸ§ͺ Write Test:" -# Test write permissions -if [ -w "storage/framework/" ]; then - echo "βœ… storage/framework/ is writable" - # Try creating a test file - if touch storage/framework/test_write_$(date +%s).tmp 2>/dev/null; then - echo "βœ… Can create files in storage/framework/" - rm -f storage/framework/test_write_*.tmp - else - echo "❌ Cannot create files in storage/framework/" - fi -else - echo "❌ storage/framework/ is NOT writable" -fi - -echo "" -echo "βš™οΈ SELinux Status (if applicable):" -if command -v getenforce &> /dev/null; then - echo "SELinux: $(getenforce)" - if [ "$(getenforce)" = "Enforcing" ]; then - echo "⚠️ SELinux is enforcing - may need additional configuration" - echo "Try: sudo setsebool -P httpd_unified on" - fi -else - echo "SELinux not installed" -fi - -echo "" -echo "πŸ“‹ Recommended Actions:" -echo "1. Fix ownership: sudo chown -R www-data:www-data $PROJECT_PATH" -echo "2. Fix permissions: sudo chmod -R 775 $PROJECT_PATH/storage/" -echo "3. Clear cache: php artisan view:clear" -echo "4. If SELinux: sudo setsebool -P httpd_unified on" \ No newline at end of file diff --git a/deploy.sh b/deploy.sh deleted file mode 100644 index 95e365a..0000000 --- a/deploy.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash - -# Deploy script untuk build di local dan upload ke server -# Usage: ./deploy.sh [server-user] [server-host] [server-path] - -# Default values (ganti sesuai server Anda) -SERVER_USER=${1:-"root"} -SERVER_HOST=${2:-"157.245.48.15"} -SERVER_PATH=${3:-"/var/www/pupr"} - -echo "πŸš€ Starting deployment process..." - -# 1. Clean previous build -echo "🧹 Cleaning previous build..." -rm -rf public/build/* - -# 2. Install dependencies (jika belum) -echo "πŸ“¦ Installing dependencies..." -npm ci --production=false - -# 3. Build project -echo "πŸ”¨ Building project..." -npm run build - -# Check if build was successful -if [ $? -ne 0 ]; then - echo "❌ Build failed!" - exit 1 -fi - -echo "βœ… Build completed successfully!" - -# 4. Upload build files to server -echo "πŸ“€ Uploading build files to server..." -rsync -avz --progress --delete public/build/ $SERVER_USER@$SERVER_HOST:$SERVER_PATH/public/build/ - -# 5. Upload other necessary files (optional) -echo "πŸ“€ Uploading other files..." -rsync -avz --progress \ - --exclude='node_modules' \ - --exclude='.git' \ - --exclude='public/build' \ - --exclude='storage/logs/*' \ - --exclude='bootstrap/cache/*' \ - ./ $SERVER_USER@$SERVER_HOST:$SERVER_PATH/ - -echo "πŸ”§ Fixing permissions on server..." -ssh $SERVER_USER@$SERVER_HOST "cd $SERVER_PATH && chmod +x fix-permissions.sh && sudo ./fix-permissions.sh $SERVER_PATH" - -echo "πŸ“¦ Installing composer dependencies on server..." -ssh $SERVER_USER@$SERVER_HOST "cd $SERVER_PATH && composer install --no-dev --optimize-autoloader" - -echo "πŸŽ‰ Deployment completed successfully!" -echo "" -echo "βœ… Permissions have been automatically fixed!" -echo "βœ… Composer dependencies installed!" -echo "βœ… Laravel caches optimized!" -echo "" -echo "🌐 Your application should now be accessible without permission errors!" \ No newline at end of file diff --git a/docker/supervisor/laravel-production.conf b/docker/supervisor/laravel-production.conf new file mode 100644 index 0000000..b290c89 --- /dev/null +++ b/docker/supervisor/laravel-production.conf @@ -0,0 +1,41 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:laravel-queue-worker] +process_name=%(program_name)s_%(process_num)02d +command=php /var/www/pupr/artisan queue:work --queue=default --timeout=82800 --tries=3 --memory=512 --sleep=3 +directory=/var/www/pupr +autostart=true +autorestart=true +numprocs=2 +redirect_stderr=true +stdout_logfile=/var/www/pupr/storage/logs/queue-worker.log +stdout_logfile_maxbytes=10MB +stdout_logfile_backups=5 +stopasgroup=true +killasgroup=true +user=www-data +priority=10 + +[program:laravel-scheduler] +process_name=%(program_name)s_%(process_num)02d +command=php /var/www/pupr/artisan schedule:work +directory=/var/www/pupr +autostart=true +autorestart=true +numprocs=1 +redirect_stderr=true +stdout_logfile=/var/www/pupr/storage/logs/scheduler.log +stdout_logfile_maxbytes=10MB +stdout_logfile_backups=5 +stopasgroup=true +killasgroup=true +user=www-data +priority=20 + +[group:laravel] +programs=laravel-queue-worker,laravel-scheduler +priority=999 \ No newline at end of file diff --git a/docker/supervisor/supervisord.conf b/docker/supervisor/supervisord.conf index 7e6efd0..731e5b6 100644 --- a/docker/supervisor/supervisord.conf +++ b/docker/supervisor/supervisord.conf @@ -15,4 +15,17 @@ stdout_logfile=/var/www/storage/logs/worker.log stopasgroup=true killasgroup=true user=www-data -priority=10 \ No newline at end of file +priority=10 + +[program:laravel-scheduler] +process_name=%(program_name)s_%(process_num)02d +command=php /var/www/artisan schedule:work +autostart=true +autorestart=true +numprocs=1 +redirect_stderr=true +stdout_logfile=/var/www/storage/logs/scheduler.log +stopasgroup=true +killasgroup=true +user=www-data +priority=20 \ No newline at end of file diff --git a/fix-permissions.sh b/fix-permissions.sh deleted file mode 100644 index 3548583..0000000 --- a/fix-permissions.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/bash - -# Script untuk fix permissions Laravel setelah deployment -# Jalankan di server production - -PROJECT_PATH=${1:-"/var/www/pupr"} - -echo "πŸ”§ Fixing Laravel permissions for: $PROJECT_PATH" - -# Check if path exists -if [ ! -d "$PROJECT_PATH" ]; then - echo "❌ Project path not found: $PROJECT_PATH" - echo "Usage: ./fix-permissions.sh /path/to/your/project" - exit 1 -fi - -cd "$PROJECT_PATH" - -echo "πŸ“ Setting correct ownership..." -# Set ownership to web server user -sudo chown -R www-data:www-data . - -echo "πŸ“‚ Setting directory permissions..." -# Set directory permissions -sudo find . -type d -exec chmod 755 {} \; - -echo "πŸ“„ Setting file permissions..." -# Set file permissions -sudo find . -type f -exec chmod 644 {} \; - -echo "πŸ” Setting special permissions for Laravel..." -# Storage and cache directories need write permissions -sudo chmod -R 775 storage/ -sudo chmod -R 775 bootstrap/cache/ - -# Make sure these directories exist -sudo mkdir -p storage/framework/views -sudo mkdir -p storage/framework/cache -sudo mkdir -p storage/framework/sessions -sudo mkdir -p storage/logs -sudo mkdir -p storage/app/public - -# Set ownership for storage and bootstrap/cache -sudo chown -R www-data:www-data storage/ -sudo chown -R www-data:www-data bootstrap/cache/ - -echo "πŸ”‘ Setting executable permissions for Artisan..." -sudo chmod +x artisan - -echo "🧹 Clearing Laravel caches..." -# Clear all caches -php artisan config:clear -php artisan route:clear -php artisan view:clear -php artisan cache:clear - -# Recreate caches with correct permissions -php artisan config:cache -php artisan route:cache -php artisan view:cache - -echo "πŸ“‹ Checking permissions..." -echo "Storage permissions:" -ls -la storage/ -echo "" -echo "Framework permissions:" -ls -la storage/framework/ -echo "" - -echo "βœ… Permissions fixed successfully!" -echo "πŸ’‘ If you still get permission errors, also run:" -echo " sudo setsebool -P httpd_can_network_connect on" -echo " sudo setsebool -P httpd_unified on" \ No newline at end of file diff --git a/resources/js/dashboards/leader.js b/resources/js/dashboards/leader.js new file mode 100644 index 0000000..e898718 --- /dev/null +++ b/resources/js/dashboards/leader.js @@ -0,0 +1,378 @@ +import Big from "big.js"; +import GlobalConfig, { addThousandSeparators } from "../global-config.js"; +import InitDatePicker from "../utils/InitDatePicker.js"; + +class BigData { + async init() { + try { + new InitDatePicker( + "#datepicker-dashboard-bigdata", + this.handleChangeDate.bind(this) + ).init(); + + // Load initial data + this.updateData("latest"); + } catch (error) { + console.error("Error initializing data:", error); + } + } + + handleChangeDate(filterDate) { + if (!filterDate) return; + this.updateData(filterDate); + } + async updateData(filterDate) { + try { + this.resumeBigData = await this.getBigDataResume(filterDate); + + this.initChartTargetPAD(filterDate); + this.initChartUsaha(); + this.initChartNonUsaha(); + this.initChartTotalPotensi(); + this.initChartVerificationDocuments(); + this.initChartNonVerificationDocuments(); + this.initChartKekuranganPotensi(); + this.initChartRealisasiTerbitPBG(); + this.initChartMenungguKlikDPMPTSP(); + this.initChartProsesDinasTeknis(); + this.initChartPotensiTataRuang(); + } catch (e) { + console.error(e); + } + } + + async getBigDataResume(filterByDate) { + try { + const response = await fetch( + `${GlobalConfig.apiHost}/api/bigdata-resume?filterByDate=${filterByDate}`, + { + credentials: "include", + headers: { + Authorization: `Bearer ${ + document.querySelector("meta[name='api-token']") + .content + }`, + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + console.error("Network response was not ok", response); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error("Error fetching chart data:", error); + return null; + } + } + + initChartTargetPAD(filterDate) { + const year = + filterDate === "latest" + ? new Date().getFullYear() + : new Date(filterDate).getFullYear(); + document + .querySelectorAll(".document-title.chart-target-pad") + .forEach((element) => { + element.innerText = `Target PAD ${year}`; + }); + document + .querySelectorAll(".document-count.chart-target-pad") + .forEach((element) => { + element.innerText = ``; + }); + document + .querySelectorAll(".document-total.chart-target-pad") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + this.resumeBigData.target_pad.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-target-pad") + .forEach((element) => { + element.innerText = `${this.resumeBigData.target_pad.percentage}%`; + }); + } + initChartTotalPotensi() { + // const countAll = this.resultDataTotal.countData ?? 0; + + document + .querySelectorAll(".document-count.chart-total-potensi") + .forEach((element) => { + // element.innerText = `${countAll}`; + element.innerText = `${this.resumeBigData.total_potensi.count}`; + }); + document + .querySelectorAll(".document-total.chart-total-potensi") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.bigTotalPotensi.toString() + this.resumeBigData.total_potensi.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-total-potensi") + .forEach((element) => { + // element.innerText = `${this.resultPercentage}%`; + element.innerText = `${this.resumeBigData.total_potensi.percentage}%`; + }); + } + initChartVerificationDocuments() { + document + .querySelectorAll(".document-count.chart-berkas-terverifikasi") + .forEach((element) => { + // element.innerText = `${this.dataVerification.count}`; + element.innerText = `${this.resumeBigData.verified_document.count}`; + }); + document + .querySelectorAll(".document-total.chart-berkas-terverifikasi") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.bigTotalVerification.toString() + this.resumeBigData.verified_document.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-berkas-terverifikasi") + .forEach((element) => { + // element.innerText = `${this.percetageResultVerification}%`; + element.innerText = `${this.resumeBigData.verified_document.percentage}%`; + }); + } + initChartNonVerificationDocuments() { + document + .querySelectorAll( + ".document-count.chart-berkas-belum-terverifikasi" + ) + .forEach((element) => { + // element.innerText = `${this.dataNonVerification.count}`; + element.innerText = `${this.resumeBigData.non_verified_document.count}`; + }); + document + .querySelectorAll( + ".document-total.chart-berkas-belum-terverifikasi" + ) + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.bigTotalNonVerification.toString() + this.resumeBigData.non_verified_document.sum.toString() + )}`; + }); + document + .querySelectorAll( + ".small-percentage.chart-berkas-belum-terverifikasi" + ) + .forEach((element) => { + // element.innerText = `${this.percentageResultNonVerification}%`; + element.innerText = `${this.resumeBigData.non_verified_document.percentage}%`; + }); + } + initChartUsaha() { + document + .querySelectorAll(".document-count.chart-business") + .forEach((element) => { + // element.innerText = `${this.dataBusiness.count}`; + element.innerText = `${this.resumeBigData.business_document.count}`; + }); + document + .querySelectorAll(".document-total.chart-business") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.bigTotalBusiness.toString() + this.resumeBigData.business_document.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-business") + .forEach((element) => { + // element.innerText = `${this.percentageResultBusiness}%`; + element.innerText = `${this.resumeBigData.business_document.percentage}%`; + }); + } + initChartNonUsaha() { + document + .querySelectorAll(".document-count.chart-non-business") + .forEach((element) => { + // element.innerText = `${this.dataNonBusiness.count}`; + element.innerText = `${this.resumeBigData.non_business_document.count}`; + }); + document + .querySelectorAll(".document-total.chart-non-business") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.bigTotalNonBusiness.toString() + this.resumeBigData.non_business_document.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-non-business") + .forEach((element) => { + // element.innerText = `${this.percentageResultNonBusiness}%`; + element.innerText = `${this.resumeBigData.non_business_document.percentage}%`; + }); + } + initChartKekuranganPotensi() { + document + .querySelectorAll(".document-count.chart-kekurangan-potensi") + .forEach((element) => { + element.innerText = ``; + }); + document + .querySelectorAll(".document-total.chart-kekurangan-potensi") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.totalKekuranganPotensi.toString() + this.resumeBigData.kekurangan_potensi.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-kekurangan-potensi") + .forEach((element) => { + // element.innerText = `${this.percentageKekuranganPotensi}%`; + element.innerText = `${this.resumeBigData.kekurangan_potensi.percentage}%`; + }); + } + initChartRealisasiTerbitPBG() { + document + .querySelectorAll(".document-count.chart-realisasi-tebit-pbg") + .forEach((element) => { + // element.innerText = `${this.dataCountRealisasiTerbit}`; + element.innerText = `${this.resumeBigData.realisasi_terbit.count}`; + }); + document + .querySelectorAll(".document-total.chart-realisasi-tebit-pbg") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.dataSumRealisasiTerbit + this.resumeBigData.realisasi_terbit.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-realisasi-tebit-pbg") + .forEach((element) => { + element.innerText = `${this.resumeBigData.realisasi_terbit.percentage}%`; + }); + } + initChartMenungguKlikDPMPTSP() { + document + .querySelectorAll(".document-count.chart-menunggu-klik-dpmptsp") + .forEach((element) => { + // element.innerText = `${this.dataCountMenungguKlikDPMPTSP}`; + element.innerText = `${this.resumeBigData.menunggu_klik_dpmptsp.count}`; + }); + document + .querySelectorAll(".document-total.chart-menunggu-klik-dpmptsp") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.dataSumMenungguKlikDPMPTSP + this.resumeBigData.menunggu_klik_dpmptsp.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-menunggu-klik-dpmptsp") + .forEach((element) => { + element.innerText = `${this.resumeBigData.menunggu_klik_dpmptsp.percentage}%`; + }); + } + initChartProsesDinasTeknis() { + document + .querySelectorAll(".document-count.chart-proses-dinas-teknis") + .forEach((element) => { + // element.innerText = `${this.dataCountProsesDinasTeknis}`; + element.innerText = `${this.resumeBigData.proses_dinas_teknis.count}`; + }); + document + .querySelectorAll(".document-total.chart-proses-dinas-teknis") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + // this.dataSumProsesDinasTeknis + this.resumeBigData.proses_dinas_teknis.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-proses-dinas-teknis") + .forEach((element) => { + element.innerText = `${this.resumeBigData.proses_dinas_teknis.percentage}%`; + }); + } + initChartPotensiTataRuang() { + document + .querySelectorAll(".document-count.chart-potensi-tata-ruang") + .forEach((element) => { + element.innerText = `${this.resumeBigData.tata_ruang.count}`; + }); + document + .querySelectorAll(".document-total.chart-potensi-tata-ruang") + .forEach((element) => { + element.innerText = `Rp.${addThousandSeparators( + this.resumeBigData.tata_ruang.sum.toString() + )}`; + }); + document + .querySelectorAll(".small-percentage.chart-potensi-tata-ruang") + .forEach((element) => { + element.innerText = `${this.resumeBigData.tata_ruang.percentage}%`; + }); + } +} + +document.addEventListener("DOMContentLoaded", async function (e) { + await new BigData().init(); +}); + +// function resizeDashboard() { +// //Target Width +// let targetElement = document.getElementById("dashboard-fixed-wrapper"); +// let targetWidth = targetElement.offsetWidth; +// //console.log("TARGET ",targetWidth); + +// //Real Object Width +// let dashboardElement = document.getElementById("dashboard-fixed-container"); +// let dashboardWidth = 1110; //dashboardElement.offsetWidth; +// //console.log("CURRENT ",dashboardWidth); + +// if (targetWidth > dashboardWidth) { +// targetWidth = dashboardWidth; +// } + +// dashboardElement.style.transformOrigin = "left top"; +// dashboardElement.style.transition = "transform 0.2s ease-in-out"; +// dashboardElement.style.transform = +// "scale(" + (targetWidth / dashboardWidth).toFixed(2) + ")"; +// //console.log("SCALE ", (targetWidth/dashboardWidth).toFixed(2)); +// } + +// window.addEventListener("load", function () { +// resizeDashboard(); +// }); + +// window.addEventListener("resize", function () { +// resizeDashboard(); +// }); + +function resizeDashboard() { + let targetElement = document.getElementById("dashboard-fixed-wrapper"); + let dashboardElement = document.getElementById("dashboard-fixed-container"); + + let targetWidth = targetElement.offsetWidth; + let dashboardWidth = 1110; + + let scaleFactor = (targetWidth / dashboardWidth).toFixed(2); + + // Prevent scaling beyond 1 (100%) to avoid overflow + scaleFactor = Math.min(scaleFactor, 1); + + dashboardElement.style.transformOrigin = "left top"; + dashboardElement.style.transition = "transform 0.2s ease-in-out"; + dashboardElement.style.transform = `scale(${scaleFactor})`; + + // Ensure horizontal scrolling is allowed if necessary + document.body.style.overflowX = "auto"; +} + +window.addEventListener("load", resizeDashboard); +window.addEventListener("resize", resizeDashboard); diff --git a/resources/js/settings/syncronize/syncronize.js b/resources/js/settings/syncronize/syncronize.js index 1782360..46db360 100644 --- a/resources/js/settings/syncronize/syncronize.js +++ b/resources/js/settings/syncronize/syncronize.js @@ -71,7 +71,6 @@ class SyncronizeTask { data.data.map((item) => [ item.id, item.message, - item.response_body, item.status, item.start_time, item.duration, diff --git a/resources/views/dashboards/leader.blade.php b/resources/views/dashboards/leader.blade.php new file mode 100644 index 0000000..918b1d5 --- /dev/null +++ b/resources/views/dashboards/leader.blade.php @@ -0,0 +1,187 @@ +@extends('layouts.vertical', ['subtitle' => 'Dashboards']) + +@section('css') +@vite(['resources/scss/dashboards/_bigdata.scss']) +@endsection + +@section('content') + +@include('layouts.partials/page-title', ['title' => 'Dashboards', 'subtitle' => 'Dashboard Pimpinan']) + +
+
+
+

+ ANALISA BIG DATA PROSES PBG
+ MELALUI APLIKASI SIBEDAS PBG +

+
+ Terakhir di update - {{$latest_created}} + +
+
+
+
+ @component('components.circle', [ + 'document_title' => 'Kekurangan Potensi', + 'document_color' => '#ff5757', + 'document_type' => '', + 'document_id' => 'chart-kekurangan-potensi', + 'visible_small_circle' => true, + 'style' => 'top:150px;' + ]) + @endcomponent + + @component('components.circle', [ + 'document_title' => 'Target PAD', + 'document_color' => '#204f6b', + 'document_type' => '', + 'document_id' => 'chart-target-pad', + 'visible_small_circle' => true, + 'style' => 'left:200px;', + 'document_url' => route('data-settings.index', ['menu_id' => $menus->where('url','data-settings.index')->first()->id]) + ]) + @endcomponent + +
+
+ +
+
+ + + + @component('components.circle', [ + 'document_title' => 'Total Potensi Berkas', + 'document_color' => '#0097b3', + 'document_type' => 'Pemohon', + 'document_id' => 'chart-total-potensi', + 'visible_small_circle' => true, + 'style' => 'left:400px;top:150px;', + 'document_url' => route('pbg-task.index', ['menu_id' => $menus->where('url','pbg-task.index')->first()->id, 'filter' => 'all']) + ]) + @endcomponent + +
+
+ +
+
+ + @component('components.circle', [ + 'document_title' => 'Perkiraan Potensi PBG Dari Tata Ruang', + 'document_color' => '#ed9d2e', + 'document_type' => '', + 'document_id' => 'chart-potensi-tata-ruang', + 'visible_small_circle' => true, + 'style' => 'left:600px;', + 'document_url' => route('web-spatial-plannings.index', ['menu_id' => $menus->where('url','web-spatial-plannings.index')->first()->id]) + ]) + @endcomponent + +
+
+ + @component('components.circle', [ + 'document_title' => 'Non Usaha', + 'document_color' => '#399787', + 'document_type' => 'Berkas', + 'document_id' => 'chart-non-business', + 'visible_small_circle' => true, + 'style' => 'left:900px;top:150px;', + 'document_url' => route('pbg-task.index', ['menu_id' => $menus->where('url','pbg-task.index')->first()->id, 'filter' => 'non-business']) + ]) + @endcomponent + + @component('components.circle', [ + 'document_title' => 'Usaha', + 'document_color' => '#5e7c89', + 'document_type' => 'Berkas', + 'document_id' => 'chart-business', + 'visible_small_circle' => true, + 'style' => 'left:900px;top:400px;', + 'document_url' => route('pbg-task.index', ['menu_id' => $menus->where('url','pbg-task.index')->first()->id, 'filter' => 'business']) + ]) + @endcomponent + + @component('components.circle', [ + 'document_title' => 'Berkas Terverifikasi', + 'document_color' => '#5170ff', + 'document_type' => 'Berkas', + 'document_id' => 'chart-berkas-terverifikasi', + 'visible_small_circle' => true, + 'style' => 'top:300px;left:200px;', + 'document_url' => route('pbg-task.index', ['menu_id' => $menus->where('url','pbg-task.index')->first()->id, 'filter' => 'verified']) + ]) + @endcomponent + +
+
+ +
+
+ + @component('components.circle', [ + 'document_title' => 'Berkas Belum Terverifikasi', + 'document_color' => '#5170ff', + 'document_type' => 'Berkas', + 'document_id' => 'chart-berkas-belum-terverifikasi', + 'visible_small_circle' => true, + 'style' => 'top:300px;left:600px;', + 'document_url' => route('pbg-task.index', ['menu_id' => $menus->where('url','pbg-task.index')->first()->id, 'filter' => 'non-verified']) + ]) + @endcomponent + +
+
+ +
+
+ + + @component('components.circle',[ + 'document_title' => 'Realisasi Terbit PBG', + 'document_color' => '#8cc540', + 'document_type' => 'Berkas', + 'document_id' => 'chart-realisasi-tebit-pbg', + 'visible_small_circle' => true, + 'style' => 'top:550px;left:100px;', + 'document_url' => 'https://docs.google.com/spreadsheets/d/1QoXzuLdEX3MK70Yrfigz0Qj5rAt4T819jX85vubBNdY/edit?gid=1514195399#gid=1514195399' + ]) + @endcomponent + +
+
+ + @component('components.circle',[ + 'document_title' => 'Menunggu Klik DPMPTSP', + 'document_color' => '#00bf61', + 'document_type' => 'Berkas', + 'document_id' => 'chart-menunggu-klik-dpmptsp', + 'visible_small_circle' => true, + 'style' => 'top:550px;left:400px', + 'document_url' => 'https://docs.google.com/spreadsheets/d/1QoXzuLdEX3MK70Yrfigz0Qj5rAt4T819jX85vubBNdY/edit?gid=1514195399#gid=1514195399' + ]) + @endcomponent + +
+
+ + @component('components.circle',[ + 'document_title' => 'Berproses Di Dinas Teknis', + 'document_color' => '#737373', + 'document_type' => 'Berkas', + 'document_id' => 'chart-proses-dinas-teknis', + 'visible_small_circle' => true, + 'style' => 'top:550px;left:700px', + 'document_url' => 'https://docs.google.com/spreadsheets/d/1QoXzuLdEX3MK70Yrfigz0Qj5rAt4T819jX85vubBNdY/edit?gid=1514195399#gid=1514195399' + ]) + @endcomponent +
+
+ +@endsection + +@section('scripts') +@vite(['resources/js/dashboards/bigdata.js']) +@endsection \ No newline at end of file diff --git a/routes/console.php b/routes/console.php index af56031..f5bd364 100644 --- a/routes/console.php +++ b/routes/console.php @@ -8,4 +8,5 @@ Artisan::command('inspire', function () { $this->comment(Inspiring::quote()); })->purpose('Display an inspiring quote')->hourly(); -Schedule::command("app:scraping-data")->dailyAt("00:00"); \ No newline at end of file +Schedule::command("app:scraping-leader-data")->dailyAt("00:00"); +Schedule::command("app:scraping-data")->dailyAt("00:30"); \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index d8f48c1..8447b4c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -51,6 +51,7 @@ Route::group(['middleware' => 'auth'], function(){ //dashboards Route::group(['prefix' => '/dashboards'], function(){ Route::get('/bigdata', [BigDataController::class, 'index'])->name('dashboard.home'); + Route::get('/leader', [BigDataController::class, 'leader'])->name('dashboard.leader'); Route::get('/dashboard-pbg', [BigDataController::class, 'pbg'])->name('dashboard.pbg'); Route::get('/lack-of-potential', [LackOfPotentialController::class, 'lack_of_potential'])->name('dashboard.lack_of_potential'); Route::get('/maps', [GoogleApisController::class, 'index'])->name('dashboard.maps'); diff --git a/server-setup.sh b/server-setup.sh deleted file mode 100644 index d97caa6..0000000 --- a/server-setup.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -# Server setup untuk optimasi memory dan build -# Jalankan dengan sudo di server production - -echo "πŸ”§ Setting up server for optimized building..." - -# 1. Check current memory -echo "πŸ“Š Current memory status:" -free -h - -# 2. Setup swap file (temporary solution for low memory) -echo "πŸ’Ύ Setting up swap file (1GB)..." -if [ ! -f /swapfile ]; then - fallocate -l 1G /swapfile - chmod 600 /swapfile - mkswap /swapfile - sysctl vm.swappiness=10 - echo '/swapfile none swap sw 0 0' >> /etc/fstab - echo 'vm.swappiness=10' >> /etc/sysctl.conf - swapon /swapfile - echo "βœ… Swap file created and activated" -else - echo "ℹ️ Swap file already exists" -fi - -# 3. Optimize Node.js for production -echo "βš™οΈ Optimizing Node.js..." -npm config set fund false -npm config set audit false - -# 4. Install PM2 untuk process management -echo "πŸ“¦ Installing PM2..." -npm install -g pm2 - -# 5. Create PM2 ecosystem file for build process -cat > ecosystem.config.js << 'EOF' -module.exports = { - apps: [{ - name: 'build-app', - script: 'npm', - args: 'run build:prod', - instances: 1, - autorestart: false, - watch: false, - max_memory_restart: '1G', - env: { - NODE_ENV: 'production', - NODE_OPTIONS: '--max-old-space-size=1024' - } - }] -} -EOF - -echo "βœ… Server setup completed!" -echo "" -echo "πŸ“ Now you can:" -echo " 1. Build with memory limit: npm run build:prod" -echo " 2. Build with PM2: pm2 start ecosystem.config.js" -echo " 3. Monitor: pm2 monit" -echo " 4. Check memory: free -h" \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 6189df8..fb2518c 100644 --- a/vite.config.js +++ b/vite.config.js @@ -4,26 +4,26 @@ import path from "path"; export default defineConfig({ server: { - host: '0.0.0.0', + host: "0.0.0.0", hmr: { - host: 'localhost' + host: "localhost", }, watch: { - usePolling: true - } + usePolling: true, + }, }, build: { - outDir: 'public/build', - assetsDir: 'assets', - manifest: true, + outDir: "public/build", + assetsDir: "assets", + manifest: "manifest.json", rollupOptions: { output: { manualChunks: undefined, - entryFileNames: 'assets/[name].js', - chunkFileNames: 'assets/[name].js', - assetFileNames: 'assets/[name].[ext]' - } - } + entryFileNames: "assets/[name].js", + chunkFileNames: "assets/[name].js", + assetFileNames: "assets/[name].[ext]", + }, + }, }, resolve: { alias: { @@ -82,6 +82,7 @@ export default defineConfig({ "resources/js/dashboards/bigdata.js", "resources/js/dashboards/potentials/inside_system.js", "resources/js/dashboards/potentials/outside_system.js", + "resources/js/dashboards/leader.js", // roles "resources/js/roles/index.js", "resources/js/roles/create.js", diff --git a/vite.config.production.js b/vite.config.production.js index 0560c05..683843b 100644 --- a/vite.config.production.js +++ b/vite.config.production.js @@ -4,46 +4,46 @@ import path from "path"; export default defineConfig({ server: { - host: '0.0.0.0', + host: "0.0.0.0", hmr: { - host: 'localhost' + host: "localhost", }, watch: { - usePolling: true - } + usePolling: true, + }, }, build: { - outDir: 'public/build', - assetsDir: 'assets', - manifest: true, + outDir: "public/build", + assetsDir: "assets", + manifest: "manifest.json", // Optimasi untuk server dengan resource terbatas - minify: 'terser', + minify: "terser", chunkSizeWarningLimit: 1000, rollupOptions: { output: { manualChunks: { // Split vendor chunks untuk mengurangi memory usage - vendor: ['bootstrap', 'moment', 'axios'], - charts: ['apexcharts'], - maps: ['leaflet', 'jsvectormap', 'gmaps'], - ui: ['sweetalert2', 'flatpickr', 'quill', 'dropzone'], - forms: ['gridjs', 'simplebar'], + vendor: ["bootstrap", "moment", "axios"], + charts: ["apexcharts"], + maps: ["leaflet", "jsvectormap", "gmaps"], + ui: ["sweetalert2", "flatpickr", "quill", "dropzone"], + forms: ["gridjs", "simplebar"], // Group by functionality to reduce memory usage per chunk dashboards: [ - 'resources/js/dashboards/bigdata.js', - 'resources/js/dashboards/pbg.js', - 'resources/js/dashboards/potentials/inside_system.js', - 'resources/js/dashboards/potentials/outside_system.js' + "resources/js/dashboards/bigdata.js", + "resources/js/dashboards/pbg.js", + "resources/js/dashboards/potentials/inside_system.js", + "resources/js/dashboards/potentials/outside_system.js", ], data: [ - 'resources/js/data/umkm/data-umkm.js', - 'resources/js/data/tourisms/data-tourisms.js', - 'resources/js/data/advertisements/data-advertisements.js' - ] + "resources/js/data/umkm/data-umkm.js", + "resources/js/data/tourisms/data-tourisms.js", + "resources/js/data/advertisements/data-advertisements.js", + ], }, - entryFileNames: 'assets/[name]-[hash].js', - chunkFileNames: 'assets/[name]-[hash].js', - assetFileNames: 'assets/[name]-[hash].[ext]' + entryFileNames: "assets/[name]-[hash].js", + chunkFileNames: "assets/[name]-[hash].js", + assetFileNames: "assets/[name]-[hash].[ext]", }, // Optimasi memory - lebih konservatif maxParallelFileOps: 1, @@ -54,9 +54,9 @@ export default defineConfig({ terserOptions: { compress: { drop_console: true, - drop_debugger: true - } - } + drop_debugger: true, + }, + }, }, resolve: { alias: { @@ -115,6 +115,7 @@ export default defineConfig({ "resources/js/dashboards/bigdata.js", "resources/js/dashboards/potentials/inside_system.js", "resources/js/dashboards/potentials/outside_system.js", + "resources/js/dashboards/leader.js", // roles "resources/js/roles/index.js", "resources/js/roles/create.js", @@ -186,6 +187,6 @@ export default defineConfig({ ], // Limit memory usage esbuild: { - target: 'es2015' - } -}); \ No newline at end of file + target: "es2015", + }, +});