Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: save file locally when receiving postFile message #317

Merged
merged 3 commits into from
Sep 4, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions public/app/config/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ module.exports = {
GET_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:get',
LOAD_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:load',
GET_SPACE_TO_LOAD_IN_CLASSROOM_CHANNEL: 'classroom:space:load:get-space',
POST_FILE_CHANNEL: 'file:post',
};
8 changes: 8 additions & 0 deletions public/app/config/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// eslint-disable-next-line import/no-extraneous-dependencies
const { app } = require('electron');
const ObjectId = require('bson-objectid');
const isWindows = require('../utils/isWindows');

// types that we support downloading
Expand Down Expand Up @@ -84,6 +85,12 @@ const ACTIONS_VERBS = {
LOGOUT: 'logout',
};

const buildFilesPath = ({ userId, spaceId, name }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be singular buildFilePath?

// add generated id to handle duplicate files
const generatedId = ObjectId().str;
return `${VAR_FOLDER}/${spaceId}/files/${userId}/${generatedId}_${name}`;
};

module.exports = {
DEFAULT_LOGGING_LEVEL,
DEFAULT_PROTOCOL,
Expand All @@ -110,4 +117,5 @@ module.exports = {
VISIBILITIES,
DEFAULT_FORMAT,
ACTIONS_VERBS,
buildFilesPath,
};
2 changes: 2 additions & 0 deletions public/app/config/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const ERROR_GETTING_SPACE_IN_CLASSROOM_MESSAGE =
const ERROR_SETTING_ACTION_ACCESSIBILITY =
'There was an error setting the action accessibility';
const ERROR_SETTING_ACTIONS_AS_ENABLED = 'There was an error enabling actions';
const ERROR_POSTING_FILE_MESSAGE = 'There was an error uploading the file';

module.exports = {
ERROR_GETTING_DEVELOPER_MODE,
Expand Down Expand Up @@ -172,4 +173,5 @@ module.exports = {
ERROR_INVALID_USERNAME_MESSAGE,
ERROR_SETTING_ACTION_ACCESSIBILITY,
ERROR_SETTING_ACTIONS_AS_ENABLED,
ERROR_POSTING_FILE_MESSAGE,
};
2 changes: 2 additions & 0 deletions public/app/listeners/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const loadSpaceInClassroom = require('./loadSpaceInClassroom');
const setActionAccessibility = require('./setActionAccessibility');
const setActionsAsEnabled = require('./setActionsAsEnabled');
const windowAllClosed = require('./windowAllClosed');
const postFile = require('./postFile');

module.exports = {
loadSpace,
Expand Down Expand Up @@ -103,4 +104,5 @@ module.exports = {
setActionAccessibility,
setActionsAsEnabled,
windowAllClosed,
postFile,
};
36 changes: 36 additions & 0 deletions public/app/listeners/postFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const fs = require('fs');
const { POST_FILE_CHANNEL } = require('../config/channels');
const { buildFilesPath } = require('../config/config');
const { ensureDirectoryExistence } = require('../utilities');
const logger = require('../logger');
const { ERROR_GENERAL } = require('../config/errors');

const postFile = mainWindow => (event, payload = {}) => {
try {
const { userId, spaceId, data } = payload;

// download file given path
const { path, name } = data;

const savePath = buildFilesPath({ userId, spaceId, name });
ensureDirectoryExistence(savePath);
fs.copyFile(path, savePath, err => {
if (err) {
throw err;
}
logger.debug(`the file ${name} was uploaded`);
});

// update data
const newData = { name, uri: `file://${savePath}` };
const newPayload = { ...payload, data: newData };

// send back the resource
mainWindow.webContents.send(POST_FILE_CHANNEL, newPayload);
} catch (e) {
logger.error(e);
mainWindow.webContents.send(POST_FILE_CHANNEL, ERROR_GENERAL);
}
};

module.exports = postFile;
14 changes: 14 additions & 0 deletions public/app/utilities.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const mkdirp = require('mkdirp');
const rimraf = require('rimraf');
const path = require('path');
const { promisify } = require('util');
const mime = require('mime-types');
const md5 = require('md5');
Expand Down Expand Up @@ -135,8 +136,21 @@ const clean = async dir => {
return promisify(rimraf)(dir);
};

/**
* Ensure directories for given filepath exist
*/
function ensureDirectoryExistence(filePath) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should use fs-extra instead of creating this function? Probably has some in-built safety.

const fs = require('fs-extra');
fs.ensureDirSync(...);

const dirname = path.dirname(filePath);
if (fs.existsSync(dirname)) {
return true;
}
ensureDirectoryExistence(dirname);
return fs.mkdirSync(dirname);
}

module.exports = {
clean,
ensureDirectoryExistence,
performFileSystemOperation,
getExtension,
isDownloadable,
Expand Down
6 changes: 6 additions & 0 deletions public/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const {
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
SET_ACTION_ACCESSIBILITY_CHANNEL,
SET_ACTIONS_AS_ENABLED_CHANNEL,
POST_FILE_CHANNEL,
} = require('./app/config/channels');
const env = require('./env.json');
const {
Expand Down Expand Up @@ -127,6 +128,7 @@ const {
setActionAccessibility,
setActionsAsEnabled,
windowAllClosed,
postFile,
} = require('./app/listeners');
const isMac = require('./app/utils/isMac');

Expand Down Expand Up @@ -488,6 +490,10 @@ app.on('ready', async () => {

// called when creating an action
ipcMain.on(POST_ACTION_CHANNEL, postAction(mainWindow, db));

// called when creating a file
ipcMain.on(POST_FILE_CHANNEL, postFile(mainWindow, db));

// called when logging in a user
ipcMain.on(SIGN_IN_CHANNEL, signIn(mainWindow, db));

Expand Down
45 changes: 45 additions & 0 deletions src/actions/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { POST_FILE_CHANNEL } from '../config/channels';
import { POST_FILE_SUCCEEDED, POST_FILE_FAILED } from '../types';
import { ERROR_GENERAL } from '../config/errors';
import { ERROR_POSTING_FILE_MESSAGE } from '../config/messages';

// eslint-disable-next-line import/prefer-default-export
export const postFile = async (
{ userId, appInstanceId, spaceId, subSpaceId, format, data, type } = {},
callback
) => {
try {
window.ipcRenderer.send(POST_FILE_CHANNEL, {
userId,
appInstanceId,
spaceId,
subSpaceId,
format,
type,
data,
});

window.ipcRenderer.once(POST_FILE_CHANNEL, async (event, response) => {
if (response === ERROR_GENERAL) {
callback({
appInstanceId,
type: POST_FILE_FAILED,
payload: ERROR_POSTING_FILE_MESSAGE,
});
} else {
callback({
// have to include the appInstanceId to avoid broadcasting
appInstanceId,
type: POST_FILE_SUCCEEDED,
payload: response,
});
}
});
} catch (err) {
callback({
appInstanceId,
type: POST_FILE_FAILED,
payload: ERROR_POSTING_FILE_MESSAGE,
});
}
};
1 change: 1 addition & 0 deletions src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './syncSpace';
export * from './loadSpace';
export * from './exportSpace';
export * from './classroom';
export * from './file';
17 changes: 16 additions & 1 deletion src/components/phase/PhaseApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ import {
APP_INSTANCE_RESOURCE_TYPES,
POST_ACTION,
ACTION_TYPES,
POST_FILE,
FILE_TYPES,
} from '../../types';
import {
getAppInstanceResources,
patchAppInstanceResource,
postAppInstanceResource,
getAppInstance,
postAction,
postFile,
} from '../../actions';
import {
DEFAULT_LANGUAGE,
Expand Down Expand Up @@ -125,7 +128,13 @@ class PhaseApp extends Component {
const { id: componentAppInstanceId } = appInstance || {};
const { type, payload } = JSON.parse(event.data);
let { id: messageAppInstanceId } = payload;
if ([...APP_INSTANCE_RESOURCE_TYPES, ...ACTION_TYPES].includes(type)) {
if (
[
...APP_INSTANCE_RESOURCE_TYPES,
...ACTION_TYPES,
...FILE_TYPES,
].includes(type)
) {
({ appInstanceId: messageAppInstanceId } = payload);
}

Expand Down Expand Up @@ -153,6 +162,12 @@ class PhaseApp extends Component {
}
break;
}
case POST_FILE: {
if (isSpaceSaved) {
return postFile(payload, this.postMessage);
}
break;
}
default:
return false;
}
Expand Down
1 change: 1 addition & 0 deletions src/config/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ module.exports = {
GET_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:get',
LOAD_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:load',
GET_SPACE_TO_LOAD_IN_CLASSROOM_CHANNEL: 'classroom:space:load:get-space',
POST_FILE_CHANNEL: 'file:post',
};
2 changes: 2 additions & 0 deletions src/config/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const ERROR_INVALID_USERNAME_MESSAGE = 'This username is invalid';
const ERROR_SETTING_ACTION_ACCESSIBILITY =
'There was an error setting the action accessibility';
const ERROR_SETTING_ACTIONS_AS_ENABLED = 'There was an error enabling actions';
const ERROR_POSTING_FILE_MESSAGE = 'There was an error uploading the file';

module.exports = {
ERROR_GETTING_DEVELOPER_MODE,
Expand Down Expand Up @@ -172,4 +173,5 @@ module.exports = {
ERROR_INVALID_USERNAME_MESSAGE,
ERROR_SETTING_ACTION_ACCESSIBILITY,
ERROR_SETTING_ACTIONS_AS_ENABLED,
ERROR_POSTING_FILE_MESSAGE,
};
5 changes: 5 additions & 0 deletions src/types/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const POST_FILE = 'POST_FILE';
export const POST_FILE_SUCCEEDED = 'POST_FILE_SUCCEEDED';
export const POST_FILE_FAILED = 'POST_FILE_FAILED';

export const FILE_TYPES = [POST_FILE, POST_FILE_SUCCEEDED, POST_FILE_FAILED];
1 change: 1 addition & 0 deletions src/types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './syncSpace';
export * from './loadSpace';
export * from './exportSpace';
export * from './classroom';
export * from './file';