diff --git a/client/modules/IDE/actions/files.js b/client/modules/IDE/actions/files.js index 3d406bcff6..8461c242f3 100644 --- a/client/modules/IDE/actions/files.js +++ b/client/modules/IDE/actions/files.js @@ -11,6 +11,8 @@ import { import { setProjectSavedTime } from './project'; import { createError } from './ide'; +const TEXT_FILE_REGEX = /\.(js|jsx|html|css|json|txt|csv|tsv|vert|frag|xml)$/i; + export function appendToFilename(filename, string) { const dotIndex = filename.lastIndexOf('.'); if (dotIndex === -1) return filename + string; @@ -246,3 +248,22 @@ export function getBlobUrl(file) { const blobURL = blobUtil.createObjectURL(fileBlob); return blobURL; } + +export function fetchS3FileContent(file) { + return (dispatch) => { + if (file.url && !file.content && TEXT_FILE_REGEX.test(file.name)) { + return fetch(file.url) + .then((response) => { + if (!response.ok) throw new Error('Failed to fetch from S3'); + return response.text(); + }) + .then((text) => { + dispatch(updateFileContent(file.id, text)); + }) + .catch((err) => { + console.error('S3 Fetch Error:', err); + }); + } + return Promise.resolve(); + }; +} diff --git a/client/modules/IDE/actions/ide.js b/client/modules/IDE/actions/ide.js index 80a43443bc..82cfe23bac 100644 --- a/client/modules/IDE/actions/ide.js +++ b/client/modules/IDE/actions/ide.js @@ -1,6 +1,7 @@ import * as ActionTypes from '../../../constants'; import { clearConsole } from './console'; import { dispatchMessage, MessageTypes } from '../../../utils/dispatcher'; +import * as FileActions from './files'; export function startVisualSketch() { return { @@ -46,9 +47,16 @@ export function stopAccessibleOutput() { } export function setSelectedFile(fileId) { - return { - type: ActionTypes.SET_SELECTED_FILE, - selectedFile: fileId + return (dispatch, getState) => { + const state = getState(); + const file = state.files.find((f) => f.id === fileId); + dispatch({ + type: ActionTypes.SET_SELECTED_FILE, + selectedFile: fileId + }); + if (file && file.url && !file.content) { + dispatch(FileActions.fetchS3FileContent(file)); + } }; } diff --git a/client/modules/IDE/actions/uploader.js b/client/modules/IDE/actions/uploader.js index 8b79ef688b..37f1222c5a 100644 --- a/client/modules/IDE/actions/uploader.js +++ b/client/modules/IDE/actions/uploader.js @@ -29,7 +29,7 @@ export async function dropzoneAcceptCallback(userId, file, done) { // eslint-disable-next-line no-param-reassign file.content = await file.text(); // Make it an error so that it won't be sent to S3, but style as a success. - done('Uploading plaintext file locally.'); + done('Large text file detected: Loading locally for editing.'); file.previewElement.classList.remove('dz-error'); file.previewElement.classList.add('dz-success'); file.previewElement.classList.add('dz-processing'); diff --git a/client/styles/components/_uploader.scss b/client/styles/components/_uploader.scss index f3cb3135fc..7eab370539 100644 --- a/client/styles/components/_uploader.scss +++ b/client/styles/components/_uploader.scss @@ -5,4 +5,16 @@ max-height: 70vh; overflow-y: auto; } + .dz-preview.dz-success { + .dz-error-message { + display: block !important; + opacity: 1 !important; + background: #4caf50 !important; + color: white !important; + + &:after { + border-bottom: 6px solid #4caf50 !important; + } + } + } }