merge: R4 TypeScript hardening H1-H6 — reduce errors 177→152 (resolve cc-graph-shapes/CCGraphNavPanel conflicts with R3)

This commit is contained in:
CC Worker 2026-06-01 02:38:50 +00:00
commit f7bb84f9b8
11 changed files with 43 additions and 24 deletions

View File

@ -23,6 +23,7 @@ export type LogCategory =
| 'neo-institute-context' | 'neo-institute-context'
| 'auth-service' | 'auth-service'
| 'graph-service' | 'graph-service'
| 'graph-sidebar'
| 'registration-service' | 'registration-service'
| 'provisioning-service' | 'provisioning-service'
| 'snapshot-service' | 'snapshot-service'

View File

@ -31,6 +31,7 @@ import {
} from '@mui/material'; } from '@mui/material';
import { import {
CloudUpload as UploadIcon, CloudUpload as UploadIcon,
Upload,
Folder as FolderIcon, Folder as FolderIcon,
FolderOpen as FolderOpenIcon, FolderOpen as FolderOpenIcon,
Description as FileIcon, Description as FileIcon,
@ -39,8 +40,12 @@ import {
PlayArrow as ProcessIcon, PlayArrow as ProcessIcon,
CheckCircle as SuccessIcon, CheckCircle as SuccessIcon,
Error as ErrorIcon, Error as ErrorIcon,
Info as InfoIcon Info as InfoIcon,
InsertDriveFile,
} from '@mui/icons-material'; } from '@mui/icons-material';
const FolderOpen = FolderOpenIcon;
const Refresh = RefreshIcon;
const Info = InfoIcon;
import { supabase } from '../../supabaseClient'; import { supabase } from '../../supabaseClient';
import { import {
pickDirectory, pickDirectory,

View File

@ -73,8 +73,9 @@ export function CCExportPdfButton({ editor, pdf }: CCExportPdfButtonProps) {
tickProgress(); tickProgress();
} }
const pdfBytes = await pdf.save();
const url = URL.createObjectURL( const url = URL.createObjectURL(
new Blob([await pdf.save()], { type: 'application/pdf' }) new Blob([pdfBytes.buffer as ArrayBuffer], { type: 'application/pdf' })
); );
tickProgress(); tickProgress();

View File

@ -17,10 +17,16 @@ export class CCTimetableLessonNodeShapeUtil extends CCBaseShapeUtil<CCTimetableL
getDefaultProps(): CCTimetableLessonNodeShape['props'] { getDefaultProps(): CCTimetableLessonNodeShape['props'] {
const defaultProps = getDefaultCCTimetableLessonNodeProps() const defaultProps = getDefaultCCTimetableLessonNodeProps()
const theme = NODE_THEMES[NODE_TYPE_THEMES[CCTimetableLessonNodeShapeUtil.type]]
return { return {
...defaultProps, ...defaultProps,
headerColor: theme.headerColor, headerColor: '',
school_db_name: '',
school_period_id: '',
subject_class: '',
date: '',
start_time: '',
end_time: '',
period_code: '',
} }
} }

View File

@ -543,6 +543,8 @@ export const getDefaultCCTimetableLessonNodeProps = () => ({
start_time: '', start_time: '',
end_time: '', end_time: '',
period_code: '', period_code: '',
school_db_name: '',
school_period_id: '',
}) })
export const getDefaultCCPlannedLessonNodeProps = () => ({ export const getDefaultCCPlannedLessonNodeProps = () => ({

View File

@ -22,7 +22,6 @@ import { CCSubjectNodeShape, CCSubjectNodeShapeUtil } from './CCSubjectNodeShape
import { CCTopicNodeShape, CCTopicNodeShapeUtil } from './CCTopicNodeShapeUtil' import { CCTopicNodeShape, CCTopicNodeShapeUtil } from './CCTopicNodeShapeUtil'
import { CCTopicLessonNodeShape, CCTopicLessonNodeShapeUtil } from './CCTopicLessonNodeShapeUtil' import { CCTopicLessonNodeShape, CCTopicLessonNodeShapeUtil } from './CCTopicLessonNodeShapeUtil'
import { CCLearningStatementNodeShape, CCLearningStatementNodeShapeUtil } from './CCLearningStatementNodeShapeUtil' import { CCLearningStatementNodeShape, CCLearningStatementNodeShapeUtil } from './CCLearningStatementNodeShapeUtil'
import { CCScienceLabNodeShape, CCScienceLabNodeShapeUtil } from './CCScienceLabNodeShapeUtil'
import { CCSchoolTimetableNodeShape, CCSchoolTimetableNodeShapeUtil } from './CCSchoolTimetableNodeShapeUtil' import { CCSchoolTimetableNodeShape, CCSchoolTimetableNodeShapeUtil } from './CCSchoolTimetableNodeShapeUtil'
import { CCAcademicYearNodeShape, CCAcademicYearNodeShapeUtil } from './CCAcademicYearNodeShapeUtil' import { CCAcademicYearNodeShape, CCAcademicYearNodeShapeUtil } from './CCAcademicYearNodeShapeUtil'
import { CCAcademicTermNodeShape, CCAcademicTermNodeShapeUtil } from './CCAcademicTermNodeShapeUtil' import { CCAcademicTermNodeShape, CCAcademicTermNodeShapeUtil } from './CCAcademicTermNodeShapeUtil'
@ -31,11 +30,11 @@ import { CCAcademicDayNodeShape, CCAcademicDayNodeShapeUtil } from './CCAcademic
import { CCAcademicPeriodNodeShape, CCAcademicPeriodNodeShapeUtil } from './CCAcademicPeriodNodeShapeUtil' import { CCAcademicPeriodNodeShape, CCAcademicPeriodNodeShapeUtil } from './CCAcademicPeriodNodeShapeUtil'
import { CCRegistrationPeriodNodeShape, CCRegistrationPeriodNodeShapeUtil } from './CCRegistrationPeriodNodeShapeUtil' import { CCRegistrationPeriodNodeShape, CCRegistrationPeriodNodeShapeUtil } from './CCRegistrationPeriodNodeShapeUtil'
import { CCTeacherTimetableNodeShape, CCTeacherTimetableNodeShapeUtil } from './CCTeacherTimetableNodeShapeUtil' import { CCTeacherTimetableNodeShape, CCTeacherTimetableNodeShapeUtil } from './CCTeacherTimetableNodeShapeUtil'
import { CCTimetableLessonNodeShape, CCTimetableLessonNodeShapeUtil } from './CCTimetableLessonNodeShapeUtil'
import { CCPlannedLessonNodeShape, CCPlannedLessonNodeShapeUtil } from './CCPlannedLessonNodeShapeUtil' import { CCPlannedLessonNodeShape, CCPlannedLessonNodeShapeUtil } from './CCPlannedLessonNodeShapeUtil'
import { CCDepartmentStructureNodeShape, CCDepartmentStructureNodeShapeUtil } from './CCDepartmentStructureNodeShapeUtil' import { CCDepartmentStructureNodeShape, CCDepartmentStructureNodeShapeUtil } from './CCDepartmentStructureNodeShapeUtil'
import { CCUserTeacherTimetableNodeShape, CCUserTeacherTimetableNodeShapeUtil } from './CCUserTeacherTimetableNodeShapeUtil' import { CCUserTeacherTimetableNodeShape, CCUserTeacherTimetableNodeShapeUtil } from './CCUserTeacherTimetableNodeShapeUtil'
import { CCTimetableLessonNodeShape, CCTimetableLessonNodeShapeUtil } from './CCUserTimetableLessonNodeShapeUtil'
import { CCScienceLabNodeShape, CCScienceLabNodeShapeUtil } from './CCScienceLabNodeShapeUtil'
// Create a const object with all node types // Create a const object with all node types
export const NODE_SHAPE_TYPES = { export const NODE_SHAPE_TYPES = {
USER: CCUserNodeShapeUtil.type, USER: CCUserNodeShapeUtil.type,

View File

@ -27,8 +27,8 @@ export class TranscriptionManager {
this.transcriptionService = new TranscriptionService(); this.transcriptionService = new TranscriptionService();
// Set up callback for transcription updates // Set up callback for transcription updates
this.transcriptionService.setTranscriptionCallback((text: string, isFinal: boolean, metadata: { start: number, end: number }) => { this.transcriptionService.setServerSegmentsCallback((segments: Array<{ text: string; start: number; end: number }>, isLastLive: boolean) => {
console.log('📝 Transcription update received:', { text, metadata }); console.log('📝 Transcription update received:', { segments: segments.length, isLastLive });
const util = this.editor.getShapeUtil<CCLiveTranscriptionShapeUtil>('cc-live-transcription'); const util = this.editor.getShapeUtil<CCLiveTranscriptionShapeUtil>('cc-live-transcription');
if (!util) { if (!util) {
console.warn('❌ Shape util not found'); console.warn('❌ Shape util not found');
@ -36,6 +36,10 @@ export class TranscriptionManager {
} }
console.log('Found transcription util:', !!util); console.log('Found transcription util:', !!util);
const text = segments.map(s => s.text).join('') || '';
const metadata = segments.length ? { start: segments[0].start, end: segments[segments.length - 1].end } : { start: 0, end: 0 };
const isFinal = isLastLive;
// Check if text is stable (same output multiple times) // Check if text is stable (same output multiple times)
const isStable = text === this.lastText; const isStable = text === this.lastText;
if (isStable) { if (isStable) {

View File

@ -200,7 +200,7 @@ export const CCExamMarkerPanel: React.FC<CCExamMarkerPanelProps> = ({
const pdfBytes = await newPdf.save(); const pdfBytes = await newPdf.save();
const url = URL.createObjectURL( const url = URL.createObjectURL(
new Blob([pdfBytes], { type: 'application/pdf' }) new Blob([pdfBytes] as unknown as BlobPart[], { type: 'application/pdf' })
); );
tickProgress(); tickProgress();
@ -297,7 +297,7 @@ export const CCExamMarkerPanel: React.FC<CCExamMarkerPanelProps> = ({
// Save the combined PDF // Save the combined PDF
const pdfBytes = await newPdf.save(); const pdfBytes = await newPdf.save();
const url = URL.createObjectURL(new Blob([pdfBytes], { type: 'application/pdf' })); const url = URL.createObjectURL(new Blob([pdfBytes] as unknown as BlobPart[], { type: 'application/pdf' }));
const a = document.createElement('a'); const a = document.createElement('a');
a.href = url; a.href = url;
a.download = currentPdf.name; a.download = currentPdf.name;

View File

@ -346,9 +346,10 @@ export const CCFilesPanelEnhanced: React.FC = () => {
ref={dirInputRef} ref={dirInputRef}
type="file" type="file"
style={{ display: 'none' }} style={{ display: 'none' }}
webkitdirectory=""
multiple multiple
onChange={handleFallbackDirectorySelect} onChange={handleFallbackDirectorySelect}
// @ts-ignore WebKit directory picker attribute for folder upload
webkitdirectory=""
/> />
<Tooltip title={isDirectoryPickerSupported() ? "Uses modern directory picker" : "Uses fallback method"}> <Tooltip title={isDirectoryPickerSupported() ? "Uses modern directory picker" : "Uses fallback method"}>

View File

@ -518,7 +518,7 @@ export function CCGraphNavPanel() {
const data = await res.json(); const data = await res.json();
setTree(data.tree); setTree(data.tree);
} catch (err) { } catch (err) {
logger.error('graph-panel', 'Failed to load graph tree', err); logger.error('navigation-panel', 'Failed to load graph tree', err);
setError('Failed to load navigation tree'); setError('Failed to load navigation tree');
} finally { } finally {
setLoading(false); setLoading(false);
@ -650,12 +650,12 @@ export function CCGraphNavPanel() {
}, []); }, []);
const handleCalendarWizardComplete = useCallback(() => { const handleCalendarWizardComplete = useCallback(() => {
logger.info('graph-panel', 'School calendar setup complete'); logger.info('navigation-panel', 'School calendar setup complete');
refreshAll(); refreshAll();
}, [refreshAll]); }, [refreshAll]);
const handleTimetableWizardComplete = useCallback((timetableId: string) => { const handleTimetableWizardComplete = useCallback((timetableId: string) => {
logger.info('graph-panel', 'Teacher timetable setup complete', { timetableId }); logger.info('navigation-panel', 'Teacher timetable setup complete', { timetableId });
refreshAll(); refreshAll();
}, [refreshAll]); }, [refreshAll]);

View File

@ -1,7 +1,7 @@
import React, { useCallback, useMemo, useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import { Box, Typography, styled, Button, ThemeProvider, createTheme, useMediaQuery } from '@mui/material'; import { Box, Typography, styled, Button, ThemeProvider, createTheme, useMediaQuery } from '@mui/material';
import Save from '@mui/icons-material/Save'; import Save from '@mui/icons-material/Save';
import Reset from '@mui/icons-material/RestartAlt'; import { RestartAlt } from '@mui/icons-material';
import { useEditor, useToasts, loadSnapshot } from '@tldraw/tldraw'; import { useEditor, useToasts, loadSnapshot } from '@tldraw/tldraw';
import { useNavigationStore } from '../../../../../../stores/navigationStore'; import { useNavigationStore } from '../../../../../../stores/navigationStore';
import { useAuth } from '../../../../../../contexts/AuthContext'; import { useAuth } from '../../../../../../contexts/AuthContext';