Skip to content

Commit 49659ce

Browse files
authored
Merge pull request #166 from Rahuljagwani/Markdown
Create Help, Help(.md for node file) added | Options button introduced
2 parents bfba8a8 + e5a02ee commit 49659ce

18 files changed

Lines changed: 1971 additions & 29 deletions

package-lock.json

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

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
2828
"react-dom": "^17.0.2",
2929
"react-icons": "^4.2.0",
3030
"react-keyed-file-browser": "^1.14.0",
31+
"react-markdown": "^8.0.7",
3132
"react-modal": "^3.13.1",
3233
"react-scripts": "4.0.3",
3334
"react-simple-code-editor": "^0.13.0",
35+
"react-spinners": "^0.13.8",
3436
"react-toastify": "^8.0.0",
3537
"react-tooltip": "^4.2.21",
3638
"web-vitals": "^0.2.4",

src/App.jsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import FileDragDrop from './component/File-drag-drop';
1414
import HistoryModal from './component/modals/History';
1515
import LocalFileBrowser from './component/fileBrowser';
1616
import FileEditModal from './component/modals/FileEdit';
17+
import MarkDown from './component/modals/markDown';
18+
import OptionsModal from './component/modals/OptionsModal';
19+
import Loader from './component/modals/Loader';
1720

1821
const app = () => {
1922
const [superState, dispatcher] = useReducer(reducer, initialState);
@@ -34,10 +37,14 @@ const app = () => {
3437
<SettingsModal superState={superState} dispatcher={dispatcher} />
3538
<HistoryModal superState={superState} dispatcher={dispatcher} />
3639
<FileEditModal superState={superState} dispatcher={dispatcher} />
40+
<OptionsModal superState={superState} dispatcher={dispatcher} />
41+
<Loader superState={superState} />
3742
<GraphCompDetails
3843
closeModal={() => dispatcher({ type: T.Model_Close })}
3944
superState={superState}
45+
dispatcher={dispatcher}
4046
/>
47+
<MarkDown superState={superState} dispatcher={dispatcher} />
4148
<FileDragDrop dispatcher={dispatcher} />
4249
<Header superState={superState} dispatcher={dispatcher} />
4350
<section className="body" style={{ display: 'flex', overflow: 'hidden' }}>

src/component/fileBrowser.jsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ const LocalFileBrowser = ({ superState, dispatcher }) => {
3030
window.localStorage.setItem('fileList', JSON.stringify(fileState));
3131
}, [fileState]);
3232

33+
useEffect(() => {
34+
setFileState(superState.fileState);
35+
}, [superState.fileState]);
36+
3337
const handleSelectFile = (data) => {
3438
const fileExtensions = ['jpeg', 'jpg', 'png', 'exe'];
3539
if (fileExtensions.includes(data.fileObj.name.split('.').pop())) {
@@ -67,7 +71,7 @@ const LocalFileBrowser = ({ superState, dispatcher }) => {
6771
modified: fileData.lastModified,
6872
size: fileData.size,
6973
fileObj: fileData,
70-
fileHandle: value,
74+
fileHandle: valueSubDir,
7175
}]);
7276
} else if (valueSubDir.kind === 'directory') {
7377
topLevel = `${topKey}/${value.name}`;
@@ -100,6 +104,7 @@ const LocalFileBrowser = ({ superState, dispatcher }) => {
100104
setFileState([]);
101105
setFileState(state);
102106
dispatcher({ type: T.SET_DIR_NAME, payload: state[0].key.split('/')[0] });
107+
dispatcher({ type: T.SET_FILE_STATE, payload: state });
103108
};
104109

105110
const newFeatureFile = async () => {

src/component/modals/FileEdit.jsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ const FileEditModal = ({ superState, dispatcher }) => {
4949
const stream = await handle.createWritable();
5050
await stream.write(codeStuff);
5151
await stream.close();
52+
const fileData = await handle.getFile();
53+
let fS = superState.fileState;
54+
fS = fS.concat([{
55+
key: `${superState.uploadedDirName}/${handle.name}`,
56+
modified: fileData.lastModified,
57+
size: fileData.size,
58+
fileObj: fileData,
59+
fileHandle: handle,
60+
}]);
61+
dispatcher({ type: T.SET_FILE_STATE, payload: fS });
5262
// dispatcher({ type: T.EDIT_TEXTFILE, payload: { show: false } });
5363
}
5464

@@ -105,7 +115,10 @@ const FileEditModal = ({ superState, dispatcher }) => {
105115
<button type="submit" className="btn btn-primary" onClick={submit}>Save</button>
106116
)}
107117
{dirButton && (
108-
<button type="submit" className="btn btn-primary" onClick={saveAsSubmit}>Save As</button>
118+
<button type="submit" className="btn btn-primary" onClick={saveAsSubmit}>
119+
Save
120+
{fileName ? ' As' : ''}
121+
</button>
109122
)}
110123
{!dirButton && (
111124
<button type="submit" className="btn btn-primary" onClick={saveSubmit}>Save As</button>

src/component/modals/GraphCompDetails.jsx

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
1+
import { toast } from 'react-toastify';
12
import React, { useState, useEffect } from 'react';
23
import './graph-comp-details.css';
34
import ParentModal from './ParentModal';
5+
import { readTextFile, createFile } from '../../toolbarActions/toolbarFunctions';
6+
import { actionType as T } from '../../reducer';
47

5-
const ModalComp = ({ closeModal, superState }) => {
8+
const ModalComp = ({ closeModal, superState, dispatcher }) => {
69
const [data, setData] = useState({});
710
const [errorMessage, setErrorMessage] = useState('');
11+
const [element, setElement] = useState(null);
12+
const [editSourceClicked, setEditSourceClicked] = useState(false);
13+
const [createSourceClicked, setCreateSourceClicked] = useState(false);
14+
const [createHelpClicked, setCreateHelpClicked] = useState(false);
815
const { modalPayload, ModelOpen } = superState;
916
const {
10-
cb, title, submitText, Children, defaultStyle, defaultLabel, labelAllowed,
17+
cb, title, submitText, Children, defaultStyle, defaultLabel, labelAllowed, type,
1118
} = modalPayload;
1219

1320
useEffect(() => {
@@ -29,15 +36,117 @@ const ModalComp = ({ closeModal, superState }) => {
2936
} else setErrorMessage(message.err);
3037
};
3138

39+
useEffect(() => {
40+
if (createSourceClicked) {
41+
createFile(superState, dispatcher);
42+
}
43+
if (editSourceClicked && element === null) {
44+
toast.error('Respective file is not present in same directory');
45+
} else if (element !== null) {
46+
readTextFile(superState, dispatcher, element.fileObj, element.fileHandle);
47+
}
48+
setEditSourceClicked(false);
49+
setCreateSourceClicked(false);
50+
}, [createSourceClicked, editSourceClicked]);
51+
52+
useEffect(() => {
53+
if (createHelpClicked) {
54+
createFile(superState, dispatcher);
55+
}
56+
setCreateHelpClicked(false);
57+
}, [createHelpClicked]);
58+
59+
const openFile = () => {
60+
setElement(null);
61+
if (superState.fileState !== undefined && data.label !== '') {
62+
const fname = data.label.split(':')[1];
63+
superState.fileState.forEach((ele) => {
64+
if (ele.key.split('/')[1] === fname || ele.key.split('/')[2] === fname) {
65+
setElement(ele);
66+
}
67+
});
68+
}
69+
if (submitText === 'Edit Node') {
70+
setEditSourceClicked(true);
71+
} else if (submitText === 'Create Node') {
72+
setCreateSourceClicked(true);
73+
}
74+
};
75+
76+
const openDoc = () => {
77+
setElement(null);
78+
if (superState.fileState !== undefined && data.label !== '') {
79+
const docname1 = data.label.split(':')[1].split('.')[0].concat('.md');
80+
const docname2 = data.label.split(':')[1].split('.')[0].concat('.txt');
81+
superState.fileState.forEach((ele) => {
82+
if (ele.key.split('/')[1] === docname1 || ele.key.split('/')[1] === docname2) {
83+
setElement(ele);
84+
}
85+
});
86+
}
87+
setCreateHelpClicked(true);
88+
};
89+
90+
const openMarkDownDoc = async () => {
91+
dispatcher({ type: T.SET_MARKDOWN_MODAL, payload: true });
92+
setElement(null);
93+
if (superState.fileState !== undefined && data.label !== '') {
94+
const docname1 = data.label.split(':')[1].split('.')[0].concat('.md');
95+
const matchingElement = superState.fileState.find((ele) => ele.key.split('/')[1] === docname1);
96+
if (matchingElement) {
97+
const fr = new FileReader();
98+
fr.onload = (x) => {
99+
// eslint-disable-next-line max-len
100+
dispatcher({ type: T.SET_INPUT_FILE, payload: { content: x.target.result, fname: matchingElement.key.split('/')[1] } });
101+
};
102+
if (matchingElement.fileHandle) {
103+
fr.readAsText(await matchingElement.fileHandle.getFile());
104+
} else if (matchingElement.fileObj) {
105+
fr.readAsText(matchingElement.fileObj);
106+
}
107+
setElement(matchingElement);
108+
}
109+
}
110+
};
111+
32112
return (
33113
<ParentModal closeModal={closeModal} ModelOpen={ModelOpen} title={title}>
34114
<form onSubmit={submit}>
35115
<div className="modal-content-body">
36-
<Children data={data} setData={setData} labelAllowed={labelAllowed} />
116+
<Children data={data} setData={setData} labelAllowed={labelAllowed} state={superState} />
37117
{errorMessage ? <div className="err">{errorMessage}</div> : <></>}
38118
</div>
39119
<div className="modal-footer">
40120
<button type="submit" className="btn btn-primary">{submitText}</button>
121+
{ type === 'Node' ? (
122+
<>
123+
<button
124+
className="btn btn-primary"
125+
type="button"
126+
onClick={openFile}
127+
>
128+
{ submitText === 'Edit Node' ? 'Edit Source' : 'Create Source' }
129+
</button>
130+
{ title === 'Edit Node'
131+
? (
132+
<button
133+
className="btn btn-primary"
134+
type="button"
135+
onClick={openMarkDownDoc}
136+
>
137+
Help
138+
</button>
139+
) : (
140+
<button
141+
className="btn btn-primary"
142+
type="button"
143+
onClick={openDoc}
144+
>
145+
Create Help
146+
</button>
147+
)}
148+
</>
149+
) : '' }
41150
</div>
42151
</form>
43152
</ParentModal>

src/component/modals/Loader.jsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
import BeatLoader from 'react-spinners/BeatLoader';
3+
import ParentModal from './ParentModal';
4+
5+
const Loader = ({ superState }) => (
6+
<ParentModal ModelOpen={superState.loader} title="Wait........">
7+
<BeatLoader color="#36d7b7" />
8+
</ParentModal>
9+
);
10+
11+
export default Loader;

src/component/modals/NodeDetails.jsx

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import './nodeDetails.css';
66
import localStorageManager from '../../graph-builder/local-storage-manager';
77

88
const NodeDetails = ({
9-
data, setData, submit, labelAllowed,
9+
data, setData, submit, labelAllowed, state,
1010
}) => {
1111
const inputRef = useCallback((node) => node && node.focus(), []);
1212
const textRef = createRef();
1313
const [widthSet] = useState(false);
14+
const [mdList, setMdList] = useState([]);
15+
const [mdCont, setMdCont] = useState(new Map(''));
1416
const [labelName, setLabelName] = useState('');
1517
const [labelFile, setLabelFile] = useState('');
1618
const indexOfFile = [];
@@ -20,6 +22,25 @@ const NodeDetails = ({
2022
setData({ ...data, style: { ...data.style, ...prop } });
2123
};
2224

25+
useEffect(() => {
26+
const list = mdList;
27+
state.fileState.forEach((ele) => {
28+
if (ele.key.toString().includes('.md')) {
29+
list.push(ele);
30+
setMdList(list);
31+
let mdmap = new Map();
32+
mdmap = mdCont;
33+
const fr = new FileReader();
34+
fr.onload = (x) => {
35+
const strCont = ' DESC: ';
36+
mdmap.set(ele, strCont.concat(x.target.result.slice(0, 50).replace('#', '')));
37+
setMdCont(mdmap);
38+
};
39+
fr.readAsText(ele.fileObj);
40+
}
41+
});
42+
}, [state.fileState]);
43+
2344
useEffect(() => {
2445
if (!widthSet) {
2546
setStyle({
@@ -101,35 +122,63 @@ const NodeDetails = ({
101122
type="text"
102123
label="Node Label file"
103124
placeholder="Select file"
125+
value={data.label.split(':')[1]}
104126
onChange={(e) => {
105-
setLabelFile(e.target.value.split('/').pop());
127+
setLabelFile(e.target.value.split('/').pop().split(' DESC: ')[0]);
106128
if (labelName) {
107129
let lname = labelName;
108130
if (labelName.slice(-1) !== ':') {
109131
setLabelName(`${labelName}:`);
110132
lname += ':';
111133
}
112-
setData({ ...data, label: lname + e.target.value.split('/').pop() });
113-
} else setData({ ...data, label: `:${e.target.value.split('/').pop()}` });
134+
setData({
135+
...data,
136+
// eslint-disable-next-line max-len
137+
label: lname + e.target.value.split('/').pop().split(' DESC: ')[0],
138+
});
139+
} else {
140+
setData({
141+
...data,
142+
// eslint-disable-next-line max-len
143+
label: `:${e.target.value.split('/').pop().split(' DESC: ')[0]}`,
144+
});
145+
}
114146
}}
115147
list="files"
116148
/>
117149
<datalist id="files">
118150
{
119151
localStorageManager.getFileList()
120152
// eslint-disable-next-line max-len, prefer-arrow-callback
121-
? JSON.parse(localStorageManager.getFileList())
153+
? state.fileState
122154
.map((item) => {
123155
const list = [];
124156
const acceptedTypes = ['.v', '.c', '.cpp', '.py', '.m', '.sh'];
125157
let index;
158+
if (item.key.toString().includes('.md')) {
159+
return null;
160+
}
126161
// eslint-disable-next-line max-len
127162
if ((acceptedTypes.some((substring) => item.key.toString().includes(substring)))) {
128-
list.push(item.key.toString());
163+
const fileName = item.key.toString().split('.')[0].concat('.md');
164+
// eslint-disable-next-line max-len
165+
const matchingFile = mdList.find((ele) => ele.key.toString() === fileName);
166+
if (mdCont.get(matchingFile)) {
167+
list.push(item.key.toString().concat(mdCont.get(matchingFile)));
168+
} else {
169+
list.push(item.key.toString());
170+
}
129171
indexOfFile.push(indexOfFile[indexOfFile.length - 1] + 1);
130172
index = indexOfFile[indexOfFile.length - 1] + 1;
131-
// eslint-disable-next-line jsx-a11y/control-has-associated-label
132-
return <option value={list} key={index} />;
173+
/* eslint-disable */
174+
return (
175+
<>
176+
<label htmlFor="dropdown">
177+
<option value={list} key={index} />
178+
</label>
179+
</>
180+
);
181+
/* eslint-enable */
133182
}
134183
return null;
135184
})

0 commit comments

Comments
 (0)