mirror of
https://github.com/azaion/ui.git
synced 2026-06-24 17:51:11 +00:00
chore: update API configuration and enhance authentication handling
- Updated Vite configuration to use the production API endpoint. - Modified TypeScript build info to include new config file. - Refactored API client to support authenticated URLs. - Updated various components to utilize the new authenticated API URL for media fetching. - Removed obsolete CSS and JS files from the distribution directory.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
VITE_API_URL=https://api.azaion.com
|
||||
Vendored
-164
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+152
File diff suppressed because one or more lines are too long
Vendored
-1
File diff suppressed because one or more lines are too long
Vendored
+13
-13
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>AZAION</title>
|
||||
<script type="module" crossorigin src="/assets/index-B-KLvAXK.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Du68yxJU.css">
|
||||
</head>
|
||||
<body class="bg-[#1e1e1e] text-[#adb5bd]">
|
||||
<div id="root"></div>
|
||||
|
||||
</body>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>AZAION</title>
|
||||
<script type="module" crossorigin src="/assets/index-Da0DwgCt.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CUCmanMv.css">
|
||||
</head>
|
||||
<body class="bg-[#1e1e1e] text-[#adb5bd]">
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+12
-3
@@ -1,3 +1,5 @@
|
||||
import { apiUrl } from '../config'
|
||||
|
||||
let accessToken: string | null = null
|
||||
|
||||
export function setToken(token: string | null) {
|
||||
@@ -8,6 +10,13 @@ export function getToken() {
|
||||
return accessToken
|
||||
}
|
||||
|
||||
export function authenticatedApiUrl(path: string): string {
|
||||
const url = apiUrl(path)
|
||||
if (!accessToken) return url
|
||||
const separator = url.includes('?') ? '&' : '?'
|
||||
return `${url}${separator}access_token=${encodeURIComponent(accessToken)}`
|
||||
}
|
||||
|
||||
async function handleResponse<T>(res: Response): Promise<T> {
|
||||
if (res.status === 204) return undefined as T
|
||||
if (!res.ok) {
|
||||
@@ -22,13 +31,13 @@ async function request<T>(url: string, options: RequestInit = {}): Promise<T> {
|
||||
if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`)
|
||||
if (options.body && typeof options.body === 'string') headers.set('Content-Type', 'application/json')
|
||||
|
||||
let res = await fetch(url, { ...options, headers })
|
||||
let res = await fetch(apiUrl(url), { ...options, headers, credentials: 'include' })
|
||||
|
||||
if (res.status === 401 && accessToken) {
|
||||
const refreshed = await refreshToken()
|
||||
if (refreshed) {
|
||||
headers.set('Authorization', `Bearer ${accessToken}`)
|
||||
res = await fetch(url, { ...options, headers })
|
||||
res = await fetch(apiUrl(url), { ...options, headers, credentials: 'include' })
|
||||
} else {
|
||||
setToken(null)
|
||||
window.location.href = '/login'
|
||||
@@ -41,7 +50,7 @@ async function request<T>(url: string, options: RequestInit = {}): Promise<T> {
|
||||
|
||||
async function refreshToken(): Promise<boolean> {
|
||||
try {
|
||||
const res = await fetch('/api/admin/auth/refresh', { method: 'POST', credentials: 'include' })
|
||||
const res = await fetch(apiUrl('/api/admin/auth/refresh'), { method: 'POST', credentials: 'include' })
|
||||
if (!res.ok) return false
|
||||
const data = await res.json()
|
||||
setToken(data.token)
|
||||
|
||||
+5
-1
@@ -1,3 +1,4 @@
|
||||
import { apiUrl } from '../config'
|
||||
import { getToken } from './client'
|
||||
|
||||
export function createSSE<T>(
|
||||
@@ -5,8 +6,11 @@ export function createSSE<T>(
|
||||
onMessage: (data: T) => void,
|
||||
onError?: (err: Event) => void,
|
||||
): () => void {
|
||||
const resolved = apiUrl(url)
|
||||
const token = getToken()
|
||||
const fullUrl = token ? `${url}${url.includes('?') ? '&' : '?'}access_token=${token}` : url
|
||||
const fullUrl = token
|
||||
? `${resolved}${resolved.includes('?') ? '&' : '?'}access_token=${encodeURIComponent(token)}`
|
||||
: resolved
|
||||
|
||||
const source = new EventSource(fullUrl)
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
const raw = import.meta.env.VITE_API_URL
|
||||
export const API_BASE_URL =
|
||||
raw === '' ? '' : (raw ?? 'https://api.azaion.com')
|
||||
|
||||
export function apiUrl(path: string): string {
|
||||
if (path.startsWith('http')) return path
|
||||
if (!API_BASE_URL) return path
|
||||
const base = API_BASE_URL.replace(/\/$/, '')
|
||||
const normalized = path.startsWith('/') ? path : `/${path}`
|
||||
return `${base}${normalized}`
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useCallback, useEffect, useRef } from 'react'
|
||||
import { useResizablePanel } from '../../hooks/useResizablePanel'
|
||||
import { api } from '../../api/client'
|
||||
import { api, authenticatedApiUrl } from '../../api/client'
|
||||
import MediaList from './MediaList'
|
||||
import VideoPlayer, { type VideoPlayerHandle } from './VideoPlayer'
|
||||
import CanvasEditor, { type CanvasEditorHandle } from './CanvasEditor'
|
||||
@@ -96,7 +96,7 @@ export default function AnnotationsPage() {
|
||||
img.crossOrigin = 'anonymous'
|
||||
img.src = selectedMedia.path.startsWith('blob:')
|
||||
? selectedMedia.path
|
||||
: `/api/annotations/media/${selectedMedia.id}/file`
|
||||
: authenticatedApiUrl(`/api/annotations/media/${selectedMedia.id}/file`)
|
||||
await new Promise(res => { img.onload = res; img.onerror = res })
|
||||
w = img.naturalWidth
|
||||
h = img.naturalHeight
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useRef, useEffect, useState, useCallback, forwardRef, useImperativeHandle } from 'react'
|
||||
import { MediaType } from '../../types'
|
||||
import type { Media, AnnotationListItem, Detection, Affiliation, CombatReadiness } from '../../types'
|
||||
import { authenticatedApiUrl } from '../../api/client'
|
||||
import { getClassColor, getPhotoModeSuffix, getClassNameFallback } from './classColors'
|
||||
|
||||
interface Props {
|
||||
@@ -76,11 +77,11 @@ const CanvasEditor = forwardRef<CanvasEditorHandle, Props>(function CanvasEditor
|
||||
const img = new Image()
|
||||
img.crossOrigin = 'anonymous'
|
||||
if (annotation && !media.path.startsWith('blob:')) {
|
||||
img.src = `/api/annotations/annotations/${annotation.id}/image`
|
||||
img.src = authenticatedApiUrl(`/api/annotations/annotations/${annotation.id}/image`)
|
||||
} else if (media.path.startsWith('blob:')) {
|
||||
img.src = media.path
|
||||
} else {
|
||||
img.src = `/api/annotations/media/${media.id}/file`
|
||||
img.src = authenticatedApiUrl(`/api/annotations/media/${media.id}/file`)
|
||||
}
|
||||
img.onload = () => {
|
||||
imgRef.current = img
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useRef, useState, useCallback, useEffect, forwardRef, useImperativeHandle } from 'react'
|
||||
import { FaPlay, FaPause, FaStop, FaStepBackward, FaStepForward, FaVolumeMute, FaVolumeUp } from 'react-icons/fa'
|
||||
import { authenticatedApiUrl } from '../../api/client'
|
||||
import type { Media } from '../../types'
|
||||
|
||||
interface Props {
|
||||
@@ -38,7 +39,7 @@ const VideoPlayer = forwardRef<VideoPlayerHandle, Props>(function VideoPlayer({
|
||||
|
||||
const videoUrl = media.path.startsWith('blob:')
|
||||
? media.path
|
||||
: `/api/annotations/media/${media.id}/file`
|
||||
: authenticatedApiUrl(`/api/annotations/media/${media.id}/file`)
|
||||
|
||||
const stepFrames = useCallback((count: number) => {
|
||||
const video = videoRef.current
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { api } from '../../api/client'
|
||||
import { api, authenticatedApiUrl } from '../../api/client'
|
||||
import { useDebounce } from '../../hooks/useDebounce'
|
||||
import { useResizablePanel } from '../../hooks/useResizablePanel'
|
||||
import { useFlight } from '../../components/FlightContext'
|
||||
@@ -183,7 +183,7 @@ export default function DatasetPage() {
|
||||
} ${item.isSeed ? 'ring-2 ring-az-red' : ''}`}
|
||||
>
|
||||
<img
|
||||
src={`/api/annotations/annotations/${item.annotationId}/thumbnail`}
|
||||
src={authenticatedApiUrl(`/api/annotations/annotations/${item.annotationId}/thumbnail`)}
|
||||
alt={item.imageName}
|
||||
className="w-full h-32 object-cover bg-az-bg"
|
||||
loading="lazy"
|
||||
|
||||
Vendored
+8
@@ -1,4 +1,12 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_API_URL?: string
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv
|
||||
}
|
||||
|
||||
declare module '*.css'
|
||||
declare module 'leaflet-polylinedecorator'
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"root":["./src/app.tsx","./src/main.tsx","./src/api/client.ts","./src/api/sse.ts","./src/auth/authcontext.tsx","./src/auth/protectedroute.tsx","./src/components/confirmdialog.tsx","./src/components/detectionclasses.tsx","./src/components/flightcontext.tsx","./src/components/header.tsx","./src/components/helpmodal.tsx","./src/features/admin/adminpage.tsx","./src/features/annotations/annotationspage.tsx","./src/features/annotations/annotationssidebar.tsx","./src/features/annotations/canvaseditor.tsx","./src/features/annotations/medialist.tsx","./src/features/annotations/videoplayer.tsx","./src/features/dataset/datasetpage.tsx","./src/features/flights/altitudechart.tsx","./src/features/flights/altitudedialog.tsx","./src/features/flights/drawcontrol.tsx","./src/features/flights/flightlistsidebar.tsx","./src/features/flights/flightmap.tsx","./src/features/flights/flightparamspanel.tsx","./src/features/flights/flightspage.tsx","./src/features/flights/jsoneditordialog.tsx","./src/features/flights/mappoint.tsx","./src/features/flights/minimap.tsx","./src/features/flights/waypointlist.tsx","./src/features/flights/windeffect.tsx","./src/features/flights/flightplanutils.ts","./src/features/flights/mapicons.ts","./src/features/flights/types.ts","./src/features/login/loginpage.tsx","./src/features/settings/settingspage.tsx","./src/hooks/usedebounce.ts","./src/hooks/useresizablepanel.ts","./src/i18n/i18n.ts","./src/types/index.ts"],"version":"5.7.3"}
|
||||
{"root":["./src/app.tsx","./src/config.ts","./src/main.tsx","./src/vite-env.d.ts","./src/api/client.ts","./src/api/sse.ts","./src/auth/authcontext.tsx","./src/auth/protectedroute.tsx","./src/components/confirmdialog.tsx","./src/components/detectionclasses.tsx","./src/components/flightcontext.tsx","./src/components/header.tsx","./src/components/helpmodal.tsx","./src/features/admin/adminpage.tsx","./src/features/annotations/annotationspage.tsx","./src/features/annotations/annotationssidebar.tsx","./src/features/annotations/canvaseditor.tsx","./src/features/annotations/medialist.tsx","./src/features/annotations/videoplayer.tsx","./src/features/annotations/classcolors.ts","./src/features/dataset/datasetpage.tsx","./src/features/flights/altitudechart.tsx","./src/features/flights/altitudedialog.tsx","./src/features/flights/drawcontrol.tsx","./src/features/flights/flightlistsidebar.tsx","./src/features/flights/flightmap.tsx","./src/features/flights/flightparamspanel.tsx","./src/features/flights/flightspage.tsx","./src/features/flights/jsoneditordialog.tsx","./src/features/flights/mappoint.tsx","./src/features/flights/minimap.tsx","./src/features/flights/waypointlist.tsx","./src/features/flights/windeffect.tsx","./src/features/flights/flightplanutils.ts","./src/features/flights/mapicons.ts","./src/features/flights/types.ts","./src/features/login/loginpage.tsx","./src/features/settings/settingspage.tsx","./src/hooks/usedebounce.ts","./src/hooks/useresizablepanel.ts","./src/i18n/i18n.ts","./src/types/index.ts"],"version":"5.7.3"}
|
||||
+2
-1
@@ -13,8 +13,9 @@ export default defineConfig({
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:8080',
|
||||
target: 'https://api.azaion.com',
|
||||
changeOrigin: true,
|
||||
secure: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user