Skip to content

Commit d406eb5

Browse files
cynthi8orangecms
authored andcommitted
refactor: Migrate from remote and fix Datalogger
Remote calls are removed in preperation for Electron 10, and showOpenDialog calls in Datalogger are fixed. showOpenDialog was promisified in Electron 7 and file import/export has been broken ever since. feat (File Import) - Allows multiple files to be selected refactor (File Import): Removed remote usage Main process now handles the dialog window creation and file copying. refactor (Logged Data): Removed remote usage Main process now handles the dataPath directory creation, directory reading, Export File dialog, and deleting files. dataPath is now pulled from App props instead of redefining it in LoggedData. refactor: Set enableRemoteModule to false fix: Export and Import snackbox messages
1 parent 832580a commit d406eb5

File tree

5 files changed

+133
-96
lines changed

5 files changed

+133
-96
lines changed

public/electron.js

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
const electron = require('electron');
22
const path = require('path');
33
const url = require('url');
4+
const fs = require('fs');
45
const { ipcMain } = require('electron');
56
const loadBalancer = require('electron-load-balancer');
67

78
const { app } = electron;
8-
const { BrowserWindow } = electron;
9+
const { BrowserWindow, dialog } = electron;
910
const nativeImage = electron.nativeImage;
1011

12+
const { extractFileName } = require('../src/utils/fileNameProcessor');
13+
1114
if (process.env.DEV) {
1215
const {
1316
default: installExtension,
@@ -41,7 +44,7 @@ function createWindow() {
4144
icon,
4245
webPreferences: {
4346
nodeIntegration: true,
44-
enableRemoteModule: true,
47+
enableRemoteModule: false,
4548
},
4649
minWidth: 500,
4750
minHeight: 300,
@@ -149,3 +152,96 @@ ipcMain.on('FETCH_LA', (event, args) => {
149152
ipcMain.on('SENSORS_SCAN', (event, args) => {
150153
mainWindow.webContents.send('SENSORS_SCAN', args);
151154
});
155+
156+
ipcMain.handle('OPEN_IMPORT_WINDOW', async (event, dataPath) => {
157+
return dialog
158+
.showOpenDialog(null, {
159+
title: 'Select file(s) to import',
160+
filters: [{ name: 'Data File', extensions: ['csv'] }],
161+
properties: ['openFile', 'multiSelections'],
162+
})
163+
.then(result => {
164+
if (result.filePaths) {
165+
var message = 'Import successful';
166+
result.filePaths.forEach(filePath => {
167+
const fileName = extractFileName(filePath);
168+
fs.copyFile(filePath, `${dataPath}/${fileName}`, err => {
169+
if (err) {
170+
console.log(err);
171+
message = 'Import failed';
172+
}
173+
});
174+
});
175+
}
176+
return message;
177+
})
178+
.catch(err => {
179+
console.log(err);
180+
});
181+
});
182+
183+
ipcMain.handle('OPEN_EXPORT_WINDOW', async (event, filePath) => {
184+
return dialog
185+
.showOpenDialog(null, {
186+
title: 'Select export location',
187+
properties: ['openDirectory'],
188+
})
189+
.then(result => {
190+
const dirPath = result.filePaths[0];
191+
if (dirPath) {
192+
var message = 'Export successful';
193+
const fileName = extractFileName(filePath);
194+
fs.copyFile(filePath, `${dirPath}/${fileName}`, err => {
195+
if (err) {
196+
console.log(err);
197+
message = 'Export failed';
198+
}
199+
});
200+
return message;
201+
}
202+
})
203+
.catch(err => {
204+
console.log(err);
205+
});
206+
});
207+
208+
ipcMain.handle('MAKE_DIRECTORY', (event, dirPath) => {
209+
if (!fs.existsSync(dirPath)) {
210+
fs.mkdirSync(dirPath, { recursive: true });
211+
}
212+
});
213+
214+
ipcMain.handle('DELETE_FILE', (event, path) => {
215+
fs.unlink(path, err => {
216+
if (err) {
217+
console.log(err);
218+
}
219+
});
220+
});
221+
222+
ipcMain.handle('LIST_FILES', (event, dirPath, extension) => {
223+
const processedFiles = fs
224+
.readdirSync(dirPath)
225+
.filter(files => {
226+
return path.extname(files).toLowerCase() === extension;
227+
})
228+
.map(file => {
229+
const filepath = path.join(dirPath, file);
230+
return {
231+
name: file,
232+
filepath,
233+
metaData: getMetaData(filepath),
234+
};
235+
});
236+
return processedFiles;
237+
});
238+
239+
getMetaData = path => {
240+
const content = fs.readFileSync(path, 'utf8');
241+
const data = content.split(/\r?\n/)[0].split(',');
242+
return {
243+
device: data[0],
244+
date: data[1],
245+
time: data[2],
246+
};
247+
};

src/App.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ class App extends Component {
252252
/>
253253
<Route
254254
path="/loggeddata"
255-
render={props => <LoggedData {...props} />}
255+
render={props => (
256+
<LoggedData {...props} dataPath={dataPath} />
257+
)}
256258
/>
257259
<Route path="/faq" render={props => <FAQ {...props} />} />
258260
<Route path="/settings" component={Settings} />

src/components/Appshell/Appshell.js

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
Stop as StopRecordIcon,
3232
ShoppingCart as CartIcon,
3333
} from '@material-ui/icons';
34-
import { extractFileName } from '../../utils/fileNameProcessor';
3534
import { Save as SaveIcon } from '@material-ui/icons';
3635
import AppIcon from '../../resources/app_icon.png';
3736
import {
@@ -50,10 +49,7 @@ import ConnectedIcon from '../../resources/device_connected.svg';
5049
import { openSnackbar } from '../../redux/actions/app';
5150

5251
const electron = window.require('electron');
53-
const { remote } = window.require('electron');
5452
const { ipcRenderer } = electron;
55-
const fs = remote.require('fs');
56-
const { dialog } = remote;
5753
const loadBalancer = window.require('electron-load-balancer');
5854

5955
const styles = theme => ({
@@ -84,26 +80,12 @@ const Appshell = ({
8480
const [drawerOpen, toggleDrawer] = useState(false);
8581
const [menuOpen, toggleMenu] = useState(null);
8682

87-
const openImportWindow = () => {
88-
dialog.showOpenDialog(
89-
null,
90-
{
91-
title: 'Select file to import',
92-
properties: ['openFile'],
93-
filters: [{ name: 'Data File', extensions: ['csv'] }],
94-
},
95-
filePath => {
96-
if (filePath) {
97-
const fileName = extractFileName(filePath[0]);
98-
fs.copyFile(filePath[0], `${dataPath}/${fileName}`, err => {
99-
if (err) {
100-
openSnackbar({ message: 'Import failed' });
101-
}
102-
openSnackbar({ message: 'Import successful' });
103-
});
104-
}
105-
},
106-
);
83+
const openImportWindow = async () => {
84+
ipcRenderer.invoke('OPEN_IMPORT_WINDOW', dataPath).then(message => {
85+
if (message) {
86+
openSnackbar({ message });
87+
}
88+
});
10789
};
10890

10991
const layoutButtonRenderer = location => {

src/screen/LoggedData/LoggedData.js

Lines changed: 24 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,11 @@ import {
2828
InstrumentWrapper,
2929
EmptyWrapper,
3030
} from './LoggedData.styles.js';
31-
import {
32-
fileNameTrimmer,
33-
extractFileName,
34-
} from '../../utils/fileNameProcessor';
31+
import { fileNameTrimmer } from '../../utils/fileNameProcessor';
3532
import { openSnackbar } from '../../redux/actions/app';
36-
const { remote } = window.require('electron');
37-
const fs = remote.require('fs');
38-
const os = remote.require('os');
39-
const path = remote.require('path');
40-
const { dialog } = remote;
33+
34+
const electron = window.require('electron');
35+
const { ipcRenderer } = electron;
4136
const chokidar = window.require('chokidar');
4237

4338
class LoggedData extends Component {
@@ -49,84 +44,46 @@ class LoggedData extends Component {
4944
};
5045
}
5146

52-
componentDidMount() {
53-
this.destDir = path.join(os.homedir(), 'Documents', 'PSLab');
54-
if (!fs.existsSync(this.destDir)) {
55-
fs.mkdirSync(this.destDir, { recursive: true });
56-
}
57-
this.watcher = chokidar.watch(this.destDir);
47+
componentDidMount = async () => {
48+
const { dataPath } = this.props;
49+
await ipcRenderer.invoke('MAKE_DIRECTORY', dataPath);
50+
this.watcher = chokidar.watch(dataPath);
5851
this.setState({
5952
loading: true,
6053
});
61-
6254
this.listFiles('.csv');
6355
this.watcher.on('all', (event, path) => {
6456
this.listFiles('.csv');
6557
});
66-
}
58+
};
6759

6860
componentWillUnmount() {
6961
this.watcher.unwatch(this.destDir);
7062
}
7163

72-
openExportWindow(filePath) {
64+
openExportWindow = async filePath => {
7365
const { openSnackbar } = this.props;
74-
const fileName = extractFileName(filePath);
75-
dialog.showOpenDialog(
76-
null,
77-
{
78-
title: 'Select export location',
79-
properties: ['openDirectory'],
80-
},
81-
dirPath => {
82-
dirPath &&
83-
fs.copyFile(filePath, `${dirPath}/${fileName}`, err => {
84-
if (err) {
85-
openSnackbar({ message: 'Export failed' });
86-
}
87-
openSnackbar({ message: 'Export successful' });
88-
});
89-
},
90-
);
91-
}
66+
ipcRenderer.invoke('OPEN_EXPORT_WINDOW', filePath).then(message => {
67+
if (message) {
68+
openSnackbar({ message: message });
69+
}
70+
});
71+
};
9272

9373
listFiles = extension => {
94-
fs.readdir(this.destDir, (err, files) => {
95-
const processedFiles = files
96-
.filter(files => {
97-
return path.extname(files).toLowerCase() === extension;
98-
})
99-
.map(file => {
100-
const filepath = path.join(this.destDir, file);
101-
return {
102-
name: file,
103-
filepath,
104-
metaData: this.getMetaData(filepath),
105-
};
74+
const { dataPath } = this.props;
75+
ipcRenderer
76+
.invoke('LIST_FILES', dataPath, extension)
77+
.then(processedFiles => {
78+
this.setState({
79+
fileList: processedFiles,
80+
loading: false,
10681
});
107-
this.setState({
108-
fileList: processedFiles,
109-
loading: false,
11082
});
111-
});
11283
};
11384

11485
deleteFile = path => {
115-
fs.unlink(path, err => {
116-
if (err) {
117-
console.log(err);
118-
}
119-
});
120-
};
121-
122-
getMetaData = path => {
123-
const content = fs.readFileSync(path, 'utf8');
124-
const data = content.split(/\r?\n/)[0].split(',');
125-
return {
126-
device: data[0],
127-
date: data[1],
128-
time: data[2],
129-
};
86+
ipcRenderer.invoke('DELETE_FILE', path);
13087
};
13188

13289
iconRenderer = device => {

src/utils/fileNameProcessor.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const fileNameTrimmer = (n, len) => {
1+
exports.fileNameTrimmer = (n, len) => {
22
const ext = n.substring(n.lastIndexOf('.') + 1, n.length).toLowerCase();
33
let filename = n.replace('.' + ext, '');
44
if (filename.length <= len) {
@@ -8,7 +8,7 @@ export const fileNameTrimmer = (n, len) => {
88
return filename + '.' + ext;
99
};
1010

11-
export const extractFileName = filePath => {
11+
exports.extractFileName = filePath => {
1212
const fileArray = filePath.split('/');
1313
return fileArray[fileArray.length - 1];
1414
};

0 commit comments

Comments
 (0)