Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit 1266d9c

Browse files
committed
feat: add tui editor
1 parent 72cfe63 commit 1266d9c

File tree

9 files changed

+173
-2
lines changed

9 files changed

+173
-2
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"dependencies": {
5757
"@popperjs/core": "^2.5.4",
5858
"@reach/router": "^1.3.4",
59+
"@toast-ui/react-editor": "^2.5.1",
5960
"axios": "^0.21.0",
6061
"classnames": "^2.2.6",
6162
"express": "^4.17.1",

src/components/FormField/index.jsx

+11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { Field } from "react-final-form";
99
import { FORM_FIELD_TYPE } from "../../constants";
1010
import TextInput from "../../components/TextInput";
1111
import TextArea from "../../components/TextArea";
12+
import TuiEditor from "../../components/TuiEditor";
1213
import ReactSelect from "../../components/ReactSelect";
1314
import DateInput from "../../components/DateInput";
1415
import "./styles.module.scss";
@@ -59,6 +60,16 @@ const FormField = ({ field }) => {
5960
step={field.step}
6061
/>
6162
)}
63+
{field.type === FORM_FIELD_TYPE.TUIEDITOR && (
64+
<TuiEditor
65+
placeholder={field.placeholder}
66+
value={input?.value ?? ""}
67+
onChange={input.onChange}
68+
// onBlur={input.onBlur}
69+
// onFocus={input.onFocus}
70+
className={meta.error && meta.touched ? "error" : ""}
71+
/>
72+
)}
6273
{field.type === FORM_FIELD_TYPE.TEXTAREA && (
6374
<TextArea
6475
placeholder={field.placeholder}

src/components/TuiEditor/index.jsx

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* TuiEditor
3+
*/
4+
5+
import React, { useState } from "react";
6+
import PropTypes from "prop-types";
7+
import cn from "classnames";
8+
import { Editor } from "@toast-ui/react-editor";
9+
import styles from "./styles.module.scss";
10+
11+
const TuiEditor = (props) => {
12+
const [editorElement, setEditorElement] = useState(null);
13+
const onChange = () => {
14+
const mk = editorElement.editorInst.getMarkdown();
15+
props.onChange(mk);
16+
};
17+
return (
18+
<div className={cn(styles["editor-container"], props.className)}>
19+
<Editor
20+
{...props}
21+
ref={setEditorElement}
22+
onChange={onChange}
23+
initialValue={props.value}
24+
/>
25+
</div>
26+
);
27+
};
28+
29+
TuiEditor.defaultProps = {
30+
height: "320px",
31+
minHeight: "320px",
32+
initialValue: "",
33+
previewStyle: "",
34+
initialEditType: "wysiwyg",
35+
language: "en-US",
36+
useCommandShortcut: true,
37+
customHTMLSanitizer: null,
38+
frontMatter: false,
39+
hideModeSwitch: true,
40+
referenceDefinition: false,
41+
usageStatistics: false,
42+
useDefaultHTMLSanitizer: true,
43+
};
44+
45+
TuiEditor.propTypes = {
46+
// Editor's initial value
47+
value: PropTypes.string,
48+
className: PropTypes.string,
49+
// Markdown editor's preview style (tab, vertical)
50+
previewStyle: PropTypes.string.isRequired,
51+
// Editor's height style value. Height is applied as border-box ex) '300px', '100%', 'auto'
52+
height: PropTypes.string,
53+
// Initial editor type (markdown, wysiwyg)
54+
initialEditType: PropTypes.string,
55+
// Editor's min-height style value in pixel ex) '300px'
56+
minHeight: PropTypes.string,
57+
// The placeholder text of the editable element.
58+
placeholder: PropTypes.string,
59+
// hide mode switch tab bar
60+
hideModeSwitch: PropTypes.bool,
61+
// language, 'en-US'
62+
language: PropTypes.string,
63+
// whether use keyboard shortcuts to perform commands
64+
useCommandShortcut: PropTypes.bool,
65+
// It would be emitted when editor fully load1
66+
onLoad: PropTypes.func,
67+
// It would be emitted when content changed
68+
onChange: PropTypes.func,
69+
// It would be emitted when format change by cursor position
70+
onStateChange: PropTypes.func,
71+
// It would be emitted when editor get focus
72+
onFocus: PropTypes.func,
73+
// It would be emitted when editor loose focus
74+
onBlur: PropTypes.func,
75+
// hooks
76+
hooks: PropTypes.arrayOf(PropTypes.object),
77+
// send hostname to google analytics
78+
usageStatistics: PropTypes.bool,
79+
// use default htmlSanitizer
80+
useDefaultHTMLSanitizer: PropTypes.bool,
81+
// toolbar items.
82+
toolbarItems: PropTypes.arrayOf(PropTypes.object),
83+
// Array of plugins. A plugin can be either a function or an array in the form of [function, options].
84+
plugins: PropTypes.arrayOf(PropTypes.object),
85+
// Using extended Autolinks specified in GFM spec
86+
extendedAutolinks: PropTypes.object,
87+
// convertor extention
88+
customConvertor: PropTypes.object,
89+
// Attributes of anchor element that should be rel, target, contenteditable, hreflang, type
90+
linkAttribute: PropTypes.object,
91+
// Object containing custom renderer functions correspond to markdown node
92+
customHTMLRenderer: PropTypes.object,
93+
// whether use the specification of link reference definition
94+
referenceDefinition: PropTypes.bool,
95+
// custom HTML sanitizer
96+
customHTMLSanitizer: PropTypes.func,
97+
// whether use the front matter
98+
frontMatter: PropTypes.bool,
99+
};
100+
101+
export default TuiEditor;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@import "styles/include";
2+
3+
.editor-container {
4+
margin-top: 10px;
5+
6+
:global {
7+
// reset style for heading list in headings selection popup
8+
.tui-popup-body {
9+
h1,h2,h3,h4,h4,h5,h6 {
10+
font-weight: revert;
11+
line-height: revert;
12+
}
13+
}
14+
15+
// reset border color
16+
.tui-editor-defaultUI {
17+
border: 1px solid #aaaaab
18+
}
19+
20+
.te-toolbar-section {
21+
border-bottom: 1px solid #aaaaab
22+
}
23+
24+
// hide uplodd file
25+
.tui-editor-popup{
26+
box-shadow: 0px 0px 15px 5px rgba(0,0,0,0.26);
27+
}
28+
29+
.te-popup-add-image .te-tab button, .te-popup-add-image .te-file-type{
30+
display: none !important;
31+
}
32+
33+
.te-popup-add-image .te-url-type{
34+
display: block !important;
35+
}
36+
}
37+
}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* TuiEditorViewer
3+
*/
4+
5+
import React, { useState } from "react";
6+
import PropTypes from "prop-types";
7+
import { Viewer } from "@toast-ui/react-editor";
8+
9+
const TuiEditorViewer = (props) => <Viewer initialValue={props.value} />;
10+
11+
TuiEditorViewer.propTypes = {
12+
value: PropTypes.string,
13+
};
14+
15+
export default TuiEditorViewer;

src/constants/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ export const ACTION_TYPE = {
168168
export const FORM_FIELD_TYPE = {
169169
TEXT: "text",
170170
TEXTAREA: "textarea",
171+
TUIEDITOR: "tuieditor",
171172
NUMBER: "number",
172173
SELECT: "select",
173174
MULTISELECT: "multiselect",

src/routes/JobDetails/index.jsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { useData } from "hooks/useData";
1212
import { getJobById } from "services/jobs";
1313
import { getSkills } from "services/skills";
1414
import LoadingIndicator from "../../components/LoadingIndicator";
15+
import TuiEditorViewer from "../../components/TuiEditorViewer";
1516
import withAuthentication from "../../hoc/withAuthentication";
1617
import DataItem from "../../components/DataItem";
1718
import IconSkill from "../../assets/images/icon-skill.svg";
@@ -64,7 +65,7 @@ const JobDetails = ({ teamId, jobId }) => {
6465
{job.title}
6566
</DataItem>
6667
<DataItem title="Job Description" icon={<IconDescription />}>
67-
{job.description}
68+
<TuiEditorViewer value={job.description} />
6869
</DataItem>
6970
<DataItem title="Number of Openings" icon={<IconOpenings />}>
7071
{job.numPositions}

src/routes/JobForm/utils.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const getEditJobConfig = (skillOptions, onSubmit) => {
4242
},
4343
{
4444
label: "Job Description",
45-
type: FORM_FIELD_TYPE.TEXTAREA,
45+
type: FORM_FIELD_TYPE.TUIEDITOR,
4646
name: "description",
4747
placeholder: "Job Description",
4848
},

src/styles/main.vendor.scss

+4
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
@import "~react-redux-toastr/src/styles/index";
55
@import "~react-responsive-modal/styles";
66
@import "~react-loader-spinner/dist/loader/css/react-spinner-loader.css";
7+
8+
// toast-ui.react-editor styles
9+
@import "~codemirror/lib/codemirror.css";
10+
@import "~@toast-ui/editor/dist/toastui-editor.css"

0 commit comments

Comments
 (0)