From 673a6a56eefee177d4fba240c762963ad1ea74c8 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 16 Nov 2025 22:43:06 +0200 Subject: [PATCH] Fix static base path (#549) --- backend/config/config.js | 6 +- frontend/App.tsx | 5 +- frontend/Layout.tsx | 7 +- frontend/components/About.tsx | 3 +- frontend/components/Admin/AdminUsersPage.tsx | 9 +- frontend/components/Calendar.tsx | 20 +- frontend/components/Inbox/InboxModal.tsx | 3 +- frontend/components/Login.tsx | 5 +- frontend/components/Navbar.tsx | 5 +- .../components/Profile/ProfileSettings.tsx | 46 ++-- .../components/Project/ProjectDetails.tsx | 7 +- frontend/components/Project/ProjectModal.tsx | 3 +- .../components/Project/ProjectShareModal.tsx | 3 +- frontend/components/Sidebar/SidebarHeader.tsx | 16 +- frontend/components/Sidebar/SidebarViews.tsx | 9 +- frontend/components/Tag/TagDetails.tsx | 17 +- frontend/components/Task/TaskItem.tsx | 8 +- frontend/components/Task/TasksToday.tsx | 7 +- .../components/Task/TodaySettingsDropdown.tsx | 3 +- frontend/components/Tasks.tsx | 13 +- .../UniversalSearch/SaveViewModal.tsx | 3 +- .../components/UniversalSearch/SearchMenu.tsx | 5 +- frontend/components/ViewDetail.tsx | 13 +- frontend/components/Views.tsx | 16 +- frontend/config/paths.ts | 115 +++++++++ frontend/contexts/TelegramStatusContext.tsx | 5 +- frontend/i18n.ts | 36 +-- frontend/index.tsx | 4 +- frontend/utils/apiKeysService.ts | 10 +- frontend/utils/areasService.ts | 9 +- frontend/utils/inboxService.ts | 11 +- frontend/utils/notesService.ts | 11 +- frontend/utils/profileService.ts | 23 +- frontend/utils/projectsService.ts | 19 +- frontend/utils/searchService.ts | 19 +- frontend/utils/sharesService.ts | 8 +- frontend/utils/tagsService.ts | 24 +- frontend/utils/tasksService.ts | 32 ++- frontend/utils/urlService.ts | 5 +- public/index.html | 11 +- webpack.config.js | 237 +++++++++--------- 41 files changed, 496 insertions(+), 315 deletions(-) create mode 100644 frontend/config/paths.ts diff --git a/backend/config/config.js b/backend/config/config.js index 51587a0..5e42c15 100644 --- a/backend/config/config.js +++ b/backend/config/config.js @@ -25,6 +25,8 @@ const credentials = { }, }; +const defaultHost = environment === 'test' ? '127.0.0.1' : '0.0.0.0'; + const config = { allowedOrigins: process.env.TUDUDI_ALLOWED_ORIGINS ? process.env.TUDUDI_ALLOWED_ORIGINS.split(',').map((origin) => @@ -51,7 +53,9 @@ const config = { frontendUrl: process.env.FRONTEND_URL || 'http://localhost:8080', - host: process.env.HOST || '0.0.0.0', + // Some CI/sandbox environments disallow binding to 0.0.0.0, so force + // loopback for tests unless HOST is explicitly provided. + host: process.env.HOST || defaultHost, port: process.env.PORT || 3002, diff --git a/frontend/App.tsx b/frontend/App.tsx index 156c48a..d3baadc 100644 --- a/frontend/App.tsx +++ b/frontend/App.tsx @@ -23,6 +23,7 @@ import TaskDetails from './components/Task/TaskDetails'; import LoadingScreen from './components/Shared/LoadingScreen'; import InboxItems from './components/Inbox/InboxItems'; import { setCurrentUser as setUserInStorage } from './utils/userUtils'; +import { getApiPath, getLocalesPath } from './config/paths'; // Lazy load Tasks component to prevent issues with tags loading const Tasks = lazy(() => import('./components/Tasks')); @@ -37,7 +38,7 @@ const App: React.FC = () => { const fetchCurrentUser = async () => { try { - const response = await fetch('/api/current_user', { + const response = await fetch(getApiPath('current_user'), { credentials: 'include', headers: { Accept: 'application/json', @@ -93,7 +94,7 @@ const App: React.FC = () => { useEffect(() => { if (i18n.isInitialized) { - fetch(`/locales/${i18n.language}/translation.json`) + fetch(getLocalesPath(`${i18n.language}/translation.json`)) .then((response) => { return response.json(); }) diff --git a/frontend/Layout.tsx b/frontend/Layout.tsx index 629018e..eeed495 100644 --- a/frontend/Layout.tsx +++ b/frontend/Layout.tsx @@ -28,6 +28,7 @@ import { } from './utils/projectsService'; import { createTask, updateTask } from './utils/tasksService'; import { isAuthError } from './utils/authUtils'; +import { Link } from 'react-router-dom'; interface LayoutProps { currentUser: User; @@ -204,12 +205,12 @@ const Layout: React.FC = ({ const taskLink = ( {t('task.updated', 'Task')}{' '} - {taskData.name} - {' '} + {' '} {t('task.updatedSuccessfully', 'updated successfully!')} ); diff --git a/frontend/components/About.tsx b/frontend/components/About.tsx index f02c0ae..0d3b5d5 100644 --- a/frontend/components/About.tsx +++ b/frontend/components/About.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { HeartIcon } from '@heroicons/react/24/outline'; +import { getApiPath } from '../config/paths'; interface AboutProps { isDarkMode?: boolean; @@ -12,7 +13,7 @@ const About: React.FC = ({ isDarkMode = false }) => { useEffect(() => { // Fetch version from the deployed app - fetch('/api/version') + fetch(getApiPath('version')) .then((response) => response.json()) .then((data) => { if (data.version) { diff --git a/frontend/components/Admin/AdminUsersPage.tsx b/frontend/components/Admin/AdminUsersPage.tsx index e274d47..87909fc 100644 --- a/frontend/components/Admin/AdminUsersPage.tsx +++ b/frontend/components/Admin/AdminUsersPage.tsx @@ -8,6 +8,7 @@ import { TrashIcon, } from '@heroicons/react/24/outline'; import ConfirmDialog from '../Shared/ConfirmDialog'; +import { getApiPath } from '../../config/paths'; interface AdminUserItem { id: number; @@ -19,7 +20,7 @@ interface AdminUserItem { } const fetchAdminUsers = async (t: any): Promise => { - const res = await fetch('/api/admin/users', { + const res = await fetch(getApiPath('admin/users'), { credentials: 'include', headers: { Accept: 'application/json' }, }); @@ -41,7 +42,7 @@ const createAdminUser = async ( surname?: string, role?: 'admin' | 'user' ): Promise => { - const res = await fetch('/api/admin/users', { + const res = await fetch(getApiPath('admin/users'), { method: 'POST', credentials: 'include', headers: { @@ -82,7 +83,7 @@ const updateAdminUser = async ( const body: any = { email, name, surname, role }; if (password) body.password = password; - const res = await fetch(`/api/admin/users/${id}`, { + const res = await fetch(getApiPath(`admin/users/${id}`), { method: 'PUT', credentials: 'include', headers: { @@ -114,7 +115,7 @@ const updateAdminUser = async ( }; const deleteAdminUser = async (id: number, t: any): Promise => { - const res = await fetch(`/api/admin/users/${id}`, { + const res = await fetch(getApiPath(`admin/users/${id}`), { method: 'DELETE', credentials: 'include', headers: { Accept: 'application/json' }, diff --git a/frontend/components/Calendar.tsx b/frontend/components/Calendar.tsx index 2f2aa7f..b10fdb9 100644 --- a/frontend/components/Calendar.tsx +++ b/frontend/components/Calendar.tsx @@ -16,6 +16,8 @@ import { el, enUS, es, ja, uk, de } from 'date-fns/locale'; import CalendarMonthView from './Calendar/CalendarMonthView'; import CalendarWeekView from './Calendar/CalendarWeekView'; import CalendarDayView from './Calendar/CalendarDayView'; +import { getApiPath } from '../config/paths'; +import { Link } from 'react-router-dom'; const getLocale = (language: string) => { switch (language) { @@ -94,7 +96,7 @@ const Calendar: React.FC = () => { const checkGoogleCalendarStatus = async () => { try { - const response = await fetch('/api/calendar/status', { + const response = await fetch(getApiPath('calendar/status'), { credentials: 'include', }); if (response.ok) { @@ -110,7 +112,7 @@ const Calendar: React.FC = () => { const loadTasks = async () => { setIsLoadingTasks(true); try { - const response = await fetch('/api/tasks', { + const response = await fetch(getApiPath('tasks'), { credentials: 'include', }); if (response.ok) { @@ -205,7 +207,7 @@ const Calendar: React.FC = () => { const loadProjects = async () => { try { - const response = await fetch('/api/projects', { + const response = await fetch(getApiPath('projects'), { credentials: 'include', }); if (response.ok) { @@ -222,7 +224,7 @@ const Calendar: React.FC = () => { setIsConnecting(true); try { - const response = await fetch('/api/calendar/auth', { + const response = await fetch(getApiPath('calendar/auth'), { credentials: 'include', }); if (response.ok) { @@ -259,7 +261,7 @@ const Calendar: React.FC = () => { } // Real disconnect API call - const response = await fetch('/api/calendar/disconnect', { + const response = await fetch(getApiPath('calendar/disconnect'), { method: 'POST', credentials: 'include', }); @@ -372,7 +374,7 @@ const Calendar: React.FC = () => { const handleCreateProject = async (name: string): Promise => { try { - const response = await fetch('/api/projects', { + const response = await fetch(getApiPath('projects'), { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include', @@ -712,13 +714,13 @@ const TaskEventModal: React.FC = ({ {/* Action Buttons */}
- {t('calendar.goToTasks')} - +