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
925d5684
Commit
925d5684
authored
Jan 26, 2026
by
Kantz
Browse files
Mahtpix error und type handling.
parent
d9a5740d
Changes
4
Hide whitespace changes
Inline
Side-by-side
math-tutor/backend/app/api/canvas.py
View file @
925d5684
...
...
@@ -5,6 +5,8 @@ import time
from
pathlib
import
Path
from
typing
import
Optional
import
logging
from
app
import
config
from
fastapi
import
APIRouter
,
HTTPException
from
pydantic
import
BaseModel
,
Field
...
...
@@ -12,6 +14,8 @@ from mpxpy.mathpix_client import MathpixClient
router
=
APIRouter
()
logger
=
logging
.
getLogger
(
__name__
)
settings
=
config
.
get_mathpix_settings
()
mathpix_client
=
None
...
...
@@ -60,7 +64,16 @@ def save_canvas(request: CanvasSaveRequest) -> CanvasSaveResponse:
handle
.
write
(
raw
)
try
:
image
=
mathpix_client
.
image_new
(
str
(
file_path
))
image
=
mathpix_client
.
image_new
(
file_path
=
str
(
file_path
),
include_line_data
=
True
)
lines
=
image
.
lines_json
()
logger
.
info
(
"Mathpix lines: %s"
,
lines
)
line_type
=
lines
[
0
][
"type"
]
if
lines
else
None
if
line_type
!=
"math"
:
return
CanvasSaveResponse
(
status
=
"error"
,
latex
=
f
"Please provide a math-formula, you provided a
{
line_type
}
."
,
saved_as
=
str
(
file_path
),
)
mmd
=
image
.
mmd
()
conversion
=
mathpix_client
.
conversion_new
(
mmd
=
mmd
,
...
...
math-tutor/frontend/src/components/Canvas/CanvasDrawer.tsx
View file @
925d5684
...
...
@@ -6,6 +6,8 @@ type CanvasDrawerProps = {
onToggle
:
()
=>
void
;
onClear
?:
()
=>
void
;
onSave
?:
(
dataUrl
:
string
)
=>
void
|
Promise
<
void
>
;
statusMessage
?:
string
;
statusKind
?:
"
info
"
|
"
error
"
|
"
ok
"
;
};
export
default
function
CanvasDrawer
({
...
...
@@ -13,6 +15,8 @@ export default function CanvasDrawer({
onToggle
,
onClear
,
onSave
,
statusMessage
,
statusKind
,
}:
CanvasDrawerProps
)
{
const
canvasRef
=
useRef
<
HTMLCanvasElement
|
null
>
(
null
);
const
[
isDrawing
,
setIsDrawing
]
=
useState
(
false
);
...
...
@@ -135,6 +139,13 @@ export default function CanvasDrawer({
</
div
>
{
isVisible
?
(
<
div
className
=
"canvas-body"
>
{
statusMessage
?
(
<
div
className
=
{
`canvas-status
${
statusKind
?
statusKind
:
"
info
"
}
`
}
>
{
statusMessage
}
</
div
>
)
:
null
}
<
div
className
=
"canvas-surface"
>
<
canvas
ref
=
{
canvasRef
}
...
...
math-tutor/frontend/src/pages/App.tsx
View file @
925d5684
...
...
@@ -18,6 +18,10 @@ export default function App() {
const
[
sections
,
setSections
]
=
useState
<
RetrievedDoc
[]
>
([]);
const
[
retrievalLoading
,
setRetrievalLoading
]
=
useState
(
false
);
const
[
retrievalError
,
setRetrievalError
]
=
useState
<
string
|
null
>
(
null
);
const
[
canvasStatus
,
setCanvasStatus
]
=
useState
<
{
kind
:
"
info
"
|
"
error
"
|
"
ok
"
;
message
:
string
;
}
|
null
>
(
null
);
const
handleSend
=
async
()
=>
{
const
trimmed
=
draft
.
trim
();
...
...
@@ -106,15 +110,10 @@ export default function App() {
};
const
handleCanvasSave
=
async
(
dataUrl
:
string
)
=>
{
setMessages
((
prev
)
=>
[
...
prev
,
{
id
:
`m-
${
Date
.
now
()}
-assistant`
,
role
:
"
assistant
"
,
text
:
"
Saving drawing and converting to LaTeX...
"
,
},
]);
setIsCanvasVisible
(
false
);
setCanvasStatus
({
kind
:
"
info
"
,
message
:
"
Saving drawing and converting to LaTeX...
"
,
});
try
{
const
response
=
await
fetch
(
"
http://localhost:8000/api/canvas/save
"
,
{
...
...
@@ -124,24 +123,39 @@ export default function App() {
});
if
(
!
response
.
ok
)
{
throw
new
Error
(
`Save failed:
${
response
.
status
}
`
);
let
message
=
`Save failed:
${
response
.
status
}
`
;
try
{
const
errorPayload
:
{
detail
?:
string
}
=
await
response
.
json
();
if
(
errorPayload
.
detail
)
{
message
=
errorPayload
.
detail
;
}
}
catch
(
error
)
{
void
error
;
}
setCanvasStatus
({
kind
:
"
error
"
,
message
});
return
;
}
const
payload
:
{
latex
?:
string
}
=
await
response
.
json
();
const
payload
:
{
status
?:
string
;
latex
?:
string
}
=
await
response
.
json
();
if
(
payload
.
status
&&
payload
.
status
!==
"
ok
"
)
{
setCanvasStatus
({
kind
:
"
error
"
,
message
:
payload
.
latex
||
"
Canvas save failed.
"
,
});
return
;
}
if
(
payload
.
latex
)
{
setDraft
((
prev
)
=>
prev
?
`
${
prev
}
${
payload
.
latex
}
`
:
payload
.
latex
);
setCanvasStatus
({
kind
:
"
ok
"
,
message
:
"
Canvas saved.
"
});
setIsCanvasVisible
(
false
);
}
}
catch
(
error
)
{
setMessages
((
prev
)
=>
[
...
prev
,
{
id
:
`m-
${
Date
.
now
()}
-assistant`
,
role
:
"
assistant
"
,
text
:
"
Canvas save failed. Check the API logs.
"
,
},
]);
setCanvasStatus
({
kind
:
"
error
"
,
message
:
"
Canvas save failed. Check the API logs.
"
,
});
void
error
;
}
};
...
...
@@ -242,6 +256,8 @@ export default function App() {
isVisible
=
{
isCanvasVisible
}
onToggle
=
{
handleToggleCanvas
}
onSave
=
{
handleCanvasSave
}
statusMessage
=
{
canvasStatus
?.
message
}
statusKind
=
{
canvasStatus
?.
kind
}
/>
)
:
null
}
</
section
>
...
...
math-tutor/frontend/src/styles/theme.css
View file @
925d5684
...
...
@@ -204,6 +204,27 @@ body {
gap
:
12px
;
}
.canvas-status
{
padding
:
8px
10px
;
border-radius
:
10px
;
background
:
#f6f0e4
;
color
:
#6f675d
;
font-size
:
12px
;
border
:
1px
solid
#d8d1c4
;
}
.canvas-status.error
{
background
:
#f3d9d6
;
color
:
#8a3b2f
;
border-color
:
#e2b4ae
;
}
.canvas-status.ok
{
background
:
#dfe9d6
;
color
:
#2d5c2c
;
border-color
:
#b7c9ab
;
}
.canvas-surface
{
border
:
1px
dashed
#b9b2a4
;
border-radius
:
12px
;
...
...
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