1- import { Button , Menu , MenuItem , Tooltip } from '@blueprintjs/core' ;
1+ import { Button , Menu , MenuItem } from '@blueprintjs/core' ;
22import { IconNames } from '@blueprintjs/icons' ;
33import { ItemListRenderer , ItemRenderer , Select } from '@blueprintjs/select' ;
44import { Chapter , Variant } from 'js-slang/dist/types' ;
5- import React from 'react' ;
5+ import React , { useEffect } from 'react' ;
66import { useDispatch } from 'react-redux' ;
7- import { playgroundConductorEvaluator } from 'src/features/playground/PlaygroundActions' ;
87
9- import { flagConductorEnable } from '../../features/conductor/flagConductorEnable' ;
10- import {
11- fullJSLanguage ,
12- fullTSLanguage ,
13- htmlLanguage ,
14- javaLanguages ,
15- pyLanguages ,
16- SALanguage ,
17- schemeLanguages ,
18- sourceLanguages ,
19- styliseSublanguage
20- } from '../application/ApplicationTypes' ;
21- import { IEvaluatorDefinition } from '../directory/language' ;
8+ import { flagLanguageDirectoryEnable } from '../../features/languageDirectory/flagLanguageDirectory' ;
9+ import LanguageDirectoryActions from '../../features/languageDirectory/LanguageDirectoryActions' ;
10+ import type { IEvaluatorDefinition } from '../../features/languageDirectory/LanguageDirectoryTypes' ;
11+ import { SALanguage } from '../application/ApplicationTypes' ;
2212import { useFeature } from '../featureFlags/useFeature' ;
23- import Constants from '../utils/Constants' ;
2413import { useTypedSelector } from '../utils/Hooks' ;
14+ import { LegacyControlBarChapterSelect } from './LegacyControlBarChapterSelect' ;
2515
2616type ControlBarChapterSelectProps = DispatchProps & StateProps ;
2717
@@ -36,126 +26,77 @@ type StateProps = {
3626 disabled ?: boolean ;
3727} ;
3828
39- const chapterListRenderer : ItemListRenderer < SALanguage > = ( {
40- itemsParentRef,
41- renderItem,
42- items
43- } ) => {
44- const defaultChoices = items . filter ( ( { variant } ) => variant === Variant . DEFAULT ) ;
45- const variantChoices = items . filter ( ( { variant } ) => variant !== Variant . DEFAULT ) ;
46-
47- return (
48- < Menu ulRef = { itemsParentRef } style = { { display : 'flex' , flexDirection : 'column' } } >
49- { defaultChoices . map ( renderItem ) }
50- { variantChoices . length > 0 && (
51- < MenuItem key = "variant-menu" text = "Variants" icon = "cog" >
52- { variantChoices . map ( renderItem ) }
53- </ MenuItem >
54- ) }
55- </ Menu >
56- ) ;
57- } ;
58-
59- const chapterRenderer : ( isFolderModeEnabled : boolean ) => ItemRenderer < SALanguage > =
60- ( isFolderModeEnabled : boolean ) =>
61- ( lang , { handleClick } ) => {
62- const isDisabled = isFolderModeEnabled && lang . chapter === Chapter . SOURCE_1 ;
63- const tooltipContent = isDisabled
64- ? 'Folder mode makes use of lists which are not available in Source 1. To switch to Source 1, disable Folder mode.'
65- : undefined ;
66- return (
67- < Tooltip
68- key = { lang . displayName }
69- content = { tooltipContent }
70- disabled = { tooltipContent === undefined }
71- >
72- < MenuItem onClick = { handleClick } text = { lang . displayName } disabled = { isDisabled } />
73- </ Tooltip >
74- ) ;
75- } ;
76-
77- const evaluatorListRenderer : ItemListRenderer < IEvaluatorDefinition > = ( {
78- itemsParentRef,
79- renderItem,
80- items
81- } ) => {
82- return (
83- < Menu ulRef = { itemsParentRef } style = { { display : 'flex' , flexDirection : 'column' } } >
84- { items . map ( renderItem ) }
85- </ Menu >
86- ) ;
87- } ;
88-
89- const evaluatorRenderer : ItemRenderer < IEvaluatorDefinition > = ( evaluator , { handleClick } ) => {
90- return < MenuItem onClick = { handleClick } text = { evaluator . name } /> ;
91- } ;
92-
93- const ChapterSelectComponent = Select . ofType < SALanguage > ( ) ;
94- const EvaluatorSelectComponent = Select < IEvaluatorDefinition > ;
95-
9629export const ControlBarChapterSelect : React . FC < ControlBarChapterSelectProps > = ( {
9730 isFolderModeEnabled,
9831 sourceChapter,
9932 sourceVariant,
10033 handleChapterSelect = ( ) => { } ,
10134 disabled = false
10235} ) => {
103- const selectedLang = useTypedSelector ( store => store . playground . languageConfig . mainLanguage ) ;
104-
105- const currentLang = useTypedSelector ( store => store . playground . conductorLanguage ) ;
106- const currentEval = useTypedSelector ( store => store . playground . conductorEvaluator ) ;
10736 const dispatch = useDispatch ( ) ;
37+ const directoryEnabled = useFeature ( flagLanguageDirectoryEnable ) ;
38+ const selectedLanguageId = useTypedSelector ( s => s . languageDirectory . selectedLanguageId ) ;
39+ const selectedEvaluatorId = useTypedSelector ( s => s . languageDirectory . selectedEvaluatorId ) ;
40+ const dirLanguages = useTypedSelector ( s => s . languageDirectory . languages ) ;
41+
42+ useEffect ( ( ) => {
43+ if ( directoryEnabled && dirLanguages . length === 0 ) {
44+ dispatch ( LanguageDirectoryActions . fetchLanguages ( ) ) ;
45+ }
46+ } , [ directoryEnabled , dirLanguages . length , dispatch ] ) ;
10847
109- const conductorEnabled = useFeature ( flagConductorEnable ) ;
110- if ( conductorEnabled ) {
111- const handleChapterSelect = ( evaluator : IEvaluatorDefinition ) => {
112- dispatch ( playgroundConductorEvaluator ( evaluator ) ) ;
113- } ;
48+ if ( ! directoryEnabled ) {
11449 return (
115- < EvaluatorSelectComponent
116- items = { currentLang . evaluators }
117- onItemSelect = { handleChapterSelect }
118- itemRenderer = { evaluatorRenderer }
119- itemListRenderer = { evaluatorListRenderer }
120- filterable = { false }
50+ < LegacyControlBarChapterSelect
51+ isFolderModeEnabled = { isFolderModeEnabled }
52+ sourceChapter = { sourceChapter }
53+ sourceVariant = { sourceVariant }
54+ handleChapterSelect = { handleChapterSelect }
12155 disabled = { disabled }
122- >
123- < Button
124- minimal
125- text = { currentEval ?. name }
126- rightIcon = { disabled ? null : IconNames . DOUBLE_CARET_VERTICAL }
127- disabled = { disabled }
128- />
129- </ EvaluatorSelectComponent >
56+ />
13057 ) ;
13158 }
13259
133- const choices = [
134- ...sourceLanguages ,
135- // Full JS/TS version uses eval(), which is a huge security risk, so we only enable
136- // for public deployments. HTML, while sandboxed, is treated the same way to be safe.
137- // See https://github.com/source-academy/frontend/pull/2460#issuecomment-1528759912
138- ...( Constants . playgroundOnly ? [ fullJSLanguage , fullTSLanguage , htmlLanguage ] : [ ] ) ,
139- ...schemeLanguages ,
140- ...pyLanguages ,
141- ...javaLanguages
142- ] ;
60+ const EvaluatorSelectComponent = Select . ofType < IEvaluatorDefinition > ( ) ;
61+
62+ const currentLanguage = dirLanguages . find ( l => l . id === selectedLanguageId ) ;
63+ const evaluators = currentLanguage ?. evaluators ?? [ ] ;
64+ const selectedEvaluator = evaluators . find ( e => e . id === selectedEvaluatorId ) ;
65+
66+ const evaluatorListRenderer : ItemListRenderer < IEvaluatorDefinition > = ( {
67+ itemsParentRef,
68+ renderItem,
69+ items
70+ } ) => (
71+ < Menu ulRef = { itemsParentRef } style = { { display : 'flex' , flexDirection : 'column' } } >
72+ { items . map ( renderItem ) }
73+ </ Menu >
74+ ) ;
75+
76+ const evaluatorRenderer : ItemRenderer < IEvaluatorDefinition > = ( evaluator , { handleClick } ) => (
77+ < MenuItem key = { evaluator . id } onClick = { handleClick } text = { evaluator . name } />
78+ ) ;
79+
80+ const onSelectEvaluator = ( evaluator : IEvaluatorDefinition ) => {
81+ dispatch ( LanguageDirectoryActions . setSelectedEvaluator ( evaluator . id ) ) ;
82+ } ;
14383
14484 return (
145- < ChapterSelectComponent
146- items = { choices . filter ( ( { mainLanguage } ) => mainLanguage === selectedLang ) }
147- onItemSelect = { handleChapterSelect }
148- itemRenderer = { chapterRenderer ( isFolderModeEnabled ) }
149- itemListRenderer = { chapterListRenderer }
85+ < EvaluatorSelectComponent
86+ items = { evaluators }
87+ onItemSelect = { onSelectEvaluator }
88+ itemRenderer = { evaluatorRenderer }
89+ itemListRenderer = { evaluatorListRenderer }
15090 filterable = { false }
15191 disabled = { disabled }
15292 >
15393 < Button
15494 minimal
155- text = { styliseSublanguage ( sourceChapter , sourceVariant ) }
95+ text = { selectedEvaluator ? selectedEvaluator . name : 'Select Evaluator' }
15696 rightIcon = { disabled ? null : IconNames . DOUBLE_CARET_VERTICAL }
97+ data-testid = "ControlBarEvaluatorSelect"
15798 disabled = { disabled }
15899 />
159- </ ChapterSelectComponent >
100+ </ EvaluatorSelectComponent >
160101 ) ;
161102} ;
0 commit comments