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' ;
6+ import { useDispatch } from 'react-redux' ;
67
7- import {
8- fullJSLanguage ,
9- fullTSLanguage ,
10- htmlLanguage ,
11- javaLanguages ,
12- pyLanguages ,
13- SALanguage ,
14- schemeLanguages ,
15- sourceLanguages ,
16- styliseSublanguage
17- } from '../application/ApplicationTypes' ;
18- import Constants from '../utils/Constants' ;
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' ;
12+ import { useFeature } from '../featureFlags/useFeature' ;
1913import { useTypedSelector } from '../utils/Hooks' ;
14+ import { LegacyControlBarChapterSelect } from './LegacyControlBarChapterSelect' ;
2015
2116type ControlBarChapterSelectProps = DispatchProps & StateProps ;
2217
@@ -31,81 +26,75 @@ type StateProps = {
3126 disabled ?: boolean ;
3227} ;
3328
34- const chapterListRenderer : ItemListRenderer < SALanguage > = ( {
35- itemsParentRef,
36- renderItem,
37- items
38- } ) => {
39- const defaultChoices = items . filter ( ( { variant } ) => variant === Variant . DEFAULT ) ;
40- const variantChoices = items . filter ( ( { variant } ) => variant !== Variant . DEFAULT ) ;
41-
42- return (
43- < Menu ulRef = { itemsParentRef } style = { { display : 'flex' , flexDirection : 'column' } } >
44- { defaultChoices . map ( renderItem ) }
45- { variantChoices . length > 0 && (
46- < MenuItem key = "variant-menu" text = "Variants" icon = "cog" >
47- { variantChoices . map ( renderItem ) }
48- </ MenuItem >
49- ) }
50- </ Menu >
51- ) ;
52- } ;
53-
54- const chapterRenderer : ( isFolderModeEnabled : boolean ) => ItemRenderer < SALanguage > =
55- ( isFolderModeEnabled : boolean ) =>
56- ( lang , { handleClick } ) => {
57- const isDisabled = isFolderModeEnabled && lang . chapter === Chapter . SOURCE_1 ;
58- const tooltipContent = isDisabled
59- ? 'Folder mode makes use of lists which are not available in Source 1. To switch to Source 1, disable Folder mode.'
60- : undefined ;
61- return (
62- < Tooltip
63- key = { lang . displayName }
64- content = { tooltipContent }
65- disabled = { tooltipContent === undefined }
66- >
67- < MenuItem onClick = { handleClick } text = { lang . displayName } disabled = { isDisabled } />
68- </ Tooltip >
69- ) ;
70- } ;
71-
72- const ChapterSelectComponent = Select . ofType < SALanguage > ( ) ;
73-
7429export const ControlBarChapterSelect : React . FC < ControlBarChapterSelectProps > = ( {
7530 isFolderModeEnabled,
7631 sourceChapter,
7732 sourceVariant,
7833 handleChapterSelect = ( ) => { } ,
7934 disabled = false
8035} ) => {
81- const selectedLang = useTypedSelector ( store => store . playground . languageConfig . mainLanguage ) ;
36+ 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 ] ) ;
8247
83- const choices = [
84- ...sourceLanguages ,
85- // Full JS/TS version uses eval(), which is a huge security risk, so we only enable
86- // for public deployments. HTML, while sandboxed, is treated the same way to be safe.
87- // See https://github.com/source-academy/frontend/pull/2460#issuecomment-1528759912
88- ...( Constants . playgroundOnly ? [ fullJSLanguage , fullTSLanguage , htmlLanguage ] : [ ] ) ,
89- ...schemeLanguages ,
90- ...pyLanguages ,
91- ...javaLanguages
92- ] ;
48+ if ( ! directoryEnabled ) {
49+ return < LegacyControlBarChapterSelect
50+ isFolderModeEnabled = { isFolderModeEnabled }
51+ sourceChapter = { sourceChapter }
52+ sourceVariant = { sourceVariant }
53+ handleChapterSelect = { handleChapterSelect }
54+ disabled = { disabled }
55+ /> ;
56+ }
57+
58+ const EvaluatorSelectComponent = Select . ofType < IEvaluatorDefinition > ( ) ;
59+
60+ const currentLanguage = dirLanguages . find ( l => l . id === selectedLanguageId ) ;
61+ const evaluators = currentLanguage ?. evaluators ?? [ ] ;
62+ const selectedEvaluator = evaluators . find ( e => e . id === selectedEvaluatorId ) ;
63+
64+ const evaluatorListRenderer : ItemListRenderer < IEvaluatorDefinition > = ( {
65+ itemsParentRef,
66+ renderItem,
67+ items
68+ } ) => (
69+ < Menu ulRef = { itemsParentRef } style = { { display : 'flex' , flexDirection : 'column' } } >
70+ { items . map ( renderItem ) }
71+ </ Menu >
72+ ) ;
73+
74+ const evaluatorRenderer : ItemRenderer < IEvaluatorDefinition > = ( evaluator , { handleClick } ) => (
75+ < MenuItem key = { evaluator . id } onClick = { handleClick } text = { evaluator . name } />
76+ ) ;
77+
78+ const onSelectEvaluator = ( evaluator : IEvaluatorDefinition ) => {
79+ dispatch ( LanguageDirectoryActions . setSelectedEvaluator ( evaluator . id ) ) ;
80+ } ;
9381
9482 return (
95- < ChapterSelectComponent
96- items = { choices . filter ( ( { mainLanguage } ) => mainLanguage === selectedLang ) }
97- onItemSelect = { handleChapterSelect }
98- itemRenderer = { chapterRenderer ( isFolderModeEnabled ) }
99- itemListRenderer = { chapterListRenderer }
83+ < EvaluatorSelectComponent
84+ items = { evaluators }
85+ onItemSelect = { onSelectEvaluator }
86+ itemRenderer = { evaluatorRenderer }
87+ itemListRenderer = { evaluatorListRenderer }
10088 filterable = { false }
10189 disabled = { disabled }
10290 >
10391 < Button
10492 minimal
105- text = { styliseSublanguage ( sourceChapter , sourceVariant ) }
93+ text = { selectedEvaluator ? selectedEvaluator . name : 'Select Evaluator' }
10694 rightIcon = { disabled ? null : IconNames . DOUBLE_CARET_VERTICAL }
95+ data-testid = "ControlBarEvaluatorSelect"
10796 disabled = { disabled }
10897 />
109- </ ChapterSelectComponent >
98+ </ EvaluatorSelectComponent >
11099 ) ;
111100} ;
0 commit comments