Merge branch 'develop' into feature/mobile-settings-screen

This commit is contained in:
Cassie Tarakajian 2020-07-01 16:51:53 -04:00
commit 7d6ba6f34f
7 changed files with 39 additions and 27 deletions

View file

@ -155,18 +155,20 @@ export function saveProject(selectedFile = null, autosave = false) {
if (!autosave) { if (!autosave) {
if (state.ide.justOpenedProject && state.preferences.autosave) { if (state.ide.justOpenedProject && state.preferences.autosave) {
dispatch(showToast(5500)); dispatch(showToast(5500));
dispatch(setToastText('Project saved.')); dispatch(setToastText('Sketch saved.'));
setTimeout(() => dispatch(setToastText('Autosave enabled.')), 1500); setTimeout(() => dispatch(setToastText('Autosave enabled.')), 1500);
dispatch(resetJustOpenedProject()); dispatch(resetJustOpenedProject());
} else { } else {
dispatch(showToast(1500)); dispatch(showToast(1500));
dispatch(setToastText('Project saved.')); dispatch(setToastText('Sketch saved.'));
} }
} }
}) })
.catch((error) => { .catch((error) => {
const { response } = error; const { response } = error;
dispatch(endSavingProject()); dispatch(endSavingProject());
dispatch(setToastText('Failed to save sketch.'));
dispatch(showToast(1500));
if (response.status === 403) { if (response.status === 403) {
dispatch(showErrorModal('staleSession')); dispatch(showErrorModal('staleSession'));
} else if (response.status === 409) { } else if (response.status === 409) {
@ -195,18 +197,20 @@ export function saveProject(selectedFile = null, autosave = false) {
if (!autosave) { if (!autosave) {
if (state.preferences.autosave) { if (state.preferences.autosave) {
dispatch(showToast(5500)); dispatch(showToast(5500));
dispatch(setToastText('Project saved.')); dispatch(setToastText('Sketch saved.'));
setTimeout(() => dispatch(setToastText('Autosave enabled.')), 1500); setTimeout(() => dispatch(setToastText('Autosave enabled.')), 1500);
dispatch(resetJustOpenedProject()); dispatch(resetJustOpenedProject());
} else { } else {
dispatch(showToast(1500)); dispatch(showToast(1500));
dispatch(setToastText('Project saved.')); dispatch(setToastText('Sketch saved.'));
} }
} }
}) })
.catch((error) => { .catch((error) => {
const { response } = error; const { response } = error;
dispatch(endSavingProject()); dispatch(endSavingProject());
dispatch(setToastText('Failed to save sketch.'));
dispatch(showToast(1500));
if (response.status === 403) { if (response.status === 403) {
dispatch(showErrorModal('staleSession')); dispatch(showErrorModal('staleSession'));
} else { } else {

View file

@ -237,16 +237,18 @@ class PreviewFrame extends React.Component {
jsFileStrings.forEach((jsFileString) => { jsFileStrings.forEach((jsFileString) => {
if (jsFileString.match(MEDIA_FILE_QUOTED_REGEX)) { if (jsFileString.match(MEDIA_FILE_QUOTED_REGEX)) {
const filePath = jsFileString.substr(1, jsFileString.length - 2); const filePath = jsFileString.substr(1, jsFileString.length - 2);
const quoteCharacter = jsFileString.substr(0, 1);
const resolvedFile = resolvePathToFile(filePath, files); const resolvedFile = resolvePathToFile(filePath, files);
if (resolvedFile) { if (resolvedFile) {
if (resolvedFile.url) { if (resolvedFile.url) {
newContent = newContent.replace(filePath, resolvedFile.url); newContent = newContent.replace(jsFileString, quoteCharacter + resolvedFile.url + quoteCharacter);
} else if (resolvedFile.name.match(PLAINTEXT_FILE_REGEX)) { } else if (resolvedFile.name.match(PLAINTEXT_FILE_REGEX)) {
// could also pull file from API instead of using bloburl // could also pull file from API instead of using bloburl
const blobURL = getBlobUrl(resolvedFile); const blobURL = getBlobUrl(resolvedFile);
this.props.setBlobUrl(resolvedFile, blobURL); this.props.setBlobUrl(resolvedFile, blobURL);
const filePathRegex = new RegExp(filePath, 'gi');
newContent = newContent.replace(filePathRegex, blobURL); newContent = newContent.replace(jsFileString, quoteCharacter + blobURL + quoteCharacter);
} }
} }
} }
@ -262,10 +264,11 @@ class PreviewFrame extends React.Component {
cssFileStrings.forEach((cssFileString) => { cssFileStrings.forEach((cssFileString) => {
if (cssFileString.match(MEDIA_FILE_QUOTED_REGEX)) { if (cssFileString.match(MEDIA_FILE_QUOTED_REGEX)) {
const filePath = cssFileString.substr(1, cssFileString.length - 2); const filePath = cssFileString.substr(1, cssFileString.length - 2);
const quoteCharacter = cssFileString.substr(0, 1);
const resolvedFile = resolvePathToFile(filePath, files); const resolvedFile = resolvePathToFile(filePath, files);
if (resolvedFile) { if (resolvedFile) {
if (resolvedFile.url) { if (resolvedFile.url) {
newContent = newContent.replace(filePath, resolvedFile.url); newContent = newContent.replace(cssFileString, quoteCharacter + resolvedFile.url + quoteCharacter);
} }
} }
} }

View file

@ -34,6 +34,15 @@ import AddToCollectionList from '../components/AddToCollectionList';
import Feedback from '../components/Feedback'; import Feedback from '../components/Feedback';
import { CollectionSearchbar } from '../components/Searchbar'; import { CollectionSearchbar } from '../components/Searchbar';
function getTitle(props) {
const { id } = props.project;
return id ? `p5.js Web Editor | ${props.project.name}` : 'p5.js Web Editor';
}
function isUserOwner(props) {
return props.project.owner && props.project.owner.id === props.user.id;
}
class IDEView extends React.Component { class IDEView extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -92,7 +101,7 @@ class IDEView extends React.Component {
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
if (this.isUserOwner() && this.props.project.id) { if (isUserOwner(this.props) && this.props.project.id) {
if (this.props.preferences.autosave && this.props.ide.unsavedChanges && !this.props.ide.justOpenedProject) { if (this.props.preferences.autosave && this.props.ide.unsavedChanges && !this.props.ide.justOpenedProject) {
if ( if (
this.props.selectedFile.name === prevProps.selectedFile.name && this.props.selectedFile.name === prevProps.selectedFile.name &&
@ -123,21 +132,12 @@ class IDEView extends React.Component {
this.autosaveInterval = null; this.autosaveInterval = null;
} }
getTitle = () => {
const { id } = this.props.project;
return id ? `p5.js Web Editor | ${this.props.project.name}` : 'p5.js Web Editor';
}
isUserOwner() {
return this.props.project.owner && this.props.project.owner.id === this.props.user.id;
}
handleGlobalKeydown(e) { handleGlobalKeydown(e) {
// 83 === s // 83 === s
if (e.keyCode === 83 && ((e.metaKey && this.isMac) || (e.ctrlKey && !this.isMac))) { if (e.keyCode === 83 && ((e.metaKey && this.isMac) || (e.ctrlKey && !this.isMac))) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
if (this.isUserOwner() || (this.props.user.authenticated && !this.props.project.owner)) { if (isUserOwner(this.props) || (this.props.user.authenticated && !this.props.project.owner)) {
this.props.saveProject(this.cmController.getContent()); this.props.saveProject(this.cmController.getContent());
} else if (this.props.user.authenticated) { } else if (this.props.user.authenticated) {
this.props.cloneProject(); this.props.cloneProject();
@ -208,7 +208,7 @@ class IDEView extends React.Component {
return ( return (
<div className="ide"> <div className="ide">
<Helmet> <Helmet>
<title>{this.getTitle()}</title> <title>{getTitle(this.props)}</title>
</Helmet> </Helmet>
{this.props.toast.isVisible && <Toast />} {this.props.toast.isVisible && <Toast />}
<Nav <Nav
@ -313,7 +313,7 @@ class IDEView extends React.Component {
isExpanded={this.props.ide.sidebarIsExpanded} isExpanded={this.props.ide.sidebarIsExpanded}
expandSidebar={this.props.expandSidebar} expandSidebar={this.props.expandSidebar}
collapseSidebar={this.props.collapseSidebar} collapseSidebar={this.props.collapseSidebar}
isUserOwner={this.isUserOwner()} isUserOwner={isUserOwner(this.props)}
clearConsole={this.props.clearConsole} clearConsole={this.props.clearConsole}
consoleEvents={this.props.console} consoleEvents={this.props.console}
showRuntimeErrorWarning={this.props.showRuntimeErrorWarning} showRuntimeErrorWarning={this.props.showRuntimeErrorWarning}

View file

@ -37,6 +37,11 @@ const getSortedCollections = createSelector(
return orderBy(collections, 'name', 'desc'); return orderBy(collections, 'name', 'desc');
} }
return orderBy(collections, 'name', 'asc'); return orderBy(collections, 'name', 'asc');
} else if (field === 'numItems') {
if (direction === DIRECTION.DESC) {
return orderBy(collections, 'items.length', 'desc');
}
return orderBy(collections, 'items.length', 'asc');
} }
const sortedCollections = [...collections].sort((a, b) => { const sortedCollections = [...collections].sort((a, b) => {
const result = const result =

View file

@ -69,9 +69,8 @@ Note that this is optional, unless you are working on the part of the applicatio
If your S3 bucket is in the US East (N Virginia) region (us-east-1), you'll If your S3 bucket is in the US East (N Virginia) region (us-east-1), you'll
need to set a custom URL base for it, because it does not follow the standard need to set a custom URL base for it, because it does not follow the standard
naming pattern as the rest of the regions. Instead, add the following to your naming pattern as the rest of the regions. Instead, add the following to your
environment/.env file: environment/.env file, changing `BUCKET_NAME` to your bucket name. This is necessary because this override is currently treated as the full path to the bucket rather than as a proper base url:
`S3_BUCKET_URL_BASE=https://s3.amazonaws.com/{BUCKET_NAME}/`
`S3_BUCKET_URL_BASE=https://s3.amazonaws.com`
If you've configured your S3 bucket and DNS records to use a custom domain If you've configured your S3 bucket and DNS records to use a custom domain
name, you can also set it using this variable. I.e.: name, you can also set it using this variable. I.e.:

View file

@ -34,6 +34,7 @@ export function serveProject(req, res) {
resolveScripts(sketchDoc, files); resolveScripts(sketchDoc, files);
resolveStyles(sketchDoc, files); resolveStyles(sketchDoc, files);
res.setHeader('Cache-Control', 'public, max-age=0');
res.send(serializeDocument(sketchDoc)); res.send(serializeDocument(sketchDoc));
}); });
}); });

View file

@ -73,7 +73,7 @@ function getCategories() {
function getSketchesInCategories(categories) { function getSketchesInCategories(categories) {
return Q.all(categories.map((category) => { return Q.all(categories.map((category) => {
const options = { const options = {
url: `${category.url.replace('?ref=master', '')}?client_id=${clientId}&client_secret=${clientSecret}`, url: `${category.url.replace('?ref=main', '')}?client_id=${clientId}&client_secret=${clientSecret}`,
method: 'GET', method: 'GET',
headers, headers,
json: true json: true
@ -107,7 +107,7 @@ function getSketchesInCategories(categories) {
function getSketchContent(projectsInAllCategories) { function getSketchContent(projectsInAllCategories) {
return Q.all(projectsInAllCategories.map(projectsInOneCategory => Q.all(projectsInOneCategory.map((project) => { return Q.all(projectsInAllCategories.map(projectsInOneCategory => Q.all(projectsInOneCategory.map((project) => {
const options = { const options = {
url: `${project.sketchUrl.replace('?ref=master', '')}?client_id=${clientId}&client_secret=${clientSecret}`, url: `${project.sketchUrl.replace('?ref=main', '')}?client_id=${clientId}&client_secret=${clientSecret}`,
method: 'GET', method: 'GET',
headers headers
}; };
@ -264,7 +264,7 @@ function createProjectsInP5user(projectsInAllCategories) {
const fileID = objectID().toHexString(); const fileID = objectID().toHexString();
newProject.files.push({ newProject.files.push({
name: assetName, name: assetName,
url: `https://cdn.jsdelivr.net/gh/processing/p5.js-website@master/src/data/examples/assets/${assetName}`, url: `https://cdn.jsdelivr.net/gh/processing/p5.js-website@main/src/data/examples/assets/${assetName}`,
id: fileID, id: fileID,
_id: fileID, _id: fileID,
children: [], children: [],