add sync to leader dashboard new from google spreadsheet
This commit is contained in:
76
.env.local.backup
Normal file
76
.env.local.backup
Normal file
@@ -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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"
|
||||
180
BUILD_GUIDE.md
180
BUILD_GUIDE.md
@@ -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
|
||||
33
app/Console/Commands/ScrapingLeaderData.php
Normal file
33
app/Console/Commands/ScrapingLeaderData.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Services\ServiceGoogleSheet;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class ScrapingLeaderData extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'app:scraping-leader-data';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Scraping leader data from google spreadsheet and save to database';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$service_google_sheet = app(ServiceGoogleSheet::class);
|
||||
$service_google_sheet->sync_leader_data();
|
||||
$this->info('Leader data synced successfully');
|
||||
}
|
||||
}
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\BigdataResume;
|
||||
use App\Models\DataSetting;
|
||||
use App\Models\ImportDatasource;
|
||||
use App\Models\PbgTaskGoogleSheet;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Google_Client;
|
||||
use Google_Service_Sheets;
|
||||
use Log;
|
||||
use Google\Client as Google_Client;
|
||||
use Google\Service\Sheets as Google_Service_Sheets;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
class ServiceGoogleSheet
|
||||
{
|
||||
protected $client;
|
||||
@@ -210,6 +212,78 @@ class ServiceGoogleSheet
|
||||
}
|
||||
}
|
||||
|
||||
public function sync_leader_data(){
|
||||
$import_datasource = ImportDatasource::create([
|
||||
'message' => '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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
|
||||
@@ -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"
|
||||
59
deploy.sh
59
deploy.sh
@@ -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!"
|
||||
41
docker/supervisor/laravel-production.conf
Normal file
41
docker/supervisor/laravel-production.conf
Normal file
@@ -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
|
||||
@@ -16,3 +16,16 @@ stopasgroup=true
|
||||
killasgroup=true
|
||||
user=www-data
|
||||
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
|
||||
@@ -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"
|
||||
378
resources/js/dashboards/leader.js
Normal file
378
resources/js/dashboards/leader.js
Normal file
@@ -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);
|
||||
@@ -71,7 +71,6 @@ class SyncronizeTask {
|
||||
data.data.map((item) => [
|
||||
item.id,
|
||||
item.message,
|
||||
item.response_body,
|
||||
item.status,
|
||||
item.start_time,
|
||||
item.duration,
|
||||
|
||||
187
resources/views/dashboards/leader.blade.php
Normal file
187
resources/views/dashboards/leader.blade.php
Normal file
@@ -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'])
|
||||
|
||||
<div id="dashboard-fixed-wrapper" class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between align-items-center mt-3 ms-2">
|
||||
<h2 class="text-danger m-0">
|
||||
ANALISA BIG DATA PROSES PBG <br>
|
||||
MELALUI APLIKASI SIBEDAS PBG
|
||||
</h2>
|
||||
<div class="text-black text-end d-flex flex-column align-items-end me-3">
|
||||
<span class="fs-5">Terakhir di update - {{$latest_created}}</span>
|
||||
<input type="text" class="form-control mt-2" style="max-width: 125px;" id="datepicker-dashboard-bigdata" placeholder="Filter Date" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dashboard-fixed-container" class="row" style="width:1110px;height:770px;position:relative;margin:auto;">
|
||||
@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
|
||||
|
||||
<div class="square dia-top-left-bottom-right" style="top:150px;left:350px;">
|
||||
</div>
|
||||
|
||||
<div class="square dia-top-right-bottom-left" style="top:150px;left:150px;">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@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
|
||||
|
||||
<div class="square dia-top-right-bottom-left" style="top:300px;left:350px;">
|
||||
</div>
|
||||
|
||||
<div class="square dia-top-left-bottom-right" style="top:300px;left:550px;">
|
||||
</div>
|
||||
|
||||
@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
|
||||
|
||||
<div class="square dia-top-right-bottom-left" style="top:150px;left:550px;">
|
||||
</div>
|
||||
|
||||
@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
|
||||
|
||||
<div class="square dia-top-right-bottom-left" style="top:500px;left:200px;width:50px">
|
||||
</div>
|
||||
|
||||
<div class="square dia-top-left-bottom-right" style="top:450px;left:350px;width:500px;height:200px;">
|
||||
</div>
|
||||
|
||||
@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
|
||||
|
||||
<div class="square dia-top-right-bottom-left" style="top:200px;left:750px;width:250px;height:150px;">
|
||||
</div>
|
||||
|
||||
<div class="square dia-top-left-bottom-right" style="top:400px;left:750px;width:250px;height:150px;">
|
||||
</div>
|
||||
|
||||
|
||||
@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
|
||||
|
||||
<div class="square" style="top:650px;left:200px;width:250px;height:2px;background-color:black;">
|
||||
</div>
|
||||
|
||||
@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
|
||||
|
||||
<div class="square" style="top:650px;left:600px;width:250px;height:2px;background-color:black;">
|
||||
</div>
|
||||
|
||||
@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
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
@vite(['resources/js/dashboards/bigdata.js'])
|
||||
@endsection
|
||||
@@ -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");
|
||||
Schedule::command("app:scraping-leader-data")->dailyAt("00:00");
|
||||
Schedule::command("app:scraping-data")->dailyAt("00:30");
|
||||
@@ -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');
|
||||
|
||||
@@ -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"
|
||||
@@ -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",
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
target: "es2015",
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user