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
2e26ac93
Commit
2e26ac93
authored
Apr 14, 2026
by
Kantz
Browse files
chat deaktiviert während das LLM läd
parent
2fbf0a51
Changes
5
Hide whitespace changes
Inline
Side-by-side
math-tutor/frontend/src/components/Chat/ChatWindow.tsx
View file @
2e26ac93
...
...
@@ -9,6 +9,7 @@ type ChatWindowProps = {
draft
:
string
;
onDraftChange
:
(
value
:
string
)
=>
void
;
onSend
:
()
=>
void
;
isSending
?:
boolean
;
onHistoryNavigate
?:
(
direction
:
"
older
"
|
"
newer
"
)
=>
boolean
;
onToggleCanvas
?:
()
=>
void
;
onUploadSolution
?:
(
file
:
File
)
=>
void
|
Promise
<
void
>
;
...
...
@@ -22,6 +23,7 @@ export default function ChatWindow({
draft
,
onDraftChange
,
onSend
,
isSending
=
false
,
onHistoryNavigate
,
onToggleCanvas
,
onUploadSolution
,
...
...
@@ -42,6 +44,7 @@ export default function ChatWindow({
value
=
{
draft
}
onChange
=
{
onDraftChange
}
onSend
=
{
onSend
}
isSending
=
{
isSending
}
onHistoryNavigate
=
{
onHistoryNavigate
}
onToggleCanvas
=
{
onToggleCanvas
}
onUploadSolution
=
{
onUploadSolution
}
...
...
math-tutor/frontend/src/components/Chat/MessageBubble.tsx
View file @
2e26ac93
...
...
@@ -50,10 +50,6 @@ export default function MessageBubble({
const
hasThinking
=
Boolean
(
thinkingText
);
useEffect
(()
=>
{
setIsThinkingExpanded
(
false
);
},
[
text
]);
const
renderMarkdown
=
(
value
:
string
)
=>
(
<
ReactMarkdown
urlTransform
=
{
(
url
)
=>
{
...
...
math-tutor/frontend/src/components/Chat/MessageInput.tsx
View file @
2e26ac93
...
...
@@ -6,6 +6,7 @@ type MessageInputProps = {
value
:
string
;
onChange
:
(
value
:
string
)
=>
void
;
onSend
:
()
=>
void
;
isSending
?:
boolean
;
onHistoryNavigate
?:
(
direction
:
"
older
"
|
"
newer
"
)
=>
boolean
;
onToggleCanvas
?:
()
=>
void
;
onUploadSolution
?:
(
file
:
File
)
=>
void
|
Promise
<
void
>
;
...
...
@@ -15,6 +16,7 @@ export default function MessageInput({
value
,
onChange
,
onSend
,
isSending
=
false
,
onHistoryNavigate
,
onToggleCanvas
,
onUploadSolution
,
...
...
@@ -44,6 +46,7 @@ export default function MessageInput({
className
=
"btn"
type
=
"button"
onClick
=
{
onToggleCanvas
}
disabled
=
{
isSending
}
aria-label
=
{
t
(
"
draw
"
)
}
title
=
{
t
(
"
draw
"
)
}
>
...
...
@@ -53,6 +56,7 @@ export default function MessageInput({
className
=
"btn"
type
=
"button"
onClick
=
{
handleUploadClick
}
disabled
=
{
isSending
}
aria-label
=
{
t
(
"
uploadSolution
"
)
}
title
=
{
t
(
"
uploadSolution
"
)
}
>
...
...
@@ -69,11 +73,19 @@ export default function MessageInput({
className
=
"btn primary"
type
=
"button"
onClick
=
{
onSend
}
disabled
=
{
!
canSend
}
disabled
=
{
!
canSend
||
isSending
}
aria-label
=
{
t
(
"
send
"
)
}
title
=
{
t
(
"
send
"
)
}
>
<
Send
width
=
{
18
}
height
=
{
18
}
aria-hidden
=
"true"
/>
{
isSending
?
(
<
span
className
=
"composer-loading"
aria-hidden
=
"true"
>
<
span
/>
<
span
/>
<
span
/>
</
span
>
)
:
(
<
Send
width
=
{
18
}
height
=
{
18
}
aria-hidden
=
"true"
/>
)
}
</
button
>
</
div
>
<
textarea
...
...
@@ -81,8 +93,14 @@ export default function MessageInput({
placeholder
=
{
t
(
"
typeQuestionOrLatex
"
)
}
rows
=
{
3
}
value
=
{
value
}
disabled
=
{
isSending
}
onChange
=
{
(
event
)
=>
onChange
(
event
.
target
.
value
)
}
onKeyDown
=
{
(
event
)
=>
{
if
(
isSending
)
{
event
.
preventDefault
();
return
;
}
const
isCursorAtStart
=
event
.
currentTarget
.
selectionStart
===
0
&&
event
.
currentTarget
.
selectionEnd
===
0
;
...
...
math-tutor/frontend/src/pages/ChatPage.tsx
View file @
2e26ac93
...
...
@@ -200,6 +200,7 @@ export default function ChatPage() {
const
[
draftHistoryIndex
,
setDraftHistoryIndex
]
=
useState
<
number
|
null
>
(
null
);
const
[
draftBeforeHistory
,
setDraftBeforeHistory
]
=
useState
<
string
|
null
>
(
null
);
const
[
isArchiving
,
setIsArchiving
]
=
useState
(
false
);
const
[
isSending
,
setIsSending
]
=
useState
(
false
);
const
[
archivedChats
,
setArchivedChats
]
=
useState
<
ArchivedChatSummary
[]
>
([]);
const
[
selectedArchiveId
,
setSelectedArchiveId
]
=
useState
(
""
);
const
[
archiveError
,
setArchiveError
]
=
useState
<
string
|
null
>
(
null
);
...
...
@@ -367,6 +368,7 @@ export default function ChatPage() {
deepLinkTarget
,
isTasksInitialized
,
navigate
,
searchParams
,
setSelectedOrchestrator
,
setTaskRef
,
setSubsectionRef
,
...
...
@@ -447,7 +449,6 @@ export default function ChatPage() {
cancelled
=
true
;
};
},
[
applyRetrievedSources
,
chatSessionId
,
isTasksInitialized
,
messages
.
length
,
...
...
@@ -612,6 +613,10 @@ export default function ChatPage() {
};
const
handleSend
=
async
()
=>
{
if
(
isSending
)
{
return
;
}
const
trimmed
=
draft
.
trim
();
if
(
!
trimmed
)
{
return
;
...
...
@@ -626,10 +631,12 @@ export default function ChatPage() {
setMessages
((
prev
)
=>
[...
prev
,
userMessage
]);
setDraft
(
""
);
resetDraftHistoryNavigation
();
setIsSending
(
true
);
setRetrievalLoading
(
true
);
setRetrievalError
(
null
);
let
chatRequestSucceeded
=
false
;
try
{
const
chatPayload
:
{
messages
:
Array
<
{
role
:
"
user
"
|
"
assistant
"
;
text
:
string
}
>
;
...
...
@@ -680,6 +687,7 @@ export default function ChatPage() {
},
]);
}
chatRequestSucceeded
=
true
;
}
catch
(
error
)
{
setMessages
((
prev
)
=>
[
...
prev
,
...
...
@@ -690,8 +698,13 @@ export default function ChatPage() {
},
]);
setRetrievalError
(
t
(
"
retrievalFailed
"
));
setRetrievalLoading
(
false
);
void
error
;
}
finally
{
setIsSending
(
false
);
}
if
(
!
chatRequestSucceeded
)
{
setRetrievalLoading
(
false
);
return
;
}
...
...
@@ -723,9 +736,8 @@ export default function ChatPage() {
}
catch
(
error
)
{
setRetrievalError
(
t
(
"
retrievalFailed
"
));
void
error
;
}
finally
{
setRetrievalLoading
(
false
);
}
setRetrievalLoading
(
false
);
};
const
handleToggleCanvas
=
()
=>
{
...
...
@@ -1161,6 +1173,7 @@ export default function ChatPage() {
draft
=
{
draft
}
onDraftChange
=
{
handleDraftChange
}
onSend
=
{
handleSend
}
isSending
=
{
isSending
}
onHistoryNavigate
=
{
handleHistoryNavigate
}
onToggleCanvas
=
{
handleToggleCanvas
}
onUploadSolution
=
{
handleCanvasUpload
}
...
...
math-tutor/frontend/src/styles/theme.css
View file @
2e26ac93
...
...
@@ -510,6 +510,33 @@ body {
margin-left
:
auto
;
}
.composer-loading
{
display
:
inline-flex
;
align-items
:
center
;
justify-content
:
center
;
gap
:
4px
;
min-width
:
28px
;
min-height
:
18px
;
}
.composer-loading
span
{
display
:
inline-block
;
width
:
5px
;
height
:
5px
;
border-radius
:
999px
;
background
:
currentColor
;
opacity
:
0.55
;
animation
:
composer-dot-bounce
1s
infinite
ease-in-out
;
}
.composer-loading
span
:nth-child
(
2
)
{
animation-delay
:
0.15s
;
}
.composer-loading
span
:nth-child
(
3
)
{
animation-delay
:
0.3s
;
}
.composer-input
{
width
:
100%
;
resize
:
vertical
;
...
...
@@ -519,6 +546,12 @@ body {
font-family
:
inherit
;
}
.composer-input
:disabled
{
background
:
#f7f3ec
;
color
:
#8b857b
;
cursor
:
not-allowed
;
}
.btn
{
border
:
1px
solid
#b9b2a4
;
background
:
#ffffff
;
...
...
@@ -539,6 +572,19 @@ body {
cursor
:
not-allowed
;
}
@keyframes
composer-dot-bounce
{
0
%,
80
%,
100
%
{
transform
:
translateY
(
0
);
opacity
:
0.45
;
}
40
%
{
transform
:
translateY
(
-3px
);
opacity
:
1
;
}
}
.btn.small
{
padding
:
4px
10px
;
font-size
:
11px
;
...
...
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