Refactor video streaming feature and update dependencies
- Replaced npm ci with npm install in docker-compose for better package management. - Introduced remote component loading for the VideoStreamingPage with error handling. - Updated the title in index.html to "Experiments Dashboard" for clarity. - Added new video remote service configuration in docker-compose for improved integration. - Removed deprecated files and components related to the video streaming feature to streamline the codebase. - Updated package.json and package-lock.json to include @originjs/vite-plugin-federation for module federation support.
This commit is contained in:
28
management-dashboard-web-app/src/shared/api/client.ts
Normal file
28
management-dashboard-web-app/src/shared/api/client.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
|
||||
|
||||
const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
|
||||
|
||||
async function request<T>(path: string, method: HttpMethod = 'GET', body?: unknown): Promise<T> {
|
||||
const res = await fetch(`${BASE_URL}${path}`, {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
})
|
||||
if (!res.ok) {
|
||||
const text = await res.text().catch(() => '')
|
||||
throw new Error(text || `Request failed: ${res.status}`)
|
||||
}
|
||||
return (await res.json()) as T
|
||||
}
|
||||
|
||||
export const apiClient = {
|
||||
get: <T>(path: string) => request<T>(path, 'GET'),
|
||||
post: <T>(path: string, body?: unknown) => request<T>(path, 'POST', body),
|
||||
put: <T>(path: string, body?: unknown) => request<T>(path, 'PUT', body),
|
||||
patch: <T>(path: string, body?: unknown) => request<T>(path, 'PATCH', body),
|
||||
delete: <T>(path: string) => request<T>(path, 'DELETE'),
|
||||
}
|
||||
|
||||
|
||||
4
management-dashboard-web-app/src/shared/api/index.ts
Normal file
4
management-dashboard-web-app/src/shared/api/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { apiClient } from './client'
|
||||
|
||||
|
||||
|
||||
30
management-dashboard-web-app/src/shared/api/video.ts
Normal file
30
management-dashboard-web-app/src/shared/api/video.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { apiClient } from './client'
|
||||
import type { VideoListParams, VideoListResponse } from '../types/video'
|
||||
|
||||
const BASE = (import.meta as any).env?.VITE_VISION_API_URL || '/api'
|
||||
|
||||
export const videoApi = {
|
||||
async list(params: VideoListParams = {}): Promise<VideoListResponse> {
|
||||
const search = new URLSearchParams()
|
||||
Object.entries(params).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null) search.append(k, String(v))
|
||||
})
|
||||
const qs = search.toString()
|
||||
return apiClient.get(`${BASE}/videos/${qs ? `?${qs}` : ''}`)
|
||||
},
|
||||
streamingUrl(fileId: string): string {
|
||||
return `${BASE}/videos/${fileId}/stream`
|
||||
},
|
||||
thumbnailUrl(fileId: string, params: { timestamp?: number; width?: number; height?: number } = {}): string {
|
||||
const search = new URLSearchParams()
|
||||
Object.entries(params).forEach(([k, v]) => {
|
||||
if (v !== undefined && v !== null) search.append(k, String(v))
|
||||
})
|
||||
const qs = search.toString()
|
||||
return `${BASE}/videos/${fileId}/thumbnail${qs ? `?${qs}` : ''}`
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
4
management-dashboard-web-app/src/shared/auth/index.ts
Normal file
4
management-dashboard-web-app/src/shared/auth/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { supabase, userManagement, type User } from '../../lib/supabase'
|
||||
export { useAuth } from '../../hooks/useAuth'
|
||||
|
||||
|
||||
6
management-dashboard-web-app/src/shared/index.ts
Normal file
6
management-dashboard-web-app/src/shared/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './types'
|
||||
export * from './ui'
|
||||
export * from './api'
|
||||
export * from './auth'
|
||||
|
||||
|
||||
6
management-dashboard-web-app/src/shared/types/index.ts
Normal file
6
management-dashboard-web-app/src/shared/types/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export type ApiResult<T> = { success: true; data: T } | { success: false; error: string }
|
||||
|
||||
export type UserRole = 'admin' | 'conductor' | 'user'
|
||||
|
||||
|
||||
|
||||
34
management-dashboard-web-app/src/shared/types/video.ts
Normal file
34
management-dashboard-web-app/src/shared/types/video.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
export interface VideoFile {
|
||||
file_id: string
|
||||
camera_name: string
|
||||
filename: string
|
||||
file_size_bytes: number
|
||||
format: string
|
||||
status: 'completed' | 'processing' | 'failed'
|
||||
created_at: string
|
||||
is_streamable: boolean
|
||||
needs_conversion: boolean
|
||||
}
|
||||
|
||||
export interface VideoListResponse {
|
||||
videos: VideoFile[]
|
||||
total_count: number
|
||||
page?: number
|
||||
total_pages?: number
|
||||
has_next?: boolean
|
||||
has_previous?: boolean
|
||||
}
|
||||
|
||||
export interface VideoListParams {
|
||||
camera_name?: string
|
||||
start_date?: string
|
||||
end_date?: string
|
||||
limit?: number
|
||||
include_metadata?: boolean
|
||||
page?: number
|
||||
offset?: number
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
4
management-dashboard-web-app/src/shared/ui/index.ts
Normal file
4
management-dashboard-web-app/src/shared/ui/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { PrimaryButton } from './widgets/PrimaryButton'
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { ButtonHTMLAttributes, PropsWithChildren } from 'react'
|
||||
|
||||
type PrimaryButtonProps = PropsWithChildren<ButtonHTMLAttributes<HTMLButtonElement>> & {
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
export function PrimaryButton({ children, loading = false, className = '', ...rest }: PrimaryButtonProps) {
|
||||
return (
|
||||
<button
|
||||
{...rest}
|
||||
className={`px-4 py-2 rounded-lg bg-indigo-600 text-white hover:bg-indigo-700 disabled:opacity-50 ${className}`}
|
||||
disabled={loading || rest.disabled}
|
||||
>
|
||||
{loading ? 'Please wait…' : children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user