diff --git a/public/electron.js b/public/electron.js index 8b438b1d..e22f42cb 100644 --- a/public/electron.js +++ b/public/electron.js @@ -1,13 +1,16 @@ const electron = require('electron'); const path = require('path'); const url = require('url'); +const fs = require('fs'); const { ipcMain } = require('electron'); const loadBalancer = require('electron-load-balancer'); const { app } = electron; -const { BrowserWindow } = electron; +const { BrowserWindow, dialog } = electron; const nativeImage = electron.nativeImage; +const { extractFileName } = require('../src/utils/fileNameProcessor'); + if (process.env.DEV) { const { default: installExtension, @@ -41,7 +44,7 @@ function createWindow() { icon, webPreferences: { nodeIntegration: true, - enableRemoteModule: true, + enableRemoteModule: false, }, minWidth: 500, minHeight: 300, @@ -149,3 +152,96 @@ ipcMain.on('FETCH_LA', (event, args) => { ipcMain.on('SENSORS_SCAN', (event, args) => { mainWindow.webContents.send('SENSORS_SCAN', args); }); + +ipcMain.handle('OPEN_IMPORT_WINDOW', async (event, dataPath) => { + return dialog + .showOpenDialog(null, { + title: 'Select file(s) to import', + filters: [{ name: 'Data File', extensions: ['csv'] }], + properties: ['openFile', 'multiSelections'], + }) + .then(result => { + if (result.filePaths) { + var message = 'Import successful'; + result.filePaths.forEach(filePath => { + const fileName = extractFileName(filePath); + fs.copyFile(filePath, `${dataPath}/${fileName}`, err => { + if (err) { + console.log(err); + message = 'Import failed'; + } + }); + }); + } + return message; + }) + .catch(err => { + console.log(err); + }); +}); + +ipcMain.handle('OPEN_EXPORT_WINDOW', async (event, filePath) => { + return dialog + .showOpenDialog(null, { + title: 'Select export location', + properties: ['openDirectory'], + }) + .then(result => { + const dirPath = result.filePaths[0]; + if (dirPath) { + var message = 'Export successful'; + const fileName = extractFileName(filePath); + fs.copyFile(filePath, `${dirPath}/${fileName}`, err => { + if (err) { + console.log(err); + message = 'Export failed'; + } + }); + return message; + } + }) + .catch(err => { + console.log(err); + }); +}); + +ipcMain.handle('MAKE_DIRECTORY', (event, dirPath) => { + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } +}); + +ipcMain.handle('DELETE_FILE', (event, path) => { + fs.unlink(path, err => { + if (err) { + console.log(err); + } + }); +}); + +ipcMain.handle('LIST_FILES', (event, dirPath, extension) => { + const processedFiles = fs + .readdirSync(dirPath) + .filter(files => { + return path.extname(files).toLowerCase() === extension; + }) + .map(file => { + const filepath = path.join(dirPath, file); + return { + name: file, + filepath, + metaData: getMetaData(filepath), + }; + }); + return processedFiles; +}); + +getMetaData = path => { + const content = fs.readFileSync(path, 'utf8'); + const data = content.split(/\r?\n/)[0].split(','); + return { + device: data[0], + date: data[1], + time: data[2], + }; +}; diff --git a/src/App.js b/src/App.js index ca49054c..ee3bf47c 100644 --- a/src/App.js +++ b/src/App.js @@ -252,7 +252,9 @@ class App extends Component { /> } + render={props => ( + + )} /> } /> diff --git a/src/components/Appshell/Appshell.js b/src/components/Appshell/Appshell.js index 71e8d8ee..ab667537 100644 --- a/src/components/Appshell/Appshell.js +++ b/src/components/Appshell/Appshell.js @@ -31,7 +31,6 @@ import { Stop as StopRecordIcon, ShoppingCart as CartIcon, } from '@material-ui/icons'; -import { extractFileName } from '../../utils/fileNameProcessor'; import { Save as SaveIcon } from '@material-ui/icons'; import AppIcon from '../../resources/app_icon.png'; import { @@ -50,10 +49,7 @@ import ConnectedIcon from '../../resources/device_connected.svg'; import { openSnackbar } from '../../redux/actions/app'; const electron = window.require('electron'); -const { remote } = window.require('electron'); const { ipcRenderer } = electron; -const fs = remote.require('fs'); -const { dialog } = remote; const loadBalancer = window.require('electron-load-balancer'); const styles = theme => ({ @@ -84,26 +80,12 @@ const Appshell = ({ const [drawerOpen, toggleDrawer] = useState(false); const [menuOpen, toggleMenu] = useState(null); - const openImportWindow = () => { - dialog.showOpenDialog( - null, - { - title: 'Select file to import', - properties: ['openFile'], - filters: [{ name: 'Data File', extensions: ['csv'] }], - }, - filePath => { - if (filePath) { - const fileName = extractFileName(filePath[0]); - fs.copyFile(filePath[0], `${dataPath}/${fileName}`, err => { - if (err) { - openSnackbar({ message: 'Import failed' }); - } - openSnackbar({ message: 'Import successful' }); - }); - } - }, - ); + const openImportWindow = async () => { + ipcRenderer.invoke('OPEN_IMPORT_WINDOW', dataPath).then(message => { + if (message) { + openSnackbar({ message }); + } + }); }; const layoutButtonRenderer = location => { diff --git a/src/screen/LoggedData/LoggedData.js b/src/screen/LoggedData/LoggedData.js index 08952bbb..28332476 100644 --- a/src/screen/LoggedData/LoggedData.js +++ b/src/screen/LoggedData/LoggedData.js @@ -28,16 +28,11 @@ import { InstrumentWrapper, EmptyWrapper, } from './LoggedData.styles.js'; -import { - fileNameTrimmer, - extractFileName, -} from '../../utils/fileNameProcessor'; +import { fileNameTrimmer } from '../../utils/fileNameProcessor'; import { openSnackbar } from '../../redux/actions/app'; -const { remote } = window.require('electron'); -const fs = remote.require('fs'); -const os = remote.require('os'); -const path = remote.require('path'); -const { dialog } = remote; + +const electron = window.require('electron'); +const { ipcRenderer } = electron; const chokidar = window.require('chokidar'); class LoggedData extends Component { @@ -49,84 +44,46 @@ class LoggedData extends Component { }; } - componentDidMount() { - this.destDir = path.join(os.homedir(), 'Documents', 'PSLab'); - if (!fs.existsSync(this.destDir)) { - fs.mkdirSync(this.destDir, { recursive: true }); - } - this.watcher = chokidar.watch(this.destDir); + componentDidMount = async () => { + const { dataPath } = this.props; + await ipcRenderer.invoke('MAKE_DIRECTORY', dataPath); + this.watcher = chokidar.watch(dataPath); this.setState({ loading: true, }); - this.listFiles('.csv'); this.watcher.on('all', (event, path) => { this.listFiles('.csv'); }); - } + }; componentWillUnmount() { this.watcher.unwatch(this.destDir); } - openExportWindow(filePath) { + openExportWindow = async filePath => { const { openSnackbar } = this.props; - const fileName = extractFileName(filePath); - dialog.showOpenDialog( - null, - { - title: 'Select export location', - properties: ['openDirectory'], - }, - dirPath => { - dirPath && - fs.copyFile(filePath, `${dirPath}/${fileName}`, err => { - if (err) { - openSnackbar({ message: 'Export failed' }); - } - openSnackbar({ message: 'Export successful' }); - }); - }, - ); - } + ipcRenderer.invoke('OPEN_EXPORT_WINDOW', filePath).then(message => { + if (message) { + openSnackbar({ message: message }); + } + }); + }; listFiles = extension => { - fs.readdir(this.destDir, (err, files) => { - const processedFiles = files - .filter(files => { - return path.extname(files).toLowerCase() === extension; - }) - .map(file => { - const filepath = path.join(this.destDir, file); - return { - name: file, - filepath, - metaData: this.getMetaData(filepath), - }; + const { dataPath } = this.props; + ipcRenderer + .invoke('LIST_FILES', dataPath, extension) + .then(processedFiles => { + this.setState({ + fileList: processedFiles, + loading: false, }); - this.setState({ - fileList: processedFiles, - loading: false, }); - }); }; deleteFile = path => { - fs.unlink(path, err => { - if (err) { - console.log(err); - } - }); - }; - - getMetaData = path => { - const content = fs.readFileSync(path, 'utf8'); - const data = content.split(/\r?\n/)[0].split(','); - return { - device: data[0], - date: data[1], - time: data[2], - }; + ipcRenderer.invoke('DELETE_FILE', path); }; iconRenderer = device => { diff --git a/src/utils/fileNameProcessor.js b/src/utils/fileNameProcessor.js index 6d5aa0e3..ce2208b8 100644 --- a/src/utils/fileNameProcessor.js +++ b/src/utils/fileNameProcessor.js @@ -1,4 +1,4 @@ -export const fileNameTrimmer = (n, len) => { +exports.fileNameTrimmer = (n, len) => { const ext = n.substring(n.lastIndexOf('.') + 1, n.length).toLowerCase(); let filename = n.replace('.' + ext, ''); if (filename.length <= len) { @@ -8,7 +8,7 @@ export const fileNameTrimmer = (n, len) => { return filename + '.' + ext; }; -export const extractFileName = filePath => { +exports.extractFileName = filePath => { const fileArray = filePath.split('/'); return fileArray[fileArray.length - 1]; };