Add World introduction and change layout

pull/54/head
Jon Eugster 3 years ago
parent cdea03781c
commit 75f356f4b2

@ -39,6 +39,7 @@ import { styled, useTheme, Theme, CSSObject } from '@mui/material/styles';
import Markdown from './Markdown'; import Markdown from './Markdown';
import Split from 'react-split' import Split from 'react-split'
import { Alert } from '@mui/material';
export const MonacoEditorContext = React.createContext<monaco.editor.IStandaloneCodeEditor>(null as any); export const MonacoEditorContext = React.createContext<monaco.editor.IStandaloneCodeEditor>(null as any);
@ -131,6 +132,49 @@ function Level() {
const {editor, infoProvider, editorConnection} = const {editor, infoProvider, editorConnection} =
useLevelEditor(worldId, levelId, codeviewRef, initialCode, onDidChangeContent) useLevelEditor(worldId, levelId, codeviewRef, initialCode, onDidChangeContent)
// TODO: This is a hack for having an introduction (i.e. level 0)
// for each world.
if (levelId == 0) {
return <>
<div className="app-bar">
<div>
<Button to={`/`}><FontAwesomeIcon icon={faHome} /></Button>
<span className="app-bar-title">
{gameInfo.data?.worlds.nodes[worldId].title && `World: ${gameInfo.data?.worlds.nodes[worldId].title}`}
</span>
</div>
<div>
<span className="app-bar-title">
{`Einführung`}
</span>
<Button disabled={levelId <= 1} inverted={true}
to={`/world/${worldId}/level/0`}
><FontAwesomeIcon icon={faArrowLeft} />&nbsp;Previous</Button>
<Button disabled={levelId >= gameInfo.data?.worldSize[worldId]} inverted={true}
to={`/world/${worldId}/level/1`}
>Next&nbsp;<FontAwesomeIcon icon={faArrowRight} /></Button>
</div>
</div>
<div className="exercise-panel">
<div ref={introductionPanelRef} className="introduction-panel">
<Alert severity="info" sx={{ mt: 1 }}>
<Markdown>
{gameInfo.data?.worlds.nodes[worldId].introduction}
</Markdown>
</Alert>
<div ref={codeviewRef} className={`codeview ${commandLineMode ? 'hidden' : ''}`}></div>
</div>
<div className="conclusion">
{levelId >= gameInfo.data?.worldSize[worldId] ?
<Button to={`/`}><FontAwesomeIcon icon={faHome} /></Button> :
<Button to={`/world/${worldId}/level/1`}>
Start&nbsp;<FontAwesomeIcon icon={faArrowRight} />
</Button>}
</div>
</div>
</>
}
return <> return <>
<div style={level.isLoading ? null : {display: "none"}} className="app-content loading"><CircularProgress /></div> <div style={level.isLoading ? null : {display: "none"}} className="app-content loading"><CircularProgress /></div>
<div style={level.isLoading ? {display: "none"} : null} className="app-bar"> <div style={level.isLoading ? {display: "none"} : null} className="app-bar">
@ -144,7 +188,7 @@ function Level() {
<span className="app-bar-title"> <span className="app-bar-title">
{levelId && `Level ${levelId}`}{level?.data?.title && `: ${level?.data?.title}`} {levelId && `Level ${levelId}`}{level?.data?.title && `: ${level?.data?.title}`}
</span> </span>
<Button disabled={levelId <= 1} inverted={true} <Button disabled={levelId <= 0} inverted={true}
to={`/world/${worldId}/level/${levelId - 1}`} to={`/world/${worldId}/level/${levelId - 1}`}
><FontAwesomeIcon icon={faArrowLeft} />&nbsp;Previous</Button> ><FontAwesomeIcon icon={faArrowLeft} />&nbsp;Previous</Button>
<Button disabled={levelId >= gameInfo.data?.worldSize[worldId]} inverted={true} <Button disabled={levelId >= gameInfo.data?.worldSize[worldId]} inverted={true}
@ -153,13 +197,20 @@ function Level() {
</div> </div>
</div> </div>
<Split minSize={0} snapOffset={200} sizes={[30, 45, 25]} className={`app-content level ${level.isLoading ? 'hidden' : ''}`}> <Split minSize={0} snapOffset={200} sizes={[0, 50, 25, 25]} className={`app-content level ${level.isLoading ? 'hidden' : ''}`}>
<div className="side-panel"> <div className="side-panel">
{/*
<div ref={introductionPanelRef} className="introduction-panel"> <div ref={introductionPanelRef} className="introduction-panel">
<Markdown>{level?.data?.introduction}</Markdown> <Markdown>{level?.data?.introduction}</Markdown>
</div> </div>
*/}
</div> </div>
<div className="exercise-panel"> <div className="exercise-panel">
<div ref={introductionPanelRef} className="introduction-panel">
<Alert severity="info" sx={{ mt: 1 }}>
<Markdown>{level?.data?.introduction}</Markdown>
</Alert>
</div>
<div className="exercise"> <div className="exercise">
{/* <h4>Aufgabe:</h4> */} {/* <h4>Aufgabe:</h4> */}
<Markdown>{level?.data?.descrText}</Markdown> <Markdown>{level?.data?.descrText}</Markdown>
@ -193,6 +244,9 @@ function Level() {
<div className="doc-panel"> <div className="doc-panel">
{!level.isLoading && <Inventory tactics={level?.data?.tactics} lemmas={level?.data?.lemmas} definitions={level?.data?.definitions} />} {!level.isLoading && <Inventory tactics={level?.data?.tactics} lemmas={level?.data?.lemmas} definitions={level?.data?.definitions} />}
</div> </div>
<div className="side-panel">
<p>Display Tactic documentation here?</p>
</div>
</Split> </Split>
</> </>
} }

@ -55,7 +55,7 @@ function Welcome() {
let position: cytoscape.Position = nodes[id].position let position: cytoscape.Position = nodes[id].position
svgElements.push( svgElements.push(
<Link key={`world${id}`} to={`/world/${id}/level/1`}> <Link key={`world${id}`} to={`/world/${id}/level/0`}>
<circle className="world-circle" cx={position.x} cy={position.y} r="8" /> <circle className="world-circle" cx={position.x} cy={position.y} r="8" />
<text className="world-name" <text className="world-name"
x={position.x} y={position.y}>{nodes[id].data.title ? nodes[id].data.title : id}</text> x={position.x} y={position.y}>{nodes[id].data.title ? nodes[id].data.title : id}</text>

@ -124,7 +124,7 @@ const InfoDisplayContent = React.memo((props: InfoDisplayContentProps) => {
<div className="goals-section"> <div className="goals-section">
{ goals && ( { goals && (
goals.goals.length > 0 goals.goals.length > 0
? <><div className="goals-section-title">Main Goal</div> ? <><div className="goals-section-title">Aktuelles Goal</div>
<Goal commandLine={true} filter={goalFilter} key='mainGoal' goal={goals.goals[0]} showHints={true} /></> <Goal commandLine={true} filter={goalFilter} key='mainGoal' goal={goals.goals[0]} showHints={true} /></>
: <div className="goals-section-title">No Goals</div> : <div className="goals-section-title">No Goals</div>
) } ) }
@ -148,8 +148,8 @@ const InfoDisplayContent = React.memo((props: InfoDisplayContentProps) => {
<><CircularProgress /><div>Loading goal...</div></>)} <><CircularProgress /><div>Loading goal...</div></>)}
<AllMessages /> <AllMessages />
<LocationsContext.Provider value={locs}> <LocationsContext.Provider value={locs}>
{goals && goals.goals.length > 1 && <div className="goals-section"> {goals && goals.goals.length > 1 && <div className="goals-section other-goals">
<div className="goals-section-title">Other Goals</div> <div className="goals-section-title">Weitere Goals</div>
{goals.goals.slice(1).map((goal, i) => {goals.goals.slice(1).map((goal, i) =>
<details key={i}><summary><InteractiveCode fmt={goal.type} /></summary> <Goal commandLine={false} filter={goalFilter} goal={goal} /></details>)} <details key={i}><summary><InteractiveCode fmt={goal.type} /></summary> <Goal commandLine={false} filter={goalFilter} goal={goal} /></details>)}

@ -75,3 +75,7 @@
.command-line-input .monaco-editor .scroll-decoration { .command-line-input .monaco-editor .scroll-decoration {
box-shadow: none; box-shadow: none;
} }
.other-goals .goals-section-title, .other-goals summary, .other-goals summary .font-code {
color: #5191d1;
}

@ -35,16 +35,15 @@
background-color: #e9f2fb; background-color: #e9f2fb;
} }
.infoview { .introduction-panel, .infoview, .exercise, .conclusion {
padding: 1em; padding-top: 1em;
} padding-left: 1em;
padding-right: 1em;
.exercise { padding-bottom: 0;
padding: 1em;
} }
.conclusion { .infoview {
padding: 1em; padding-top: 0em;
} }
.exercise { .exercise {
@ -64,10 +63,6 @@
margin-bottom: 0; margin-bottom: 0;
} }
.introduction-panel {
padding: 1em;
}
.input-mode-switch { .input-mode-switch {
margin: 0; margin: 0;
display: flex; display: flex;

@ -4,7 +4,7 @@ import { Connection } from '../connection'
interface GameInfo { interface GameInfo {
title: null|string, title: null|string,
introduction: null|string, introduction: null|string,
worlds: null|{nodes: {[id:string]: {id: string, title: string}}, edges: string[][]}, worlds: null|{nodes: {[id:string]: {id: string, title: string, introduction: string}}, edges: string[][]},
worldSize: null|{[key: string]: number}, worldSize: null|{[key: string]: number},
authors: null|string[], authors: null|string[],
conclusion: null|string, conclusion: null|string,

@ -174,7 +174,10 @@ structure World where
deriving Inhabited deriving Inhabited
instance : ToJson World := ⟨ instance : ToJson World := ⟨
fun world => Json.mkObj [("name", toJson world.name), ("title", world.title)] fun world => Json.mkObj [
("name", toJson world.name),
("title", world.title),
("introduction", world.introduction)]
/-! ## Game -/ /-! ## Game -/

Loading…
Cancel
Save