8000 web: supports python · brpapa/recursion-tree-visualizer@624cd35 · GitHub
[go: up one dir, main page]

Skip to content 8000

Commit 624cd35

Browse files
committed
web: supports python
1 parent 0ecfdb2 commit 624cd35

File tree

15 files changed

+4432
-4343
lines changed

15 files changed

+4432
-4343
lines changed

packages/web/package-lock.json

Lines changed: 4232 additions & 4172 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/web/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "web",
2+
"name": "web-client",
33
"version": "1.0.0",
44
"author": "Bruno Papa <bruno.papa@hotmail.com>",
55
"private": true,
@@ -24,11 +24,11 @@
2424
"@types/react": "^16.9.32",
2525
"@types/react-dom": "^16.9.6",
2626
"@types/styled-components": "^5.0.1",
27-
"@typescript-eslint/eslint-plugin": "^2.34.0",
28-
"@typescript-eslint/parser": "^2.34.0",
27+
"@typescript-eslint/eslint-plugin": "^4.19.0",
28+
"@typescript-eslint/parser": "^4.19.0",
2929
"eslint": "^6.8.0",
30-
"eslint-plugin-react": "^7.20.6",
31-
"eslint-plugin-react-hooks": "^4.1.0",
30+
"eslint-plugin-react": "^7.23.1",
31+
"eslint-plugin-react-hooks": "^4.2.0",
3232
"react-scripts": "^4.0.3",
3333
"typescript": "^3.8.3"
3434
},

packages/web/src/components/app/styles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const Sidebar = styled.div`
1414
1515
width: 100%;
1616
${({theme}) => theme.devices.desktop} {
17-
width: 350px;
17+
width: 390px;
1818
}
1919
`
2020
export const Main = styled.div`

packages/web/src/components/function-form/code-editor/index.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,30 @@ type Props = {
1616
lang: Language
1717
value: string
1818
onValueChange: (value: string) => void
19+
onValueReset?: () => void
1920
shouldValueChange?: (value: string) => boolean
2021
}
2122

2223
const CodeEditor = ({
2324
lang,
2425
value,
2526
onValueChange,
27+
onValueReset,
2628
shouldValueChange,
2729
}: Props) => {
2830
const theme = useContext(ThemeContext)
2931

3032
const onCodeChange = useCallback(
3133
(newCode: string) => {
34+
if (onValueReset && /^(\s*)$/.test(newCode)) {
35+
onValueReset()
36+
return
37+
}
38+
3239
if (!shouldValueChange || shouldValueChange(newCode))
3340
onValueChange(newCode)
3441
},
35-
[onValueChange, shouldValueChange]
42+
[onValueChange, onValueReset, shouldValueChange]
3643
)
3744

3845
const highlight = useCallback(

packages/web/src/components/function-form/index.tsx

Lines changed: 98 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,27 @@ import { ThemeContext } from 'styled-components'
33
import { toast } from 'react-hot-toast'
44

55
import * as s from './styles'
6-
import Switch from './switch'
76
import CodeEditor from './code-editor'
87
import { buildFnCodeValidator, buildFnCallValidator } from './validators'
9-
import { buildFnCodeDecomposer, buildFnCodeComposer, composeFnData, decomposeFnData } from './template-handler'
8+
import {
9+
buildFnCodeDecomposer,
10+
buildFnCodeComposer,
11+
composeFnData,
12+
decomposeFnData,
13+
} from './template-handler'
1014
import templates from '../../config/templates'
1115
import useFormInput from '../../hooks/use-form-input'
1216
import useCarbonAds from '../../hooks/use-carbon-ads'
1317
import useLocalStorage from '../../hooks/use-local-storage'
14-
import { Template, ThemeType, FunctionData, Language } from '../../types'
18+
import {
19+
Template,
20+
ThemeType,
21+
FunctionData,
22+
Language,
23< 8000 span class="diff-text-marker">+
GlobalVar,
24+
} from '../../types'
1525
import './carbon-ads.css'
16-
import { DEFAULT_LANGUAGE, DEFAULT_TEMPLATE, LANGUAGES } from '../../config/consts'
17-
18-
type GlobalVar = { name: string; value: string }
26+
import * as consts from '../../config/consts'
1927

2028
type Props = {
2129
onSubmit: (
@@ -27,30 +35,32 @@ type Props = {
2735
}
2836

2937
const FunctionForm = ({ onSubmit, onThemeChange }: Props) => {
30-
const [lang, setLang] = useLocalStorage<Language>('fn-lang', DEFAULT_LANGUAGE)
38+
const [lang, setLang] = useLocalStorage<Language>(
39+
'fn-lang',
40+
consts.DEFAULT_LANGUAGE
41+
)
3142
const [fnCall, setFnCall] = useFormInput(
3243
'fn-call',
3344
'fn()',
3445
buildFnCallValidator(lang)
3546
)
36-
const [fnCode, setFnCode] = useLocalStorage('fn-code', buildFnCodeComposer(DEFAULT_LANGUAGE)())
47+
const [fnCode, setFnCode] = useLocalStorage('fn-code', consts.DEFAULT_FN_CODE)
3748
const [fnGlobalVars, setFnGlobalVars] = useLocalStorage<GlobalVar[]>(
3849
'fn-global-vars',
39-
[
40-
{ name: '', value: '' },
41-
{ name: '', value: '' },
42-
]
50+
consts.DEFAULT_GLOBAL_VARS
4351
)
4452

4553
const [memoize, setMemoize] = useLocalStorage('memoize', false)
4654
const [animate, setAnimate] = useLocalStorage('animate', true)
47-
55+
4856
const theme = useContext(ThemeContext)
4957

50-
// if null, user changed the default template code
51-
const [activeTemplate, setActiveTemplate] = useState<Template | null>(DEFAULT_TEMPLATE)
52-
53-
const adsRef = useCarbonAds()
58+
// if null, user changed the default code that comes in with template
59+
const [activeTemplate, setActiveTemplate] = useState<Template | null>(
60+
consts.DEFAULT_TEMPLATE
61+
)
62+
63+
const divRefAds = useCarbonAds()
5464

5565
const handleSelectTemplateChange = (
5666
e: React.ChangeEvent<HTMLSelectElement>
@@ -64,39 +74,37 @@ const FunctionForm = ({ onSubmit, onThemeChange }: Props) => {
6474
setFnGlobalVars(res.fnGlobalVars)
6575
}
6676

67-
// useEffect(() => {
68-
// console.log(activeTemplate)
69-
// }, [activeTemplate])
70-
71-
// const handleSelectLanguageChange = (
72-
// e: React.ChangeEvent<HTMLSelectElement>
73-
// ) => {
74-
// const newLang = e.target.value as Language
75-
// setLang(newLang)
76-
77-
// // DOING: testing (selecione um template node, mude o codigo manualmente e mude pra python)
78-
// if (activeTemplate === null) {
79-
// // keep user-defined body and params names (both contained in fnCode)
80-
// setFnCode((prevFnCode) => {
81-
// const decomposeFnCode = buildFnCodeDecomposer(lang)
82-
// const composeFnCode = buildFnCodeComposer(newLang)
83-
// return composeFnCode(decomposeFnCode(prevFnCode))
84-
// })
85-
// } else {
86-
// const { fnCode, fnCall, fnGlobalVars } = decomposeFnData(
87-
// templates[activeTemplate].fnData[newLang],
88-
// newLang
89-
// )
90-
// setFnCode(fnCode)
91-
// setFnCall(fnCall)
92-
// setFnGlobalVars(fnGlobalVars)
93-
// }
94-
// }
77+
const handleSelectLanguageChange = (
78+
e: React.ChangeEvent<HTMLSelectElement>
79+
) => {
80+
const newLang = e.target.value as Language
81+
setLang(newLang)
82+
83+
if (activeTemplate === null) {
84+
// keep only the previous params names (inside fnCode)
85+
setFnCode((prevFnCode) => {
86+
const decomposeFnCode = buildFnCodeDecomposer(lang)
87+
const composeFnCode = buildFnCodeComposer(newLang)
88+
89+
const { paramsNames } = decomposeFnCode(prevFnCode)
90+
return composeFnCode({ paramsNames })
91+
})
92+
} else {
93+
const { fnCode, fnCall, fnGlobalVars } = decomposeFnData(
94+
templates[activeTemplate].fnData[newLang],
95+
newLang
96+
)
97+
setFnCode(fnCode)
98+
setFnCall(fnCall)
99+
setFnGlobalVars(fnGlobalVars)
100+
}
101+
}
95102

96103
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
97104
e.preventDefault()
98105

99106
// client-side validation
107+
// TODO: remover try/catch
100108
try {
101109
const fnData = composeFnData(fnCode, fnCall.value, fnGlobalVars, lang) // throw error
102110
onSubmit(lang, fnData, { memoize, animate })
@@ -108,7 +116,7 @@ const FunctionForm = ({ onSubmit, onThemeChange }: Props) => {
108116
return (
109117
<s.FormContainer onSubmit={handleFormSubmit}>
110118
<s.FormContent>
111-
<div ref={adsRef} />
119+
<div ref={divRefAds} />
112120

113121
<s.Title>Pre-defined templates</s.Title>
114122
<s.Select
@@ -135,7 +143,7 @@ const FunctionForm = ({ onSubmit, onThemeChange }: Props) => {
135143
})
136144
}}
137145
/>
138-
<span style={{margin: '0 0.3em'}}>=</span>
146+
<span style={{ margin: '0 0.3em' }}>=</span>
139147
<CodeEditor
140148
lang={lang}
141149
value={value}
@@ -149,40 +157,60 @@ const FunctionForm = ({ onSubmit, onThemeChange }: Props) => {
149157
</s.VariableContainer>
150158
))}
151159

152-
{/* <s.Title>Language</s.Title>
153-
<s.Select value={lang} onChange={handleSelectLanguageChange}>
154-
{LANGUAGES.map((lang) => (
155-
<option key={lang} value={lang}>
156-
{lang}
157-
</option>
158-
))}
159-
</s.Select> */}
160-
161160
<s.Title>Recursive function</s.Title>
162-
<CodeEditor
163-
lang={lang}
164-
value={fnCode}
165-
shouldValueChange={buildFnCodeValidator(lang)}
166-
onValueChange={(newValue) => {
167-
setFnCode((prevValue) => {
168-
if (prevValue !== newValue) setActiveTemplate(null)
169-
return newValue
170-
})
171-
}}
172-
/>
161+
<div style={{ position: 'relative' }}>
162+
<s.Select
163+
value={lang}
164+
onChange={handleSelectLanguageChange}
165+
style={{
166+
position: 'absolute',
167+
top: '-27px',
168+
right: '0',
169+
width: '80px',
170+
height: '22px',
171+
fontSize: '14px'
172+
}}
173+
>
174+
{consts.LANGUAGES.map((lang) => (
175+
<option key={lang} value={lang}>
176+
{lang}
177+
</option>
178+
))}
179+
</s.Select>
180+
<CodeEditor
181+
lang={lang}
182+
value={fnCode}
183+
shouldValueChange={buildFnCodeValidator(lang)}
184+
onValueChange={(newValue) => {
185+
setFnCode((prevValue) => {
186+
if (prevValue !== newValue) setActiveTemplate(null)
187+
return newValue
188+
})
189+
}}
190+
onValueReset={() => {
191+
const composeFnCode = buildFnCodeComposer(lang)
192+
setFnCode(composeFnCode())
193+
}}
194+
/>
195+
</div>
173196

174197
<s.Title>Options</s.Title>
175198
<s.Option>
176199
<span>Enable step-by-step animation</span>
177-
<Switch checked={animate} onChange={() => setAnimate((p) => !p)} />
200+
<s.Switch checked={animate} onChange={() => setAnimate((p) => !p)} />
178201
</s.Option>
179202
<s.Option>
180203
<span>Enable memoization</span>
181-
<Switch checked={memoize} onChange={() => setMemoize((p) => !p)} />
204+
<s.Switch checked={memoize} onChange={() => setMemoize((p) => !p)} />
182205
</s.Option>
183206
<s.Option>
184207
<span>Enable dark mode</span>
185-
<Switch checked={theme.type === 'dark'} onChange={() => onThemeChange(theme.type === 'light'? 'dark' : 'light')} />
208+
<s.Switch
209+
checked={theme.type === 'dark'}
210+
onChange={() =>
211+
onThemeChange(theme.type === 'light' ? 'dark' : 'light')
212+
}
213+
/>
186214
</s.Option>
187215
</s.FormContent>
188216

packages/web/src/components/function-form/styles.ts

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ const commonFormItem = css`
1818

1919
export const Title = styled.p`
2020
padding-top: 1.4em;
21-
padding-bottom: 0.2em;
21+
padding-bottom: 0.3em;
2222
padding-left: 0.1em;
2323
font-weight: bold;
24-
font-size: 1.05em;
24+
font-size: 1.10em;
2525
`
2626
export const Select = styled.select`
2727
${commonFormItem}
@@ -68,14 +68,6 @@ export const SubmitButton = styled(Button).attrs({ type: 'submit' })`
6868
border: 0;
6969
}
7070
`
71-
export const Error = styled.p`
72-
border-radius: 5px;
73-
margin-top: 15px;
74-
padding: 2px;
75-
text-align: center;
76-
background-color: ${({ theme }) => theme.colors.error};
77-
color: white;
78-
`
7971
export const VariableContainer = styled.div`
8072
display: flex;
8173
align-items: center;
@@ -114,3 +106,49 @@ export const FormContainer = styled.form`
114106
justify-content: space-between;
115107
height: 100%;
116108
`
109+
110+
export const Switch = styled.input.attrs({ type: 'checkbox' })`
111+
--active: ${({ theme }) => theme.colors.primary};
112+
--active-inner: #fff;
113+
--border: ${({ theme }) => theme.colors.borderAccent};
114+
--background: ${({ theme }) => theme.colors.foregroundAccent};
115+
116+
appearance: none;
117+
height: 21px;
118+
width: 38px;
119+
border-radius: 11px;
120+
outline: none;
121+
display: inline-block;
122+
vertical-align: top;
123+
position: relative;
124+
margin: 0;
125+
margin-right: 0.2em;
126+
cursor: pointer;
127+
border: 1px solid var(--bc, var(--border));
128+
background: var(--b, var(--background));
129+
130+
&:after {
131+
content: '';
132+
display: block;
133+
position: absolute;
134+
transition: transform var(--d-t, 0.3s) var(--d-t-e, ease),
135+
opacity var(--d-o, 0.2s);
136+
left: 2px;
137+
top: 2px;
138+
border-radius: 50%;
139+
width: 15px;
140+
height: 15px;
141+
background: var(--ab, var(--border));
142+
transform: translateX(var(--x, 0));
143+
}
144+
145+
&:checked {
146+
--b: var(--active);
147+
--bc: var(--active);
148+
--d-o: 0.3s;
149+
--d-t: 0.6s;
150+
--d-t-e: cubic-bezier(0.2, 0.85, 0.32, 1.2);
151+
--ab: var(--active-inner);
152+
--x: 17px;
153+
}
154+
`

packages/web/src/components/function-form/switch/index.tsx

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)
0