diff --git a/client/src/app/api/ontimeApi.js b/client/src/app/api/ontimeApi.js index 4ebc5f73b..71b4678b7 100644 --- a/client/src/app/api/ontimeApi.js +++ b/client/src/app/api/ontimeApi.js @@ -28,7 +28,6 @@ export const downloadEvents = async () => { }; export const uploadEvents = async (file) => { - console.log('uploading', file); const formData = new FormData(); formData.append('jsondb', file); // appending file await axios @@ -40,3 +39,7 @@ export const uploadEvents = async (file) => { .then((res) => console.log(res.data)) .catch((err) => console.error(err)); }; + +export const uploadEventsWithPath = async (filepath) => { + await axios.post(ontimeURL + '/dbpath', { path: filepath }); +}; diff --git a/client/src/features/menu/MenuBar.jsx b/client/src/features/menu/MenuBar.jsx index cc400a978..3d32ea0bf 100644 --- a/client/src/features/menu/MenuBar.jsx +++ b/client/src/features/menu/MenuBar.jsx @@ -1,4 +1,6 @@ -import { downloadEvents } from 'app/api/ontimeApi'; +import { useMutation, useQueryClient } from 'react-query'; +import { downloadEvents, uploadEventsWithPath } from 'app/api/ontimeApi'; +import { EVENTS_TABLE } from 'app/api/apiConstants'; import DownloadIconBtn from './buttons/DownloadIconBtn'; import SettingsIconBtn from './buttons/SettingsIconBtn'; import InfoIconBtn from './buttons/InfoIconBtn'; @@ -7,15 +9,49 @@ import MinIconBtn from './buttons/MinIconBtn'; import QuitIconBtn from './buttons/QuitIconBtn'; import style from './MenuBar.module.css'; import HelpIconBtn from './buttons/HelpIconBtn'; -const { ipcRenderer } = window.require('electron'); +import UploadIconBtn from './buttons/UploadIconBtn'; + +const { ipcRenderer, remote } = window.require('electron'); export default function MenuBar(props) { const { onOpen, onClose } = props; + const queryClient = useQueryClient(); + const uploaddbPath = useMutation(uploadEventsWithPath, { + onSettled: () => { + queryClient.invalidateQueries(EVENTS_TABLE); + }, + }); const handleDownload = () => { downloadEvents(); }; + const handleUpload = () => { + remote.dialog + .showOpenDialog({ + title: 'Select the File to be uploaded', + buttonLabel: 'Upload', + filters: [ + { + name: 'Text Files', + extensions: ['json'], + }, + ], + // Specifying the File Selector Property + properties: ['openFile'], + }) + .then((file) => { + // Stating whether dialog operation was + // cancelled or not. + if (!file.canceled) { + uploaddbPath.mutate(file.filePaths[0].toString()); + } + }) + .catch((err) => { + console.log(err); + }); + }; + const handleIPC = (action) => { switch (action) { case 'min': @@ -55,11 +91,17 @@ export default function MenuBar(props) { clickhandler={() => handleIPC('help')} /> +
+ + } + colorScheme='white' + onClick={clickhandler} + _focus={{ boxShadow: 'none' }} + {...rest} + /> + + ); +} diff --git a/server/main.js b/server/main.js index 31c3f3bf1..f8770d887 100644 --- a/server/main.js +++ b/server/main.js @@ -7,10 +7,10 @@ const { dialog, ipcMain, shell, + Notification, } = require('electron'); const path = require('path'); const { electron } = require('process'); -const { Notification } = require('electron'); const env = process.env.NODE_ENV || 'prod'; @@ -100,6 +100,7 @@ function createWindow() { // TODO: what are recommended alternatives to node integration? nodeIntegration: true, contextIsolation: false, + enableRemoteModule: true, }, }); diff --git a/server/src/controllers/ontimeController.js b/server/src/controllers/ontimeController.js index 981d6265e..ed5a8dd9c 100644 --- a/server/src/controllers/ontimeController.js +++ b/server/src/controllers/ontimeController.js @@ -29,6 +29,7 @@ async function deleteFile(file) { // parses version 1 of the data system async function parsev1(jsonData) { + let numEntries = 0; if ('events' in jsonData) { let events = []; let ids = []; @@ -51,15 +52,19 @@ async function parsev1(jsonData) { isPublic: e.isPublic, id: e.id, }); + numEntries++; } else if (e.type === 'delay') { events.push({ ...delayDef, duration: e.duration }); + numEntries++; } else if (e.type === 'block') { events.push({ ...blockDef }); + numEntries++; } } // write to db db.data.events = events; db.write(); + console.log(`Uploaded file with ${numEntries} entries`); } if ('event' in jsonData) { @@ -99,15 +104,7 @@ export const dbDownload = async (req, res) => { }); }; -// Create controller for POST request to '/ontime/db' -// Returns - -export const dbUpload = async (req, res) => { - if (!req.file) { - res.status(400).send({ message: 'File not found' }); - return; - } - - const file = req.file.path; +const upload = async (file, req, res) => { if (!fs.existsSync(file)) { res.status(500).send({ message: 'Upload failed' }); return; @@ -115,11 +112,8 @@ export const dbUpload = async (req, res) => { try { // get file - let rawdata = fs.readFileSync(file); - let uploadedJson = JSON.parse(rawdata); - - // delete file - deleteFile(file); + const rawdata = fs.readFileSync(file); + const uploadedJson = JSON.parse(rawdata); // check version if (uploadedJson.settings.version === 1) parsev1(uploadedJson); @@ -134,3 +128,25 @@ export const dbUpload = async (req, res) => { res.status(400).send({ message: error }); } }; + +// Create controller for POST request to '/ontime/db' +// Returns - +export const dbUpload = async (req, res) => { + if (!req.file) { + res.status(400).send({ message: 'File not found' }); + return; + } + + const file = req.file.path; + upload(file, req, res); +}; + +// Create controller for POST request to '/ontime/dbpath' +// Returns - +export const dbPathToUpload = async (req, res) => { + if (!req.body.path) { + res.status(400).send({ message: 'Path to file not found' }); + return; + } + upload(req.body.path, req, res); +}; diff --git a/server/src/routes/ontimeRouter.js b/server/src/routes/ontimeRouter.js index e5b5e5670..8c1141170 100644 --- a/server/src/routes/ontimeRouter.js +++ b/server/src/routes/ontimeRouter.js @@ -2,10 +2,17 @@ import express from 'express'; import uploadJson from '../utils/upload.js'; export const router = express.Router(); -import { dbDownload, dbUpload } from '../controllers/ontimeController.js'; +import { + dbDownload, + dbUpload, + dbPathToUpload, +} from '../controllers/ontimeController.js'; // create route between controller and '/ontime/db' endpoint router.get('/db', dbDownload); // create route between controller and '/ontime/db' endpoint router.post('/db', uploadJson, dbUpload); + +// create route between controller and '/ontime/dbpath' endpoint +router.post('/dbpath', dbPathToUpload);