diff --git a/groups/RODA/.env b/groups/RODA/.env
deleted file mode 100644
index b5545e4..0000000
--- a/groups/RODA/.env
+++ /dev/null
@@ -1,4 +0,0 @@
-DASHBOARD_TARGET_URL=https://dashboard.informatika.untan.ac.id/index.php?penelitian
-DASHBOARD_PROXY_1=https://api.codetabs.com/v1/proxy?quest={{url}}
-DASHBOARD_PROXY_2=https://api.allorigins.win/get?url={{url}}&ts={{ts}}
-DASHBOARD_PROXY_3=https://thingproxy.freeboard.io/fetch/{{rawUrl}}
\ No newline at end of file
diff --git a/groups/RODA/index.html b/groups/RODA/index.html
index 05b5752..70bbaf5 100644
--- a/groups/RODA/index.html
+++ b/groups/RODA/index.html
@@ -77,12 +77,6 @@
debugLogs: false,
dashboardRuntimeFetch: 'always',
dashboardApiUrl: 'api/dashboard',
- dashboardTargetUrl: 'https://dashboard.informatika.untan.ac.id/index.php?penelitian',
- dashboardProxyTemplates: [
- 'https://api.codetabs.com/v1/proxy?quest={{url}}',
- 'https://api.allorigins.win/get?url={{url}}&ts={{ts}}',
- 'https://thingproxy.freeboard.io/fetch/{{rawUrl}}'
- ]
};
@@ -1662,56 +1656,33 @@
}
let lastError = null;
+
+ if (isDashboardRuntimeFetchAllowed()) {
+ const dashboardApiUrl = window.APP_CONFIG?.dashboardApiUrl?.trim();
+
+ if (dashboardApiUrl) {
+ try {
+ const rows = await fetchProxyRows(dashboardApiUrl);
+ applyDashboardRows(rows);
+ return;
+ } catch (error) {
+ lastError = error;
+ }
+ }
+ }
+
+ // Fallback ke data yang di-embed saat build jika runtime fetch gagal atau dinonaktifkan
const embeddedHtml = readEmbeddedDashboardHtml();
if (embeddedHtml) {
try {
applyDashboardRows(parseDashboardRows(embeddedHtml));
return;
} catch (error) {
- lastError = error;
+ lastError = lastError || error;
}
}
- if (!isDashboardRuntimeFetchAllowed()) {
- renderRisetFeedback('Pemuatan Data Gagal', getDashboardErrorMessage(lastError || new Error('DASHBOARD_RUNTIME_FETCH_DISABLED')), 'Coba Lagi', 'fetchDashboardData()');
- return;
- }
-
- const targetUrl = window.APP_CONFIG?.dashboardTargetUrl?.trim();
- const dashboardApiUrl = window.APP_CONFIG?.dashboardApiUrl?.trim();
- const proxyTemplates = Array.isArray(window.APP_CONFIG?.dashboardProxyTemplates)
- ? window.APP_CONFIG.dashboardProxyTemplates.filter(Boolean)
- : [];
-
- const proxyServers = dashboardApiUrl ? [() => dashboardApiUrl] : [];
-
- if (targetUrl) {
- proxyTemplates.forEach((template) => {
- proxyServers.push((url) => template
- .replaceAll('{{url}}', encodeURIComponent(url))
- .replaceAll('{{rawUrl}}', url)
- .replaceAll('{{ts}}', String(Date.now())));
- });
- }
-
- if (!proxyServers.length) {
- renderRisetFeedback('Pemuatan Data Gagal', getDashboardErrorMessage(new Error('DASHBOARD_PROXY_NOT_CONFIGURED')), 'Coba Lagi', 'fetchDashboardData()');
- return;
- }
-
- try {
- const proxyUrls = proxyServers.map((getProxyUrl) => getProxyUrl(targetUrl));
- const rows = await Promise.any(proxyUrls.map((proxyUrl) => fetchProxyRows(proxyUrl)));
- applyDashboardRows(rows);
- return;
- } catch (error) {
- lastError = error instanceof AggregateError && error.errors?.length
- ? error.errors[error.errors.length - 1]
- : error;
- }
-
- // Jika semua proxy gagal
- renderRisetFeedback('Pemuatan Data Gagal', getDashboardErrorMessage(lastError), 'Coba Lagi', 'fetchDashboardData()');
+ renderRisetFeedback('Pemuatan Data Gagal', getDashboardErrorMessage(lastError || new Error('DASHBOARD_RUNTIME_FETCH_DISABLED')), 'Coba Lagi', 'fetchDashboardData()');
}
diff --git a/groups/RODA/server.js b/groups/RODA/server.js
index 2bf9d4e..626f615 100644
--- a/groups/RODA/server.js
+++ b/groups/RODA/server.js
@@ -6,69 +6,21 @@ const { URL } = require('url');
const ROOT_DIR = __dirname;
const PARENT_DIR = path.join(__dirname, '..', '..');
const INDEX_PATH = path.join(ROOT_DIR, 'index.html');
-const ENV_PATH = path.join(ROOT_DIR, '.env');
const HOST = process.env.HOST || '127.0.0.1';
const PORT = Number(process.env.PORT || 3000);
-const DEFAULT_DASHBOARD_TARGET_URL = 'https://dashboard.informatika.untan.ac.id/index.php?penelitian';
+const DASHBOARD_TARGET_URL = 'https://dashboard.informatika.untan.ac.id/index.php?penelitian';
const RODA_PATH_PREFIX = '/groups/RODA';
function logServerError(scope, error, extra = {}) {
console.error(`[${scope}]`, error && error.stack ? error.stack : error, extra);
}
-function parseEnvFile(filePath) {
- if (!fs.existsSync(filePath)) {
- return {};
- }
-
- const env = {};
- const lines = fs.readFileSync(filePath, 'utf8').split(/\r?\n/);
-
- for (const rawLine of lines) {
- const line = rawLine.trim();
- if (!line || line.startsWith('#')) {
- continue;
- }
-
- const separatorIndex = line.indexOf('=');
- if (separatorIndex === -1) {
- continue;
- }
-
- const key = line.slice(0, separatorIndex).trim();
- let value = line.slice(separatorIndex + 1).trim();
-
- if (
- (value.startsWith('"') && value.endsWith('"')) ||
- (value.startsWith("'") && value.endsWith("'"))
- ) {
- value = value.slice(1, -1);
- }
-
- env[key] = value;
- }
-
- return env;
-}
-
function getAppConfig() {
- const env = {
- ...parseEnvFile(ENV_PATH),
- ...process.env
- };
-
- const dashboardProxyTemplates = [
- env.DASHBOARD_PROXY_1,
- env.DASHBOARD_PROXY_2,
- env.DASHBOARD_PROXY_3
- ].filter(Boolean);
-
return {
- debugLogs: env.DEBUG_LOGS === 'true',
- dashboardRuntimeFetch: env.DASHBOARD_RUNTIME_FETCH || 'always',
- dashboardApiUrl: env.DASHBOARD_API_URL || 'api/dashboard',
- dashboardTargetUrl: env.DASHBOARD_TARGET_URL || DEFAULT_DASHBOARD_TARGET_URL,
- dashboardProxyTemplates
+ debugLogs: false,
+ dashboardRuntimeFetch: 'always',
+ dashboardApiUrl: 'api/dashboard',
+ dashboardTargetUrl: DASHBOARD_TARGET_URL,
};
}
@@ -76,10 +28,6 @@ const DASHBOARD_CACHE_TTL_MS = 5 * 60 * 1000;
let dashboardCache = { html: null, timestamp: 0 };
async function fetchDashboardHtml() {
- const targetUrl = getAppConfig().dashboardTargetUrl;
- if (!targetUrl) {
- throw new Error('DASHBOARD_TARGET_URL kosong');
- }
const now = Date.now();
if (dashboardCache.html && (now - dashboardCache.timestamp) < DASHBOARD_CACHE_TTL_MS) {
@@ -89,7 +37,7 @@ async function fetchDashboardHtml() {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 12000);
try {
- const response = await fetch(targetUrl, {
+ const response = await fetch(DASHBOARD_TARGET_URL, {
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'
@@ -111,35 +59,14 @@ async function fetchDashboardHtml() {
}
}
-function validateAppConfig(config) {
- const errors = [];
-
- if (!config.dashboardTargetUrl) {
- errors.push('DASHBOARD_TARGET_URL belum diisi.');
- }
-
- return errors;
-}
-
function injectConfig(html) {
const configScript = ``;
- const defaultConfigScript = '';
-
- if (html.includes(defaultConfigScript)) {
- return html.replace(defaultConfigScript, configScript);
- }
-
return html.replace('', ` ${configScript}\n`);
}
function sendHtml(res) {
try {
const html = fs.readFileSync(INDEX_PATH, 'utf8');
- const configErrors = validateAppConfig(getAppConfig());
- if (configErrors.length) {
- logServerError('config', new Error('Invalid app config'), { configErrors });
- }
-
const withConfig = injectConfig(html);
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(withConfig);