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
4053103d
Commit
4053103d
authored
Apr 15, 2026
by
Kantz
Browse files
änderungen in der auswahl sauber entfernt
parent
09b170b8
Changes
4
Hide whitespace changes
Inline
Side-by-side
math-tutor/README.md
View file @
4053103d
...
...
@@ -85,7 +85,7 @@ Notes:
-
`subsection_key`
must match an existing subsection entry from the task catalog.
-
The links use hyphenated subsection slugs in the URL, while the app resolves them back to the catalog key.
-
The
socratic subsection list in the UI is built from
`backend/sources/tasks/_subsection_map.json`
and the
`subsections`
arrays in the task files
.
-
The
fallback
`/select-socratic`
page only shows the subsection dropdown and start button
.
-
If the link is invalid, the frontend falls back to
`/select-socratic`
.
-
The socratic dialog is not locked by deep link, so users can still switch subsections afterwards.
...
...
math-tutor/frontend/src/i18n.ts
View file @
4053103d
...
...
@@ -74,13 +74,9 @@
taskSelectionSubtitle
:
"
Choose a task and start a tutor session
"
,
socraticSelectionTitle
:
"
Select a Subsection
"
,
socraticSelectionSubtitle
:
"
Choose a subsection and start a socratic session
"
,
socraticDeepLinkList
:
"
Direct socratic links
"
,
socraticDeepLinkListSubtitle
:
"
Open a socratic dialog directly for any available subsection.
"
,
subsection
:
"
Subsection
"
,
taskFile
:
"
Task Set
"
,
taskId
:
"
Task ID
"
,
subsectionFile
:
"
Subsection Set
"
,
subsectionKey
:
"
Subsection Key
"
,
solveWithTutor
:
"
Solve with Tutor
"
,
startSocratic
:
"
Start Socratic
"
,
...
...
@@ -181,13 +177,9 @@
taskSelectionSubtitle
:
"
Wähle eine Aufgabe und starte den Tutor-Chat
"
,
socraticSelectionTitle
:
"
Unterabschnitt auswählen
"
,
socraticSelectionSubtitle
:
"
Wähle einen Unterabschnitt und starte den sokratischen Chat
"
,
socraticDeepLinkList
:
"
Direkte sokratische Links
"
,
socraticDeepLinkListSubtitle
:
"
Öffne einen sokratischen Dialog direkt für jeden verfügbaren Unterabschnitt.
"
,
subsection
:
"
Unterabschnitt
"
,
taskFile
:
"
Aufgabenset
"
,
taskId
:
"
Aufgaben-ID
"
,
subsectionFile
:
"
Unterabschnitt-Set
"
,
subsectionKey
:
"
Unterabschnitt-Schlüssel
"
,
solveWithTutor
:
"
Mit Tutor lösen
"
,
startSocratic
:
"
Sokratischen Dialog führen
"
,
...
...
math-tutor/frontend/src/pages/SocraticSelectionPage.tsx
View file @
4053103d
import
{
useEffect
,
useMemo
,
useRef
}
from
"
react
"
;
import
{
Link
,
useNavigate
}
from
"
react-router-dom
"
;
import
{
useNavigate
}
from
"
react-router-dom
"
;
import
type
{
OrchestratorName
}
from
"
../api/orchestratorApi
"
;
import
{
selectSubsection
}
from
"
../api/taskApi
"
;
import
OrchestratorSelect
from
"
../components/Orchestrator/OrchestratorSelect
"
;
import
{
t
}
from
"
../i18n
"
;
import
{
useTutorSession
}
from
"
../state/tutorSession
"
;
import
{
getSelectionRouteForOrchestrator
}
from
"
../utils/orchestratorRoutes
"
;
import
{
subsectionKeyToSlug
}
from
"
../utils/subsectionKey
"
;
import
"
../styles/theme.css
"
;
import
sumintLogo
from
"
../../SuMINT-Logo.png
"
;
type
SocraticLinkGroup
=
{
key
:
string
;
title
:
string
;
fileId
:
string
;
entries
:
SocraticLinkEntry
[];
};
type
SocraticLinkEntry
=
{
subsectionKey
:
string
;
slug
:
string
;
label
:
string
;
summary
:
string
;
refsText
:
string
;
href
:
string
;
};
const
buildSocraticHref
=
(
subsectionKey
:
string
):
string
=>
`/chat?orchestrator=socratic&subsection_key=
${
encodeURIComponent
(
subsectionKey
)}
`
;
export
default
function
SocraticSelectionPage
()
{
const
navigate
=
useNavigate
();
const
{
...
...
@@ -38,7 +18,6 @@ export default function SocraticSelectionPage() {
switchOrchestrator
,
isOrchestratorSelectable
,
orchestratorError
,
taskFiles
,
subsections
,
selectedSubsectionRef
,
selectedSubsection
,
...
...
@@ -50,77 +29,6 @@ export default function SocraticSelectionPage() {
}
=
useTutorSession
();
const
subsectionDisplayRef
=
useRef
<
HTMLDivElement
|
null
>
(
null
);
const
socraticLinkGroups
=
useMemo
<
SocraticLinkGroup
[]
>
(()
=>
{
const
groupIndex
=
new
Map
<
string
,
SocraticLinkGroup
>
();
const
globalOrder
=
new
Map
<
string
,
number
>
();
subsections
.
forEach
((
option
,
index
)
=>
{
globalOrder
.
set
(
option
.
subsection_key
,
index
);
});
const
fileBySubsectionKey
=
new
Map
<
string
,
{
fileId
:
string
;
title
:
string
;
}
>
();
taskFiles
.
forEach
((
file
)
=>
{
const
title
=
file
.
title
||
file
.
file_id
;
(
file
.
subsection_options
||
[]).
forEach
((
option
)
=>
{
if
(
!
fileBySubsectionKey
.
has
(
option
.
subsection_key
))
{
fileBySubsectionKey
.
set
(
option
.
subsection_key
,
{
fileId
:
file
.
file_id
,
title
,
});
}
});
});
subsections
.
forEach
((
option
)
=>
{
const
source
=
fileBySubsectionKey
.
get
(
option
.
subsection_key
);
const
groupKey
=
source
?.
fileId
||
"
__ungrouped__
"
;
const
groupTitle
=
source
?.
title
||
t
(
"
subsectionFile
"
);
const
refsText
=
option
.
refs
.
map
((
ref
)
=>
ref
.
join
(
"
:
"
)).
join
(
"
,
"
);
const
entry
:
SocraticLinkEntry
=
{
subsectionKey
:
option
.
subsection_key
,
slug
:
subsectionKeyToSlug
(
option
.
subsection_key
),
label
:
option
.
label
||
option
.
subsection_key
,
summary
:
option
.
summary
||
""
,
refsText
,
href
:
buildSocraticHref
(
subsectionKeyToSlug
(
option
.
subsection_key
)),
};
const
existing
=
groupIndex
.
get
(
groupKey
);
if
(
existing
)
{
existing
.
entries
.
push
(
entry
);
return
;
}
groupIndex
.
set
(
groupKey
,
{
key
:
groupKey
,
title
:
groupTitle
,
fileId
:
source
?.
fileId
||
""
,
entries
:
[
entry
],
});
});
return
[...
groupIndex
.
values
()]
.
map
((
group
)
=>
({
...
group
,
entries
:
group
.
entries
.
sort
((
a
,
b
)
=>
{
const
aOrder
=
globalOrder
.
get
(
a
.
subsectionKey
)
??
Number
.
MAX_SAFE_INTEGER
;
const
bOrder
=
globalOrder
.
get
(
b
.
subsectionKey
)
??
Number
.
MAX_SAFE_INTEGER
;
if
(
aOrder
!==
bOrder
)
{
return
aOrder
-
bOrder
;
}
return
a
.
label
.
localeCompare
(
b
.
label
);
}),
}))
.
sort
((
a
,
b
)
=>
a
.
title
.
localeCompare
(
b
.
title
));
},
[
subsections
,
taskFiles
]);
const
subsectionMenuOptions
=
useMemo
(
()
=>
subsections
.
map
((
option
)
=>
({
...
...
math-tutor/frontend/src/styles/theme.css
View file @
4053103d
...
...
@@ -938,110 +938,6 @@ body {
padding
:
18px
;
}
.socratic-link-section
{
display
:
flex
;
flex-direction
:
column
;
gap
:
10px
;
margin-top
:
4px
;
padding-top
:
12px
;
border-top
:
1px
solid
#e2ded5
;
}
.socratic-link-subtitle
{
margin
:
0
;
color
:
#6f675d
;
font-size
:
13px
;
}
.socratic-link-groups
{
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.socratic-link-group
{
display
:
flex
;
flex-direction
:
column
;
gap
:
10px
;
padding
:
12px
;
border
:
1px
solid
#e2ded5
;
border-radius
:
14px
;
background
:
#fffdf8
;
}
.socratic-link-group-header
{
display
:
flex
;
justify-content
:
space-between
;
gap
:
12px
;
align-items
:
baseline
;
}
.socratic-link-group-title
{
font-weight
:
600
;
font-size
:
14px
;
}
.socratic-link-group-meta
{
color
:
#6f675d
;
font-size
:
12px
;
white-space
:
nowrap
;
}
.socratic-link-items
{
display
:
grid
;
grid-template-columns
:
repeat
(
auto-fit
,
minmax
(
220px
,
1
fr
));
gap
:
10px
;
}
.socratic-link-item
{
display
:
flex
;
flex-direction
:
column
;
gap
:
4px
;
min-height
:
100%
;
padding
:
12px
;
border-radius
:
12px
;
border
:
1px
solid
#d8d1c4
;
background
:
linear-gradient
(
180deg
,
#fff
0%
,
#fff8eb
100%
);
color
:
inherit
;
text-decoration
:
none
;
transition
:
transform
0.12s
ease
,
box-shadow
0.12s
ease
,
border-color
0.12s
ease
;
}
.socratic-link-item
:hover
,
.socratic-link-item
:focus-visible
{
transform
:
translateY
(
-1px
);
border-color
:
#b9b2a4
;
box-shadow
:
0
10px
22px
rgba
(
29
,
27
,
22
,
0.08
);
outline
:
none
;
}
.socratic-link-item-title
{
font-weight
:
600
;
}
.socratic-link-item-key
,
.socratic-link-item-meta
,
.socratic-link-item-summary
{
font-size
:
12px
;
color
:
#6f675d
;
}
.socratic-link-item-summary
{
white-space
:
pre-line
;
}
.task-panel-empty
{
padding
:
8px
10px
;
border-radius
:
10px
;
background
:
#fff
;
border
:
1px
dashed
#d8d1c4
;
color
:
#6f675d
;
font-size
:
12px
;
}
.task-select-title
{
margin
:
0
;
font-size
:
20px
;
...
...
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