- {this.state.isMounted && !window.devToolsExtension && __process.env.NODE_ENV === 'development' && }
+ {this.state.isMounted && !window.devToolsExtension && getConfig('NODE_ENV') === 'development' && }
{this.props.children}
);
diff --git a/client/modules/IDE/actions/assets.js b/client/modules/IDE/actions/assets.js
index 483e6d4e..79df4285 100644
--- a/client/modules/IDE/actions/assets.js
+++ b/client/modules/IDE/actions/assets.js
@@ -1,10 +1,7 @@
-import axios from 'axios';
+import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
import { startLoader, stopLoader } from './loader';
-const __process = (typeof global !== 'undefined' ? global : window).process;
-const ROOT_URL = __process.env.API_URL;
-
function setAssets(assets, totalSize) {
return {
type: ActionTypes.SET_ASSETS,
@@ -16,7 +13,7 @@ function setAssets(assets, totalSize) {
export function getAssets() {
return (dispatch) => {
dispatch(startLoader());
- axios.get(`${ROOT_URL}/S3/objects`, { withCredentials: true })
+ apiClient.get('/S3/objects')
.then((response) => {
dispatch(setAssets(response.data.assets, response.data.totalSize));
dispatch(stopLoader());
@@ -39,7 +36,7 @@ export function deleteAsset(assetKey) {
export function deleteAssetRequest(assetKey) {
return (dispatch) => {
- axios.delete(`${ROOT_URL}/S3/${assetKey}`, { withCredentials: true })
+ apiClient.delete(`/S3/${assetKey}`)
.then((response) => {
dispatch(deleteAsset(assetKey));
})
diff --git a/client/modules/IDE/actions/collections.js b/client/modules/IDE/actions/collections.js
index 03cf2a64..3aa954ac 100644
--- a/client/modules/IDE/actions/collections.js
+++ b/client/modules/IDE/actions/collections.js
@@ -1,11 +1,9 @@
-import axios from 'axios';
import { browserHistory } from 'react-router';
+import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
import { startLoader, stopLoader } from './loader';
import { setToastText, showToast } from './toast';
-const __process = (typeof global !== 'undefined' ? global : window).process;
-const ROOT_URL = __process.env.API_URL;
const TOAST_DISPLAY_TIME_MS = 1500;
@@ -15,11 +13,11 @@ export function getCollections(username) {
dispatch(startLoader());
let url;
if (username) {
- url = `${ROOT_URL}/${username}/collections`;
+ url = `/${username}/collections`;
} else {
- url = `${ROOT_URL}/collections`;
+ url = '/collections';
}
- axios.get(url, { withCredentials: true })
+ apiClient.get(url)
.then((response) => {
dispatch({
type: ActionTypes.SET_COLLECTIONS,
@@ -41,8 +39,8 @@ export function getCollections(username) {
export function createCollection(collection) {
return (dispatch) => {
dispatch(startLoader());
- const url = `${ROOT_URL}/collections`;
- return axios.post(url, collection, { withCredentials: true })
+ const url = '/collections';
+ return apiClient.post(url, collection)
.then((response) => {
dispatch({
type: ActionTypes.CREATE_COLLECTION
@@ -73,8 +71,8 @@ export function createCollection(collection) {
export function addToCollection(collectionId, projectId) {
return (dispatch) => {
dispatch(startLoader());
- const url = `${ROOT_URL}/collections/${collectionId}/${projectId}`;
- return axios.post(url, { withCredentials: true })
+ const url = `/collections/${collectionId}/${projectId}`;
+ return apiClient.post(url)
.then((response) => {
dispatch({
type: ActionTypes.ADD_TO_COLLECTION,
@@ -105,8 +103,8 @@ export function addToCollection(collectionId, projectId) {
export function removeFromCollection(collectionId, projectId) {
return (dispatch) => {
dispatch(startLoader());
- const url = `${ROOT_URL}/collections/${collectionId}/${projectId}`;
- return axios.delete(url, { withCredentials: true })
+ const url = `/collections/${collectionId}/${projectId}`;
+ return apiClient.delete(url)
.then((response) => {
dispatch({
type: ActionTypes.REMOVE_FROM_COLLECTION,
@@ -136,8 +134,8 @@ export function removeFromCollection(collectionId, projectId) {
export function editCollection(collectionId, { name, description }) {
return (dispatch) => {
- const url = `${ROOT_URL}/collections/${collectionId}`;
- return axios.patch(url, { name, description }, { withCredentials: true })
+ const url = `/collections/${collectionId}`;
+ return apiClient.patch(url, { name, description })
.then((response) => {
dispatch({
type: ActionTypes.EDIT_COLLECTION,
@@ -159,8 +157,8 @@ export function editCollection(collectionId, { name, description }) {
export function deleteCollection(collectionId) {
return (dispatch) => {
- const url = `${ROOT_URL}/collections/${collectionId}`;
- return axios.delete(url, { withCredentials: true })
+ const url = `/collections/${collectionId}`;
+ return apiClient.delete(url)
.then((response) => {
dispatch({
type: ActionTypes.DELETE_COLLECTION,
diff --git a/client/modules/IDE/actions/files.js b/client/modules/IDE/actions/files.js
index 004600b2..e17e46c5 100644
--- a/client/modules/IDE/actions/files.js
+++ b/client/modules/IDE/actions/files.js
@@ -1,13 +1,11 @@
-import axios from 'axios';
import objectID from 'bson-objectid';
import blobUtil from 'blob-util';
import { reset } from 'redux-form';
+import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
import { setUnsavedChanges, closeNewFolderModal, closeNewFileModal } from './ide';
import { setProjectSavedTime } from './project';
-const __process = (typeof global !== 'undefined' ? global : window).process;
-const ROOT_URL = __process.env.API_URL;
function appendToFilename(filename, string) {
const dotIndex = filename.lastIndexOf('.');
@@ -50,7 +48,7 @@ export function createFile(formProps) {
parentId,
children: []
};
- axios.post(`${ROOT_URL}/projects/${state.project.id}/files`, postParams, { withCredentials: true })
+ apiClient.post(`/projects/${state.project.id}/files`, postParams)
.then((response) => {
dispatch({
type: ActionTypes.CREATE_FILE,
@@ -106,7 +104,7 @@ export function createFolder(formProps) {
parentId,
fileType: 'folder'
};
- axios.post(`${ROOT_URL}/projects/${state.project.id}/files`, postParams, { withCredentials: true })
+ apiClient.post(`/projects/${state.project.id}/files`, postParams)
.then((response) => {
dispatch({
type: ActionTypes.CREATE_FILE,
@@ -161,7 +159,7 @@ export function deleteFile(id, parentId) {
parentId
}
};
- axios.delete(`${ROOT_URL}/projects/${state.project.id}/files/${id}`, deleteConfig, { withCredentials: true })
+ apiClient.delete(`/projects/${state.project.id}/files/${id}`, deleteConfig)
.then(() => {
dispatch({
type: ActionTypes.DELETE_FILE,
diff --git a/client/modules/IDE/actions/preferences.js b/client/modules/IDE/actions/preferences.js
index 01ba077c..a182da76 100644
--- a/client/modules/IDE/actions/preferences.js
+++ b/client/modules/IDE/actions/preferences.js
@@ -1,11 +1,8 @@
-import axios from 'axios';
+import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
-const __process = (typeof global !== 'undefined' ? global : window).process;
-const ROOT_URL = __process.env.API_URL;
-
function updatePreferences(formParams, dispatch) {
- axios.put(`${ROOT_URL}/preferences`, formParams, { withCredentials: true })
+ apiClient.put('/preferences', formParams)
.then(() => {
})
.catch((error) => {
diff --git a/client/modules/IDE/actions/project.js b/client/modules/IDE/actions/project.js
index d42c307d..9055d484 100644
--- a/client/modules/IDE/actions/project.js
+++ b/client/modules/IDE/actions/project.js
@@ -1,8 +1,9 @@
import { browserHistory } from 'react-router';
-import axios from 'axios';
import objectID from 'bson-objectid';
import each from 'async/each';
import isEqual from 'lodash/isEqual';
+import apiClient from '../../../utils/apiClient';
+import getConfig from '../../../utils/getConfig';
import * as ActionTypes from '../../../constants';
import { showToast, setToastText } from './toast';
import {
@@ -14,8 +15,7 @@ import {
} from './ide';
import { clearState, saveState } from '../../../persistState';
-const __process = (typeof global !== 'undefined' ? global : window).process;
-const ROOT_URL = __process.env.API_URL;
+const ROOT_URL = getConfig('API_URL');
export function setProject(project) {
return {
@@ -52,7 +52,7 @@ export function setNewProject(project) {
export function getProject(id, username) {
return (dispatch, getState) => {
dispatch(justOpenedProject());
- axios.get(`${ROOT_URL}/${username}/projects/${id}`, { withCredentials: true })
+ apiClient.get(`/${username}/projects/${id}`)
.then((response) => {
dispatch(setProject(response.data));
dispatch(setUnsavedChanges(false));
@@ -142,7 +142,7 @@ export function saveProject(selectedFile = null, autosave = false) {
fileToUpdate.content = selectedFile.content;
}
if (state.project.id) {
- return axios.put(`${ROOT_URL}/projects/${state.project.id}`, formParams, { withCredentials: true })
+ return apiClient.put(`/projects/${state.project.id}`, formParams)
.then((response) => {
dispatch(endSavingProject());
dispatch(setUnsavedChanges(false));
@@ -155,18 +155,20 @@ export function saveProject(selectedFile = null, autosave = false) {
if (!autosave) {
if (state.ide.justOpenedProject && state.preferences.autosave) {
dispatch(showToast(5500));
- dispatch(setToastText('Project saved.'));
+ dispatch(setToastText('Sketch saved.'));
setTimeout(() => dispatch(setToastText('Autosave enabled.')), 1500);
dispatch(resetJustOpenedProject());
} else {
dispatch(showToast(1500));
- dispatch(setToastText('Project saved.'));
+ dispatch(setToastText('Sketch saved.'));
}
}
})
.catch((error) => {
const { response } = error;
dispatch(endSavingProject());
+ dispatch(setToastText('Failed to save sketch.'));
+ dispatch(showToast(1500));
if (response.status === 403) {
dispatch(showErrorModal('staleSession'));
} else if (response.status === 409) {
@@ -177,7 +179,7 @@ export function saveProject(selectedFile = null, autosave = false) {
});
}
- return axios.post(`${ROOT_URL}/projects`, formParams, { withCredentials: true })
+ return apiClient.post('/projects', formParams)
.then((response) => {
dispatch(endSavingProject());
const { hasChanges, synchedProject } = getSynchedProject(getState(), response.data);
@@ -195,18 +197,20 @@ export function saveProject(selectedFile = null, autosave = false) {
if (!autosave) {
if (state.preferences.autosave) {
dispatch(showToast(5500));
- dispatch(setToastText('Project saved.'));
+ dispatch(setToastText('Sketch saved.'));
setTimeout(() => dispatch(setToastText('Autosave enabled.')), 1500);
dispatch(resetJustOpenedProject());
} else {
dispatch(showToast(1500));
- dispatch(setToastText('Project saved.'));
+ dispatch(setToastText('Sketch saved.'));
}
}
})
.catch((error) => {
const { response } = error;
dispatch(endSavingProject());
+ dispatch(setToastText('Failed to save sketch.'));
+ dispatch(showToast(1500));
if (response.status === 403) {
dispatch(showErrorModal('staleSession'));
} else {
@@ -260,7 +264,7 @@ export function cloneProject(id) {
if (!id) {
resolve(getState());
} else {
- fetch(`${ROOT_URL}/projects/${id}`)
+ apiClient.get(`/projects/${id}`)
.then(res => res.json())
.then(data => resolve({
files: data.files,
@@ -287,7 +291,7 @@ export function cloneProject(id) {
const formParams = {
url: file.url
};
- axios.post(`${ROOT_URL}/S3/copy`, formParams, { withCredentials: true })
+ apiClient.post('/S3/copy', formParams)
.then((response) => {
file.url = response.data.url;
callback(null);
@@ -298,7 +302,7 @@ export function cloneProject(id) {
}, (err) => {
// if not errors in duplicating the files on S3, then duplicate it
const formParams = Object.assign({}, { name: `${state.project.name} copy` }, { files: newFiles });
- axios.post(`${ROOT_URL}/projects`, formParams, { withCredentials: true })
+ apiClient.post('/projects', formParams)
.then((response) => {
browserHistory.push(`/${response.data.user.username}/sketches/${response.data.id}`);
dispatch(setNewProject(response.data));
@@ -337,7 +341,7 @@ export function setProjectSavedTime(updatedAt) {
export function changeProjectName(id, newName) {
return (dispatch, getState) => {
const state = getState();
- axios.put(`${ROOT_URL}/projects/${id}`, { name: newName }, { withCredentials: true })
+ apiClient.put(`/projects/${id}`, { name: newName })
.then((response) => {
if (response.status === 200) {
dispatch({
@@ -364,7 +368,7 @@ export function changeProjectName(id, newName) {
export function deleteProject(id) {
return (dispatch, getState) => {
- axios.delete(`${ROOT_URL}/projects/${id}`, { withCredentials: true })
+ apiClient.delete(`/projects/${id}`)
.then(() => {
const state = getState();
if (id === state.project.id) {
diff --git a/client/modules/IDE/actions/projects.js b/client/modules/IDE/actions/projects.js
index eb653ec8..d41747b5 100644
--- a/client/modules/IDE/actions/projects.js
+++ b/client/modules/IDE/actions/projects.js
@@ -1,21 +1,18 @@
-import axios from 'axios';
+import apiClient from '../../../utils/apiClient';
import * as ActionTypes from '../../../constants';
import { startLoader, stopLoader } from './loader';
-const __process = (typeof global !== 'undefined' ? global : window).process;
-const ROOT_URL = __process.env.API_URL;
-
// eslint-disable-next-line
export function getProjects(username) {
return (dispatch) => {
dispatch(startLoader());
let url;
if (username) {
- url = `${ROOT_URL}/${username}/projects`;
+ url = `/${username}/projects`;
} else {
- url = `${ROOT_URL}/projects`;
+ url = '/projects';
}
- axios.get(url, { withCredentials: true })
+ apiClient.get(url)
.then((response) => {
dispatch({
type: ActionTypes.SET_PROJECTS,
diff --git a/client/modules/IDE/actions/uploader.js b/client/modules/IDE/actions/uploader.js
index c7a0139f..eca1ffe6 100644
--- a/client/modules/IDE/actions/uploader.js
+++ b/client/modules/IDE/actions/uploader.js
@@ -1,11 +1,10 @@
-import axios from 'axios';
+import apiClient from '../../../utils/apiClient';
+import getConfig from '../../../utils/getConfig';
import { createFile } from './files';
import { TEXT_FILE_REGEX } from '../../../../server/utils/fileUtils';
-const __process = (typeof global !== 'undefined' ? global : window).process;
-const s3BucketHttps = __process.env.S3_BUCKET_URL_BASE ||
- `https://s3-${__process.env.AWS_REGION}.amazonaws.com/${__process.env.S3_BUCKET}/`;
-const ROOT_URL = __process.env.API_URL;
+const s3BucketHttps = getConfig('S3_BUCKET_URL_BASE') ||
+ `https://s3-${getConfig('AWS_REGION')}.amazonaws.com/${getConfig('S3_BUCKET')}/`;
const MAX_LOCAL_FILE_SIZE = 80000; // bytes, aka 80 KB
function localIntercept(file, options = {}) {
@@ -46,18 +45,13 @@ export function dropzoneAcceptCallback(userId, file, done) {
});
} else {
file.postData = []; // eslint-disable-line
- axios.post(
- `${ROOT_URL}/S3/sign`, {
- name: file.name,
- type: file.type,
- size: file.size,
- userId
+ apiClient.post('/S3/sign', {
+ name: file.name,
+ type: file.type,
+ size: file.size,
+ userId
// _csrf: document.getElementById('__createPostToken').value
- },
- {
- withCredentials: true
- }
- )
+ })
.then((response) => {
file.custom_status = 'ready'; // eslint-disable-line
file.postData = response.data; // eslint-disable-line
diff --git a/client/modules/IDE/components/About.jsx b/client/modules/IDE/components/About.jsx
index 213a1f46..81bca172 100644
--- a/client/modules/IDE/components/About.jsx
+++ b/client/modules/IDE/components/About.jsx
@@ -1,15 +1,16 @@
import React from 'react';
import { Helmet } from 'react-helmet';
-
+import { useTranslation } from 'react-i18next';
import SquareLogoIcon from '../../../images/p5js-square-logo.svg';
// import PlayIcon from '../../../images/play.svg';
import AsteriskIcon from '../../../images/p5-asterisk.svg';
function About(props) {
+ const { t } = useTranslation();
return (
- p5.js Web Editor | About
+ p5.js Web Editor | About
@@ -25,7 +26,7 @@ function About(props) {
*/}
-
New to p5.js?
+
{t('NewP5')}
- Examples
+ {t('Examples')}
@@ -43,12 +44,12 @@ function About(props) {
rel="noopener noreferrer"
>
- Learn
+ {t('Learn')}
-
Resources
+
{t('Resources')}
- Libraries
+ {t('Libraries')}
@@ -66,7 +67,7 @@ function About(props) {
rel="noopener noreferrer"
>
- Reference
+ {t('Reference')}
@@ -76,7 +77,7 @@ function About(props) {
rel="noopener noreferrer"
>
- Forum
+ {t('Forum')}
@@ -86,7 +87,7 @@ function About(props) {
href="https://github.com/processing/p5.js-web-editor"
target="_blank"
rel="noopener noreferrer"
- >Contribute
+ >{t('Contribute')}
@@ -94,7 +95,7 @@ function About(props) {
href="https://github.com/processing/p5.js-web-editor/issues/new"
target="_blank"
rel="noopener noreferrer"
- >Report a bug
+ >{t('Report')}
diff --git a/client/modules/IDE/components/AssetSize.jsx b/client/modules/IDE/components/AssetSize.jsx
index 2e4c1282..cf2356e2 100644
--- a/client/modules/IDE/components/AssetSize.jsx
+++ b/client/modules/IDE/components/AssetSize.jsx
@@ -3,8 +3,9 @@ import React from 'react';
import { connect } from 'react-redux';
import prettyBytes from 'pretty-bytes';
-const __process = (typeof global !== 'undefined' ? global : window).process;
-const limit = __process.env.UPLOAD_LIMIT || 250000000;
+import getConfig from '../../../utils/getConfig';
+
+const limit = getConfig('UPLOAD_LIMIT') || 250000000;
const MAX_SIZE_B = limit;
const formatPercent = (percent) => {
diff --git a/client/modules/IDE/components/FileNode.jsx b/client/modules/IDE/components/FileNode.jsx
index bd077874..57238cf8 100644
--- a/client/modules/IDE/components/FileNode.jsx
+++ b/client/modules/IDE/components/FileNode.jsx
@@ -206,12 +206,14 @@ export class FileNode extends React.Component {
}
-
Code Editing
+
{t('CodeEditing')}
- Code editing keyboard shortcuts follow Sublime Text shortcuts.
+ {t('Code editing keyboard shortcuts follow')} {t('Sublime Text shortcuts')}.
-
{'\u21E7'} + Tab
- Tidy
+ {t('Tidy')}
-
{metaKeyName} + F
- Find Text
+ {t('FindText')}
-
{metaKeyName} + G
- Find Next Text Match
+ {t('FindNextTextMatch')}
-
{metaKeyName} + {'\u21E7'} + G
- Find Previous Text Match
+ {t('FindPreviousTextMatch')}
-
{metaKeyName} + [
- Indent Code Left
+ {t('IndentCodeLeft')}
-
{metaKeyName} + ]
- Indent Code Right
+ {t('IndentCodeRight')}
-
{metaKeyName} + /
- Comment Line
+ {t('CommentLine')}
General
@@ -56,31 +58,31 @@ function KeyboardShortcutModal() {
{metaKeyName} + S
-
Save
+
{t('Save')}
{metaKeyName} + Enter
- Start Sketch
+ {t('StartSketch')}
{metaKeyName} + {'\u21E7'} + Enter
- Stop Sketch
+ {t('StopSketch')}
{metaKeyName} + {'\u21E7'} + 1
- Turn on Accessible Output
+ {t('TurnOnAccessibleOutput')}
{metaKeyName} + {'\u21E7'} + 2
- Turn off Accessible Output
+ {t('TurnOffAccessibleOutput')}
diff --git a/client/modules/IDE/components/Preferences.jsx b/client/modules/IDE/components/Preferences.jsx
index 1b5c342b..1a658c3c 100644
--- a/client/modules/IDE/components/Preferences.jsx
+++ b/client/modules/IDE/components/Preferences.jsx
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import { Helmet } from 'react-helmet';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
+import { withTranslation } from 'react-i18next';
// import { bindActionCreators } from 'redux';
// import { connect } from 'react-redux';
// import * as PreferencesActions from '../actions/preferences';
@@ -98,13 +99,13 @@ class Preferences extends React.Component {