Skip to content

Commit ded743a

Browse files
SujalLamalmmrssa
authored andcommitted
markdown editor design
1 parent 2e41cc1 commit ded743a

4 files changed

Lines changed: 209 additions & 1 deletion

File tree

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,20 @@
1111
"aws-amplify": "^3.3.27",
1212
"axios": "^0.21.1",
1313
"dotenv": "^8.2.0",
14-
"immutability-helper": "^3.1.1",
14+
"draft-js": "^0.11.7",
15+
"draftjs-to-markdown": "^0.6.0",
1516
"file-saver": "^2.0.5",
17+
"immutability-helper": "^3.1.1",
1618
"js-file-download": "^0.4.12",
19+
"markdown-draft-js": "^2.3.0",
1720
"moment": "^2.29.1",
1821
"node-sass": "^6.0.0",
1922
"parcel-bundler": "^1.12.4",
2023
"react": "^17.0.2",
2124
"react-dnd": "^14.0.2",
2225
"react-dnd-html5-backend": "^14.0.0",
2326
"react-dom": "^17.0.2",
27+
"react-draft-wysiwyg": "^1.14.7",
2428
"react-dropzone": "^11.3.2",
2529
"react-hook-form": "^6.15.4",
2630
"react-player": "^2.9.0",

src/App.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import AddTest from './screens/addTest/AddTest'
5252
import LogoutUser from './screens/logoutUser/LogoutUser'
5353
import Category from './screens/category/Category'
5454
import PageNotFound from './screens/pageNotFound/PageNotFound'
55+
import MarkDownEditor from './components/markDownEditor/MarkDownEditor'
5556

5657
function App () {
5758
return (
@@ -121,6 +122,7 @@ function App () {
121122
<PrivateRoute component={MyProfile} exact path='/myProfile' />
122123
<PrivateRoute component={UserInfo} exact path='/userInfo' />
123124
<PrivateRoute component={() => <MyCoursePage unpaid='unpaid' />} path='/coursepage' />
125+
<Route path="/markdown-editor" component={MarkDownEditor} />
124126
<PrivateRoute component={PageNotFound} />
125127
</Switch>
126128
</ScrollToTop>
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import React, { useState } from "react";
2+
import { Editor } from "react-draft-wysiwyg";
3+
import "../../../node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
4+
// import draftToMarkdown from "draftjs-to-markdown";
5+
import Button from "../button/Button";
6+
import DashboardLayout from "../../layout/dashboardLayout/DashboardLayout";
7+
import { RichUtils } from 'draft-js';
8+
import { draftToMarkdown, markdownToDraft } from 'markdown-draft-js';
9+
import { EditorState, convertToRaw, convertFromRaw } from 'draft-js';
10+
11+
import './MarkDownEditor.scss'
12+
13+
const MarkDownEditor = () => {
14+
const [editorState, setEditorState] = useState(EditorState.createEmpty());
15+
const [markDown, setMarkDown] = useState(false);
16+
const [markDownText, setMarkDownText] = useState(null);
17+
18+
function onEditorStateChange(editorState) {
19+
setEditorState(editorState);
20+
}
21+
22+
function changeToMarkDown() {
23+
const rawContentState = convertToRaw(editorState.getCurrentContent());
24+
setMarkDownText(draftToMarkdown(rawContentState));
25+
setMarkDown(true)
26+
}
27+
28+
function changeToEditor() {
29+
30+
const markDownData = markdownToDraft(markDownText);
31+
const rawMarkDown = convertFromRaw(markDownData);
32+
33+
setEditorState(EditorState.createWithContent(rawMarkDown))
34+
setMarkDown(false)
35+
}
36+
37+
function uploadImageCallBack(file) {
38+
// return new Promise(
39+
// (resolve, reject) => {
40+
// const xhr = new XMLHttpRequest(); // eslint-disable-line no-undef
41+
// xhr.open('POST', 'https://api.imgur.com/3/image');
42+
// xhr.setRequestHeader('Authorization', 'Client-ID 8d26ccd12712fca');
43+
// const data = new FormData(); // eslint-disable-line no-undef
44+
// data.append('image', file);
45+
// xhr.send(data);
46+
// xhr.addEventListener('load', () => {
47+
// const response = JSON.parse(xhr.responseText);
48+
// resolve(response);
49+
// });
50+
// xhr.addEventListener('error', () => {
51+
// const error = JSON.parse(xhr.responseText);
52+
// reject(error);
53+
// });
54+
// },
55+
// );
56+
}
57+
58+
const toolbarOptions = {
59+
options: ['inline', 'blockType', 'fontSize', 'fontFamily', 'list', 'textAlign', 'link', 'image', 'remove', 'history'],
60+
image: {
61+
className: 'button-color',
62+
uploadCallback: uploadImageCallBack,
63+
previewImage: true
64+
},
65+
// blockType: {
66+
// className: 'button-color'
67+
// },
68+
// inline: {
69+
// className: 'button-color'
70+
// },
71+
// history: {
72+
// className: 'button-color'
73+
// },
74+
// remove: {
75+
// className: 'button-color'
76+
// },
77+
// fontSize: {
78+
// className: 'button-color'
79+
// },
80+
// fontFamily: {
81+
// className: 'button-color'
82+
// },
83+
// list: {
84+
// className: 'button-color'
85+
// },
86+
// textAlign: {
87+
// className: 'button-color'
88+
// },
89+
// link: {
90+
// className: 'button-color'
91+
// },
92+
93+
}
94+
95+
// const styleButton = (array) => {
96+
97+
// const customStyle = array.map(item => Object.prototype.constructor({`${item ":" "button-color"}`}))
98+
// return [...customStyle]
99+
// }
100+
101+
// const styledButtonClass = styleButton(toolbarOptions.options);
102+
// console.log(styledButtonClass)
103+
104+
//styling mark down editor
105+
const editorStyle = {
106+
border: "0.5px solid var(--dropdowns)",
107+
backgroundColor: "var(--cards)",
108+
height: "200px",
109+
borderRadius: '4px',
110+
color: 'var(--primary-white)',
111+
marginBottom: "40px",
112+
padding: '8px',
113+
overflowY: "auto"
114+
}
115+
116+
const toolbarStyle = {
117+
background: 'var(--dropdowns)',
118+
marginBottom: "14px",
119+
border: "0.5px solid var(--dropdowns)",
120+
borderRadius: '4px',
121+
padding: '8px'
122+
}
123+
124+
return (
125+
<>
126+
<div className="mark-down-container">
127+
{!markDown ? <Editor
128+
toolbarStyle={toolbarStyle}
129+
editorStyle={editorStyle}
130+
editorState={editorState}
131+
onEditorStateChange={onEditorStateChange}
132+
toolbar={toolbarOptions}
133+
// toolbarCustomButtons={[<CustomOption />]}
134+
/>
135+
: <textarea style={editorStyle} value={markDownText} onChange={e => setMarkDownText(e.target.value)} />
136+
}
137+
{
138+
!markDown
139+
? <button className="secondary-btn markdown-button" onClick={changeToMarkDown}>Mark down</button>
140+
: <button className="secondary-btn markdown-button" onClick={changeToEditor}>Editor</button>
141+
}
142+
</div>
143+
<div>
144+
</div>
145+
</>
146+
)
147+
}
148+
149+
// const CustomOption = ({editorState, onChange}) => {
150+
151+
// const toggleMarkDown = () => {
152+
// const newState = RichUtils.toggleInlineStyle(
153+
// editorState,
154+
// 'Mark Down',
155+
// );
156+
// if (newState) {
157+
// onChange(newState);
158+
// }
159+
// };
160+
// return(<div className="rdw-storybook-custom-option" onClick={toggleMarkDown}>MD</div>)
161+
// }
162+
163+
export default MarkDownEditor
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
.mark-down-container {
2+
width: 100%;
3+
height: auto;
4+
position: relative;
5+
6+
textarea {
7+
width: 100%;
8+
resize: none;
9+
}
10+
11+
.markdown-button {
12+
position: absolute;
13+
z-index: 100;
14+
bottom: 55px;
15+
right: 10px;
16+
width: 100px;
17+
height: 30px;
18+
padding: 0;
19+
// outline: none;
20+
// border: 1px solid var(--strokes);
21+
// background: var(--background-color);
22+
// color: var(--primary-white);
23+
// padding: 8px 12px;
24+
// border-radius: 4px;
25+
// cursor: pointer;
26+
}
27+
}
28+
29+
.button-color {
30+
background-color: var(--primary-grey);
31+
border-color: var(--primary-grey);
32+
padding: 8px;
33+
}
34+
35+
.rdw-storybook-custom-option {
36+
border: 1px solid #f1f1f1;
37+
padding: 3px 10px;
38+
height: 22px;
39+
}

0 commit comments

Comments
 (0)