Skip to content

Commit 040553d

Browse files
BandanaKMHailey
andauthored
feat(Codebytes): move language selection component disc 354 (#17)
* working version * update to include gamut styles * add simple code editor * add editor container styles * fix prettier issues * pass onCopy from parent * use isIframeProp * pass down snippets base url from parent * simple monaco editor * update tslint for scale * incorporate review feedback * fix prettier issues * default snippets endpoint to empty string * use rem * update example text * use language prop * add language selection comp * use colors gray * remove env file * run prettier * change function name to onEdit * update story names * comment on change handlers * update stories * fix prettier * pairing session - new props, types, and passing on handler * use monaco-editor/react package * update monaco editor package version * remove comments * add additional story for language and text not provided * update text * update stories * update stories * fix typings * remove gitignore * use theme navy * fix linting issues * update dependencies * slight change in editorOnMount naming * fix linting issues * rename env * remove eslint comment * fix lint * update select * fix linter error * use pascal case for language option * fix lint * package bump Co-authored-by: Hailey <[email protected]>
1 parent 7845d30 commit 040553d

File tree

8 files changed

+140
-31
lines changed

8 files changed

+140
-31
lines changed

packages/codebytes/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@codecademy/codebytes",
33
"description": "Codebytes Code Editor",
4-
"version": "0.3.0",
4+
"version": "0.3.1",
55
"author": "Codecademy Engineering <[email protected]>",
66
"sideEffects": [
77
"**/*.css",

packages/codebytes/src/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { languageOption } from './consts';
1+
import type { LanguageOption } from './consts';
22

33
interface Response {
44
stderr: string;
@@ -7,7 +7,7 @@ interface Response {
77
}
88

99
interface PostSnippetData {
10-
language: languageOption;
10+
language: LanguageOption;
1111
code: string;
1212
}
1313

packages/codebytes/src/consts.ts

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// key = language param to send to snippets service
22
// val = label in language selection drop down
3-
export const languageOptions = {
4-
'': 'Select your language',
3+
export const LanguageOptions = {
4+
'': 'Select a language',
55
cpp: 'C++',
66
csharp: 'C#',
77
golang: 'Go',
@@ -12,4 +12,53 @@ export const languageOptions = {
1212
scheme: 'Scheme',
1313
};
1414

15-
export type languageOption = keyof typeof languageOptions;
15+
export type LanguageOption = keyof typeof LanguageOptions;
16+
17+
export const validLanguages = Object.keys(LanguageOptions).filter(
18+
(option) => !!option
19+
) as LanguageOption[];
20+
21+
const cpp = `#include <iostream>
22+
int main() {
23+
std::cout << "Hello world!";
24+
return 0;
25+
}`;
26+
27+
const csharp = `namespace HelloWorld {
28+
class Hello {
29+
static void Main(string[] args) {
30+
System.Console.WriteLine("Hello world!");
31+
}
32+
}
33+
}`;
34+
35+
const golang = `package main
36+
import "fmt"
37+
func main() {
38+
fmt.Println("Hello world!")
39+
}`;
40+
41+
const javascript = "console.log('Hello world!');";
42+
43+
const php = `<?php
44+
echo "Hello world!";
45+
?>`;
46+
47+
const python = "print('Hello world!')";
48+
49+
const ruby = 'puts "Hello world!"';
50+
51+
const scheme = `(begin
52+
(display "Hello world!")
53+
(newline))`;
54+
55+
export const helloWorld = {
56+
cpp,
57+
csharp,
58+
golang,
59+
javascript,
60+
php,
61+
python,
62+
ruby,
63+
scheme,
64+
} as const;

packages/codebytes/src/editor.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import styled from '@emotion/styled';
1010
import React, { useState } from 'react';
1111

1212
import { postSnippet } from './api';
13-
import type { languageOption } from './consts';
13+
import type { LanguageOption } from './consts';
1414
import { Drawers } from './drawers';
1515
import { SimpleMonacoEditor } from './MonacoEditor';
1616

@@ -36,7 +36,7 @@ const DOCKER_SIGTERM = 143;
3636

3737
type EditorProps = {
3838
hideCopyButton: boolean;
39-
language: languageOption;
39+
language: LanguageOption;
4040
text: string;
4141
onChange: (text: string) => void;
4242
onCopy?: (text: string, language: string) => void;

packages/codebytes/src/index.tsx

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,21 @@ import { StyleProps } from '@codecademy/variance';
55
import styled from '@emotion/styled';
66
import React, { useState } from 'react';
77

8-
import { languageOption } from './consts';
8+
import { helloWorld, LanguageOption } from './consts';
99
import { Editor } from './editor';
10+
import { LanguageSelection } from './languageSelection';
11+
12+
type CodebytesChangeHandler = (text: string, language: LanguageOption) => void;
1013

1114
export interface CodeByteEditorProps {
1215
text: string;
13-
language: languageOption;
16+
language: LanguageOption;
1417
hideCopyButton: boolean;
15-
onCopy?: (text: string, language: string) => void;
18+
onCopy?: CodebytesChangeHandler;
1619
isIFrame?: boolean;
17-
snippetsBaseUrl?: string /* TODO in DISC-353: Determine best way to host and include snippets endpoint for both staging and production in both the monolith and next.js repo. */;
18-
onTextChange?: (text: string) => void;
20+
snippetsBaseUrl?: string;
21+
onEdit?: CodebytesChangeHandler;
22+
onLanguageChange?: CodebytesChangeHandler;
1923
}
2024

2125
const editorStates = states({
@@ -42,14 +46,15 @@ const EditorContainer = styled(Background)<EditorStyleProps>(
4246

4347
export const CodeByteEditor: React.FC<CodeByteEditorProps> = ({
4448
text: initialText,
45-
language,
49+
language: initialLanguage,
4650
hideCopyButton,
47-
onCopy,
4851
isIFrame = false,
4952
snippetsBaseUrl = process.env.CONTAINER_API_BASE,
50-
onTextChange,
53+
onEdit,
54+
onLanguageChange,
5155
}) => {
5256
const [text, setText] = useState<string>(initialText);
57+
const [language, setLanguage] = useState<LanguageOption>(initialLanguage);
5358
return (
5459
<EditorContainer bg="black" as="main" isIFrame={isIFrame}>
5560
<Box borderBottom={1} borderColor="gray-900" py={4} pl={8}>
@@ -62,17 +67,28 @@ export const CodeByteEditor: React.FC<CodeByteEditorProps> = ({
6267
aria-label="visit codecademy.com"
6368
/>
6469
</Box>
65-
<Editor
66-
language={language}
67-
text={text}
68-
hideCopyButton={hideCopyButton}
69-
onChange={(newText: string) => {
70-
setText(newText);
71-
onTextChange?.(newText);
72-
}}
73-
onCopy={onCopy}
74-
snippetsBaseUrl={snippetsBaseUrl}
75-
/>
70+
{language ? (
71+
<Editor
72+
language={language}
73+
text={text}
74+
hideCopyButton={hideCopyButton}
75+
onChange={(newText: string) => {
76+
setText(newText);
77+
onEdit?.(newText, language);
78+
}}
79+
snippetsBaseUrl={snippetsBaseUrl}
80+
/>
81+
) : (
82+
<LanguageSelection
83+
onChange={(newLanguage) => {
84+
const newText: string =
85+
text || (newLanguage ? helloWorld[newLanguage] : '');
86+
setLanguage(newLanguage);
87+
setText(newText);
88+
onLanguageChange?.(newText, newLanguage);
89+
}}
90+
/>
91+
)}
7692
</EditorContainer>
7793
);
7894
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Select, Text } from '@codecademy/gamut';
2+
import { ColorMode } from '@codecademy/gamut-styles';
3+
import React from 'react';
4+
5+
import type { LanguageOption } from './consts';
6+
import { LanguageOptions } from './consts';
7+
8+
export type LanguageSelectionProps = {
9+
onChange: (newLanguage: LanguageOption) => void;
10+
};
11+
12+
export const LanguageSelection: React.FC<LanguageSelectionProps> = ({
13+
onChange,
14+
}) => {
15+
return (
16+
<ColorMode mode="dark" flex={1} px={16} pt={48}>
17+
<Text mb={16}>Which language do you want to code in?</Text>
18+
<Select
19+
id="language-select"
20+
aria-label="Select a language"
21+
options={LanguageOptions}
22+
onChange={(e) => onChange(e.target.value as LanguageOption)}
23+
/>
24+
</ColorMode>
25+
);
26+
};

packages/styleguide/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
"@babel/cli": "^7.13.10",
1818
"@babel/core": "^7.13.10",
1919
"@codecademy/gamut": "^42.1.1",
20-
"@codecademy/variance": "*",
2120
"@codecademy/webpack-config": "^6.0.0",
21+
"@codecademy/variance": "*",
2222
"@emotion/cache": "^11.4.0",
2323
"@emotion/react": "^11.4.0",
2424
"@emotion/styled": "^11.3.0",

packages/styleguide/stories/CodeByteEditor.stories.mdx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ import { Canvas, Meta, Story } from '@storybook/addon-docs/blocks';
2020

2121
<Canvas>
2222
<Story
23-
name="default"
23+
name="Language and text provided"
2424
args={{
2525
text:
2626
'console.log("Welcome to the Codebytes Editor!");',
27-
language: 'javascript',
2827
snippetsBaseUrl: process.env.CONTAINER_API_BASE,
28+
language: "javascript"
2929
}}
3030
>
3131
{(args) => (
@@ -40,4 +40,22 @@ import { Canvas, Meta, Story } from '@storybook/addon-docs/blocks';
4040
</GamutProvider>
4141
)}
4242
</Story>
43-
</Canvas>
43+
<Story
44+
name="Language and text not provided"
45+
args={{
46+
snippetsBaseUrl: process.env.CONTAINER_API_BASE,
47+
}}
48+
>
49+
{(args) => (
50+
<GamutProvider
51+
cache={createEmotionCache({ container: document.head })}
52+
theme={theme}
53+
>
54+
<AssetProvider />
55+
<AppWrapper>
56+
<CodeByteEditor {...args} />
57+
</AppWrapper>
58+
</GamutProvider>
59+
)}
60+
</Story>
61+
</Canvas>

0 commit comments

Comments
 (0)