From 02f4cb23b488e5aaacabd4cd9618cd8fd61716d6 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 26 Sep 2019 16:17:22 -0400 Subject: [PATCH 01/18] fixes #1162, fixes #1118 --- client/modules/IDE/components/NewFileModal.jsx | 5 +++-- server/utils/fileUtils.js | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/client/modules/IDE/components/NewFileModal.jsx b/client/modules/IDE/components/NewFileModal.jsx index aeed9598..433c3daa 100644 --- a/client/modules/IDE/components/NewFileModal.jsx +++ b/client/modules/IDE/components/NewFileModal.jsx @@ -5,6 +5,7 @@ import classNames from 'classnames'; import InlineSVG from 'react-inlinesvg'; import NewFileForm from './NewFileForm'; import FileUploader from './FileUploader'; +import { CREATE_FILE_REGEX } from '../../../../server/utils/fileUtils'; const exitUrl = require('../../../images/exit.svg'); @@ -71,8 +72,8 @@ function validate(formProps) { if (!formProps.name) { errors.name = 'Please enter a name'; - } else if (!formProps.name.match(/(.+\.js$|.+\.css$|.+\.json$|.+\.txt$|.+\.csv$|.+\.tsv$)/i)) { - errors.name = 'File must be of type JavaScript, CSS, JSON, TXT, CSV, or TSV.'; + } else if (!formProps.name.match(CREATE_FILE_REGEX)) { + errors.name = 'Invalid file type. Valid extensions are .js, .css, .json, .txt, .csv, .tsv, .frag, and .vert.'; } return errors; diff --git a/server/utils/fileUtils.js b/server/utils/fileUtils.js index 0e6a7e58..c63cff9f 100644 --- a/server/utils/fileUtils.js +++ b/server/utils/fileUtils.js @@ -3,7 +3,7 @@ export const fileExtensionsArray = ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'wav', 'flac', 'ogg', 'oga', 'mp4', 'm4p', 'mp3', 'm4a', 'aiff', 'aif', 'm4v', 'aac', 'webm', 'mpg', 'mp2', 'mpeg', 'mpe', 'mpv', 'js', 'jsx', 'html', 'htm', 'css', 'json', 'csv', 'obj', 'svg', - 'otf', 'ttf', 'txt', 'mov', 'vert', 'frag']; + 'otf', 'ttf', 'txt', 'mov', 'vert', 'frag', 'bin']; export const mimeTypes = `image/*,audio/*,text/javascript,text/html,text/css, application/json,application/x-font-ttf,application/x-font-truetype,text/plain, @@ -22,6 +22,8 @@ export const STRING_REGEX = /(['"])((\\\1|.)*?)\1/gm; // these are files that have to be linked to with a blob url export const PLAINTEXT_FILE_REGEX = /.+\.(json|txt|csv|vert|frag|tsv)$/i; // these are files that users would want to edit as text (maybe svg should be here?) -export const TEXT_FILE_REGEX = /.+\.(json|txt|csv|vert|frag|js|css|html|htm|jsx)$/i; +export const TEXT_FILE_REGEX = /.+\.(json|txt|csv|tsv|vert|frag|js|css|html|htm|jsx)$/i; export const NOT_EXTERNAL_LINK_REGEX = /^(?!(http:\/\/|https:\/\/))/; export const EXTERNAL_LINK_REGEX = /^(http:\/\/|https:\/\/)/; + +export const CREATE_FILE_REGEX = /.+\.(json|txt|csv|tsv|js|css|frag|vert)$/i; From ad937824965734c4aafd5e2c917be2e77717222d Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Tue, 1 Oct 2019 16:32:07 -0400 Subject: [PATCH 02/18] fixes #1170 --- client/components/Nav.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/components/Nav.jsx b/client/components/Nav.jsx index d78c2098..f00a26cb 100644 --- a/client/components/Nav.jsx +++ b/client/components/Nav.jsx @@ -170,7 +170,7 @@ class Nav extends React.PureComponent { handleDownload() { this.props.autosaveProject(); - this.props.exportProjectAsZip(this.props.project.id); + projectActions.exportProjectAsZip(this.props.project.id); this.setDropdown('none'); } @@ -633,7 +633,6 @@ Nav.propTypes = { setToastText: PropTypes.func.isRequired, saveProject: PropTypes.func.isRequired, autosaveProject: PropTypes.func.isRequired, - exportProjectAsZip: PropTypes.func.isRequired, cloneProject: PropTypes.func.isRequired, user: PropTypes.shape({ authenticated: PropTypes.bool.isRequired, From 0b36126854fc387151ccb3daad8608a74b6da945 Mon Sep 17 00:00:00 2001 From: Frank Winter Date: Wed, 2 Oct 2019 22:18:54 +0200 Subject: [PATCH 03/18] Change DELETE request for projects Fixes #1165 (#1172) * Change DELETE request for projects * fixes #1165, by updating requestsOfType to check for null or undefined values * remove unnecessary whitespace changes --- server/utils/requestsOfType.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/utils/requestsOfType.js b/server/utils/requestsOfType.js index 5aac7b8c..43bfeb1d 100644 --- a/server/utils/requestsOfType.js +++ b/server/utils/requestsOfType.js @@ -4,7 +4,7 @@ header does not match `type` */ const requestsOfType = type => (req, res, next) => { - const hasContentType = req.get('content-type') !== null; + const hasContentType = req.get('content-type') !== undefined && req.get('content-type') !== null; const isCorrectType = req.is(type) === null || req.is(type) === type; if (hasContentType && !isCorrectType) { From 81a76a1529c876777085f8380fcd5e32d31b9114 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 26 Sep 2019 16:58:21 -0400 Subject: [PATCH 04/18] re #1067, when a line or lines are highlighted, tab will indent them --- client/modules/IDE/components/Editor.jsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index cb330b32..738e7666 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -108,7 +108,16 @@ class Editor extends React.Component { delete this._cm.options.lint.options.errors; this._cm.setOption('extraKeys', { - Tab: cm => cm.replaceSelection(' '.repeat(INDENTATION_AMOUNT)), + Tab: (cm) => { + // might need to specify and indent more? + const selection = cm.doc.getSelection(); + if (selection.length > 0) { + cm.execCommand('indentMore'); + } else { + cm.replaceSelection(' '.repeat(INDENTATION_AMOUNT)); + } + }, + // Tab: 'indentMore', [`${metaKey}-Enter`]: () => null, [`Shift-${metaKey}-Enter`]: () => null, [`${metaKey}-F`]: 'findPersistent', From c925da8c175a97f71e69a9b637efff855ebaa515 Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Wed, 2 Oct 2019 16:48:33 -0400 Subject: [PATCH 05/18] re #1067, remove lingering commented-out code --- client/modules/IDE/components/Editor.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index 738e7666..6200348c 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -117,7 +117,6 @@ class Editor extends React.Component { cm.replaceSelection(' '.repeat(INDENTATION_AMOUNT)); } }, - // Tab: 'indentMore', [`${metaKey}-Enter`]: () => null, [`Shift-${metaKey}-Enter`]: () => null, [`${metaKey}-F`]: 'findPersistent', From 3360c7c799a98f7a9fac7421b649309dd7807a3c Mon Sep 17 00:00:00 2001 From: Cassie Tarakajian Date: Thu, 3 Oct 2019 15:51:34 -0400 Subject: [PATCH 06/18] fixes #963: fixes bug in which files/folders would get added to selected file (or root), rather than the file that you opened the popover from --- client/modules/IDE/actions/files.js | 18 ++---------------- client/modules/IDE/actions/ide.js | 10 ++++++---- client/modules/IDE/components/FileNode.jsx | 4 ++-- client/modules/IDE/components/Sidebar.jsx | 7 ++++--- client/modules/IDE/reducers/ide.js | 5 +++-- 5 files changed, 17 insertions(+), 27 deletions(-) diff --git a/client/modules/IDE/actions/files.js b/client/modules/IDE/actions/files.js index ff56454a..0bbf292d 100644 --- a/client/modules/IDE/actions/files.js +++ b/client/modules/IDE/actions/files.js @@ -41,14 +41,7 @@ export function updateFileContent(id, content) { export function createFile(formProps) { return (dispatch, getState) => { const state = getState(); - const selectedFile = state.files.find(file => file.isSelectedFile); - const rootFile = state.files.find(file => file.name === 'root'); - let parentId; - if (selectedFile.fileType === 'folder') { - parentId = selectedFile.id; - } else { - parentId = rootFile.id; - } + const { parentId } = state.ide; if (state.project.id) { const postParams = { name: createUniqueName(formProps.name, parentId, state.files), @@ -99,14 +92,7 @@ export function createFile(formProps) { export function createFolder(formProps) { return (dispatch, getState) => { const state = getState(); - const selectedFile = state.files.find(file => file.isSelectedFile); - const rootFile = state.files.find(file => file.name === 'root'); - let parentId; - if (selectedFile.fileType === 'folder') { - parentId = selectedFile.id; - } else { - parentId = rootFile.id; - } + const { parentId } = state.ide; if (state.project.id) { const postParams = { name: createUniqueName(formProps.name, parentId, state.files), diff --git a/client/modules/IDE/actions/ide.js b/client/modules/IDE/actions/ide.js index 1d7c2998..b6351a7d 100644 --- a/client/modules/IDE/actions/ide.js +++ b/client/modules/IDE/actions/ide.js @@ -62,9 +62,10 @@ export function resetSelectedFile(previousId) { }; } -export function newFile() { +export function newFile(parentId) { return { - type: ActionTypes.SHOW_MODAL + type: ActionTypes.SHOW_MODAL, + parentId }; } @@ -122,9 +123,10 @@ export function closeProjectOptions() { }; } -export function newFolder() { +export function newFolder(parentId) { return { - type: ActionTypes.SHOW_NEW_FOLDER_MODAL + type: ActionTypes.SHOW_NEW_FOLDER_MODAL, + parentId }; } diff --git a/client/modules/IDE/components/FileNode.jsx b/client/modules/IDE/components/FileNode.jsx index 1b28bd4e..12496b38 100644 --- a/client/modules/IDE/components/FileNode.jsx +++ b/client/modules/IDE/components/FileNode.jsx @@ -188,7 +188,7 @@ export class FileNode extends React.Component {