bug fixes for frontend when trying to npm run build
This commit is contained in:
parent
1a1ed3048d
commit
aafc4078ae
24 changed files with 63 additions and 63 deletions
BIN
DEPLOYMENT.md
BIN
DEPLOYMENT.md
Binary file not shown.
|
|
@ -77,7 +77,7 @@ services:
|
|||
redis:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "8000:8000"
|
||||
- "8003:8000"
|
||||
environment:
|
||||
# App configuration
|
||||
APP_ENV: ${APP_ENV:-dev}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ReactNode } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import { useAuthStore } from '../../lib/auth';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ReactNode } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useAuthStore } from '../../lib/auth';
|
||||
import type { UserRole } from '../../types/api';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|||
import { render, screen, waitFor } from '../../../test/utils'
|
||||
import { RequireAuth } from '../RequireAuth'
|
||||
import { useAuthStore } from '../../../lib/auth'
|
||||
import { UserRole } from '../../../types/api'
|
||||
import { createMockUser } from '../../../test/utils'
|
||||
|
||||
// Mock the auth store
|
||||
|
|
@ -18,7 +17,6 @@ describe('RequireAuth', () => {
|
|||
})
|
||||
|
||||
it('renders children when user is authenticated', () => {
|
||||
const mockUser = createMockUser()
|
||||
mockUseAuthStore.mockReturnValue({
|
||||
isAuthenticated: true,
|
||||
isLoading: false,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
||||
import { Component } from 'react';
|
||||
import type { ErrorInfo, ReactNode } from 'react';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { ReactNode, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Sidebar } from './Sidebar';
|
||||
import { Navbar } from './Navbar';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useState, useCallback } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { useDropzone, type FileRejection } from 'react-dropzone';
|
||||
|
||||
interface UploadDropzoneProps {
|
||||
onFileSelect: (file: File) => void;
|
||||
|
|
@ -16,7 +16,7 @@ export function UploadDropzone({
|
|||
}: UploadDropzoneProps) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const onDrop = useCallback((acceptedFiles: File[], rejectedFiles: { file: File; errors: { code: string }[] }[]) => {
|
||||
const onDrop = useCallback((acceptedFiles: File[], rejectedFiles: FileRejection[]) => {
|
||||
setError(null);
|
||||
|
||||
if (rejectedFiles.length > 0) {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ export function VideoWithCaptions({
|
|||
const video = videoRef.current;
|
||||
if (!video) return;
|
||||
|
||||
let timeoutId: number;
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
const handleTimeUpdate = () => {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { createContext, useContext, ReactNode, useCallback } from 'react';
|
||||
import { createContext, useContext, useCallback } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useJobStatusWebSocket } from '../hooks/useJobStatusWebSocket';
|
||||
import { useToastContext } from './ToastContext';
|
||||
import { getStatusMessageConfig } from '../utils/jobStatusMessages';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { createContext, useContext, ReactNode, useState, useCallback } from 'react';
|
||||
import { createContext, useContext, useState, useCallback } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export interface NotificationItem {
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { createContext, useContext, ReactNode } from 'react';
|
||||
import { createContext, useContext } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useToast } from '../hooks/useToast';
|
||||
import { useNotificationContext } from './NotificationContext';
|
||||
import type { ToastMessage } from '../components/Toast/Toast';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
||||
import { renderHook, waitFor } from '@testing-library/react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { ReactNode } from 'react'
|
||||
import type { ReactNode } from 'react'
|
||||
import {
|
||||
useJobs,
|
||||
useJob,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import type {
|
|||
} from '../types/api';
|
||||
|
||||
// Query hooks
|
||||
export function useJobs(filters?: { status?: string; mine?: boolean }, options?: { enabled?: boolean }) {
|
||||
export function useJobs(filters?: { status?: string; mine?: boolean; page?: number; size?: number }, options?: { enabled?: boolean }) {
|
||||
return useQuery({
|
||||
queryKey: ['jobs', filters],
|
||||
queryFn: () => apiClient.getJobs(filters),
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export const useAuthStore = create<AuthState>((set) => ({
|
|||
|
||||
refreshAuth: async () => {
|
||||
try {
|
||||
const response = await apiClient.refresh();
|
||||
await apiClient.refresh();
|
||||
// Token refresh succeeded, but we don't have user info
|
||||
// In a proper implementation, the refresh endpoint would return user data
|
||||
// For now, we'll assume if refresh succeeds and we have existing user, we're authenticated
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ export function FinalDetail() {
|
|||
language={language}
|
||||
assets={assets}
|
||||
jobId={id!}
|
||||
audioUrl={downloads?.downloads?.[language]?.audio_description_mp3}
|
||||
audioUrl={typeof downloads?.downloads?.[language] === 'object' ? downloads?.downloads?.[language]?.audio_description_mp3 : undefined}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ export function QCDetail() {
|
|||
const isProcessing = approveEnglishMutation.isPending || rejectJobMutation.isPending || updateVttMutation.isPending || adjustTimingMutation.isPending;
|
||||
|
||||
// Get video URL from downloads
|
||||
const videoUrl = downloads?.downloads?.source_video || '';
|
||||
const videoUrl = typeof downloads?.downloads?.source_video === 'string'
|
||||
? downloads.downloads.source_video
|
||||
: '';
|
||||
|
||||
// Load VTT content when fetched
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -69,14 +69,16 @@ export function JobDetail() {
|
|||
|
||||
|
||||
// Get video URL from downloads
|
||||
const videoUrl = downloads?.downloads?.source_video || '';
|
||||
const videoUrl = typeof downloads?.downloads?.source_video === 'string'
|
||||
? downloads.downloads.source_video
|
||||
: '';
|
||||
|
||||
const tabs = [
|
||||
{ id: 'overview', label: 'Overview', icon: '📋' },
|
||||
{ id: 'video', label: 'Video Preview', icon: '🎥', disabled: !videoUrl },
|
||||
{ id: 'assets', label: 'Assets', icon: '📁' },
|
||||
{ id: 'history', label: 'History', icon: '📜' },
|
||||
] as const;
|
||||
{ id: 'overview' as const, label: 'Overview', icon: '📋', disabled: false },
|
||||
{ id: 'video' as const, label: 'Video Preview', icon: '🎥', disabled: !videoUrl },
|
||||
{ id: 'assets' as const, label: 'Assets', icon: '📁', disabled: false },
|
||||
{ id: 'history' as const, label: 'History', icon: '📜', disabled: false },
|
||||
];
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
|
|
@ -182,8 +184,8 @@ export function JobDetail() {
|
|||
{videoUrl ? (
|
||||
<VideoWithCaptions
|
||||
videoUrl={videoUrl}
|
||||
captionsVtt={englishVtt?.captions_vtt}
|
||||
audioDescriptionVtt={englishVtt?.audio_description_vtt}
|
||||
captionsVtt={englishVtt?.captions_vtt || ''}
|
||||
audioDescriptionVtt={englishVtt?.audio_description_vtt || ''}
|
||||
/>
|
||||
) : (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
|
|
@ -346,7 +348,7 @@ export function JobDetail() {
|
|||
{job.error && (
|
||||
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<h3 className="text-sm font-medium text-red-800 mb-2">Processing Error</h3>
|
||||
<p className="text-xs text-red-600">{job.error.message}</p>
|
||||
<p className="text-xs text-red-600">{String(job.error.message || 'Unknown error')}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -105,13 +105,7 @@ export function NewJob() {
|
|||
setValue('transcreation', transcreation.filter(l => l !== lang));
|
||||
};
|
||||
|
||||
const toggleTranscreation = (lang: string) => {
|
||||
if (transcreation.includes(lang)) {
|
||||
setValue('transcreation', transcreation.filter(l => l !== lang));
|
||||
} else {
|
||||
setValue('transcreation', [...transcreation, lang]);
|
||||
}
|
||||
};
|
||||
// Removed toggleTranscreation - not currently used
|
||||
|
||||
// Success state
|
||||
if (createdJob) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { ReactElement } from 'react'
|
||||
import { render, RenderOptions } from '@testing-library/react'
|
||||
import type { ReactElement } from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import type { RenderOptions } from '@testing-library/react'
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { BrowserRouter } from 'react-router-dom'
|
||||
import { User, UserRole } from '../types/api'
|
||||
import type { User, UserRole } from '../types/api'
|
||||
|
||||
// Mock user for testing
|
||||
export const createMockUser = (overrides: Partial<User> = {}): User => ({
|
||||
|
|
|
|||
|
|
@ -139,7 +139,4 @@ export interface BulkDeleteResponse {
|
|||
|
||||
export interface JobDeleteResponse {
|
||||
message: string;
|
||||
}
|
||||
|
||||
// Ensure Job is properly exported
|
||||
export type { Job };
|
||||
}
|
||||
|
|
@ -23,5 +23,6 @@
|
|||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedSideEffectImports": true
|
||||
},
|
||||
"include": ["src"]
|
||||
"include": ["src"],
|
||||
"exclude": ["src/**/*.test.ts", "src/**/*.test.tsx", "src/test"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# Frontend Build and Deploy Script
|
||||
# =============================================================================
|
||||
# Builds the React frontend and deploys to Apache document root
|
||||
# Run from: /opt/accessible-video/
|
||||
# Run from: /opt/video-accessibility/
|
||||
# Usage: ./scripts/build-frontend.sh
|
||||
# =============================================================================
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ BLUE='\033[0;34m'
|
|||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
PROJECT_DIR="/opt/accessible-video"
|
||||
PROJECT_DIR="/opt/video-accessibility"
|
||||
FRONTEND_DIR="$PROJECT_DIR/frontend"
|
||||
DEPLOY_DIR="/var/www/html/video-accessibility"
|
||||
|
||||
|
|
@ -100,9 +100,9 @@ build_frontend() {
|
|||
|
||||
cd "$FRONTEND_DIR"
|
||||
|
||||
# Install dependencies
|
||||
# Install dependencies (including dev dependencies needed for build)
|
||||
print_info "Installing dependencies..."
|
||||
npm ci --only=production
|
||||
npm ci
|
||||
print_success "Dependencies installed"
|
||||
|
||||
# Build the application
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
# Deployment Script for Accessible Video Platform
|
||||
# =============================================================================
|
||||
# This script handles building and deploying the application
|
||||
# Run from: /opt/accessible-video/
|
||||
# Run from: /opt/video-accessibility/
|
||||
# Usage: ./scripts/deploy.sh [options]
|
||||
# =============================================================================
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ BLUE='\033[0;34m'
|
|||
NC='\033[0m' # No Color
|
||||
|
||||
# Configuration
|
||||
PROJECT_DIR="/opt/accessible-video"
|
||||
PROJECT_DIR="/opt/video-accessibility"
|
||||
COMPOSE_FILES="-f docker-compose.yml -f docker-compose.prod.yml"
|
||||
|
||||
# =============================================================================
|
||||
|
|
@ -39,7 +39,7 @@ print_error() {
|
|||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW} $1${NC}"
|
||||
echo -e "${YELLOW}<EFBFBD> $1${NC}"
|
||||
}
|
||||
|
||||
print_info() {
|
||||
|
|
@ -55,7 +55,7 @@ preflight_checks() {
|
|||
|
||||
# Check if running from correct directory
|
||||
if [ ! -f "docker-compose.yml" ]; then
|
||||
print_error "docker-compose.yml not found. Please run from /opt/accessible-video/"
|
||||
print_error "docker-compose.yml not found. Please run from /opt/video-accessibility/"
|
||||
exit 1
|
||||
fi
|
||||
print_success "Running from correct directory"
|
||||
|
|
@ -88,12 +88,12 @@ preflight_checks() {
|
|||
fi
|
||||
print_success "Docker is running"
|
||||
|
||||
# Check if docker-compose is available
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
print_error "docker-compose is not installed"
|
||||
# Check if docker compose is available
|
||||
if ! docker compose version &> /dev/null; then
|
||||
print_error "docker compose is not installed"
|
||||
exit 1
|
||||
fi
|
||||
print_success "docker-compose is available"
|
||||
print_success "docker compose is available"
|
||||
|
||||
echo ""
|
||||
}
|
||||
|
|
@ -142,17 +142,17 @@ deploy_backend() {
|
|||
|
||||
# Build images
|
||||
print_info "Building Docker images (this may take a few minutes)..."
|
||||
docker-compose $COMPOSE_FILES build --no-cache
|
||||
docker compose $COMPOSE_FILES build --no-cache
|
||||
print_success "Docker images built"
|
||||
|
||||
# Stop existing containers
|
||||
print_info "Stopping existing containers..."
|
||||
docker-compose $COMPOSE_FILES down
|
||||
docker compose $COMPOSE_FILES down
|
||||
print_success "Containers stopped"
|
||||
|
||||
# Start services
|
||||
print_info "Starting services..."
|
||||
docker-compose $COMPOSE_FILES up -d
|
||||
docker compose $COMPOSE_FILES up -d
|
||||
print_success "Services started"
|
||||
|
||||
# Wait for services to be healthy
|
||||
|
|
@ -160,9 +160,9 @@ deploy_backend() {
|
|||
sleep 10
|
||||
|
||||
# Check service health
|
||||
if docker-compose $COMPOSE_FILES ps | grep -q "unhealthy"; then
|
||||
if docker compose $COMPOSE_FILES ps | grep -q "unhealthy"; then
|
||||
print_error "Some services are unhealthy!"
|
||||
docker-compose $COMPOSE_FILES ps
|
||||
docker compose $COMPOSE_FILES ps
|
||||
exit 1
|
||||
fi
|
||||
print_success "All services are healthy"
|
||||
|
|
@ -217,7 +217,7 @@ run_migrations() {
|
|||
print_header "Running Database Migrations"
|
||||
|
||||
print_info "Running migrations..."
|
||||
docker-compose $COMPOSE_FILES exec -T api python migrate.py
|
||||
docker compose $COMPOSE_FILES exec -T api python migrate.py
|
||||
print_success "Migrations completed"
|
||||
|
||||
echo ""
|
||||
|
|
@ -231,7 +231,7 @@ display_status() {
|
|||
print_header "Deployment Status"
|
||||
|
||||
echo -e "${BLUE}Container Status:${NC}"
|
||||
docker-compose $COMPOSE_FILES ps
|
||||
docker compose $COMPOSE_FILES ps
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}Service URLs:${NC}"
|
||||
|
|
@ -243,10 +243,10 @@ display_status() {
|
|||
echo -e "${GREEN}Deployment completed successfully!${NC}"
|
||||
echo ""
|
||||
echo "To view logs:"
|
||||
echo " docker-compose $COMPOSE_FILES logs -f [service]"
|
||||
echo " docker compose $COMPOSE_FILES logs -f [service]"
|
||||
echo ""
|
||||
echo "To restart a service:"
|
||||
echo " docker-compose $COMPOSE_FILES restart [service]"
|
||||
echo " docker compose $COMPOSE_FILES restart [service]"
|
||||
echo ""
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue