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
b857e4c4
Commit
b857e4c4
authored
Mar 05, 2026
by
Kantz
Browse files
Enter sendet nun Nachricht und Modus help wird angezeigt
parent
1a2a006d
Changes
4
Hide whitespace changes
Inline
Side-by-side
math-tutor/frontend/src/components/Chat/MessageInput.tsx
View file @
b857e4c4
...
@@ -46,7 +46,7 @@ export default function MessageInput({
...
@@ -46,7 +46,7 @@ export default function MessageInput({
value
=
{
value
}
value
=
{
value
}
onChange
=
{
(
event
)
=>
onChange
(
event
.
target
.
value
)
}
onChange
=
{
(
event
)
=>
onChange
(
event
.
target
.
value
)
}
onKeyDown
=
{
(
event
)
=>
{
onKeyDown
=
{
(
event
)
=>
{
if
(
event
.
key
===
"
Enter
"
&&
event
.
ctrl
Key
)
{
if
(
event
.
key
===
"
Enter
"
&&
!
event
.
shift
Key
)
{
event
.
preventDefault
();
event
.
preventDefault
();
onSend
();
onSend
();
}
}
...
...
math-tutor/frontend/src/components/Orchestrator/OrchestratorSelect.tsx
View file @
b857e4c4
import
{
useId
}
from
"
react
"
;
import
type
{
OrchestratorName
}
from
"
../../api/orchestratorApi
"
;
import
type
{
OrchestratorName
}
from
"
../../api/orchestratorApi
"
;
import
{
t
}
from
"
../../i18n
"
;
import
{
t
}
from
"
../../i18n
"
;
...
@@ -8,23 +9,83 @@ type OrchestratorSelectProps = {
...
@@ -8,23 +9,83 @@ type OrchestratorSelectProps = {
disabled
?:
boolean
;
disabled
?:
boolean
;
};
};
const
labelMap
:
Record
<
OrchestratorName
,
string
>
=
{
type
ModeMeta
=
{
qa
:
"
QA
"
,
labelKey
:
tutor
:
"
Tutor
"
,
|
"
orchestratorModeQaLabel
"
task
:
"
Task
"
,
|
"
orchestratorModeTutorLabel
"
|
"
orchestratorModeTaskLabel
"
;
descriptionKey
:
|
"
orchestratorModeQaDescription
"
|
"
orchestratorModeTutorDescription
"
|
"
orchestratorModeTaskDescription
"
;
};
};
const
modeMetaMap
:
Record
<
OrchestratorName
,
ModeMeta
>
=
{
qa
:
{
labelKey
:
"
orchestratorModeQaLabel
"
,
descriptionKey
:
"
orchestratorModeQaDescription
"
,
},
tutor
:
{
labelKey
:
"
orchestratorModeTutorLabel
"
,
descriptionKey
:
"
orchestratorModeTutorDescription
"
,
},
task
:
{
labelKey
:
"
orchestratorModeTaskLabel
"
,
descriptionKey
:
"
orchestratorModeTaskDescription
"
,
},
};
type
ModeDescriptionDisplay
=
"
tooltip
"
|
"
helperText
"
|
"
optionSuffix
"
;
// Variants kept local for easy switching without touching page-level integrations.
const
MODE_DESCRIPTION_DISPLAY
:
ModeDescriptionDisplay
=
"
tooltip
"
;
export
default
function
OrchestratorSelect
({
export
default
function
OrchestratorSelect
({
value
,
value
,
options
,
options
,
onChange
,
onChange
,
disabled
=
false
,
disabled
=
false
,
}:
OrchestratorSelectProps
)
{
}:
OrchestratorSelectProps
)
{
const
selectId
=
useId
();
const
helpPopoverId
=
useId
();
const
selectedModeMeta
=
modeMetaMap
[
value
];
const
renderTooltip
=
MODE_DESCRIPTION_DISPLAY
===
"
tooltip
"
;
const
renderHelperText
=
MODE_DESCRIPTION_DISPLAY
===
"
helperText
"
;
const
renderOptionSuffix
=
MODE_DESCRIPTION_DISPLAY
===
"
optionSuffix
"
;
return
(
return
(
<
label
className
=
"orchestrator-select-wrap"
htmlFor
=
"orchestrator-select"
>
<
div
className
=
"orchestrator-select-wrap"
>
<
span
className
=
"orchestrator-select-label"
>
{
t
(
"
orchestratorMode
"
)
}
</
span
>
<
div
className
=
"orchestrator-select-label-row"
>
<
label
className
=
"orchestrator-select-label"
htmlFor
=
{
selectId
}
>
{
t
(
"
orchestratorMode
"
)
}
</
label
>
{
renderTooltip
?
(
<
div
className
=
"orchestrator-help"
>
<
button
type
=
"button"
className
=
"orchestrator-help-trigger"
aria-label
=
{
t
(
"
orchestratorModeDescriptionTitle
"
)
}
aria-describedby
=
{
helpPopoverId
}
>
i
</
button
>
<
div
id
=
{
helpPopoverId
}
role
=
"tooltip"
className
=
"orchestrator-help-popover"
>
<
div
className
=
"orchestrator-help-title"
>
{
t
(
"
orchestratorModeDescriptionTitle
"
)
}
</
div
>
<
div
className
=
"orchestrator-help-list"
>
{
options
.
map
((
option
)
=>
(
<
div
key
=
{
option
}
className
=
"orchestrator-help-item"
>
<
span
className
=
"orchestrator-help-mode"
>
{
t
(
modeMetaMap
[
option
].
labelKey
)
}
:
</
span
>
<
span
>
{
t
(
modeMetaMap
[
option
].
descriptionKey
)
}
</
span
>
</
div
>
))
}
</
div
>
</
div
>
</
div
>
)
:
null
}
</
div
>
<
select
<
select
id
=
"orchestrator-
select
"
id
=
{
select
Id
}
className
=
"task-select orchestrator-select"
className
=
"task-select orchestrator-select"
value
=
{
value
}
value
=
{
value
}
onChange
=
{
(
event
)
=>
onChange
(
event
.
target
.
value
as
OrchestratorName
)
}
onChange
=
{
(
event
)
=>
onChange
(
event
.
target
.
value
as
OrchestratorName
)
}
...
@@ -32,10 +93,15 @@ export default function OrchestratorSelect({
...
@@ -32,10 +93,15 @@ export default function OrchestratorSelect({
>
>
{
options
.
map
((
option
)
=>
(
{
options
.
map
((
option
)
=>
(
<
option
key
=
{
option
}
value
=
{
option
}
>
<
option
key
=
{
option
}
value
=
{
option
}
>
{
labelMap
[
option
]
}
{
renderOptionSuffix
?
`
${
t
(
modeMetaMap
[
option
].
labelKey
)}
-
${
t
(
modeMetaMap
[
option
].
descriptionKey
)}
`
:
t
(
modeMetaMap
[
option
].
labelKey
)
}
</
option
>
</
option
>
))
}
))
}
</
select
>
</
select
>
</
label
>
{
renderHelperText
?
(
<
div
className
=
"orchestrator-mode-helper"
>
{
t
(
selectedModeMeta
.
descriptionKey
)
}
</
div
>
)
:
null
}
</
div
>
);
);
}
}
math-tutor/frontend/src/i18n.ts
View file @
b857e4c4
...
@@ -17,6 +17,13 @@
...
@@ -17,6 +17,13 @@
newChat
:
"
New Chat
"
,
newChat
:
"
New Chat
"
,
loading
:
"
Loading...
"
,
loading
:
"
Loading...
"
,
orchestratorMode
:
"
Mode
"
,
orchestratorMode
:
"
Mode
"
,
orchestratorModeQaLabel
:
"
QA
"
,
orchestratorModeTutorLabel
:
"
Tutor
"
,
orchestratorModeTaskLabel
:
"
Task
"
,
orchestratorModeDescriptionTitle
:
"
Mode help
"
,
orchestratorModeQaDescription
:
"
Direct answers based on the script
"
,
orchestratorModeTutorDescription
:
"
Help with your own questions
"
,
orchestratorModeTaskDescription
:
"
Help with textbook exercises
"
,
directChildren
:
"
Direct children
"
,
directChildren
:
"
Direct children
"
,
taskChildren
:
"
Task sources
"
,
taskChildren
:
"
Task sources
"
,
indirectChildren
:
"
Indirect children
"
,
indirectChildren
:
"
Indirect children
"
,
...
@@ -75,6 +82,13 @@
...
@@ -75,6 +82,13 @@
newChat
:
"
neuer Chat
"
,
newChat
:
"
neuer Chat
"
,
loading
:
"
Lade...
"
,
loading
:
"
Lade...
"
,
orchestratorMode
:
"
Modus
"
,
orchestratorMode
:
"
Modus
"
,
orchestratorModeQaLabel
:
"
QA
"
,
orchestratorModeTutorLabel
:
"
Tutor
"
,
orchestratorModeTaskLabel
:
"
Task
"
,
orchestratorModeDescriptionTitle
:
"
Modus-Hilfe
"
,
orchestratorModeQaDescription
:
"
Direkte Antworten basierend auf dem Skript
"
,
orchestratorModeTutorDescription
:
"
Hilfe bei selbst gestellten Fragen
"
,
orchestratorModeTaskDescription
:
"
Hilfe bei Aufgaben aus dem Lehrwerk
"
,
directChildren
:
"
Direkte Quellen
"
,
directChildren
:
"
Direkte Quellen
"
,
taskChildren
:
"
Aufgaben-Quellen
"
,
taskChildren
:
"
Aufgaben-Quellen
"
,
indirectChildren
:
"
Indirekte Quellen
"
,
indirectChildren
:
"
Indirekte Quellen
"
,
...
...
math-tutor/frontend/src/styles/theme.css
View file @
b857e4c4
...
@@ -67,6 +67,7 @@ body {
...
@@ -67,6 +67,7 @@ body {
.orchestrator-select-wrap
{
.orchestrator-select-wrap
{
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
flex-wrap
:
wrap
;
gap
:
8px
;
gap
:
8px
;
padding
:
4px
8px
;
padding
:
4px
8px
;
border
:
1px
solid
#d8d1c4
;
border
:
1px
solid
#d8d1c4
;
...
@@ -74,6 +75,12 @@ body {
...
@@ -74,6 +75,12 @@ body {
background
:
#fef9f0
;
background
:
#fef9f0
;
}
}
.orchestrator-select-label-row
{
display
:
flex
;
align-items
:
center
;
gap
:
6px
;
}
.orchestrator-select-label
{
.orchestrator-select-label
{
font-size
:
12px
;
font-size
:
12px
;
color
:
#6f675d
;
color
:
#6f675d
;
...
@@ -84,6 +91,83 @@ body {
...
@@ -84,6 +91,83 @@ body {
padding
:
4px
8px
;
padding
:
4px
8px
;
}
}
.orchestrator-help
{
position
:
relative
;
}
.orchestrator-help-trigger
{
width
:
18px
;
height
:
18px
;
border-radius
:
999px
;
border
:
1px
solid
#b9b2a4
;
background
:
#fff
;
color
:
#6f675d
;
font-size
:
11px
;
font-weight
:
600
;
line-height
:
1
;
display
:
inline-flex
;
align-items
:
center
;
justify-content
:
center
;
cursor
:
help
;
}
.orchestrator-help-trigger
:focus-visible
{
outline
:
2px
solid
#6f675d
;
outline-offset
:
1px
;
}
.orchestrator-help-popover
{
position
:
absolute
;
top
:
calc
(
100%
+
8px
);
left
:
0
;
width
:
320px
;
padding
:
10px
;
border
:
1px
solid
#d8d1c4
;
border-radius
:
12px
;
background
:
#fff
;
box-shadow
:
0
10px
26px
rgba
(
29
,
27
,
22
,
0.15
);
color
:
#1d1b16
;
font-size
:
12px
;
z-index
:
40
;
opacity
:
0
;
visibility
:
hidden
;
pointer-events
:
none
;
transition
:
opacity
0.15s
ease
;
}
.orchestrator-help
:hover
.orchestrator-help-popover
,
.orchestrator-help
:focus-within
.orchestrator-help-popover
{
opacity
:
1
;
visibility
:
visible
;
}
.orchestrator-help-title
{
font-weight
:
600
;
margin-bottom
:
6px
;
}
.orchestrator-help-list
{
display
:
flex
;
flex-direction
:
column
;
gap
:
6px
;
}
.orchestrator-help-item
{
display
:
flex
;
gap
:
6px
;
}
.orchestrator-help-mode
{
font-weight
:
600
;
min-width
:
42px
;
}
.orchestrator-mode-helper
{
flex-basis
:
100%
;
font-size
:
12px
;
color
:
#6f675d
;
}
.pill
{
.pill
{
padding
:
6px
12px
;
padding
:
6px
12px
;
border-radius
:
999px
;
border-radius
:
999px
;
...
@@ -582,6 +666,13 @@ body {
...
@@ -582,6 +666,13 @@ body {
width
:
100%
;
width
:
100%
;
}
}
.orchestrator-help-popover
{
left
:
auto
;
right
:
0
;
width
:
auto
;
max-width
:
min
(
92vw
,
360px
);
}
.chat-window
{
.chat-window
{
min-height
:
360px
;
min-height
:
360px
;
}
}
...
...
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