diff --git a/groups/RODA/index.html b/groups/RODA/index.html
index 87c4cbc..1fd1020 100644
--- a/groups/RODA/index.html
+++ b/groups/RODA/index.html
@@ -1541,6 +1541,11 @@
return rows;
}
+ function shouldUseLocalDashboardProxy() {
+ const hostname = window.location.hostname;
+ return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '';
+ }
+
async function fetchDashboardData() {
const grid = document.getElementById('riset-grid');
if (grid) {
@@ -1557,10 +1562,10 @@
? window.APP_CONFIG.dashboardProxyTemplates.filter(Boolean)
: [];
- // Sumber utama: endpoint proxy lokal (server.js fetch server-side, tanpa CORS).
- const proxyServers = [() => '/api/dashboard'];
+ // Endpoint server.js hanya ada saat development lokal.
+ const proxyServers = shouldUseLocalDashboardProxy() ? [() => '/api/dashboard'] : [];
- // Fallback: proxy publik (butuh targetUrl untuk membangun URL).
+ // Deployment static memakai proxy publik karena tidak menjalankan server.js.
if (targetUrl) {
proxyTemplates.forEach((template) => {
proxyServers.push((url) => template
@@ -1570,6 +1575,10 @@
});
}
+ if (!proxyServers.length) {
+ throw new Error('DASHBOARD_PROXY_NOT_CONFIGURED');
+ }
+
let lastError = null;
for (const getProxyUrl of proxyServers) {
diff --git a/netlify.toml b/netlify.toml
index 2a8fe6c..0cab1ff 100644
--- a/netlify.toml
+++ b/netlify.toml
@@ -4,12 +4,3 @@
[build.environment]
NODE_VERSION = "22"
-
-[functions]
- directory = "netlify/functions"
- node_bundler = "esbuild"
-
-[[redirects]]
- from = "/api/dashboard"
- to = "/.netlify/functions/dashboard"
- status = 200
diff --git a/netlify/functions/dashboard.js b/netlify/functions/dashboard.js
deleted file mode 100644
index c9fad0d..0000000
--- a/netlify/functions/dashboard.js
+++ /dev/null
@@ -1,68 +0,0 @@
-const DEFAULT_DASHBOARD_URL = 'https://dashboard.informatika.untan.ac.id/index.php?penelitian';
-const CACHE_TTL_MS = 5 * 60 * 1000;
-
-let dashboardCache = {
- html: '',
- timestamp: 0,
-};
-
-function getDashboardUrl() {
- return process.env.DASHBOARD_TARGET_URL || DEFAULT_DASHBOARD_URL;
-}
-
-function response(statusCode, body, extraHeaders = {}) {
- return {
- statusCode,
- headers: {
- 'Content-Type': 'text/html; charset=utf-8',
- 'Cache-Control': 'public, max-age=60, stale-while-revalidate=300',
- ...extraHeaders,
- },
- body,
- };
-}
-
-exports.handler = async () => {
- const now = Date.now();
-
- if (dashboardCache.html && now - dashboardCache.timestamp < CACHE_TTL_MS) {
- return response(200, dashboardCache.html, { 'X-Cache': 'HIT' });
- }
-
- const controller = new AbortController();
- const timeoutId = setTimeout(() => controller.abort(), 12000);
-
- try {
- const dashboardResponse = await fetch(getDashboardUrl(), {
- signal: controller.signal,
- headers: {
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36',
- },
- });
-
- if (!dashboardResponse.ok) {
- throw new Error(`HTTP_ERROR_${dashboardResponse.status}`);
- }
-
- const html = await dashboardResponse.text();
- dashboardCache = { html, timestamp: Date.now() };
-
- return response(200, html, { 'X-Cache': 'MISS' });
- } catch (error) {
- if (dashboardCache.html) {
- return response(200, dashboardCache.html, { 'X-Cache': 'STALE' });
- }
-
- return {
- statusCode: 502,
- headers: {
- 'Content-Type': 'text/plain; charset=utf-8',
- },
- body: error && error.name === 'AbortError'
- ? 'DASHBOARD_FETCH_TIMEOUT'
- : 'DASHBOARD_FETCH_FAILED',
- };
- } finally {
- clearTimeout(timeoutId);
- }
-};