Merge branch 'main' of github.com:leanprover-community/lean4game
commit
e4d5010163
@ -0,0 +1,64 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import './inventory.css'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
import { faLock, faLockOpen, faBook, faHammer, faBan } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import Markdown from './Markdown';
|
||||||
|
import { useLoadDocQuery } from '../state/api';
|
||||||
|
|
||||||
|
function Inventory({ tactics, lemmas } :
|
||||||
|
{lemmas: {name: string, locked: boolean, disabled: boolean}[],
|
||||||
|
tactics: {name: string, locked: boolean, disabled: boolean}[]}) {
|
||||||
|
|
||||||
|
const [docName, setDocName] = useState(null)
|
||||||
|
const [docType, setDocType] = useState(null)
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="inventory">
|
||||||
|
<h2>Tactics</h2>
|
||||||
|
<div className="inventory-list">
|
||||||
|
{ tactics.map(tac =>
|
||||||
|
<InventoryItem key={tac.name} showDoc={() => {setDocName(tac.name); setDocType("tactic")}}
|
||||||
|
name={tac.name} locked={tac.locked} disabled={tac.disabled} />) }
|
||||||
|
{/* TODO: Click on Tactic: show info
|
||||||
|
TODO: click on paste icon -> paste into command line */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Lemmas</h2>
|
||||||
|
<div className="inventory-list">
|
||||||
|
{ lemmas.map(lem =>
|
||||||
|
<InventoryItem key={lem.name} showDoc={() => {setDocName(lem.name); setDocType("lemma")}}
|
||||||
|
name={lem.name} locked={lem.locked} disabled={lem.disabled} />) }
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{docName && <Documentation name={docName} type={docType} />}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function InventoryItem({name, locked, disabled, showDoc}) {
|
||||||
|
const icon = locked ? <FontAwesomeIcon icon={faLock} /> :
|
||||||
|
disabled ? <FontAwesomeIcon icon={faBan} /> : ""
|
||||||
|
const className = locked ? "locked" : disabled ? "disabled" : ""
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
if (!locked && !disabled) {
|
||||||
|
showDoc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div className={`item ${className}`} onClick={handleClick}>{icon} {name}</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
function Documentation({name, type}) {
|
||||||
|
|
||||||
|
const doc = useLoadDocQuery({type: type, name: name})
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<h2 className="doc">{doc.data?.name}</h2>
|
||||||
|
<Markdown>{doc.data?.text}</Markdown>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Inventory;
|
@ -1,104 +0,0 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
import '@fontsource/roboto/300.css';
|
|
||||||
import '@fontsource/roboto/400.css';
|
|
||||||
import '@fontsource/roboto/500.css';
|
|
||||||
import '@fontsource/roboto/700.css';
|
|
||||||
|
|
||||||
import { Paper, Box, Typography, Accordion, AccordionSummary, AccordionDetails, Tabs, Tab, Divider, Button, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';
|
|
||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
||||||
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
|
||||||
import { faUpload, faArrowRotateRight, faChevronLeft, faChevronRight, faBook, faHammer } from '@fortawesome/free-solid-svg-icons'
|
|
||||||
import Markdown from './Markdown';
|
|
||||||
|
|
||||||
function TacticDoc(props) {
|
|
||||||
return (
|
|
||||||
<Accordion>
|
|
||||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
|
||||||
<Typography>{props.tactic.name}</Typography>
|
|
||||||
</AccordionSummary>
|
|
||||||
<AccordionDetails>
|
|
||||||
<Markdown>{props.tactic.content}</Markdown>
|
|
||||||
</AccordionDetails>
|
|
||||||
</Accordion>)
|
|
||||||
}
|
|
||||||
|
|
||||||
function LemmaDoc({ lemma }) {
|
|
||||||
return (
|
|
||||||
<Accordion>
|
|
||||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
|
||||||
<Typography>{lemma.userName}</Typography>
|
|
||||||
</AccordionSummary>
|
|
||||||
<AccordionDetails>
|
|
||||||
<Markdown>{lemma.content}</Markdown>
|
|
||||||
</AccordionDetails>
|
|
||||||
</Accordion>)
|
|
||||||
}
|
|
||||||
|
|
||||||
function LemmaDocs({ lemmas }) {
|
|
||||||
const [categories, setCategories] = useState(new Map())
|
|
||||||
const [curCategory, setCurCategory] = useState("")
|
|
||||||
|
|
||||||
const changeTab = (event: React.SyntheticEvent, newValue : string) => {
|
|
||||||
setCurCategory(newValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const cats = new Map()
|
|
||||||
lemmas.forEach(function (item) {
|
|
||||||
const category = item.category
|
|
||||||
cats.set(category, (cats.get(category) || []).concat([item]))
|
|
||||||
});
|
|
||||||
setCategories(cats)
|
|
||||||
setCurCategory(cats.keys().next().value)
|
|
||||||
}, [lemmas]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
|
|
||||||
<Tabs
|
|
||||||
value={curCategory}
|
|
||||||
onChange={changeTab}
|
|
||||||
aria-label="Categories" variant="scrollable" scrollButtons="auto">
|
|
||||||
{(Array.from(categories)).map(([category, _]) => <Tab value={category} label={category} key={category} wrapped />)}
|
|
||||||
</Tabs>
|
|
||||||
</Box>
|
|
||||||
{curCategory && categories.get(curCategory).map((lemma) => <LemmaDoc lemma={lemma} key={lemma.name} />)}
|
|
||||||
</div>)
|
|
||||||
}
|
|
||||||
|
|
||||||
function LeftPanel({ spells, inventory, showSidePanel, setShowSidePanel }) {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<List className="side">
|
|
||||||
<ListItem key="tactics" disablePadding sx={{ display: 'block' }}>
|
|
||||||
<ListItemButton sx={{ minHeight: 48, justifyContent: showSidePanel ? 'initial' : 'center', px: 2.5 }} onClick={() => setShowSidePanel(true)}>
|
|
||||||
<ListItemIcon sx={{minWidth: 0, mr: showSidePanel ? 3 : 'auto', justifyContent: 'center' }}>
|
|
||||||
<FontAwesomeIcon icon={faHammer}></FontAwesomeIcon>
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText primary="Known Tactics" sx={{ display: showSidePanel ? null : "none" }} />
|
|
||||||
</ListItemButton>
|
|
||||||
{spells && spells.length > 0 &&
|
|
||||||
<Paper sx={{ px: 2, py: 1, display: showSidePanel ? null : "none" }} elevation={0} >
|
|
||||||
{spells.map((spell) => <TacticDoc key={spell.name} tactic={spell} />)}
|
|
||||||
</Paper>}
|
|
||||||
</ListItem>
|
|
||||||
<ListItem key="lemmas" disablePadding sx={{ display: 'block' }}>
|
|
||||||
<ListItemButton sx={{ minHeight: 48, justifyContent: showSidePanel ? 'initial' : 'center', px: 2.5 }} >
|
|
||||||
<ListItemIcon sx={{minWidth: 0, mr: showSidePanel ? 3 : 'auto', justifyContent: 'center' }}>
|
|
||||||
<FontAwesomeIcon icon={faBook}></FontAwesomeIcon>
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText primary="Known Lemmas" sx={{ display: showSidePanel ? null : "none" }} />
|
|
||||||
</ListItemButton>
|
|
||||||
{inventory && inventory.length > 0 &&
|
|
||||||
<Paper sx={{ px: 2, py: 1, mt: 2, display: showSidePanel ? null : "none" }} elevation={0} >
|
|
||||||
<LemmaDocs lemmas={inventory} />
|
|
||||||
</Paper>}
|
|
||||||
</ListItem>
|
|
||||||
</List>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LeftPanel;
|
|
@ -0,0 +1,38 @@
|
|||||||
|
.inventory {
|
||||||
|
padding: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inventory h2 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: .2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.inventory h2.doc {
|
||||||
|
margin-top: 1.5em;
|
||||||
|
font-weight: 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inventory-list {
|
||||||
|
display: flex;
|
||||||
|
gap: .5em;
|
||||||
|
flex-wrap : wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inventory .item {
|
||||||
|
background: #fff;
|
||||||
|
border: solid 1px #777;
|
||||||
|
padding: .1em .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inventory .item.locked,
|
||||||
|
.inventory .item.disabled {
|
||||||
|
border: solid 1px #ccc;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.inventory .item:not(.locked):not(.disabled) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
Loading…
Reference in New Issue