Skip to content

Commit eabf5a9

Browse files
authored
Merge pull request #15 from Aviral09/dev
Implementation of save feature in Edge/Chrome
2 parents b33d3eb + e4ef5fc commit eabf5a9

10 files changed

Lines changed: 183 additions & 126 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "concore-editor",
33
"version": "0.1.0",
44
"private": true,
5-
"homepage": "concore-editor",
5+
"homepage": "/concore-editor",
66
"dependencies": {
77
"@szhsin/react-menu": "^1.10.0",
88
"@testing-library/jest-dom": "^5.11.4",

src/App.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const app = () => {
2929
<FileDragDrop dispatcher={dispatcher} />
3030
<Header superState={superState} dispatcher={dispatcher} />
3131
<section className="body" style={{ display: 'flex', overflow: 'hidden' }}>
32-
<div style={{ flex: 15 }}>
32+
<div style={{ display: 'flex' }}>
3333
<LocalFileBrowser dispatcher={dispatcher} />
3434
</div>
3535
<div className="graph" style={{ display: 'flex', overflow: 'hidden' }}>

src/component/fileBrowser.css

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
/* Same file as react-file-browser.css in node modules but with few modifications */
2+
.inputButton{
3+
font-size: large;
4+
text-align: center;
5+
color: #fff;
6+
padding-top: 10px;
7+
padding-bottom: 10px;
8+
width: 100%;
9+
border: 2px solid white;
10+
background-color: #1e88e5;
11+
font-weight: bold;
12+
display: block;
13+
}
14+
15+
216
div.rendered-react-keyed-file-browser div.action-bar {
317
margin-bottom: 0.5rem;
418
flex-wrap: wrap;
@@ -29,8 +43,8 @@ div.rendered-react-keyed-file-browser div.action-bar {
2943
margin-right: 0.5rem; }
3044

3145
div.rendered-react-keyed-file-browser div.files {
32-
overflow-y: scroll;
33-
height: 75vh;
46+
overflow: auto;
47+
width: 30vw;
3448
}
3549

3650
div.rendered-react-keyed-file-browser div.files table {
@@ -47,7 +61,12 @@ div.rendered-react-keyed-file-browser div.files table {
4761
margin: 0;
4862
padding: 0.25rem; }
4963
div.rendered-react-keyed-file-browser div.files table th {
50-
font-weight: bold; }
64+
font-weight: bold;
65+
width:1px;
66+
white-space:nowrap; }
67+
div.rendered-react-keyed-file-browser div.files table td {
68+
width:1px;
69+
white-space:nowrap; }
5170
div.rendered-react-keyed-file-browser div.files table th.size, div.rendered-react-keyed-file-browser div.files table th.modified, div.rendered-react-keyed-file-browser div.files table td.size, div.rendered-react-keyed-file-browser div.files table td.modified {
5271
text-align: right; }
5372
div.rendered-react-keyed-file-browser div.files table th.name i, div.rendered-react-keyed-file-browser div.files table td.name i {

src/component/fileBrowser.jsx

Lines changed: 102 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
/* eslint-disable no-param-reassign */
55
/* eslint-disable react/state-in-constructor */
66
import React, { useEffect, useState } from 'react';
7-
import FileBrowser from 'react-keyed-file-browser';
7+
import FileBrowser, { FileRenderers, FolderRenderers } from 'react-keyed-file-browser';
88
import { readFile, readTextFile } from '../toolbarActions/toolbarFunctions';
99
import { actionType as T } from '../reducer';
1010
import './fileBrowser.css';
1111

1212
const LocalFileBrowser = ({ superState, dispatcher }) => {
1313
const fileRef = React.useRef();
14+
const [dirButton, setDirButton] = useState(false);
1415

1516
useEffect(() => {
17+
if (navigator.userAgent.indexOf('Edg') !== -1 || navigator.userAgent.indexOf('Chrome') !== -1) {
18+
setDirButton(true);
19+
}
1620
dispatcher({ type: T.SET_FILE_REF, payload: fileRef });
1721
}, []);
1822

@@ -26,18 +30,6 @@ const LocalFileBrowser = ({ superState, dispatcher }) => {
2630
// // return files;
2731
// // }
2832
// return { files };
29-
// // files: [
30-
// // {
31-
// // key: '/home/emory/Desktop/github',
32-
// // modified: +Moment().subtract(1, 'hours'),
33-
// // size: 1.5 * 1024 * 1024,
34-
// // },
35-
// // {
36-
// // key: '/concore/demo/sample2.graphml',
37-
// // modified: +Moment().subtract(3, 'days'),
38-
// // size: 545 * 1024,
39-
// // },
40-
// // ],
4133
// });
4234

4335
// TODO
@@ -49,86 +41,114 @@ const LocalFileBrowser = ({ superState, dispatcher }) => {
4941
window.localStorage.setItem('fileList', JSON.stringify(fileState));
5042
}, [fileState]);
5143

52-
// const handleCreateFolder = (key) => {
53-
// setFileState((state) => {
54-
// state.files = state.files.concat([{
55-
// key: key,
56-
// }]);
57-
// console.log(fileState);
58-
// return state;
59-
// });
60-
// };
61-
62-
// TODO
63-
// const handleCreateFiles = (files, prefix) => {
64-
// setFileState((state) => {
65-
// const newFiles = files.map((file) => {
66-
// let newKey = prefix;
67-
// if (prefix !== '' && prefix.substring(prefix.length - 1, prefix.length) !== '/') {
68-
// newKey += '/';
69-
// }
70-
// newKey += file.name;
71-
// return {
72-
// key: newKey,
73-
// size: file.size,
74-
// modified: +Moment(),
75-
// };
76-
// });
77-
78-
// const uniqueNewFiles = [];
79-
// newFiles.map((newFile) => {
80-
// let exists = false;
81-
// state.files.map((existingFile) => {
82-
// if (existingFile.key === newFile.key) {
83-
// exists = true;
84-
// }
85-
// });
86-
// if (!exists) {
87-
// uniqueNewFiles.push(newFile);
88-
// }
89-
// });
90-
// state.files = state.files.concat(uniqueNewFiles);
91-
// return state;
92-
// });
93-
// };
94-
9544
const handleSelectFile = (data) => {
96-
if (data.fileObj.name.split('.').pop() === 'graphml') readFile(superState, dispatcher, data.fileObj);
45+
// eslint-disable-next-line max-len
46+
if (data.fileObj.name.split('.').pop() === 'graphml') readFile(superState, dispatcher, data.fileObj, data.fileHandle);
9747
else {
98-
readTextFile(superState, dispatcher, data.fileObj);
48+
readTextFile(superState, dispatcher, data.fileObj, data.fileHandle);
49+
}
50+
};
51+
52+
const handleFileInDirs = async (topKey, value) => {
53+
let state = [];
54+
// eslint-disable-next-line no-restricted-syntax
55+
for await (const [key, valueSubDir] of value.entries()) {
56+
if (valueSubDir.kind === 'file') {
57+
const fileData = await valueSubDir.getFile();
58+
state = state.concat([{
59+
key: `${topKey}/${value.name}/${key}`,
60+
modified: fileData.lastModified,
61+
size: fileData.size,
62+
fileObj: fileData,
63+
fileHandle: value,
64+
}]);
65+
} else if (valueSubDir.kind === 'directory') {
66+
const res = await handleFileInDirs();
67+
state = state.concat(res);
68+
}
69+
}
70+
return state;
71+
};
72+
73+
const newFeature = async () => {
74+
const dirHandle = await window.showDirectoryPicker();
75+
let state = [];
76+
// eslint-disable-next-line no-restricted-syntax
77+
for await (const [key, value] of dirHandle.entries()) {
78+
if (value.kind === 'file') {
79+
const fileData = await value.getFile();
80+
state = state.concat([{
81+
key: `${dirHandle.name}/${key}`,
82+
modified: fileData.lastModified,
83+
size: fileData.size,
84+
fileObj: fileData,
85+
fileHandle: value,
86+
}]);
87+
} else if (value.kind === 'directory') {
88+
const res = await handleFileInDirs(dirHandle.name, value);
89+
state = state.concat(res);
90+
}
9991
}
92+
setFileState([]);
93+
setFileState(state);
10094
};
10195

10296
return (
10397
<div>
104-
<input
105-
type="file"
106-
ref={fileRef}
107-
onClick={(e) => { e.target.value = null; }}
108-
onChange={(e) => {
109-
setFileState((state) => {
110-
for (let i = 0; i < e.target.files.length; i += 1) {
111-
state = state.concat([{
112-
key: e.target.files[i].name,
113-
modified: e.target.files[i].lastModifiedDate,
114-
size: e.target.files[i].size,
115-
fileObj: e.target.files[i],
116-
}]);
117-
}
118-
return state;
119-
});
120-
window.localStorage.setItem('fileList', JSON.stringify(fileState));
121-
}}
122-
directory
123-
webkitdirectory="true"
124-
/>
98+
{!dirButton && (
99+
<label
100+
className="inputButton"
101+
htmlFor="fileButton"
102+
>
103+
Upload Directory
104+
<input
105+
type="file"
106+
accept=".py, .m, .c, .cpp, .v, .sh"
107+
ref={fileRef}
108+
id="fileButton"
109+
style={{ display: 'none' }}
110+
onClick={(e) => { e.target.value = null; }}
111+
onChange={(e) => {
112+
setFileState([]);
113+
setFileState((state) => {
114+
for (let i = 0; i < e.target.files.length; i += 1) {
115+
state = state.concat([{
116+
key: e.target.files[i].webkitRelativePath,
117+
modified: e.target.files[i].lastModified,
118+
size: e.target.files[i].size,
119+
fileObj: e.target.files[i],
120+
}]);
121+
}
122+
return state;
123+
});
124+
window.localStorage.setItem('fileList', JSON.stringify(fileState));
125+
}}
126+
directory
127+
webkitdirectory="true"
128+
/>
129+
</label>
130+
) }
131+
{dirButton && (
132+
<button
133+
type="button"
134+
className="inputButton"
135+
disabled={!dirButton}
136+
onClick={newFeature}
137+
>
138+
Upload Directory
139+
</button>
140+
)}
141+
<h4>
142+
Folder Name :
143+
{' '}
144+
{fileState[0] ? fileState[0].key.split('/')[0] : '' }
145+
</h4>
125146
<FileBrowser
126147
files={fileState}
127148
onSelectFile={handleSelectFile}
128149
detailRenderer={() => null}
129-
// TODO
130-
// onCreateFolder={handleCreateFolder}
131-
// onCreateFiles={handleCreateFiles}
150+
fileRenderer={FileRenderers.TableFile}
151+
folderRenderer={FolderRenderers.TableFolder}
132152
/>
133153
</div>
134154
);

src/component/modals/EdgeDetails.jsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useCallback } from 'react';
2-
import ColorBox from './ColorBox';
2+
// import ColorBox from './ColorBox';
33
import './edgeDetails.css';
44

55
const Triangle = ({ size, color }) => {
@@ -18,20 +18,20 @@ const Triangle = ({ size, color }) => {
1818
const EdgeDetails = ({
1919
data, setData, submit, labelAllowed,
2020
}) => {
21-
const setStyle = (prop) => setData({ ...data, style: { ...data.style, ...prop } });
21+
// const setStyle = (prop) => setData({ ...data, style: { ...data.style, ...prop } });
2222
const inputRef = useCallback((node) => node && node.focus(), []);
23-
const RadioBtn = ({ name, shape }) => (
24-
<label htmlFor="ellipse">
25-
<input
26-
type="radio"
27-
name="shape"
28-
value={shape}
29-
checked={data.style.shape === shape}
30-
onChange={() => setStyle({ shape })}
31-
/>
32-
{name}
33-
</label>
34-
);
23+
// const RadioBtn = ({ name, shape }) => (
24+
// <label htmlFor="ellipse">
25+
// <input
26+
// type="radio"
27+
// name="shape"
28+
// value={shape}
29+
// checked={data.style.shape === shape}
30+
// onChange={() => setStyle({ shape })}
31+
// />
32+
// {name}
33+
// </label>
34+
// );
3535

3636
return (
3737
<div className="edgeform" onSubmit={submit}>
@@ -61,7 +61,7 @@ const EdgeDetails = ({
6161
onChange={(e) => setData({ ...data, label: `${e.target.value}` })}
6262
/>
6363
) : ''}
64-
<div> Shape</div>
64+
{/* <div> Shape</div>
6565
<div className="span-rest hascheckbox">
6666
<div><RadioBtn name="Solid" shape="solid" /></div>
6767
<div><RadioBtn name="Dotted" shape="dotted" /></div>
@@ -78,7 +78,7 @@ const EdgeDetails = ({
7878
color={data.style.backgroundColor}
7979
setColor={(color) => setStyle({ backgroundColor: color })}
8080
type="dark"
81-
/>
81+
/> */}
8282
</div>
8383
</div>
8484
);

src/component/modals/FileEdit.jsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ const FileEditModal = ({ superState, dispatcher }) => {
1414
const close = () => dispatcher({ type: T.EDIT_TEXTFILE, payload: { show: false } });
1515
// TODO - Save file
1616
async function submit() {
17-
// eslint-disable-next-line prefer-const
18-
// let fileHandle = superState.fileObj;
19-
// console.log(fileHandle);
20-
// const stream = await fileHandle.createWriter();
21-
// await stream.write(codeStuff);
22-
// await stream.close();
17+
if (superState.fileHandle) {
18+
const stream = await superState.fileHandle.createWritable();
19+
await stream.write(codeStuff);
20+
await stream.close();
21+
} else {
22+
// eslint-disable-next-line no-alert
23+
alert('Switch to Edge/Chrome!');
24+
}
2325
dispatcher({ type: T.EDIT_TEXTFILE, payload: { show: false } });
2426
}
2527

@@ -41,6 +43,9 @@ const FileEditModal = ({ superState, dispatcher }) => {
4143
title={fileName}
4244
>
4345
<div className="File Edit Container">
46+
<div className="footer">
47+
<button type="submit" className="btn btn-primary" onClick={submit}>Save</button>
48+
</div>
4449
<div
4550
style={{
4651
minHeight: '400px',

0 commit comments

Comments
 (0)