Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
math_tutor_dev
public_math_tutor
Commits
0893fd21
Commit
0893fd21
authored
Feb 18, 2026
by
Kantz
Browse files
Canvas größe verringert und deutsche Übersetztung hinzugefügt
parent
6ab334f1
Changes
10
Hide whitespace changes
Inline
Side-by-side
math-tutor/frontend/src/components/Canvas/CanvasDrawer.tsx
View file @
0893fd21
import
{
useEffect
,
useRef
,
useState
}
from
"
react
"
;
import
{
useEffect
,
useRef
,
useState
}
from
"
react
"
;
import
CanvasToggle
from
"
./CanvasToggle
"
;
import
CanvasToggle
from
"
./CanvasToggle
"
;
import
{
t
}
from
"
../../i18n
"
;
type
CanvasDrawerProps
=
{
type
CanvasDrawerProps
=
{
isVisible
:
boolean
;
isVisible
:
boolean
;
...
@@ -37,8 +38,8 @@ export default function CanvasDrawer({
...
@@ -37,8 +38,8 @@ export default function CanvasDrawer({
}
}
const
ratio
=
window
.
devicePixelRatio
||
1
;
const
ratio
=
window
.
devicePixelRatio
||
1
;
const
width
=
720
;
const
width
=
Math
.
min
(
560
,
window
.
innerWidth
-
80
)
;
const
height
=
32
0
;
const
height
=
15
0
;
canvas
.
width
=
width
*
ratio
;
canvas
.
width
=
width
*
ratio
;
canvas
.
height
=
height
*
ratio
;
canvas
.
height
=
height
*
ratio
;
...
@@ -134,7 +135,20 @@ export default function CanvasDrawer({
...
@@ -134,7 +135,20 @@ export default function CanvasDrawer({
return
(
return
(
<
div
className
=
"canvas-zone"
>
<
div
className
=
"canvas-zone"
>
<
div
className
=
"canvas-header"
>
<
div
className
=
"canvas-header"
>
<
div
className
=
"canvas-title"
>
Canvas
</
div
>
<
div
className
=
"canvas-title"
>
{
t
(
"
canvas
"
)
}
</
div
>
{
isVisible
?
(
<
div
className
=
"canvas-actions canvas-actions-header"
>
<
button
className
=
"btn"
type
=
"button"
onClick
=
{
handleToggleEraser
}
>
{
isErasing
?
t
(
"
pen
"
)
:
t
(
"
eraser
"
)
}
</
button
>
<
button
className
=
"btn"
type
=
"button"
onClick
=
{
handleClear
}
>
{
t
(
"
clear
"
)
}
</
button
>
<
button
className
=
"btn primary"
type
=
"button"
onClick
=
{
handleSave
}
>
{
t
(
"
saveAndConvert
"
)
}
</
button
>
</
div
>
)
:
null
}
<
CanvasToggle
isVisible
=
{
isVisible
}
onToggle
=
{
onToggle
}
/>
<
CanvasToggle
isVisible
=
{
isVisible
}
onToggle
=
{
onToggle
}
/>
</
div
>
</
div
>
{
isVisible
?
(
{
isVisible
?
(
...
@@ -156,20 +170,9 @@ export default function CanvasDrawer({
...
@@ -156,20 +170,9 @@ export default function CanvasDrawer({
onPointerLeave
=
{
handlePointerUp
}
onPointerLeave
=
{
handlePointerUp
}
/>
/>
</
div
>
</
div
>
<
div
className
=
"canvas-actions"
>
<
button
className
=
"btn"
type
=
"button"
onClick
=
{
handleToggleEraser
}
>
{
isErasing
?
"
Pen
"
:
"
Eraser
"
}
</
button
>
<
button
className
=
"btn"
type
=
"button"
onClick
=
{
handleClear
}
>
Clear
</
button
>
<
button
className
=
"btn primary"
type
=
"button"
onClick
=
{
handleSave
}
>
Save + Convert
</
button
>
</
div
>
</
div
>
</
div
>
)
:
(
)
:
(
<
div
className
=
"canvas-hidden"
>
C
anvas
h
idden
</
div
>
<
div
className
=
"canvas-hidden"
>
{
t
(
"
c
anvas
H
idden
"
)
}
</
div
>
)
}
)
}
</
div
>
</
div
>
);
);
...
...
math-tutor/frontend/src/components/Canvas/CanvasToggle.tsx
View file @
0893fd21
import
{
t
}
from
"
../../i18n
"
;
type
CanvasToggleProps
=
{
type
CanvasToggleProps
=
{
isVisible
:
boolean
;
isVisible
:
boolean
;
onToggle
:
()
=>
void
;
onToggle
:
()
=>
void
;
...
@@ -9,7 +11,7 @@ export default function CanvasToggle({
...
@@ -9,7 +11,7 @@ export default function CanvasToggle({
}:
CanvasToggleProps
)
{
}:
CanvasToggleProps
)
{
return
(
return
(
<
button
className
=
"btn"
type
=
"button"
onClick
=
{
onToggle
}
>
<
button
className
=
"btn"
type
=
"button"
onClick
=
{
onToggle
}
>
{
isVisible
?
"
H
ide
"
:
"
S
how
"
}
{
isVisible
?
t
(
"
h
ide
"
)
:
t
(
"
s
how
"
)
}
</
button
>
</
button
>
);
);
}
}
math-tutor/frontend/src/components/Chat/ChatWindow.tsx
View file @
0893fd21
...
@@ -2,6 +2,7 @@ import MessageInput from "./MessageInput";
...
@@ -2,6 +2,7 @@ import MessageInput from "./MessageInput";
import
MessageList
from
"
./MessageList
"
;
import
MessageList
from
"
./MessageList
"
;
import
type
{
ChatMessage
}
from
"
./MessageList
"
;
import
type
{
ChatMessage
}
from
"
./MessageList
"
;
import
type
{
RetrievedDoc
}
from
"
../Retrieval/DocPanel
"
;
import
type
{
RetrievedDoc
}
from
"
../Retrieval/DocPanel
"
;
import
{
t
}
from
"
../../i18n
"
;
type
ChatWindowProps
=
{
type
ChatWindowProps
=
{
messages
:
ChatMessage
[];
messages
:
ChatMessage
[];
...
@@ -26,7 +27,7 @@ export default function ChatWindow({
...
@@ -26,7 +27,7 @@ export default function ChatWindow({
}:
ChatWindowProps
)
{
}:
ChatWindowProps
)
{
return
(
return
(
<
div
className
=
"chat-window"
>
<
div
className
=
"chat-window"
>
<
div
className
=
"chat-title"
>
Chat
</
div
>
<
div
className
=
"chat-title"
>
{
t
(
"
chat
"
)
}
</
div
>
<
MessageList
<
MessageList
messages
=
{
messages
}
messages
=
{
messages
}
onInspectDoc
=
{
onInspectDoc
}
onInspectDoc
=
{
onInspectDoc
}
...
...
math-tutor/frontend/src/components/Chat/MessageBubble.tsx
View file @
0893fd21
import
{
useEffect
,
useRef
}
from
"
react
"
;
import
{
useEffect
,
useRef
}
from
"
react
"
;
import
ReactMarkdown
from
"
react-markdown
"
;
import
ReactMarkdown
from
"
react-markdown
"
;
import
type
{
RetrievedDoc
}
from
"
../Retrieval/DocPanel
"
;
import
type
{
RetrievedDoc
}
from
"
../Retrieval/DocPanel
"
;
import
{
t
}
from
"
../../i18n
"
;
type
MessageBubbleProps
=
{
type
MessageBubbleProps
=
{
role
:
"
user
"
|
"
assistant
"
;
role
:
"
user
"
|
"
assistant
"
;
...
@@ -48,7 +49,9 @@ export default function MessageBubble({
...
@@ -48,7 +49,9 @@ export default function MessageBubble({
return
(
return
(
<
div
className
=
{
`message-bubble
${
role
}
`
}
ref
=
{
bubbleRef
}
>
<
div
className
=
{
`message-bubble
${
role
}
`
}
ref
=
{
bubbleRef
}
>
<
div
className
=
"message-role"
>
{
role
}
</
div
>
<
div
className
=
"message-role"
>
{
role
===
"
user
"
?
t
(
"
roleUser
"
)
:
t
(
"
roleAssistant
"
)
}
</
div
>
<
div
className
=
"message-text"
>
<
div
className
=
"message-text"
>
<
ReactMarkdown
<
ReactMarkdown
components
=
{
{
components
=
{
{
...
...
math-tutor/frontend/src/components/Chat/MessageInput.tsx
View file @
0893fd21
import
{
EditPencil
,
Send
}
from
"
iconoir-react
"
;
import
{
EditPencil
,
Send
}
from
"
iconoir-react
"
;
import
{
t
}
from
"
../../i18n
"
;
type
MessageInputProps
=
{
type
MessageInputProps
=
{
value
:
string
;
value
:
string
;
...
@@ -22,8 +23,8 @@ export default function MessageInput({
...
@@ -22,8 +23,8 @@ export default function MessageInput({
className
=
"btn"
className
=
"btn"
type
=
"button"
type
=
"button"
onClick
=
{
onToggleCanvas
}
onClick
=
{
onToggleCanvas
}
aria-label
=
"D
raw"
aria-label
=
{
t
(
"
d
raw
"
)
}
title
=
"D
raw"
title
=
{
t
(
"
d
raw
"
)
}
>
>
<
EditPencil
width
=
{
18
}
height
=
{
18
}
aria-hidden
=
"true"
/>
<
EditPencil
width
=
{
18
}
height
=
{
18
}
aria-hidden
=
"true"
/>
</
button
>
</
button
>
...
@@ -32,15 +33,15 @@ export default function MessageInput({
...
@@ -32,15 +33,15 @@ export default function MessageInput({
type
=
"button"
type
=
"button"
onClick
=
{
onSend
}
onClick
=
{
onSend
}
disabled
=
{
!
canSend
}
disabled
=
{
!
canSend
}
aria-label
=
"S
end"
aria-label
=
{
t
(
"
s
end
"
)
}
title
=
"S
end"
title
=
{
t
(
"
s
end
"
)
}
>
>
<
Send
width
=
{
18
}
height
=
{
18
}
aria-hidden
=
"true"
/>
<
Send
width
=
{
18
}
height
=
{
18
}
aria-hidden
=
"true"
/>
</
button
>
</
button
>
</
div
>
</
div
>
<
textarea
<
textarea
className
=
"composer-input"
className
=
"composer-input"
placeholder
=
"Type your question or paste LaTeX..."
placeholder
=
{
t
(
"
typeQuestionOrLatex
"
)
}
rows
=
{
3
}
rows
=
{
3
}
value
=
{
value
}
value
=
{
value
}
onChange
=
{
(
event
)
=>
onChange
(
event
.
target
.
value
)
}
onChange
=
{
(
event
)
=>
onChange
(
event
.
target
.
value
)
}
...
...
math-tutor/frontend/src/components/Retrieval/DocCard.tsx
View file @
0893fd21
import
{
useEffect
,
useRef
}
from
"
react
"
;
import
{
useEffect
,
useRef
}
from
"
react
"
;
import
ReactMarkdown
from
"
react-markdown
"
;
import
ReactMarkdown
from
"
react-markdown
"
;
import
{
t
}
from
"
../../i18n
"
;
declare
global
{
declare
global
{
interface
Window
{
interface
Window
{
...
@@ -63,10 +64,10 @@ export default function DocCard({
...
@@ -63,10 +64,10 @@ export default function DocCard({
</
div
>
</
div
>
<
div
className
=
"doc-actions"
>
<
div
className
=
"doc-actions"
>
<
button
className
=
"btn small"
type
=
"button"
onClick
=
{
onInspect
}
>
<
button
className
=
"btn small"
type
=
"button"
onClick
=
{
onInspect
}
>
I
nspect
{
t
(
"
i
nspect
"
)
}
</
button
>
</
button
>
<
button
className
=
"btn small"
type
=
"button"
onClick
=
{
onCite
}
>
<
button
className
=
"btn small"
type
=
"button"
onClick
=
{
onCite
}
>
Cite
{
t
(
"
cite
"
)
}
</
button
>
</
button
>
</
div
>
</
div
>
</
details
>
</
details
>
...
...
math-tutor/frontend/src/components/Retrieval/DocPanel.tsx
View file @
0893fd21
import
DocCard
from
"
./DocCard
"
;
import
DocCard
from
"
./DocCard
"
;
import
{
t
}
from
"
../../i18n
"
;
export
type
RetrievedDoc
=
{
export
type
RetrievedDoc
=
{
uid
:
string
;
uid
:
string
;
...
@@ -37,7 +38,7 @@ const buildTitle = (doc: RetrievedDoc) => {
...
@@ -37,7 +38,7 @@ const buildTitle = (doc: RetrievedDoc) => {
meta
.
subsection_title
||
meta
.
subsection_title
||
meta
.
section_title
||
meta
.
section_title
||
meta
.
path
||
meta
.
path
||
"
U
ntitled
"
t
(
"
u
ntitled
"
)
);
);
};
};
...
@@ -113,16 +114,16 @@ export default function DocPanel({
...
@@ -113,16 +114,16 @@ export default function DocPanel({
return
(
return
(
<
div
className
=
"retrieval-panel"
>
<
div
className
=
"retrieval-panel"
>
<
div
className
=
"retrieval-title"
>
R
etrieved
Notes
</
div
>
<
div
className
=
"retrieval-title"
>
{
t
(
"
r
etrievedNotes
"
)
}
</
div
>
{
isLoading
?
<
div
className
=
"retrieval-state"
>
L
oading
...
</
div
>
:
null
}
{
isLoading
?
<
div
className
=
"retrieval-state"
>
{
t
(
"
l
oading
"
)
}
</
div
>
:
null
}
{
error
?
<
div
className
=
"retrieval-state error"
>
{
error
}
</
div
>
:
null
}
{
error
?
<
div
className
=
"retrieval-state error"
>
{
error
}
</
div
>
:
null
}
{
!
isLoading
&&
!
error
&&
total
===
0
?
(
{
!
isLoading
&&
!
error
&&
total
===
0
?
(
<
div
className
=
"retrieval-state"
>
No results yet.
</
div
>
<
div
className
=
"retrieval-state"
>
{
t
(
"
noResultsYet
"
)
}
</
div
>
)
:
null
}
)
:
null
}
{
renderGroup
(
"
D
irect
c
hildren
"
,
directChildren
,
onCiteDoc
,
onInspectDoc
)
}
{
renderGroup
(
t
(
"
d
irect
C
hildren
"
)
,
directChildren
,
onCiteDoc
,
onInspectDoc
)
}
{
renderGroup
(
"
I
ndirect
c
hildren
"
,
indirectChildren
,
onCiteDoc
,
onInspectDoc
)
}
{
renderGroup
(
t
(
"
i
ndirect
C
hildren
"
)
,
indirectChildren
,
onCiteDoc
,
onInspectDoc
)
}
{
renderGroup
(
"
S
ubsection
s
ummary
"
,
subsections
,
onCiteDoc
,
onInspectDoc
)
}
{
renderGroup
(
t
(
"
s
ubsection
S
ummary
"
)
,
subsections
,
onCiteDoc
,
onInspectDoc
)
}
{
renderGroup
(
"
S
ection
s
ummary
"
,
sections
,
onCiteDoc
,
onInspectDoc
)
}
{
renderGroup
(
t
(
"
s
ection
S
ummary
"
)
,
sections
,
onCiteDoc
,
onInspectDoc
)
}
</
div
>
</
div
>
);
);
}
}
math-tutor/frontend/src/i18n.ts
0 → 100644
View file @
0893fd21
const
translations
=
{
en
:
{
chats
:
"
Chats
"
,
prototypeWorkspace
:
"
Prototype Workspace
"
,
task
:
"
Task
"
,
chat
:
"
Chat
"
,
canvas
:
"
Canvas
"
,
retrievedNotes
:
"
Retrieved Notes
"
,
typeQuestionOrLatex
:
"
Type your question or paste LaTeX...
"
,
noResultsYet
:
"
No results yet.
"
,
eraser
:
"
Eraser
"
,
pen
:
"
Pen
"
,
clear
:
"
Clear
"
,
saveAndConvert
:
"
Save + Convert
"
,
hide
:
"
Hide
"
,
show
:
"
Show
"
,
newChat
:
"
New Chat
"
,
loading
:
"
Loading...
"
,
directChildren
:
"
Direct children
"
,
indirectChildren
:
"
Indirect children
"
,
subsectionSummary
:
"
Subsection summary
"
,
sectionSummary
:
"
Section summary
"
,
untitled
:
"
Untitled
"
,
inspect
:
"
Inspect
"
,
cite
:
"
Cite
"
,
draw
:
"
Draw
"
,
send
:
"
Send
"
,
roleUser
:
"
user
"
,
roleAssistant
:
"
assistant
"
,
noTasksAvailable
:
"
No tasks available
"
,
noTaskSelected
:
"
No task selected.
"
,
savedChats
:
"
Saved Chats
"
,
saving
:
"
Saving...
"
,
noSavedChatsYet
:
"
No saved chats yet.
"
,
canvasHidden
:
"
Canvas hidden
"
,
failedLoadTasks
:
"
Could not load tasks.
"
,
chatRequestFailed
:
"
The chat request failed. Please check backend logs.
"
,
retrievalFailed
:
"
Source retrieval failed. Please check backend logs.
"
,
failedLoadSavedChats
:
"
Could not load saved chats.
"
,
failedLoadSelectedChat
:
"
Could not load the selected chat.
"
,
savingDrawingConverting
:
"
Saving drawing and converting to LaTeX...
"
,
saveFailedStatus
:
"
Saving failed (status: {status}).
"
,
canvasSaveFailed
:
"
Saving the canvas failed.
"
,
canvasSaved
:
"
Canvas saved.
"
,
canvasSaveFailedCheckLogs
:
"
Saving the canvas failed. Please check backend logs.
"
,
},
de
:
{
chats
:
"
Chats
"
,
prototypeWorkspace
:
"
Prototyp-Arbeitsbereich
"
,
task
:
"
Aufgabe
"
,
chat
:
"
Chat
"
,
canvas
:
"
Canvas
"
,
retrievedNotes
:
"
Quellen
"
,
typeQuestionOrLatex
:
"
Gebe hier deine Frage ein. Nutze $ $ für mathematische Eingaben...
"
,
noResultsYet
:
"
bisher keine Quellen
"
,
eraser
:
"
Radierer
"
,
pen
:
"
Stift
"
,
clear
:
"
Leeren
"
,
saveAndConvert
:
"
Speichern + Konvertieren
"
,
hide
:
"
verstecken
"
,
show
:
"
anzeigen
"
,
newChat
:
"
neuer Chat
"
,
loading
:
"
Lade...
"
,
directChildren
:
"
Direkte Quellen
"
,
indirectChildren
:
"
Indirekte Quellen
"
,
subsectionSummary
:
"
Unterabschnitt-Zusammenfassung
"
,
sectionSummary
:
"
Abschnitt-Zusammenfassung
"
,
untitled
:
"
Ohne Titel
"
,
inspect
:
"
Ansehen
"
,
cite
:
"
Zitieren
"
,
draw
:
"
Zeichnen
"
,
send
:
"
Senden
"
,
roleUser
:
"
nutzer
"
,
roleAssistant
:
"
assistent
"
,
noTasksAvailable
:
"
Keine Aufgaben verfuegbar
"
,
noTaskSelected
:
"
Keine Aufgabe ausgewaehlt.
"
,
savedChats
:
"
Gespeicherte Chats
"
,
saving
:
"
Speichere...
"
,
noSavedChatsYet
:
"
Noch keine gespeicherten Chats.
"
,
canvasHidden
:
"
Canvas ausgeblendet
"
,
failedLoadTasks
:
"
Aufgaben konnten nicht geladen werden.
"
,
chatRequestFailed
:
"
Chat-Anfrage ist fehlgeschlagen. Bitte pruefe die Backend-Logs.
"
,
retrievalFailed
:
"
Quellenabruf ist fehlgeschlagen. Bitte pruefe die Backend-Logs.
"
,
failedLoadSavedChats
:
"
Gespeicherte Chats konnten nicht geladen werden.
"
,
failedLoadSelectedChat
:
"
Der ausgewaehlte Chat konnte nicht geladen werden.
"
,
savingDrawingConverting
:
"
Zeichnung wird gespeichert und in LaTeX konvertiert...
"
,
saveFailedStatus
:
"
Speichern fehlgeschlagen (Status: {status}).
"
,
canvasSaveFailed
:
"
Speichern des Canvas fehlgeschlagen.
"
,
canvasSaved
:
"
Canvas gespeichert.
"
,
canvasSaveFailedCheckLogs
:
"
Speichern des Canvas fehlgeschlagen. Bitte pruefe die Backend-Logs.
"
,
},
}
as
const
;
type
Language
=
keyof
typeof
translations
;
type
TranslationKey
=
keyof
(
typeof
translations
)[
"
en
"
];
const
envLanguage
=
String
(
import
.
meta
.
env
.
VITE_FRONTEND_LANG
||
"
en
"
)
.
trim
()
.
toLowerCase
();
export
const
language
:
Language
=
envLanguage
.
startsWith
(
"
de
"
)
?
"
de
"
:
"
en
"
;
export
const
t
=
(
key
:
TranslationKey
,
vars
?:
Record
<
string
,
string
|
number
>
):
string
=>
{
let
value
:
string
=
translations
[
language
][
key
]
||
translations
.
en
[
key
];
if
(
!
vars
)
{
return
value
;
}
Object
.
entries
(
vars
).
forEach
(([
name
,
raw
])
=>
{
value
=
value
.
replaceAll
(
`{
${
name
}
}`
,
String
(
raw
));
});
return
value
;
};
math-tutor/frontend/src/pages/App.tsx
View file @
0893fd21
...
@@ -5,6 +5,7 @@ import CanvasDrawer from "../components/Canvas/CanvasDrawer";
...
@@ -5,6 +5,7 @@ import CanvasDrawer from "../components/Canvas/CanvasDrawer";
import
DocPanel
from
"
../components/Retrieval/DocPanel
"
;
import
DocPanel
from
"
../components/Retrieval/DocPanel
"
;
import
type
{
ChatMessage
}
from
"
../components/Chat/MessageList
"
;
import
type
{
ChatMessage
}
from
"
../components/Chat/MessageList
"
;
import
type
{
RetrievedDoc
}
from
"
../components/Retrieval/DocPanel
"
;
import
type
{
RetrievedDoc
}
from
"
../components/Retrieval/DocPanel
"
;
import
{
t
}
from
"
../i18n
"
;
const
backendUrl
=
import
.
meta
.
env
.
VITE_BACKEND_URL
||
"
http://localhost:8000
"
;
const
backendUrl
=
import
.
meta
.
env
.
VITE_BACKEND_URL
||
"
http://localhost:8000
"
;
...
@@ -252,7 +253,7 @@ export default function App() {
...
@@ -252,7 +253,7 @@ export default function App() {
if
(
!
isActive
)
{
if
(
!
isActive
)
{
return
;
return
;
}
}
setTasksError
(
"
F
ailed
to l
oad
t
asks
.
"
);
setTasksError
(
t
(
"
f
ailed
L
oad
T
asks
"
)
);
setIsTaskModeEnabled
(
false
);
setIsTaskModeEnabled
(
false
);
setTaskFiles
([]);
setTaskFiles
([]);
setSelectedTaskRef
(
null
);
setSelectedTaskRef
(
null
);
...
@@ -349,13 +350,14 @@ export default function App() {
...
@@ -349,13 +350,14 @@ export default function App() {
}
}
const
payload
:
{
reply
?:
string
}
=
await
response
.
json
();
const
payload
:
{
reply
?:
string
}
=
await
response
.
json
();
if
(
payload
.
reply
)
{
const
reply
=
payload
.
reply
;
if
(
typeof
reply
===
"
string
"
&&
reply
.
length
>
0
)
{
setMessages
((
prev
)
=>
[
setMessages
((
prev
)
=>
[
...
prev
,
...
prev
,
{
{
id
:
`m-
${
Date
.
now
()}
-assistant`
,
id
:
`m-
${
Date
.
now
()}
-assistant`
,
role
:
"
assistant
"
,
role
:
"
assistant
"
,
text
:
payload
.
reply
,
text
:
reply
,
},
},
]);
]);
}
}
...
@@ -365,10 +367,10 @@ export default function App() {
...
@@ -365,10 +367,10 @@ export default function App() {
{
{
id
:
`m-
${
Date
.
now
()}
-assistant`
,
id
:
`m-
${
Date
.
now
()}
-assistant`
,
role
:
"
assistant
"
,
role
:
"
assistant
"
,
text
:
"
C
hat
r
equest
f
ailed
. Check the API logs.
"
,
text
:
t
(
"
c
hat
R
equest
F
ailed
"
)
,
},
},
]);
]);
setRetrievalError
(
"
R
etrieval
f
ailed
. Check the API logs.
"
);
setRetrievalError
(
t
(
"
r
etrieval
F
ailed
"
)
);
setRetrievalLoading
(
false
);
setRetrievalLoading
(
false
);
void
error
;
void
error
;
return
;
return
;
...
@@ -425,7 +427,7 @@ export default function App() {
...
@@ -425,7 +427,7 @@ export default function App() {
setSubsections
(
nextSubsections
);
setSubsections
(
nextSubsections
);
setSections
(
nextSections
);
setSections
(
nextSections
);
}
catch
(
error
)
{
}
catch
(
error
)
{
setRetrievalError
(
"
R
etrieval
f
ailed
. Check the API logs.
"
);
setRetrievalError
(
t
(
"
r
etrieval
F
ailed
"
)
);
void
error
;
void
error
;
}
finally
{
}
finally
{
setRetrievalLoading
(
false
);
setRetrievalLoading
(
false
);
...
@@ -472,7 +474,7 @@ export default function App() {
...
@@ -472,7 +474,7 @@ export default function App() {
setSelectedArchiveId
(
payload
[
0
].
chat_id
);
setSelectedArchiveId
(
payload
[
0
].
chat_id
);
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
setArchiveError
(
"
F
ailed
to l
oad
s
aved
c
hats
.
"
);
setArchiveError
(
t
(
"
f
ailed
L
oad
S
aved
C
hats
"
)
);
void
error
;
void
error
;
}
}
};
};
...
@@ -495,7 +497,7 @@ export default function App() {
...
@@ -495,7 +497,7 @@ export default function App() {
setMessages
(
payload
.
history
||
[]);
setMessages
(
payload
.
history
||
[]);
setChatSessionId
(
payload
.
chat_id
);
setChatSessionId
(
payload
.
chat_id
);
}
catch
(
error
)
{
}
catch
(
error
)
{
setArchiveError
(
"
F
ailed
to l
oad
s
elected
c
hat
.
"
);
setArchiveError
(
t
(
"
f
ailed
L
oad
S
elected
C
hat
"
)
);
void
error
;
void
error
;
}
}
};
};
...
@@ -535,7 +537,7 @@ export default function App() {
...
@@ -535,7 +537,7 @@ export default function App() {
const
handleCanvasSave
=
async
(
dataUrl
:
string
)
=>
{
const
handleCanvasSave
=
async
(
dataUrl
:
string
)
=>
{
setCanvasStatus
({
setCanvasStatus
({
kind
:
"
info
"
,
kind
:
"
info
"
,
message
:
"
S
aving
d
rawing
and c
onverting
to LaTeX...
"
,
message
:
t
(
"
s
aving
D
rawing
C
onverting
"
)
,
});
});
try
{
try
{
...
@@ -546,7 +548,7 @@ export default function App() {
...
@@ -546,7 +548,7 @@ export default function App() {
});
});
if
(
!
response
.
ok
)
{
if
(
!
response
.
ok
)
{
let
message
=
`S
ave
f
ailed:
${
response
.
status
}
`
;
let
message
=
t
(
"
s
ave
F
ailed
Status
"
,
{
status
:
response
.
status
})
;
try
{
try
{
const
errorPayload
:
{
detail
?:
string
}
=
await
response
.
json
();
const
errorPayload
:
{
detail
?:
string
}
=
await
response
.
json
();
if
(
errorPayload
.
detail
)
{
if
(
errorPayload
.
detail
)
{
...
@@ -563,21 +565,20 @@ export default function App() {
...
@@ -563,21 +565,20 @@ export default function App() {
if
(
payload
.
status
&&
payload
.
status
!==
"
ok
"
)
{
if
(
payload
.
status
&&
payload
.
status
!==
"
ok
"
)
{
setCanvasStatus
({
setCanvasStatus
({
kind
:
"
error
"
,
kind
:
"
error
"
,
message
:
payload
.
latex
||
"
C
anvas
s
ave
f
ailed
.
"
,
message
:
payload
.
latex
||
t
(
"
c
anvas
S
ave
F
ailed
"
)
,
});
});
return
;
return
;
}
}
if
(
payload
.
latex
)
{
const
latex
=
payload
.
latex
;
setDraft
((
prev
)
=>
if
(
typeof
latex
===
"
string
"
&&
latex
.
length
>
0
)
{
prev
?
`
${
prev
}
${
payload
.
latex
}
`
:
payload
.
latex
setDraft
((
prev
)
=>
(
prev
?
`
${
prev
}
${
latex
}
`
:
latex
));
);
setCanvasStatus
({
kind
:
"
ok
"
,
message
:
t
(
"
canvasSaved
"
)
});
setCanvasStatus
({
kind
:
"
ok
"
,
message
:
"
Canvas saved.
"
});
setIsCanvasVisible
(
false
);
setIsCanvasVisible
(
false
);
}
}
}
catch
(
error
)
{
}
catch
(
error
)
{
setCanvasStatus
({
setCanvasStatus
({
kind
:
"
error
"
,
kind
:
"
error
"
,
message
:
"
C
anvas
s
ave
f
ailed
.
Check
the API l
ogs
.
"
,
message
:
t
(
"
c
anvas
S
ave
F
ailedCheck
L
ogs
"
)
,
});
});
void
error
;
void
error
;
}
}
...
@@ -593,7 +594,7 @@ export default function App() {
...
@@ -593,7 +594,7 @@ export default function App() {
doc
.
metadata
.
subsection_title
||
doc
.
metadata
.
subsection_title
||
doc
.
metadata
.
section_title
||
doc
.
metadata
.
section_title
||
doc
.
metadata
.
path
||
doc
.
metadata
.
path
||
"
Document
"
;
t
(
"
untitled
"
)
;
const
html
=
`<!doctype html>
const
html
=
`<!doctype html>
<html lang="en">
<html lang="en">
...
@@ -655,13 +656,13 @@ export default function App() {
...
@@ -655,13 +656,13 @@ export default function App() {
className
=
"btn sidebar-toggle"
className
=
"btn sidebar-toggle"
onClick
=
{
handleOpenSidebar
}
onClick
=
{
handleOpenSidebar
}
>
>
C
hats
{
t
(
"
c
hats
"
)
}
</
button
>
</
button
>
<
div
className
=
"brand"
>
<
div
className
=
"brand"
>
<
span
className
=
"brand-mark"
>
SUM
</
span
>
<
span
className
=
"brand-mark"
>
SUM
</
span
>
<
div
className
=
"brand-text"
>
<
div
className
=
"brand-text"
>
<
div
className
=
"brand-title"
>
Math Tutor
</
div
>
<
div
className
=
"brand-title"
>
Math Tutor
</
div
>
<
div
className
=
"brand-subtitle"
>
P
rototype
Workspace
</
div
>
<
div
className
=
"brand-subtitle"
>
{
t
(
"
p
rototypeWorkspace
"
)
}
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className
=
"header-meta"
>
<
div
className
=
"header-meta"
>
...
@@ -676,7 +677,7 @@ export default function App() {
...
@@ -676,7 +677,7 @@ export default function App() {
{
isTaskModeEnabled
?
(
{
isTaskModeEnabled
?
(
<
section
className
=
"task-panel"
>
<
section
className
=
"task-panel"
>
<
div
className
=
"task-panel-header"
>
<
div
className
=
"task-panel-header"
>
<
div
className
=
"task-panel-title"
>
Task
</
div
>
<
div
className
=
"task-panel-title"
>
{
t
(
"
task
"
)
}
</
div
>
<
select
<
select
className
=
"task-select"
className
=
"task-select"
value
=
{
value
=
{
...
@@ -694,12 +695,12 @@ export default function App() {
...
@@ -694,12 +695,12 @@ export default function App() {
</
option
>
</
option
>
))
))
)
:
(
)
:
(
<
option
value
=
""
>
No t
asks
a
vailable
</
option
>
<
option
value
=
""
>
{
t
(
"
noT
asks
A
vailable
"
)
}
</
option
>
)
}
)
}
</
select
>
</
select
>
</
div
>
</
div
>
<
div
className
=
"task-panel-content"
ref
=
{
taskDisplayRef
}
>
<
div
className
=
"task-panel-content"
ref
=
{
taskDisplayRef
}
>
{
selectedTask
?.
fullText
||
"
No t
ask
s
elected
.
"
}
{
selectedTask
?.
fullText
||
t
(
"
noT
ask
S
elected
"
)
}
</
div
>
</
div
>
{
tasksError
?
<
div
className
=
"task-panel-error"
>
{
tasksError
}
</
div
>
:
null
}
{
tasksError
?
<
div
className
=
"task-panel-error"
>
{
tasksError
}
</
div
>
:
null
}
</
section
>
</
section
>
...
@@ -742,7 +743,7 @@ export default function App() {
...
@@ -742,7 +743,7 @@ export default function App() {
</
main
>
</
main
>
<
div
className
=
{
`sidebar
${
isSidebarOpen
?
"
active
"
:
""
}
`
}
>
<
div
className
=
{
`sidebar
${
isSidebarOpen
?
"
active
"
:
""
}
`
}
>
<
div
className
=
"sd-header"
>
<
div
className
=
"sd-header"
>
<
h4
className
=
"sd-title"
>
S
aved
Chats
</
h4
>
<
h4
className
=
"sd-title"
>
{
t
(
"
s
avedChats
"
)
}
</
h4
>
<
button
<
button
type
=
"button"
type
=
"button"
className
=
"sidebar-button"
className
=
"sidebar-button"
...
@@ -760,7 +761,7 @@ export default function App() {
...
@@ -760,7 +761,7 @@ export default function App() {
onClick
=
{
handleNewChat
}
onClick
=
{
handleNewChat
}
disabled
=
{
isArchiving
}
disabled
=
{
isArchiving
}
>
>
{
isArchiving
?
"
S
aving
...
"
:
"
N
ew
Chat
"
}
{
isArchiving
?
t
(
"
s
aving
"
)
:
t
(
"
n
ewChat
"
)
}
</
button
>
</
button
>
</
li
>
</
li
>
<
li
>
<
li
>
...
@@ -785,7 +786,7 @@ export default function App() {
...
@@ -785,7 +786,7 @@ export default function App() {
))
))
)
:
(
)
:
(
<
li
>
<
li
>
<
div
className
=
"sd-empty"
>
No s
aved
c
hats
yet.
</
div
>
<
div
className
=
"sd-empty"
>
{
t
(
"
noS
aved
C
hats
Yet
"
)
}
</
div
>
</
li
>
</
li
>
)
}
)
}
</
ul
>
</
ul
>
...
...
math-tutor/frontend/src/styles/theme.css
View file @
0893fd21
...
@@ -366,13 +366,14 @@ body {
...
@@ -366,13 +366,14 @@ body {
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
gap
:
12px
;
gap
:
12px
;
flex
:
0
0
320px
;
flex
:
0
0
auto
;
}
}
.canvas-header
{
.canvas-header
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
justify-content
:
space-between
;
gap
:
8px
;
flex-wrap
:
wrap
;
}
}
.canvas-body
{
.canvas-body
{
...
@@ -411,8 +412,8 @@ body {
...
@@ -411,8 +412,8 @@ body {
.canvas-board
{
.canvas-board
{
width
:
100%
;
width
:
100%
;
height
:
10
0%
;
height
:
6
0%
;
min-height
:
2
00px
;
min-height
:
1
00px
;
display
:
block
;
display
:
block
;
cursor
:
crosshair
;
cursor
:
crosshair
;
}
}
...
@@ -420,6 +421,11 @@ body {
...
@@ -420,6 +421,11 @@ body {
.canvas-actions
{
.canvas-actions
{
display
:
flex
;
display
:
flex
;
gap
:
8px
;
gap
:
8px
;
flex-wrap
:
wrap
;
}
.canvas-actions-header
{
margin-left
:
auto
;
}
}
.canvas-hidden
{
.canvas-hidden
{
...
@@ -549,7 +555,7 @@ body {
...
@@ -549,7 +555,7 @@ body {
flex
:
1
1
120px
;
flex
:
1
1
120px
;
}
}
.canvas-actions
{
.canvas-actions
-header
{
flex-direction
:
column
;
margin-left
:
0
;
}
}
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment