mirror of
https://github.com/Dvorinka/Trackeep.git
synced 2026-06-04 12:32:58 +00:00
Configure Docker publishing with correct GitHub username
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
const DEFAULT_API_ORIGIN = 'http://localhost:8080';
|
||||
|
||||
const trimTrailingSlash = (value: string): string => value.replace(/\/+$/, '');
|
||||
|
||||
const trimApiSuffix = (value: string): string => value.replace(/\/api\/v1$/, '');
|
||||
|
||||
export const getApiOrigin = (): string => {
|
||||
const raw = (import.meta.env.VITE_API_URL as string | undefined)?.trim();
|
||||
if (!raw) {
|
||||
return DEFAULT_API_ORIGIN;
|
||||
}
|
||||
|
||||
const normalized = trimTrailingSlash(raw);
|
||||
return trimApiSuffix(normalized);
|
||||
};
|
||||
|
||||
export const getApiV1BaseUrl = (): string => {
|
||||
const origin = getApiOrigin();
|
||||
return `${origin}/api/v1`;
|
||||
};
|
||||
+10
-10
@@ -1,10 +1,11 @@
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:9090/api/v1';
|
||||
import { isEnvDemoMode } from '@/lib/demo-mode';
|
||||
import { getApiV1BaseUrl } from '@/lib/api-url';
|
||||
|
||||
// Check if we're in demo mode
|
||||
const API_BASE_URL = getApiV1BaseUrl();
|
||||
|
||||
// Demo mode is controlled by environment only.
|
||||
const isDemoMode = () => {
|
||||
return localStorage.getItem('demoMode') === 'true' ||
|
||||
document.title.includes('Demo Mode') ||
|
||||
window.location.search.includes('demo=true');
|
||||
return isEnvDemoMode();
|
||||
};
|
||||
|
||||
// Helper function to get auth headers
|
||||
@@ -47,15 +48,14 @@ class ApiClient {
|
||||
const response = await fetch(url, config);
|
||||
|
||||
if (!response.ok) {
|
||||
// If backend fails, fall back to demo mode
|
||||
console.warn(`API endpoint ${endpoint} failed, falling back to demo mode`);
|
||||
return this.getMockResponse(endpoint, options);
|
||||
const message = await response.text();
|
||||
throw new Error(message || `HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.warn(`API request failed for ${endpoint}, falling back to demo mode:`, error);
|
||||
return this.getMockResponse(endpoint, options);
|
||||
console.error(`API request failed for ${endpoint}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { createContext, useContext, type ParentComponent, onMount } from 'solid-js';
|
||||
import { createStore } from 'solid-js/store';
|
||||
import { isEnvDemoMode } from '@/lib/demo-mode';
|
||||
import { getApiV1BaseUrl } from '@/lib/api-url';
|
||||
|
||||
// Check if we're in demo mode (same logic as api.ts)
|
||||
// Demo mode is controlled by environment only.
|
||||
const isDemoMode = () => {
|
||||
return localStorage.getItem('demoMode') === 'true' ||
|
||||
document.title.includes('Demo Mode') ||
|
||||
window.location.search.includes('demo=true');
|
||||
return isEnvDemoMode();
|
||||
};
|
||||
|
||||
// Types
|
||||
@@ -44,7 +44,7 @@ export interface AuthResponse {
|
||||
}
|
||||
|
||||
// API base URL
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8080/api/v1';
|
||||
const API_BASE_URL = getApiV1BaseUrl();
|
||||
|
||||
// Create auth context
|
||||
const AuthContext = createContext<AuthContextType>();
|
||||
@@ -67,7 +67,7 @@ export const AuthProvider: ParentComponent = (props) => {
|
||||
user: null,
|
||||
token: null,
|
||||
isAuthenticated: false,
|
||||
isLoading: false, // Start with false to avoid loading spinner in ProtectedRoute
|
||||
isLoading: true,
|
||||
});
|
||||
|
||||
// Initialize auth state from localStorage
|
||||
@@ -400,18 +400,12 @@ export const useAuth = () => {
|
||||
|
||||
// Helper function to get auth headers for API requests
|
||||
export const getAuthHeaders = () => {
|
||||
// Check if we're in demo mode first
|
||||
const isDemo = localStorage.getItem('demoMode') === 'true' ||
|
||||
document.title.includes('Demo Mode') ||
|
||||
window.location.search.includes('demo=true');
|
||||
|
||||
const isDemo = isDemoMode();
|
||||
let token = null;
|
||||
|
||||
if (isDemo) {
|
||||
// In demo mode, use a mock token
|
||||
token = 'demo-token-' + Date.now();
|
||||
token = localStorage.getItem('token') || localStorage.getItem('trackeep_token') || ('demo-token-' + Date.now());
|
||||
} else {
|
||||
// In normal mode, get token from localStorage
|
||||
token = localStorage.getItem('token') || localStorage.getItem('trackeep_token');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
// Brave Search API integration
|
||||
const BACKEND_API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8080/api/v1';
|
||||
import { isDemoMode } from '@/lib/demo-mode';
|
||||
import { getApiV1BaseUrl } from '@/lib/api-url';
|
||||
|
||||
const BACKEND_API_URL = getApiV1BaseUrl();
|
||||
const BRAVE_API_KEY = import.meta.env.VITE_BRAVE_API_KEY || 'BSAw0HNI1v3rKmXlSTr0C_UfZDjw7fT';
|
||||
|
||||
// Use the variable to avoid unused warning
|
||||
@@ -7,10 +10,7 @@ console.log('Brave API key available:', !!BRAVE_API_KEY);
|
||||
|
||||
// Helper function to get auth headers
|
||||
const getAuthHeaders = () => {
|
||||
// Check if we're in demo mode
|
||||
const isDemo = import.meta.env.VITE_DEMO_MODE === 'true' ||
|
||||
document.title.includes('Demo Mode') ||
|
||||
window.location.search.includes('demo=true');
|
||||
const isDemo = isDemoMode();
|
||||
|
||||
let token = null;
|
||||
|
||||
|
||||
@@ -11,13 +11,7 @@ import {
|
||||
getMockLearningPaths,
|
||||
getMockStats
|
||||
} from './mockData';
|
||||
|
||||
// Check if we're in demo mode
|
||||
const isDemoMode = () => {
|
||||
return localStorage.getItem('demoMode') === 'true' ||
|
||||
document.title.includes('Demo Mode') ||
|
||||
window.location.search.includes('demo=true');
|
||||
};
|
||||
import { isDemoMode } from './demo-mode';
|
||||
|
||||
// Demo mode API client that falls back to mock data
|
||||
export class DemoModeApiClient {
|
||||
|
||||
@@ -106,6 +106,15 @@ export interface VaultItem {
|
||||
target_conversation_id?: number | null;
|
||||
}
|
||||
|
||||
export interface UserFile {
|
||||
id: number;
|
||||
original_name: string;
|
||||
mime_type: string;
|
||||
file_size: number;
|
||||
created_at: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export interface WsEvent {
|
||||
type: string;
|
||||
conversation_id?: number;
|
||||
@@ -186,6 +195,11 @@ export const messagesApi = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
}),
|
||||
revealSensitiveMessage: (messageId: number) =>
|
||||
apiRequest<{ message_id: number; plaintext: string }>(`/messages/${messageId}/reveal-sensitive`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({}),
|
||||
}),
|
||||
listVaultItems: () => apiRequest<{ items: VaultItem[] }>('/password-vault/items'),
|
||||
createVaultItem: (payload: any) => apiRequest<any>('/password-vault/items', {
|
||||
method: 'POST',
|
||||
@@ -206,6 +220,28 @@ export const messagesApi = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
}),
|
||||
listUserFiles: async (query: string = '', limit: number = 20): Promise<UserFile[]> => {
|
||||
const token = getToken();
|
||||
const params = new URLSearchParams();
|
||||
if (query.trim()) {
|
||||
params.set('q', query.trim());
|
||||
}
|
||||
if (Number.isFinite(limit) && limit > 0) {
|
||||
params.set('limit', String(Math.min(100, Math.floor(limit))));
|
||||
}
|
||||
|
||||
const suffix = params.toString() ? `?${params.toString()}` : '';
|
||||
const res = await fetch(`${API_BASE_URL}/api/v1/files${suffix}`, {
|
||||
headers: {
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
},
|
||||
});
|
||||
if (!res.ok) {
|
||||
const errorData = await res.json().catch(() => ({}));
|
||||
throw new Error(errorData.error || `Request failed (${res.status})`);
|
||||
}
|
||||
return res.json();
|
||||
},
|
||||
};
|
||||
|
||||
export async function uploadChatFile(file: File): Promise<{ id: number; original_name: string; mime_type: string }> {
|
||||
|
||||
Reference in New Issue
Block a user