Resolve merge conflicts with master
This commit is contained in:
commit
148ab78466
63 changed files with 3465 additions and 3729 deletions
|
@ -1,17 +1,20 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
|
|
||||||
const addIcon = require('../images/plus.svg');
|
import AddIcon from '../images/plus.svg';
|
||||||
const removeIcon = require('../images/minus.svg');
|
import RemoveIcon from '../images/minus.svg';
|
||||||
|
|
||||||
const AddRemoveButton = ({ type, onClick }) => {
|
const AddRemoveButton = ({ type, onClick }) => {
|
||||||
const alt = type === 'add' ? 'add to collection' : 'remove from collection';
|
const alt = type === 'add' ? 'Add to collection' : 'Remove from collection';
|
||||||
const icon = type === 'add' ? addIcon : removeIcon;
|
const Icon = type === 'add' ? AddIcon : RemoveIcon;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className="overlay__close-button" onClick={onClick}>
|
<button
|
||||||
<InlineSVG src={icon} alt={alt} />
|
className="overlay__close-button"
|
||||||
|
onClick={onClick}
|
||||||
|
aria-label={alt}
|
||||||
|
>
|
||||||
|
<Icon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,6 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { withRouter } from 'react-router';
|
import { withRouter } from 'react-router';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import * as IDEActions from '../modules/IDE/actions/ide';
|
import * as IDEActions from '../modules/IDE/actions/ide';
|
||||||
import * as toastActions from '../modules/IDE/actions/toast';
|
import * as toastActions from '../modules/IDE/actions/toast';
|
||||||
|
@ -12,10 +11,10 @@ import { setAllAccessibleOutput } from '../modules/IDE/actions/preferences';
|
||||||
import { logoutUser } from '../modules/User/actions';
|
import { logoutUser } from '../modules/User/actions';
|
||||||
|
|
||||||
import { metaKeyName, } from '../utils/metaKey';
|
import { metaKeyName, } from '../utils/metaKey';
|
||||||
import caretLeft from '../images/left-arrow.svg';
|
|
||||||
|
|
||||||
const triangleUrl = require('../images/down-filled-triangle.svg');
|
import CaretLeftIcon from '../images/left-arrow.svg';
|
||||||
const logoUrl = require('../images/p5js-logo-small.svg');
|
import TriangleIcon from '../images/down-filled-triangle.svg';
|
||||||
|
import LogoIcon from '../images/p5js-logo-small.svg';
|
||||||
|
|
||||||
const __process = (typeof global !== 'undefined' ? global : window).process;
|
const __process = (typeof global !== 'undefined' ? global : window).process;
|
||||||
|
|
||||||
|
@ -229,11 +228,11 @@ class Nav extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<ul className="nav__items-left">
|
<ul className="nav__items-left">
|
||||||
<li className="nav__item-logo">
|
<li className="nav__item-logo">
|
||||||
<InlineSVG src={logoUrl} alt="p5.js logo" className="svg__logo" />
|
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
|
||||||
</li>
|
</li>
|
||||||
<li className="nav__item nav__item--no-icon">
|
<li className="nav__item nav__item--no-icon">
|
||||||
<Link to="/" className="nav__back-link">
|
<Link to="/" className="nav__back-link">
|
||||||
<InlineSVG src={caretLeft} className="nav__back-icon" />
|
<CaretLeftIcon className="nav__back-icon" focusable="false" aria-hidden="true" />
|
||||||
<span className="nav__item-header">
|
<span className="nav__item-header">
|
||||||
Back to Editor
|
Back to Editor
|
||||||
</span>
|
</span>
|
||||||
|
@ -247,7 +246,7 @@ class Nav extends React.PureComponent {
|
||||||
return (
|
return (
|
||||||
<ul className="nav__items-left">
|
<ul className="nav__items-left">
|
||||||
<li className="nav__item-logo">
|
<li className="nav__item-logo">
|
||||||
<InlineSVG src={logoUrl} alt="p5.js logo" className="svg__logo" />
|
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
|
||||||
</li>
|
</li>
|
||||||
<li className={navDropdownState.file}>
|
<li className={navDropdownState.file}>
|
||||||
<button
|
<button
|
||||||
|
@ -261,7 +260,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">File</span>
|
<span className="nav__item-header">File</span>
|
||||||
<InlineSVG className="nav__item-header-triangle" src={triangleUrl} />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown">
|
<ul className="nav__dropdown">
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -363,7 +362,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Edit</span>
|
<span className="nav__item-header">Edit</span>
|
||||||
<InlineSVG className="nav__item-header-triangle" src={triangleUrl} />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown" >
|
<ul className="nav__dropdown" >
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -423,7 +422,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Sketch</span>
|
<span className="nav__item-header">Sketch</span>
|
||||||
<InlineSVG className="nav__item-header-triangle" src={triangleUrl} />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown">
|
<ul className="nav__dropdown">
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -498,7 +497,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="nav__item-header">Help</span>
|
<span className="nav__item-header">Help</span>
|
||||||
<InlineSVG className="nav__item-header-triangle" src={triangleUrl} />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown">
|
<ul className="nav__dropdown">
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
@ -575,7 +574,7 @@ class Nav extends React.PureComponent {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
My Account
|
My Account
|
||||||
<InlineSVG className="nav__item-header-triangle" src={triangleUrl} />
|
<TriangleIcon className="nav__item-header-triangle" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="nav__dropdown">
|
<ul className="nav__dropdown">
|
||||||
<li className="nav__dropdown-item">
|
<li className="nav__dropdown-item">
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
|
|
||||||
const logoUrl = require('../images/p5js-logo-small.svg');
|
import LogoIcon from '../images/p5js-logo-small.svg';
|
||||||
const arrowUrl = require('../images/triangle-arrow-left.svg');
|
import ArrowIcon from '../images/triangle-arrow-left.svg';
|
||||||
|
|
||||||
class NavBasic extends React.PureComponent {
|
class NavBasic extends React.PureComponent {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -15,13 +14,13 @@ class NavBasic extends React.PureComponent {
|
||||||
<nav className="nav" title="main-navigation" ref={(node) => { this.node = node; }}>
|
<nav className="nav" title="main-navigation" ref={(node) => { this.node = node; }}>
|
||||||
<ul className="nav__items-left">
|
<ul className="nav__items-left">
|
||||||
<li className="nav__item-logo">
|
<li className="nav__item-logo">
|
||||||
<InlineSVG src={logoUrl} alt="p5.js logo" className="svg__logo" />
|
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
|
||||||
</li>
|
</li>
|
||||||
{ this.props.onBack && (
|
{ this.props.onBack && (
|
||||||
<li className="nav__item">
|
<li className="nav__item">
|
||||||
<button onClick={this.props.onBack}>
|
<button onClick={this.props.onBack}>
|
||||||
<span className="nav__item-header">
|
<span className="nav__item-header">
|
||||||
<InlineSVG src={arrowUrl} alt="Left arrow" />
|
<ArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
Back to the editor
|
Back to the editor
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
|
|
||||||
const logoUrl = require('../images/p5js-logo-small.svg');
|
import LogoIcon from '../images/p5js-logo-small.svg';
|
||||||
const editorUrl = require('../images/code.svg');
|
import CodeIcon from '../images/code.svg';
|
||||||
|
|
||||||
const PreviewNav = ({ owner, project }) => (
|
const PreviewNav = ({ owner, project }) => (
|
||||||
<nav className="nav preview-nav">
|
<nav className="nav preview-nav">
|
||||||
<div className="nav__items-left">
|
<div className="nav__items-left">
|
||||||
<div className="nav__item-logo">
|
<div className="nav__item-logo">
|
||||||
<InlineSVG src={logoUrl} alt="p5.js logo" className="svg__logo" />
|
<LogoIcon role="img" aria-label="p5.js Logo" focusable="false" className="svg__logo" />
|
||||||
</div>
|
</div>
|
||||||
<Link className="nav__item" to={`/${owner.username}/sketches/${project.id}`}>{project.name}</Link>
|
<Link className="nav__item" to={`/${owner.username}/sketches/${project.id}`}>{project.name}</Link>
|
||||||
<p className="toolbar__project-owner">by</p>
|
<p className="toolbar__project-owner">by</p>
|
||||||
<Link className="nav__item" to={`/${owner.username}/sketches/`}>{owner.username}</Link>
|
<Link className="nav__item" to={`/${owner.username}/sketches/`}>{owner.username}</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="nav__items-right">
|
<div className="nav__items-right">
|
||||||
<Link to={`/${owner.username}/sketches/${project.id}`}>
|
<Link to={`/${owner.username}/sketches/${project.id}`} aria-label="Edit Sketch" >
|
||||||
<InlineSVG className="preview-nav__editor-svg" src={editorUrl} />
|
<CodeIcon className="preview-nav__editor-svg" focusable="false" aria-hidden="true" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -11,8 +11,11 @@ exports[`Nav renders correctly 1`] = `
|
||||||
<li
|
<li
|
||||||
className="nav__item-logo"
|
className="nav__item-logo"
|
||||||
>
|
>
|
||||||
<span
|
<test-file-stub
|
||||||
className="isvg loading svg__logo"
|
aria-label="p5.js Logo"
|
||||||
|
className="svg__logo"
|
||||||
|
focusable="false"
|
||||||
|
role="img"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
|
@ -29,8 +32,10 @@ exports[`Nav renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
File
|
File
|
||||||
</span>
|
</span>
|
||||||
<span
|
<test-file-stub
|
||||||
className="isvg loading nav__item-header-triangle"
|
aria-hidden="true"
|
||||||
|
className="nav__item-header-triangle"
|
||||||
|
focusable="false"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<ul
|
<ul
|
||||||
|
@ -108,8 +113,10 @@ exports[`Nav renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</span>
|
</span>
|
||||||
<span
|
<test-file-stub
|
||||||
className="isvg loading nav__item-header-triangle"
|
aria-hidden="true"
|
||||||
|
className="nav__item-header-triangle"
|
||||||
|
focusable="false"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<ul
|
<ul
|
||||||
|
@ -201,8 +208,10 @@ exports[`Nav renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
Sketch
|
Sketch
|
||||||
</span>
|
</span>
|
||||||
<span
|
<test-file-stub
|
||||||
className="isvg loading nav__item-header-triangle"
|
aria-hidden="true"
|
||||||
|
className="nav__item-header-triangle"
|
||||||
|
focusable="false"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<ul
|
<ul
|
||||||
|
@ -282,8 +291,10 @@ exports[`Nav renders correctly 1`] = `
|
||||||
>
|
>
|
||||||
Help
|
Help
|
||||||
</span>
|
</span>
|
||||||
<span
|
<test-file-stub
|
||||||
className="isvg loading nav__item-header-triangle"
|
aria-hidden="true"
|
||||||
|
className="nav__item-header-triangle"
|
||||||
|
focusable="false"
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
<ul
|
<ul
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { browserHistory } from 'react-router';
|
import { browserHistory } from 'react-router';
|
||||||
|
|
||||||
const exitUrl = require('../../../images/exit.svg');
|
import ExitIcon from '../../../images/exit.svg';
|
||||||
|
|
||||||
class Overlay extends React.Component {
|
class Overlay extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -81,8 +80,8 @@ class Overlay extends React.Component {
|
||||||
<h2 className="overlay__title">{title}</h2>
|
<h2 className="overlay__title">{title}</h2>
|
||||||
<div className="overlay__actions">
|
<div className="overlay__actions">
|
||||||
{actions}
|
{actions}
|
||||||
<button className="overlay__close-button" onClick={this.close} >
|
<button className="overlay__close-button" onClick={this.close} aria-label={`Close ${title} overlay`} >
|
||||||
<InlineSVG src={exitUrl} alt="close overlay" />
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
|
@ -27,7 +27,8 @@ export function getCollections(username) {
|
||||||
});
|
});
|
||||||
dispatch(stopLoader());
|
dispatch(stopLoader());
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.ERROR,
|
type: ActionTypes.ERROR,
|
||||||
error: response.data
|
error: response.data
|
||||||
|
@ -57,7 +58,8 @@ export function createCollection(collection) {
|
||||||
|
|
||||||
browserHistory.push(location);
|
browserHistory.push(location);
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
console.error('Error creating collection', response.data);
|
console.error('Error creating collection', response.data);
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.ERROR,
|
type: ActionTypes.ERROR,
|
||||||
|
@ -87,7 +89,8 @@ export function addToCollection(collectionId, projectId) {
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.ERROR,
|
type: ActionTypes.ERROR,
|
||||||
error: response.data
|
error: response.data
|
||||||
|
@ -118,7 +121,8 @@ export function removeFromCollection(collectionId, projectId) {
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.ERROR,
|
type: ActionTypes.ERROR,
|
||||||
error: response.data
|
error: response.data
|
||||||
|
@ -141,7 +145,8 @@ export function editCollection(collectionId, { name, description }) {
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.ERROR,
|
type: ActionTypes.ERROR,
|
||||||
error: response.data
|
error: response.data
|
||||||
|
@ -164,7 +169,8 @@ export function deleteCollection(collectionId) {
|
||||||
});
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.ERROR,
|
type: ActionTypes.ERROR,
|
||||||
error: response.data
|
error: response.data
|
||||||
|
|
|
@ -65,10 +65,13 @@ export function createFile(formProps) {
|
||||||
// });
|
// });
|
||||||
dispatch(setUnsavedChanges(true));
|
dispatch(setUnsavedChanges(true));
|
||||||
})
|
})
|
||||||
.catch(response => dispatch({
|
.catch((error) => {
|
||||||
type: ActionTypes.ERROR,
|
const { response } = error;
|
||||||
error: response.data
|
dispatch({
|
||||||
}));
|
type: ActionTypes.ERROR,
|
||||||
|
error: response.data
|
||||||
|
});
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const id = objectID().toHexString();
|
const id = objectID().toHexString();
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -113,10 +116,13 @@ export function createFolder(formProps) {
|
||||||
dispatch(setProjectSavedTime(response.data.project.updatedAt));
|
dispatch(setProjectSavedTime(response.data.project.updatedAt));
|
||||||
dispatch(closeNewFolderModal());
|
dispatch(closeNewFolderModal());
|
||||||
})
|
})
|
||||||
.catch(response => dispatch({
|
.catch((error) => {
|
||||||
type: ActionTypes.ERROR,
|
const { response } = error;
|
||||||
error: response.data
|
dispatch({
|
||||||
}));
|
type: ActionTypes.ERROR,
|
||||||
|
error: response.data
|
||||||
|
});
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const id = objectID().toHexString();
|
const id = objectID().toHexString();
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -163,7 +169,8 @@ export function deleteFile(id, parentId) {
|
||||||
parentId
|
parentId
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.ERROR,
|
type: ActionTypes.ERROR,
|
||||||
error: response.data
|
error: response.data
|
||||||
|
|
|
@ -8,10 +8,13 @@ function updatePreferences(formParams, dispatch) {
|
||||||
axios.put(`${ROOT_URL}/preferences`, formParams, { withCredentials: true })
|
axios.put(`${ROOT_URL}/preferences`, formParams, { withCredentials: true })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
})
|
})
|
||||||
.catch(response => dispatch({
|
.catch((error) => {
|
||||||
type: ActionTypes.ERROR,
|
const { response } = error;
|
||||||
error: response.data
|
dispatch({
|
||||||
}));
|
type: ActionTypes.ERROR,
|
||||||
|
error: response.data
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setFontSize(value) {
|
export function setFontSize(value) {
|
||||||
|
|
|
@ -57,10 +57,13 @@ export function getProject(id) {
|
||||||
dispatch(setProject(response.data));
|
dispatch(setProject(response.data));
|
||||||
dispatch(setUnsavedChanges(false));
|
dispatch(setUnsavedChanges(false));
|
||||||
})
|
})
|
||||||
.catch(response => dispatch({
|
.catch((error) => {
|
||||||
type: ActionTypes.ERROR,
|
const { response } = error;
|
||||||
error: response.data
|
dispatch({
|
||||||
}));
|
type: ActionTypes.ERROR,
|
||||||
|
error: response.data
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +164,8 @@ export function saveProject(selectedFile = null, autosave = false) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch(endSavingProject());
|
dispatch(endSavingProject());
|
||||||
if (response.status === 403) {
|
if (response.status === 403) {
|
||||||
dispatch(showErrorModal('staleSession'));
|
dispatch(showErrorModal('staleSession'));
|
||||||
|
@ -200,7 +204,8 @@ export function saveProject(selectedFile = null, autosave = false) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch(endSavingProject());
|
dispatch(endSavingProject());
|
||||||
if (response.status === 403) {
|
if (response.status === 403) {
|
||||||
dispatch(showErrorModal('staleSession'));
|
dispatch(showErrorModal('staleSession'));
|
||||||
|
@ -298,10 +303,13 @@ export function cloneProject(id) {
|
||||||
browserHistory.push(`/${response.data.user.username}/sketches/${response.data.id}`);
|
browserHistory.push(`/${response.data.user.username}/sketches/${response.data.id}`);
|
||||||
dispatch(setNewProject(response.data));
|
dispatch(setNewProject(response.data));
|
||||||
})
|
})
|
||||||
.catch(response => dispatch({
|
.catch((error) => {
|
||||||
type: ActionTypes.PROJECT_SAVE_FAIL,
|
const { response } = error;
|
||||||
error: response.data
|
dispatch({
|
||||||
}));
|
type: ActionTypes.PROJECT_SAVE_FAIL,
|
||||||
|
error: response.data
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -344,8 +352,8 @@ export function changeProjectName(id, newName) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
console.log(response);
|
const { response } = error;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.PROJECT_SAVE_FAIL,
|
type: ActionTypes.PROJECT_SAVE_FAIL,
|
||||||
error: response.data
|
error: response.data
|
||||||
|
@ -368,7 +376,8 @@ export function deleteProject(id) {
|
||||||
id
|
id
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
if (response.status === 403) {
|
if (response.status === 403) {
|
||||||
dispatch(showErrorModal('staleSession'));
|
dispatch(showErrorModal('staleSession'));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -23,7 +23,8 @@ export function getProjects(username) {
|
||||||
});
|
});
|
||||||
dispatch(stopLoader());
|
dispatch(stopLoader());
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.ERROR,
|
type: ActionTypes.ERROR,
|
||||||
error: response.data
|
error: response.data
|
||||||
|
|
|
@ -65,7 +65,8 @@ export function dropzoneAcceptCallback(userId, file, done) {
|
||||||
file.previewTemplate.className += ' uploading'; // eslint-disable-line
|
file.previewTemplate.className += ' uploading'; // eslint-disable-line
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
file.custom_status = 'rejected'; // eslint-disable-line
|
file.custom_status = 'rejected'; // eslint-disable-line
|
||||||
if (response.data && response.data.responseText && response.data.responseText.message) {
|
if (response.data && response.data.responseText && response.data.responseText.message) {
|
||||||
done(response.data.responseText.message);
|
done(response.data.responseText.message);
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
const squareLogoUrl = require('../../../images/p5js-square-logo.svg');
|
import SquareLogoIcon from '../../../images/p5js-square-logo.svg';
|
||||||
// const playUrl = require('../../../images/play.svg');
|
// import PlayIcon from '../../../images/play.svg';
|
||||||
const asteriskUrl = require('../../../images/p5-asterisk.svg');
|
import AsteriskIcon from '../../../images/p5-asterisk.svg';
|
||||||
|
|
||||||
function About(props) {
|
function About(props) {
|
||||||
return (
|
return (
|
||||||
|
@ -13,7 +12,7 @@ function About(props) {
|
||||||
<title>p5.js Web Editor | About</title>
|
<title>p5.js Web Editor | About</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="about__content-column">
|
<div className="about__content-column">
|
||||||
<InlineSVG className="about__logo" src={squareLogoUrl} alt="p5js Square Logo" />
|
<SquareLogoIcon className="about__logo" role="img" aria-label="p5.js Logo" focusable="false" />
|
||||||
{/* Video button to hello p5 video page */}
|
{/* Video button to hello p5 video page */}
|
||||||
{/* <p className="about__play-video">
|
{/* <p className="about__play-video">
|
||||||
<a
|
<a
|
||||||
|
@ -21,7 +20,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<InlineSVG className="about__play-video-button" src={playUrl} alt="Play Hello Video" />
|
<PlayIcon className="about__play-video-button" title="Play Hello Video" />
|
||||||
Play hello! video</a>
|
Play hello! video</a>
|
||||||
</p> */}
|
</p> */}
|
||||||
</div>
|
</div>
|
||||||
|
@ -33,7 +32,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<InlineSVG className="about__content-column-asterisk" src={asteriskUrl} alt="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Examples
|
Examples
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -43,7 +42,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<InlineSVG className="about__content-column-asterisk" src={asteriskUrl} alt="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Learn
|
Learn
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -56,7 +55,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<InlineSVG className="about__content-column-asterisk" src={asteriskUrl} alt="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Libraries
|
Libraries
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -66,7 +65,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<InlineSVG className="about__content-column-asterisk" src={asteriskUrl} alt="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Reference
|
Reference
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
@ -76,7 +75,7 @@ function About(props) {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
<InlineSVG className="about__content-column-asterisk" src={asteriskUrl} alt="p5 asterisk" />
|
<AsteriskIcon className="about__content-column-asterisk" aria-hidden="true" focusable="false" />
|
||||||
Forum
|
Forum
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -5,11 +5,10 @@ import { bindActionCreators } from 'redux';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import prettyBytes from 'pretty-bytes';
|
import prettyBytes from 'pretty-bytes';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
|
|
||||||
import Loader from '../../App/components/loader';
|
import Loader from '../../App/components/loader';
|
||||||
import * as AssetActions from '../actions/assets';
|
import * as AssetActions from '../actions/assets';
|
||||||
import downFilledTriangle from '../../../images/down-filled-triangle.svg';
|
import DownFilledTriangleIcon from '../../../images/down-filled-triangle.svg';
|
||||||
|
|
||||||
class AssetListRowBase extends React.Component {
|
class AssetListRowBase extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -86,8 +85,9 @@ class AssetListRowBase extends React.Component {
|
||||||
onClick={this.toggleOptions}
|
onClick={this.toggleOptions}
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
|
aria-label="Toggle Open/Close Asset Options"
|
||||||
>
|
>
|
||||||
<InlineSVG src={downFilledTriangle} alt="Menu" />
|
<DownFilledTriangleIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
{optionsOpen &&
|
{optionsOpen &&
|
||||||
<ul
|
<ul
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
@ -19,8 +18,8 @@ import { SketchSearchbar } from '../Searchbar';
|
||||||
|
|
||||||
import CollectionListRow from './CollectionListRow';
|
import CollectionListRow from './CollectionListRow';
|
||||||
|
|
||||||
const arrowUp = require('../../../../images/sort-arrow-up.svg');
|
import ArrowUpIcon from '../../../../images/sort-arrow-up.svg';
|
||||||
const arrowDown = require('../../../../images/sort-arrow-down.svg');
|
import ArrowDownIcon from '../../../../images/sort-arrow-down.svg';
|
||||||
|
|
||||||
class CollectionList extends React.Component {
|
class CollectionList extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -83,21 +82,43 @@ class CollectionList extends React.Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getButtonLabel = (fieldName, displayName) => {
|
||||||
|
const { field, direction } = this.props.sorting;
|
||||||
|
let buttonLabel;
|
||||||
|
if (field !== fieldName) {
|
||||||
|
if (field === 'name') {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
}
|
||||||
|
} else if (direction === SortingActions.DIRECTION.ASC) {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
}
|
||||||
|
return buttonLabel;
|
||||||
|
}
|
||||||
|
|
||||||
_renderFieldHeader = (fieldName, displayName) => {
|
_renderFieldHeader = (fieldName, displayName) => {
|
||||||
const { field, direction } = this.props.sorting;
|
const { field, direction } = this.props.sorting;
|
||||||
const headerClass = classNames({
|
const headerClass = classNames({
|
||||||
'sketches-table__header': true,
|
'sketches-table__header': true,
|
||||||
'sketches-table__header--selected': field === fieldName
|
'sketches-table__header--selected': field === fieldName
|
||||||
});
|
});
|
||||||
|
const buttonLabel = this._getButtonLabel(fieldName, displayName);
|
||||||
return (
|
return (
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
<button className="sketch-list__sort-button" onClick={() => this.props.toggleDirectionForField(fieldName)}>
|
<button
|
||||||
|
className="sketch-list__sort-button"
|
||||||
|
onClick={() => this.props.toggleDirectionForField(fieldName)}
|
||||||
|
aria-label={buttonLabel}
|
||||||
|
>
|
||||||
<span className={headerClass}>{displayName}</span>
|
<span className={headerClass}>{displayName}</span>
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
||||||
<InlineSVG src={arrowUp} />
|
<ArrowUpIcon role="img" aria-label="Ascending" focusable="false" />
|
||||||
}
|
}
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
||||||
<InlineSVG src={arrowDown} />
|
<ArrowDownIcon role="img" aria-label="Descending" focusable="false" />
|
||||||
}
|
}
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import format from 'date-fns/format';
|
import format from 'date-fns/format';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
@ -10,7 +9,7 @@ import * as CollectionsActions from '../../actions/collections';
|
||||||
import * as IdeActions from '../../actions/ide';
|
import * as IdeActions from '../../actions/ide';
|
||||||
import * as ToastActions from '../../actions/toast';
|
import * as ToastActions from '../../actions/toast';
|
||||||
|
|
||||||
const downFilledTriangle = require('../../../../images/down-filled-triangle.svg');
|
import DownFilledTriangleIcon from '../../../../images/down-filled-triangle.svg';
|
||||||
|
|
||||||
class CollectionListRowBase extends React.Component {
|
class CollectionListRowBase extends React.Component {
|
||||||
static projectInCollection(project, collection) {
|
static projectInCollection(project, collection) {
|
||||||
|
@ -129,8 +128,9 @@ class CollectionListRowBase extends React.Component {
|
||||||
onClick={this.toggleOptions}
|
onClick={this.toggleOptions}
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
|
aria-label="Toggle Open/Close collection options"
|
||||||
>
|
>
|
||||||
<InlineSVG src={downFilledTriangle} alt="Menu" />
|
<DownFilledTriangleIcon title="Menu" />
|
||||||
</button>
|
</button>
|
||||||
{optionsOpen &&
|
{optionsOpen &&
|
||||||
<ul
|
<ul
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Console as ConsoleFeed } from 'console-feed';
|
import { Console as ConsoleFeed } from 'console-feed';
|
||||||
import {
|
import {
|
||||||
CONSOLE_FEED_WITHOUT_ICONS, CONSOLE_FEED_LIGHT_STYLES,
|
CONSOLE_FEED_WITHOUT_ICONS, CONSOLE_FEED_LIGHT_STYLES,
|
||||||
CONSOLE_FEED_DARK_STYLES, CONSOLE_FEED_CONTRAST_STYLES
|
CONSOLE_FEED_DARK_STYLES, CONSOLE_FEED_CONTRAST_STYLES
|
||||||
} from '../../../styles/components/_console-feed.scss';
|
} from '../../../styles/components/_console-feed.scss';
|
||||||
import warnLightUrl from '../../../images/console-warn-light.svg';
|
import warnLightUrl from '../../../images/console-warn-light.svg?byUrl';
|
||||||
import warnDarkUrl from '../../../images/console-warn-dark.svg';
|
import warnDarkUrl from '../../../images/console-warn-dark.svg?byUrl';
|
||||||
import warnContrastUrl from '../../../images/console-warn-contrast.svg';
|
import warnContrastUrl from '../../../images/console-warn-contrast.svg?byUrl';
|
||||||
import errorLightUrl from '../../../images/console-error-light.svg';
|
import errorLightUrl from '../../../images/console-error-light.svg?byUrl';
|
||||||
import errorDarkUrl from '../../../images/console-error-dark.svg';
|
import errorDarkUrl from '../../../images/console-error-dark.svg?byUrl';
|
||||||
import errorContrastUrl from '../../../images/console-error-contrast.svg';
|
import errorContrastUrl from '../../../images/console-error-contrast.svg?byUrl';
|
||||||
import debugLightUrl from '../../../images/console-debug-light.svg';
|
import debugLightUrl from '../../../images/console-debug-light.svg?byUrl';
|
||||||
import debugDarkUrl from '../../../images/console-debug-dark.svg';
|
import debugDarkUrl from '../../../images/console-debug-dark.svg?byUrl';
|
||||||
import debugContrastUrl from '../../../images/console-debug-contrast.svg';
|
import debugContrastUrl from '../../../images/console-debug-contrast.svg?byUrl';
|
||||||
import infoLightUrl from '../../../images/console-info-light.svg';
|
import infoLightUrl from '../../../images/console-info-light.svg?byUrl';
|
||||||
import infoDarkUrl from '../../../images/console-info-dark.svg';
|
import infoDarkUrl from '../../../images/console-info-dark.svg?byUrl';
|
||||||
import infoContrastUrl from '../../../images/console-info-contrast.svg';
|
import infoContrastUrl from '../../../images/console-info-contrast.svg?byUrl';
|
||||||
|
|
||||||
const upArrowUrl = require('../../../images/up-arrow.svg');
|
import UpArrowIcon from '../../../images/up-arrow.svg';
|
||||||
const downArrowUrl = require('../../../images/down-arrow.svg');
|
import DownArrowIcon from '../../../images/down-arrow.svg';
|
||||||
|
|
||||||
class Console extends React.Component {
|
class Console extends React.Component {
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
|
@ -91,18 +90,18 @@ class Console extends React.Component {
|
||||||
<div className="preview-console__header">
|
<div className="preview-console__header">
|
||||||
<h2 className="preview-console__header-title">Console</h2>
|
<h2 className="preview-console__header-title">Console</h2>
|
||||||
<div className="preview-console__header-buttons">
|
<div className="preview-console__header-buttons">
|
||||||
<button className="preview-console__clear" onClick={this.props.clearConsole} aria-label="clear console">
|
<button className="preview-console__clear" onClick={this.props.clearConsole} aria-label="Clear console">
|
||||||
Clear
|
Clear
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="preview-console__collapse"
|
className="preview-console__collapse"
|
||||||
onClick={this.props.collapseConsole}
|
onClick={this.props.collapseConsole}
|
||||||
aria-label="collapse console"
|
aria-label="Close console"
|
||||||
>
|
>
|
||||||
<InlineSVG src={downArrowUrl} />
|
<DownArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button className="preview-console__expand" onClick={this.props.expandConsole} aria-label="expand console">
|
<button className="preview-console__expand" onClick={this.props.expandConsole} aria-label="Open console" >
|
||||||
<InlineSVG src={upArrowUrl} />
|
<UpArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Clipboard from 'clipboard';
|
import Clipboard from 'clipboard';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import shareUrl from '../../../images/share.svg';
|
import ShareIcon from '../../../images/share.svg';
|
||||||
|
|
||||||
class CopyableInput extends React.Component {
|
class CopyableInput extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -70,8 +69,9 @@ class CopyableInput extends React.Component {
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
href={value}
|
href={value}
|
||||||
className="copyable-input__preview"
|
className="copyable-input__preview"
|
||||||
|
aria-label={`Open ${label} view in new tab`}
|
||||||
>
|
>
|
||||||
<InlineSVG src={shareUrl} alt={`open ${label} view in new tab`} />
|
<ShareIcon focusable="false" aria-hidden="true" />
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
|
|
||||||
const editIconUrl = require('../../../images/pencil.svg');
|
import EditIcon from '../../../images/pencil.svg';
|
||||||
|
|
||||||
function EditIcon() {
|
|
||||||
return <InlineSVG className="editable-input__icon" src={editIconUrl} alt="Edit" />;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO I think this needs a description prop so that it's accessible
|
||||||
function EditableInput({
|
function EditableInput({
|
||||||
validate, value, emptyPlaceholder, InputComponent, inputProps, onChange
|
validate, value, emptyPlaceholder, InputComponent, inputProps, onChange
|
||||||
}) {
|
}) {
|
||||||
|
@ -52,9 +48,13 @@ function EditableInput({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={classes}>
|
<span className={classes}>
|
||||||
<button className="editable-input__label" onClick={beginEditing}>
|
<button
|
||||||
|
className="editable-input__label"
|
||||||
|
onClick={beginEditing}
|
||||||
|
aria-label={`Edit ${displayValue} value`}
|
||||||
|
>
|
||||||
<span>{displayValue}</span>
|
<span>{displayValue}</span>
|
||||||
<EditIcon />
|
<EditIcon className="editable-input__icon" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<InputComponent
|
<InputComponent
|
||||||
|
|
|
@ -24,7 +24,6 @@ import 'codemirror/addon/edit/matchbrackets';
|
||||||
import { JSHINT } from 'jshint';
|
import { JSHINT } from 'jshint';
|
||||||
import { CSSLint } from 'csslint';
|
import { CSSLint } from 'csslint';
|
||||||
import { HTMLHint } from 'htmlhint';
|
import { HTMLHint } from 'htmlhint';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import '../../../utils/htmlmixed';
|
import '../../../utils/htmlmixed';
|
||||||
|
@ -36,6 +35,11 @@ import { metaKey, } from '../../../utils/metaKey';
|
||||||
|
|
||||||
import search from '../../../utils/codemirror-search';
|
import search from '../../../utils/codemirror-search';
|
||||||
|
|
||||||
|
import beepUrl from '../../../sounds/audioAlert.mp3';
|
||||||
|
import UnsavedChangesDotIcon from '../../../images/unsaved-changes-dot.svg';
|
||||||
|
import RightArrowIcon from '../../../images/right-arrow.svg';
|
||||||
|
import LeftArrowIcon from '../../../images/left-arrow.svg';
|
||||||
|
|
||||||
search(CodeMirror);
|
search(CodeMirror);
|
||||||
|
|
||||||
const beautifyCSS = beautifyJS.css;
|
const beautifyCSS = beautifyJS.css;
|
||||||
|
@ -45,11 +49,6 @@ window.JSHINT = JSHINT;
|
||||||
window.CSSLint = CSSLint;
|
window.CSSLint = CSSLint;
|
||||||
window.HTMLHint = HTMLHint;
|
window.HTMLHint = HTMLHint;
|
||||||
|
|
||||||
const beepUrl = require('../../../sounds/audioAlert.mp3');
|
|
||||||
const unsavedChangesDotUrl = require('../../../images/unsaved-changes-dot.svg');
|
|
||||||
const rightArrowUrl = require('../../../images/right-arrow.svg');
|
|
||||||
const leftArrowUrl = require('../../../images/left-arrow.svg');
|
|
||||||
|
|
||||||
const IS_TAB_INDENT = false;
|
const IS_TAB_INDENT = false;
|
||||||
const INDENTATION_AMOUNT = 2;
|
const INDENTATION_AMOUNT = 2;
|
||||||
|
|
||||||
|
@ -321,23 +320,27 @@ class Editor extends React.Component {
|
||||||
>
|
>
|
||||||
<header className="editor__header">
|
<header className="editor__header">
|
||||||
<button
|
<button
|
||||||
aria-label="collapse file navigation"
|
aria-label="Open Sketch files navigation"
|
||||||
className="sidebar__contract"
|
className="sidebar__contract"
|
||||||
onClick={this.props.collapseSidebar}
|
onClick={this.props.collapseSidebar}
|
||||||
>
|
>
|
||||||
<InlineSVG src={leftArrowUrl} />
|
<LeftArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
aria-label="expand file navigation"
|
aria-label="Close sketch files navigation"
|
||||||
className="sidebar__expand"
|
className="sidebar__expand"
|
||||||
onClick={this.props.expandSidebar}
|
onClick={this.props.expandSidebar}
|
||||||
>
|
>
|
||||||
<InlineSVG src={rightArrowUrl} />
|
<RightArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<div className="editor__file-name">
|
<div className="editor__file-name">
|
||||||
<span>
|
<span>
|
||||||
{this.props.file.name}
|
{this.props.file.name}
|
||||||
{this.props.unsavedChanges ? <InlineSVG src={unsavedChangesDotUrl} /> : null}
|
<span className="editor__unsaved-changes">
|
||||||
|
{this.props.unsavedChanges ?
|
||||||
|
<UnsavedChangesDotIcon role="img" aria-label="Sketch has unsaved changes" focusable="false" /> :
|
||||||
|
null}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<Timer
|
<Timer
|
||||||
projectSavedTime={this.props.projectSavedTime}
|
projectSavedTime={this.props.projectSavedTime}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import githubLogoUrl from '../../../images/github.svg';
|
import GitHubLogo from '../../../images/github.svg';
|
||||||
|
|
||||||
function Feedback(props) {
|
function Feedback(props) {
|
||||||
return (
|
return (
|
||||||
|
@ -24,7 +23,7 @@ function Feedback(props) {
|
||||||
className="feedback__github-link"
|
className="feedback__github-link"
|
||||||
>
|
>
|
||||||
Go to Github
|
Go to Github
|
||||||
<InlineSVG className="feedback__github-logo" src={githubLogoUrl} />
|
<GitHubLogo className="feedback__github-logo" focusable="false" aria-hidden="true" />
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,14 +2,13 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import * as IDEActions from '../actions/ide';
|
import * as IDEActions from '../actions/ide';
|
||||||
import * as FileActions from '../actions/files';
|
import * as FileActions from '../actions/files';
|
||||||
import downArrowUrl from '../../../images/down-filled-triangle.svg';
|
import DownArrowIcon from '../../../images/down-filled-triangle.svg';
|
||||||
import folderRightUrl from '../../../images/triangle-arrow-right.svg';
|
import FolderRightIcon from '../../../images/triangle-arrow-right.svg';
|
||||||
import folderDownUrl from '../../../images/triangle-arrow-down.svg';
|
import FolderDownIcon from '../../../images/triangle-arrow-down.svg';
|
||||||
import fileUrl from '../../../images/file.svg';
|
import FileIcon from '../../../images/file.svg';
|
||||||
|
|
||||||
export class FileNode extends React.Component {
|
export class FileNode extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -185,7 +184,7 @@ export class FileNode extends React.Component {
|
||||||
<span className="file-item__spacer"></span>
|
<span className="file-item__spacer"></span>
|
||||||
{ isFile &&
|
{ isFile &&
|
||||||
<span className="sidebar__file-item-icon">
|
<span className="sidebar__file-item-icon">
|
||||||
<InlineSVG src={fileUrl} />
|
<FileIcon focusable="false" aria-hidden="true" />
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
{ isFolder &&
|
{ isFolder &&
|
||||||
|
@ -193,14 +192,16 @@ export class FileNode extends React.Component {
|
||||||
<button
|
<button
|
||||||
className="sidebar__file-item-closed"
|
className="sidebar__file-item-closed"
|
||||||
onClick={this.showFolderChildren}
|
onClick={this.showFolderChildren}
|
||||||
|
aria-label="Open folder contents"
|
||||||
>
|
>
|
||||||
<InlineSVG className="folder-right" src={folderRightUrl} />
|
<FolderRightIcon className="folder-right" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="sidebar__file-item-open"
|
className="sidebar__file-item-open"
|
||||||
onClick={this.hideFolderChildren}
|
onClick={this.hideFolderChildren}
|
||||||
|
aria-label="Close file contents"
|
||||||
>
|
>
|
||||||
<InlineSVG className="folder-down" src={folderDownUrl} />
|
<FolderDownIcon className="folder-down" focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -222,14 +223,14 @@ export class FileNode extends React.Component {
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="sidebar__file-item-show-options"
|
className="sidebar__file-item-show-options"
|
||||||
aria-label="view file options"
|
aria-label="Toggle open/close file options"
|
||||||
ref={(element) => { this[`fileOptions-${this.props.id}`] = element; }}
|
ref={(element) => { this[`fileOptions-${this.props.id}`] = element; }}
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
onClick={this.toggleFileOptions}
|
onClick={this.toggleFileOptions}
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
>
|
>
|
||||||
<InlineSVG src={downArrowUrl} />
|
<DownArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<div className="sidebar__file-item-options">
|
<div className="sidebar__file-item-options">
|
||||||
<ul title="file options">
|
<ul title="file options">
|
||||||
|
|
|
@ -3,13 +3,12 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { bindActionCreators, compose } from 'redux';
|
import { bindActionCreators, compose } from 'redux';
|
||||||
import { reduxForm } from 'redux-form';
|
import { reduxForm } from 'redux-form';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import NewFileForm from './NewFileForm';
|
import NewFileForm from './NewFileForm';
|
||||||
import { closeNewFileModal } from '../actions/ide';
|
import { closeNewFileModal } from '../actions/ide';
|
||||||
import { createFile } from '../actions/files';
|
import { createFile } from '../actions/files';
|
||||||
import { CREATE_FILE_REGEX } from '../../../../server/utils/fileUtils';
|
import { CREATE_FILE_REGEX } from '../../../../server/utils/fileUtils';
|
||||||
|
|
||||||
const exitUrl = require('../../../images/exit.svg');
|
import ExitIcon from '../../../images/exit.svg';
|
||||||
|
|
||||||
|
|
||||||
// At some point this will probably be generalized to a generic modal
|
// At some point this will probably be generalized to a generic modal
|
||||||
|
@ -35,8 +34,12 @@ class NewFileModal extends React.Component {
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
<div className="modal__header">
|
<div className="modal__header">
|
||||||
<h2 className="modal__title">Create File</h2>
|
<h2 className="modal__title">Create File</h2>
|
||||||
<button className="modal__exit-button" onClick={this.props.closeNewFileModal}>
|
<button
|
||||||
<InlineSVG src={exitUrl} alt="Close New File Modal" />
|
className="modal__exit-button"
|
||||||
|
onClick={this.props.closeNewFileModal}
|
||||||
|
aria-label="Close New File Modal"
|
||||||
|
>
|
||||||
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<NewFileForm
|
<NewFileForm
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { reduxForm } from 'redux-form';
|
import { reduxForm } from 'redux-form';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import NewFolderForm from './NewFolderForm';
|
import NewFolderForm from './NewFolderForm';
|
||||||
|
|
||||||
const exitUrl = require('../../../images/exit.svg');
|
import ExitIcon from '../../../images/exit.svg';
|
||||||
|
|
||||||
class NewFolderModal extends React.Component {
|
class NewFolderModal extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -17,8 +16,12 @@ class NewFolderModal extends React.Component {
|
||||||
<div className="modal-content-folder">
|
<div className="modal-content-folder">
|
||||||
<div className="modal__header">
|
<div className="modal__header">
|
||||||
<h2 className="modal__title">Create Folder</h2>
|
<h2 className="modal__title">Create Folder</h2>
|
||||||
<button className="modal__exit-button" onClick={this.props.closeModal}>
|
<button
|
||||||
<InlineSVG src={exitUrl} alt="Close New Folder Modal" />
|
className="modal__exit-button"
|
||||||
|
onClick={this.props.closeModal}
|
||||||
|
aria-label="Close New Folder Modal"
|
||||||
|
>
|
||||||
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<NewFolderForm {...this.props} />
|
<NewFolderForm {...this.props} />
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
||||||
// import { bindActionCreators } from 'redux';
|
// import { bindActionCreators } from 'redux';
|
||||||
// import { connect } from 'react-redux';
|
// import { connect } from 'react-redux';
|
||||||
// import * as PreferencesActions from '../actions/preferences';
|
// import * as PreferencesActions from '../actions/preferences';
|
||||||
|
|
||||||
const plusUrl = require('../../../images/plus.svg');
|
import PlusIcon from '../../../images/plus.svg';
|
||||||
const minusUrl = require('../../../images/minus.svg');
|
import MinusIcon from '../../../images/minus.svg';
|
||||||
const beepUrl = require('../../../sounds/audioAlert.mp3');
|
import beepUrl from '../../../sounds/audioAlert.mp3';
|
||||||
|
|
||||||
class Preferences extends React.Component {
|
class Preferences extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -150,7 +149,7 @@ class Preferences extends React.Component {
|
||||||
aria-label="decrease font size"
|
aria-label="decrease font size"
|
||||||
disabled={this.state.fontSize <= 8}
|
disabled={this.state.fontSize <= 8}
|
||||||
>
|
>
|
||||||
<InlineSVG src={minusUrl} alt="Decrease Font Size" />
|
<MinusIcon focusable="false" aria-hidden="true" />
|
||||||
<h6 className="preference__label">Decrease</h6>
|
<h6 className="preference__label">Decrease</h6>
|
||||||
</button>
|
</button>
|
||||||
<form onSubmit={this.onFontInputSubmit}>
|
<form onSubmit={this.onFontInputSubmit}>
|
||||||
|
@ -171,7 +170,7 @@ class Preferences extends React.Component {
|
||||||
aria-label="increase font size"
|
aria-label="increase font size"
|
||||||
disabled={this.state.fontSize >= 36}
|
disabled={this.state.fontSize >= 36}
|
||||||
>
|
>
|
||||||
<InlineSVG src={plusUrl} alt="Increase Font Size" />
|
<PlusIcon focusable="false" aria-hidden="true" />
|
||||||
<h6 className="preference__label">Increase</h6>
|
<h6 className="preference__label">Increase</h6>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
|
|
||||||
const check = require('../../../../images/check_encircled.svg');
|
import CheckIcon from '../../../../images/check_encircled.svg';
|
||||||
const close = require('../../../../images/close.svg');
|
import CloseIcon from '../../../../images/close.svg';
|
||||||
|
|
||||||
const Icons = ({ isAdded }) => {
|
const Icons = ({ isAdded }) => {
|
||||||
const classes = [
|
const classes = [
|
||||||
|
@ -13,9 +12,9 @@ const Icons = ({ isAdded }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
<InlineSVG className="quick-add__remove-icon" src={close} alt="Remove from collection" />
|
<CloseIcon className="quick-add__remove-icon" role="img" aria-label="Descending" focusable="false" />
|
||||||
<InlineSVG className="quick-add__in-icon" src={check} alt="In collection" />
|
<CheckIcon className="quick-add__in-icon" role="img" aria-label="Descending" focusable="false" />
|
||||||
<InlineSVG className="quick-add__add-icon" src={close} alt="Add to collection" />
|
<CloseIcon className="quick-add__add-icon" role="img" aria-label="Descending" focusable="false" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,22 +6,25 @@ import Icons from './Icons';
|
||||||
|
|
||||||
const Item = ({
|
const Item = ({
|
||||||
isAdded, onSelect, name, url
|
isAdded, onSelect, name, url
|
||||||
}) => (
|
}) => {
|
||||||
<li className="quick-add__item" onClick={onSelect}> { /* eslint-disable-line */ }
|
const buttonLabel = isAdded ? 'Remove from collection' : 'Add to collection';
|
||||||
<button className="quick-add__item-toggle" onClick={onSelect}>
|
return (
|
||||||
<Icons isAdded={isAdded} />
|
<li className="quick-add__item" onClick={onSelect}> { /* eslint-disable-line */ }
|
||||||
</button>
|
<button className="quick-add__item-toggle" onClick={onSelect} aria-label={buttonLabel}>
|
||||||
<span className="quick-add__item-name">{name}</span>
|
<Icons isAdded={isAdded} />
|
||||||
<Link
|
</button>
|
||||||
className="quick-add__item-view"
|
<span className="quick-add__item-name">{name}</span>
|
||||||
to={url}
|
<Link
|
||||||
target="_blank"
|
className="quick-add__item-view"
|
||||||
onClick={e => e.stopPropogation()}
|
to={url}
|
||||||
>
|
target="_blank"
|
||||||
View
|
onClick={e => e.stopPropogation()}
|
||||||
</Link>
|
>
|
||||||
</li>
|
View
|
||||||
);
|
</Link>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const ItemType = PropTypes.shape({
|
const ItemType = PropTypes.shape({
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { throttle } from 'lodash';
|
import { throttle } from 'lodash';
|
||||||
|
|
||||||
const searchIcon = require('../../../../images/magnifyingglass.svg');
|
import SearchIcon from '../../../../images/magnifyingglass.svg';
|
||||||
|
|
||||||
class Searchbar extends React.Component {
|
class Searchbar extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -46,7 +45,7 @@ class Searchbar extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div className={`searchbar ${searchValue === '' ? 'searchbar--is-empty' : ''}`}>
|
<div className={`searchbar ${searchValue === '' ? 'searchbar--is-empty' : ''}`}>
|
||||||
<div className="searchbar__button">
|
<div className="searchbar__button">
|
||||||
<InlineSVG className="searchbar__icon" src={searchIcon} />
|
<SearchIcon className="searchbar__icon" focusable="false" aria-hidden="true" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
className="searchbar__input"
|
className="searchbar__input"
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import ConnectedFileNode from './FileNode';
|
import ConnectedFileNode from './FileNode';
|
||||||
|
|
||||||
const downArrowUrl = require('../../../images/down-filled-triangle.svg');
|
import DownArrowIcon from '../../../images/down-filled-triangle.svg';
|
||||||
|
|
||||||
class Sidebar extends React.Component {
|
class Sidebar extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -76,7 +75,7 @@ class Sidebar extends React.Component {
|
||||||
</h3>
|
</h3>
|
||||||
<div className="sidebar__icons">
|
<div className="sidebar__icons">
|
||||||
<button
|
<button
|
||||||
aria-label="add file or folder"
|
aria-label="Toggle open/close sketch file options"
|
||||||
className="sidebar__add"
|
className="sidebar__add"
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
ref={(element) => { this.sidebarOptions = element; }}
|
ref={(element) => { this.sidebarOptions = element; }}
|
||||||
|
@ -84,7 +83,7 @@ class Sidebar extends React.Component {
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
>
|
>
|
||||||
<InlineSVG src={downArrowUrl} />
|
<DownArrowIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="sidebar__project-options">
|
<ul className="sidebar__project-options">
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -2,7 +2,6 @@ import format from 'date-fns/format';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
@ -19,9 +18,9 @@ import Loader from '../../App/components/loader';
|
||||||
import Overlay from '../../App/components/Overlay';
|
import Overlay from '../../App/components/Overlay';
|
||||||
import AddToCollectionList from './AddToCollectionList';
|
import AddToCollectionList from './AddToCollectionList';
|
||||||
|
|
||||||
const arrowUp = require('../../../images/sort-arrow-up.svg');
|
import ArrowUpIcon from '../../../images/sort-arrow-up.svg';
|
||||||
const arrowDown = require('../../../images/sort-arrow-down.svg');
|
import ArrowDownIcon from '../../../images/sort-arrow-down.svg';
|
||||||
const downFilledTriangle = require('../../../images/down-filled-triangle.svg');
|
import DownFilledTriangleIcon from '../../../images/down-filled-triangle.svg';
|
||||||
|
|
||||||
class SketchListRowBase extends React.Component {
|
class SketchListRowBase extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -168,8 +167,9 @@ class SketchListRowBase extends React.Component {
|
||||||
onClick={this.toggleOptions}
|
onClick={this.toggleOptions}
|
||||||
onBlur={this.onBlurComponent}
|
onBlur={this.onBlurComponent}
|
||||||
onFocus={this.onFocusComponent}
|
onFocus={this.onFocusComponent}
|
||||||
|
aria-label="Toggle Open/Close Sketch Options"
|
||||||
>
|
>
|
||||||
<InlineSVG src={downFilledTriangle} alt="Menu" />
|
<DownFilledTriangleIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
{optionsOpen &&
|
{optionsOpen &&
|
||||||
<ul
|
<ul
|
||||||
|
@ -326,15 +326,15 @@ class SketchList extends React.Component {
|
||||||
super(props);
|
super(props);
|
||||||
this.props.getProjects(this.props.username);
|
this.props.getProjects(this.props.username);
|
||||||
this.props.resetSorting();
|
this.props.resetSorting();
|
||||||
this._renderFieldHeader = this._renderFieldHeader.bind(this);
|
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isInitialDataLoad: true,
|
isInitialDataLoad: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if (this.props.sketches !== nextProps.sketches && Array.isArray(nextProps.sketches)) {
|
if (this.props.sketches !== prevProps.sketches && Array.isArray(this.props.sketches)) {
|
||||||
|
// eslint-disable-next-line react/no-did-update-set-state
|
||||||
this.setState({
|
this.setState({
|
||||||
isInitialDataLoad: false,
|
isInitialDataLoad: false,
|
||||||
});
|
});
|
||||||
|
@ -368,21 +368,43 @@ class SketchList extends React.Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderFieldHeader(fieldName, displayName) {
|
_getButtonLabel = (fieldName, displayName) => {
|
||||||
|
const { field, direction } = this.props.sorting;
|
||||||
|
let buttonLabel;
|
||||||
|
if (field !== fieldName) {
|
||||||
|
if (field === 'name') {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
}
|
||||||
|
} else if (direction === SortingActions.DIRECTION.ASC) {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
}
|
||||||
|
return buttonLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
_renderFieldHeader = (fieldName, displayName) => {
|
||||||
const { field, direction } = this.props.sorting;
|
const { field, direction } = this.props.sorting;
|
||||||
const headerClass = classNames({
|
const headerClass = classNames({
|
||||||
'sketches-table__header': true,
|
'sketches-table__header': true,
|
||||||
'sketches-table__header--selected': field === fieldName
|
'sketches-table__header--selected': field === fieldName
|
||||||
});
|
});
|
||||||
|
const buttonLabel = this._getButtonLabel(fieldName, displayName);
|
||||||
return (
|
return (
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
<button className="sketch-list__sort-button" onClick={() => this.props.toggleDirectionForField(fieldName)}>
|
<button
|
||||||
|
className="sketch-list__sort-button"
|
||||||
|
onClick={() => this.props.toggleDirectionForField(fieldName)}
|
||||||
|
aria-label={buttonLabel}
|
||||||
|
>
|
||||||
<span className={headerClass}>{displayName}</span>
|
<span className={headerClass}>{displayName}</span>
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
||||||
<InlineSVG src={arrowUp} />
|
<ArrowUpIcon role="img" aria-label="Ascending" focusable="false" />
|
||||||
}
|
}
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
||||||
<InlineSVG src={arrowDown} />
|
<ArrowDownIcon role="img" aria-label="Descending" focusable="false" />
|
||||||
}
|
}
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
|
|
|
@ -2,10 +2,9 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import * as ToastActions from '../actions/toast';
|
import * as ToastActions from '../actions/toast';
|
||||||
|
|
||||||
const exitUrl = require('../../../images/exit.svg');
|
import ExitIcon from '../../../images/exit.svg';
|
||||||
|
|
||||||
function Toast(props) {
|
function Toast(props) {
|
||||||
return (
|
return (
|
||||||
|
@ -13,8 +12,8 @@ function Toast(props) {
|
||||||
<p>
|
<p>
|
||||||
{props.text}
|
{props.text}
|
||||||
</p>
|
</p>
|
||||||
<button className="toast__close" onClick={props.hideToast}>
|
<button className="toast__close" onClick={props.hideToast} aria-label="Close Alert" >
|
||||||
<InlineSVG src={exitUrl} alt="Close Keyboard Shortcuts Overlay" />
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,16 +3,14 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
|
|
||||||
import * as IDEActions from '../actions/ide';
|
import * as IDEActions from '../actions/ide';
|
||||||
import * as preferenceActions from '../actions/preferences';
|
import * as preferenceActions from '../actions/preferences';
|
||||||
import * as projectActions from '../actions/project';
|
import * as projectActions from '../actions/project';
|
||||||
|
|
||||||
const playUrl = require('../../../images/play.svg');
|
import PlayIcon from '../../../images/play.svg';
|
||||||
const stopUrl = require('../../../images/stop.svg');
|
import StopIcon from '../../../images/stop.svg';
|
||||||
const preferencesUrl = require('../../../images/preferences.svg');
|
import PreferencesIcon from '../../../images/preferences.svg';
|
||||||
const editProjectNameUrl = require('../../../images/pencil.svg');
|
import EditProjectNameIcon from '../../../images/pencil.svg';
|
||||||
|
|
||||||
class Toolbar extends React.Component {
|
class Toolbar extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -61,6 +59,8 @@ class Toolbar extends React.Component {
|
||||||
'toolbar__project-name-container--editing': this.props.project.isEditingName
|
'toolbar__project-name-container--editing': this.props.project.isEditingName
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const canEditProjectName = this.canEditProjectName();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="toolbar">
|
<div className="toolbar">
|
||||||
<button
|
<button
|
||||||
|
@ -70,25 +70,25 @@ class Toolbar extends React.Component {
|
||||||
this.props.setTextOutput(true);
|
this.props.setTextOutput(true);
|
||||||
this.props.setGridOutput(true);
|
this.props.setGridOutput(true);
|
||||||
}}
|
}}
|
||||||
aria-label="play sketch"
|
aria-label="Play sketch"
|
||||||
disabled={this.props.infiniteLoop}
|
disabled={this.props.infiniteLoop}
|
||||||
>
|
>
|
||||||
<InlineSVG src={playUrl} alt="Play Sketch" />
|
<PlayIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={playButtonClass}
|
className={playButtonClass}
|
||||||
onClick={this.props.startSketch}
|
onClick={this.props.startSketch}
|
||||||
aria-label="play only visual sketch"
|
aria-label="Play only visual sketch"
|
||||||
disabled={this.props.infiniteLoop}
|
disabled={this.props.infiniteLoop}
|
||||||
>
|
>
|
||||||
<InlineSVG src={playUrl} alt="Play only visual Sketch" />
|
<PlayIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={stopButtonClass}
|
className={stopButtonClass}
|
||||||
onClick={this.props.stopSketch}
|
onClick={this.props.stopSketch}
|
||||||
aria-label="stop sketch"
|
aria-label="Stop sketch"
|
||||||
>
|
>
|
||||||
<InlineSVG src={stopUrl} alt="Stop Sketch" />
|
<StopIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
<div className="toolbar__autorefresh">
|
<div className="toolbar__autorefresh">
|
||||||
<input
|
<input
|
||||||
|
@ -104,24 +104,28 @@ class Toolbar extends React.Component {
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className={nameContainerClass}>
|
<div className={nameContainerClass}>
|
||||||
<a
|
<button
|
||||||
className="toolbar__project-name"
|
className="toolbar__project-name"
|
||||||
href={this.props.owner ? `/${this.props.owner.username}/sketches/${this.props.project.id}` : ''}
|
onClick={() => {
|
||||||
onClick={(e) => {
|
if (canEditProjectName) {
|
||||||
if (this.canEditProjectName()) {
|
|
||||||
e.preventDefault();
|
|
||||||
this.originalProjectName = this.props.project.name;
|
this.originalProjectName = this.props.project.name;
|
||||||
this.props.showEditProjectName();
|
this.props.showEditProjectName();
|
||||||
setTimeout(() => this.projectNameInput.focus(), 0);
|
setTimeout(() => this.projectNameInput.focus(), 0);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
disabled={!canEditProjectName}
|
||||||
|
aria-label="Edit sketch name"
|
||||||
>
|
>
|
||||||
<span>{this.props.project.name}</span>
|
<span>{this.props.project.name}</span>
|
||||||
{
|
{
|
||||||
this.canEditProjectName() &&
|
canEditProjectName &&
|
||||||
<InlineSVG className="toolbar__edit-name-button" src={editProjectNameUrl} alt="Edit Project Name" />
|
<EditProjectNameIcon
|
||||||
|
className="toolbar__edit-name-button"
|
||||||
|
focusable="false"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</a>
|
</button>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
maxLength="128"
|
maxLength="128"
|
||||||
|
@ -151,9 +155,9 @@ class Toolbar extends React.Component {
|
||||||
<button
|
<button
|
||||||
className={preferencesButtonClass}
|
className={preferencesButtonClass}
|
||||||
onClick={this.props.openPreferences}
|
onClick={this.props.openPreferences}
|
||||||
aria-label="preferences"
|
aria-label="Open Preferences"
|
||||||
>
|
>
|
||||||
<InlineSVG src={preferencesUrl} alt="Preferences" />
|
<PreferencesIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,11 +2,10 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import prettyBytes from 'pretty-bytes';
|
import prettyBytes from 'pretty-bytes';
|
||||||
import FileUploader from './FileUploader';
|
import FileUploader from './FileUploader';
|
||||||
import { getreachedTotalSizeLimit } from '../selectors/users';
|
import { getreachedTotalSizeLimit } from '../selectors/users';
|
||||||
import exitUrl from '../../../images/exit.svg';
|
import ExitIcon from '../../../images/exit.svg';
|
||||||
|
|
||||||
const __process = (typeof global !== 'undefined' ? global : window).process;
|
const __process = (typeof global !== 'undefined' ? global : window).process;
|
||||||
const limit = __process.env.UPLOAD_LIMIT || 250000000;
|
const limit = __process.env.UPLOAD_LIMIT || 250000000;
|
||||||
|
@ -33,8 +32,12 @@ class UploadFileModal extends React.Component {
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
<div className="modal__header">
|
<div className="modal__header">
|
||||||
<h2 className="modal__title">Upload File</h2>
|
<h2 className="modal__title">Upload File</h2>
|
||||||
<button className="modal__exit-button" onClick={this.props.closeModal}>
|
<button
|
||||||
<InlineSVG src={exitUrl} alt="Close New File Modal" />
|
className="modal__exit-button"
|
||||||
|
onClick={this.props.closeModal}
|
||||||
|
aria-label="Close upload file modal"
|
||||||
|
>
|
||||||
|
<ExitIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{ this.props.reachedTotalSizeLimit &&
|
{ this.props.reachedTotalSizeLimit &&
|
||||||
|
|
|
@ -26,7 +26,10 @@ export function signUpUser(previousPath, formValues) {
|
||||||
dispatch(justOpenedProject());
|
dispatch(justOpenedProject());
|
||||||
browserHistory.push(previousPath);
|
browserHistory.push(previousPath);
|
||||||
})
|
})
|
||||||
.catch(response => dispatch(authError(response.data.error)));
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
|
dispatch(authError(response.data.error));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +85,8 @@ export function getUser() {
|
||||||
preferences: response.data.preferences
|
preferences: response.data.preferences
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
const message = response.message || response.data.error;
|
const message = response.message || response.data.error;
|
||||||
dispatch(authError(message));
|
dispatch(authError(message));
|
||||||
});
|
});
|
||||||
|
@ -98,7 +102,8 @@ export function validateSession() {
|
||||||
dispatch(showErrorModal('staleSession'));
|
dispatch(showErrorModal('staleSession'));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((response) => {
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
if (response.status === 404) {
|
if (response.status === 404) {
|
||||||
dispatch(showErrorModal('staleSession'));
|
dispatch(showErrorModal('staleSession'));
|
||||||
}
|
}
|
||||||
|
@ -114,7 +119,10 @@ export function logoutUser() {
|
||||||
type: ActionTypes.UNAUTH_USER
|
type: ActionTypes.UNAUTH_USER
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(response => dispatch(authError(response.data.error)));
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
|
dispatch(authError(response.data.error));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,10 +135,13 @@ export function initiateResetPassword(formValues) {
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// do nothing
|
// do nothing
|
||||||
})
|
})
|
||||||
.catch(response => dispatch({
|
.catch((error) => {
|
||||||
type: ActionTypes.ERROR,
|
const { response } = error;
|
||||||
message: response.data
|
dispatch({
|
||||||
}));
|
type: ActionTypes.ERROR,
|
||||||
|
message: response.data
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,10 +154,13 @@ export function initiateVerification() {
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// do nothing
|
// do nothing
|
||||||
})
|
})
|
||||||
.catch(response => dispatch({
|
.catch((error) => {
|
||||||
type: ActionTypes.ERROR,
|
const { response } = error;
|
||||||
message: response.data
|
dispatch({
|
||||||
}));
|
type: ActionTypes.ERROR,
|
||||||
|
message: response.data
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,10 +175,13 @@ export function verifyEmailConfirmation(token) {
|
||||||
type: ActionTypes.EMAIL_VERIFICATION_VERIFIED,
|
type: ActionTypes.EMAIL_VERIFICATION_VERIFIED,
|
||||||
message: response.data,
|
message: response.data,
|
||||||
}))
|
}))
|
||||||
.catch(response => dispatch({
|
.catch((error) => {
|
||||||
type: ActionTypes.EMAIL_VERIFICATION_INVALID,
|
const { response } = error;
|
||||||
message: response.data
|
dispatch({
|
||||||
}));
|
type: ActionTypes.EMAIL_VERIFICATION_INVALID,
|
||||||
|
message: response.data
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +233,10 @@ export function updateSettings(formValues) {
|
||||||
dispatch(showToast(5500));
|
dispatch(showToast(5500));
|
||||||
dispatch(setToastText('Settings saved.'));
|
dispatch(setToastText('Settings saved.'));
|
||||||
})
|
})
|
||||||
.catch(response => Promise.reject(new Error(response.data.error)));
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
|
Promise.reject(new Error(response.data.error));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createApiKeySuccess(user) {
|
export function createApiKeySuccess(user) {
|
||||||
|
@ -232,7 +252,10 @@ export function createApiKey(label) {
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
dispatch(createApiKeySuccess(response.data));
|
dispatch(createApiKeySuccess(response.data));
|
||||||
})
|
})
|
||||||
.catch(response => Promise.reject(new Error(response.data.error)));
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
|
Promise.reject(new Error(response.data.error));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeApiKey(keyId) {
|
export function removeApiKey(keyId) {
|
||||||
|
@ -244,5 +267,8 @@ export function removeApiKey(keyId) {
|
||||||
user: response.data
|
user: response.data
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(response => Promise.reject(new Error(response.data.error)));
|
.catch((error) => {
|
||||||
|
const { response } = error;
|
||||||
|
Promise.reject(new Error(response.data.error));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,8 @@ class APIKeyForm extends React.Component {
|
||||||
type="submit"
|
type="submit"
|
||||||
label="Create new key"
|
label="Create new key"
|
||||||
>
|
>
|
||||||
|
{/* TODO make sure this aria label is right for the button */}
|
||||||
|
{/* <PlusIcon className="api-key-form__create-icon" focusable="false" aria-hidden="true" /> */}
|
||||||
Create
|
Create
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import format from 'date-fns/format';
|
import format from 'date-fns/format';
|
||||||
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
||||||
import orderBy from 'lodash/orderBy';
|
import orderBy from 'lodash/orderBy';
|
||||||
|
|
||||||
import { APIKeyPropType } from './APIKeyForm';
|
import { APIKeyPropType } from './APIKeyForm';
|
||||||
|
|
||||||
const trashCan = require('../../../images/trash-can.svg');
|
import TrashCanIcon from '../../../images/trash-can.svg';
|
||||||
|
|
||||||
function APIKeyList({ apiKeys, onRemove }) {
|
function APIKeyList({ apiKeys, onRemove }) {
|
||||||
return (
|
return (
|
||||||
|
@ -32,8 +31,12 @@ function APIKeyList({ apiKeys, onRemove }) {
|
||||||
<td>{format(new Date(key.createdAt), 'MMM D, YYYY h:mm A')}</td>
|
<td>{format(new Date(key.createdAt), 'MMM D, YYYY h:mm A')}</td>
|
||||||
<td>{lastUsed}</td>
|
<td>{lastUsed}</td>
|
||||||
<td className="api-key-list__action">
|
<td className="api-key-list__action">
|
||||||
<button className="api-key-list__delete-button" onClick={() => onRemove(key)}>
|
<button
|
||||||
<InlineSVG src={trashCan} alt="Delete Key" />
|
className="api-key-list__delete-button"
|
||||||
|
onClick={() => onRemove(key)}
|
||||||
|
aria-label="Delete API Key"
|
||||||
|
>
|
||||||
|
<TrashCanIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -2,7 +2,6 @@ import format from 'date-fns/format';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { useState, useRef, useEffect } from 'react';
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
|
@ -23,9 +22,10 @@ import AddToCollectionSketchList from '../../IDE/components/AddToCollectionSketc
|
||||||
import CopyableInput from '../../IDE/components/CopyableInput';
|
import CopyableInput from '../../IDE/components/CopyableInput';
|
||||||
import { SketchSearchbar } from '../../IDE/components/Searchbar';
|
import { SketchSearchbar } from '../../IDE/components/Searchbar';
|
||||||
|
|
||||||
const arrowUp = require('../../../images/sort-arrow-up.svg');
|
import DropdownArrowIcon from '../../../images/down-arrow.svg';
|
||||||
const arrowDown = require('../../../images/sort-arrow-down.svg');
|
import ArrowUpIcon from '../../../images/sort-arrow-up.svg';
|
||||||
const removeIcon = require('../../../images/close.svg');
|
import ArrowDownIcon from '../../../images/sort-arrow-down.svg';
|
||||||
|
import RemoveIcon from '../../../images/close.svg';
|
||||||
|
|
||||||
const ShareURL = ({ value }) => {
|
const ShareURL = ({ value }) => {
|
||||||
const [showURL, setShowURL] = useState(false);
|
const [showURL, setShowURL] = useState(false);
|
||||||
|
@ -57,6 +57,13 @@ const ShareURL = ({ value }) => {
|
||||||
onClick={() => setShowURL(!showURL)}
|
onClick={() => setShowURL(!showURL)}
|
||||||
>Share
|
>Share
|
||||||
</Button>
|
</Button>
|
||||||
|
{/* TODO make sure this has the right aria-label and SVG attributes */}
|
||||||
|
{/* <button>
|
||||||
|
aria-label="Show collection share URL"
|
||||||
|
>
|
||||||
|
<span>Share</span>
|
||||||
|
<DropdownArrowIcon className="collection-share__arrow" focusable="false" aria-hidden="true" />
|
||||||
|
</button> */}
|
||||||
{ showURL &&
|
{ showURL &&
|
||||||
<div className="collection__share-dropdown">
|
<div className="collection__share-dropdown">
|
||||||
<CopyableInput value={value} label="Link to Collection" />
|
<CopyableInput value={value} label="Link to Collection" />
|
||||||
|
@ -97,8 +104,9 @@ class CollectionItemRowBase extends React.Component {
|
||||||
<button
|
<button
|
||||||
className="collection-row__remove-button"
|
className="collection-row__remove-button"
|
||||||
onClick={this.handleSketchRemove}
|
onClick={this.handleSketchRemove}
|
||||||
|
aria-label="Remove sketch from collection"
|
||||||
>
|
>
|
||||||
<InlineSVG src={removeIcon} alt="Remove" />
|
<RemoveIcon focusable="false" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>);
|
</tr>);
|
||||||
|
@ -295,21 +303,43 @@ class Collection extends React.Component {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_getButtonLabel = (fieldName, displayName) => {
|
||||||
|
const { field, direction } = this.props.sorting;
|
||||||
|
let buttonLabel;
|
||||||
|
if (field !== fieldName) {
|
||||||
|
if (field === 'name') {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
}
|
||||||
|
} else if (direction === SortingActions.DIRECTION.ASC) {
|
||||||
|
buttonLabel = `Sort by ${displayName} descending.`;
|
||||||
|
} else {
|
||||||
|
buttonLabel = `Sort by ${displayName} ascending.`;
|
||||||
|
}
|
||||||
|
return buttonLabel;
|
||||||
|
}
|
||||||
|
|
||||||
_renderFieldHeader(fieldName, displayName) {
|
_renderFieldHeader(fieldName, displayName) {
|
||||||
const { field, direction } = this.props.sorting;
|
const { field, direction } = this.props.sorting;
|
||||||
const headerClass = classNames({
|
const headerClass = classNames({
|
||||||
'arrowDown': true,
|
'arrowDown': true,
|
||||||
'sketches-table__header--selected': field === fieldName
|
'sketches-table__header--selected': field === fieldName
|
||||||
});
|
});
|
||||||
|
const buttonLabel = this._getButtonLabel(fieldName, displayName);
|
||||||
return (
|
return (
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
<button className="sketch-list__sort-button" onClick={() => this.props.toggleDirectionForField(fieldName)}>
|
<button
|
||||||
|
className="sketch-list__sort-button"
|
||||||
|
onClick={() => this.props.toggleDirectionForField(fieldName)}
|
||||||
|
aria-label={buttonLabel}
|
||||||
|
>
|
||||||
<span className={headerClass}>{displayName}</span>
|
<span className={headerClass}>{displayName}</span>
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.ASC &&
|
||||||
<InlineSVG src={arrowUp} />
|
<ArrowUpIcon role="img" aria-label="Ascending" focusable="false" />
|
||||||
}
|
}
|
||||||
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
{field === fieldName && direction === SortingActions.DIRECTION.DESC &&
|
||||||
<InlineSVG src={arrowDown} />
|
<ArrowDownIcon role="img" aria-label="Descending" focusable="false" />
|
||||||
}
|
}
|
||||||
</button>
|
</button>
|
||||||
</th>
|
</th>
|
||||||
|
|
22
client/modules/User/components/GithubButton.jsx
Normal file
22
client/modules/User/components/GithubButton.jsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import GithubIcon from '../../../images/github.svg';
|
||||||
|
|
||||||
|
function GithubButton(props) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className="github-button"
|
||||||
|
href="/auth/github"
|
||||||
|
>
|
||||||
|
<GithubIcon className="github-icon" role="img" aria-label="GitHub Logo" focusable="false" />
|
||||||
|
<span>{props.buttonText}</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GithubButton.propTypes = {
|
||||||
|
buttonText: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GithubButton;
|
22
client/modules/User/components/GoogleButton.jsx
Normal file
22
client/modules/User/components/GoogleButton.jsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import GoogleIcon from '../../../images/google.svg';
|
||||||
|
|
||||||
|
function GoogleButton(props) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className="google-button"
|
||||||
|
href="/auth/google/"
|
||||||
|
>
|
||||||
|
<GoogleIcon className="google-icon" role="img" aria-label="Google Logo" focusable="false" />
|
||||||
|
<span>{props.buttonText}</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GoogleButton.propTypes = {
|
||||||
|
buttonText: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GoogleButton;
|
|
@ -101,12 +101,12 @@ class DashboardView extends React.Component {
|
||||||
renderContent(tabKey, username) {
|
renderContent(tabKey, username) {
|
||||||
switch (tabKey) {
|
switch (tabKey) {
|
||||||
case TabKey.assets:
|
case TabKey.assets:
|
||||||
return <AssetList username={username} />;
|
return <AssetList key={username} username={username} />;
|
||||||
case TabKey.collections:
|
case TabKey.collections:
|
||||||
return <CollectionList username={username} />;
|
return <CollectionList key={username} username={username} />;
|
||||||
case TabKey.sketches:
|
case TabKey.sketches:
|
||||||
default:
|
default:
|
||||||
return <SketchList username={username} />;
|
return <SketchList key={username} username={username} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,13 @@
|
||||||
@mixin icon() {
|
@mixin icon() {
|
||||||
@include themify() {
|
@include themify() {
|
||||||
color: getThemifyVariable('icon-color');
|
color: getThemifyVariable('icon-color');
|
||||||
& g, & polygon {
|
& g, & polygon, & path {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
fill: getThemifyVariable('icon-color');
|
fill: getThemifyVariable('icon-color');
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
color: getThemifyVariable('icon-hover-color');
|
color: getThemifyVariable('icon-hover-color');
|
||||||
& g, & polygon {
|
& g, & polygon, & path {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
fill: getThemifyVariable('icon-hover-color');
|
fill: getThemifyVariable('icon-hover-color');
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,26 +5,25 @@
|
||||||
width: #{44 / $base-font-size}rem;
|
width: #{44 / $base-font-size}rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
line-height: #{49 / $base-font-size}rem;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
background-color: getThemifyVariable('toolbar-button-background-color');
|
background-color: getThemifyVariable('toolbar-button-background-color');
|
||||||
color: getThemifyVariable('toolbar-button-color');
|
color: getThemifyVariable('toolbar-button-color');
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('toolbar-button-color');
|
fill: getThemifyVariable('toolbar-button-color');
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: getThemifyVariable('button-background-hover-color');
|
background-color: getThemifyVariable('button-background-hover-color');
|
||||||
color: getThemifyVariable('button-hover-color');
|
color: getThemifyVariable('button-hover-color');
|
||||||
|
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('button-hover-color');
|
fill: getThemifyVariable('button-hover-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&--selected {
|
&--selected {
|
||||||
background-color: getThemifyVariable('button-background-hover-color');
|
background-color: getThemifyVariable('button-background-hover-color');
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('button-hover-color');
|
fill: getThemifyVariable('button-hover-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,12 +33,12 @@
|
||||||
%icon-toast{
|
%icon-toast{
|
||||||
@include themify() {
|
@include themify() {
|
||||||
color: $toast-text-color
|
color: $toast-text-color
|
||||||
& g {
|
& g, & path {
|
||||||
fill: $toast-text-color
|
fill: $toast-text-color
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
color: getThemifyVariable('icon-toast-hover-color');
|
color: getThemifyVariable('icon-toast-hover-color');
|
||||||
& g {
|
& g, & path {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
fill: getThemifyVariable('icon-toast-hover-color');
|
fill: getThemifyVariable('icon-toast-hover-color');
|
||||||
}
|
}
|
||||||
|
@ -59,12 +58,12 @@
|
||||||
|
|
||||||
%none-themify-icon-with-hover {
|
%none-themify-icon-with-hover {
|
||||||
color: $medium-dark;
|
color: $medium-dark;
|
||||||
& g {
|
& g, & path {
|
||||||
fill: $medium-dark;
|
fill: $medium-dark;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $p5js-pink;
|
color: $p5js-pink;
|
||||||
& g {
|
& g, & path {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
fill: $p5js-pink;
|
fill: $p5js-pink;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +82,7 @@
|
||||||
border: 2px solid getThemifyVariable('button-border-color');
|
border: 2px solid getThemifyVariable('button-border-color');
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: #{10 / $base-font-size}rem #{30 / $base-font-size}rem;
|
padding: #{10 / $base-font-size}rem #{30 / $base-font-size}rem;
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('button-color');
|
fill: getThemifyVariable('button-color');
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +90,7 @@
|
||||||
border-color: getThemifyVariable('button-background-hover-color');
|
border-color: getThemifyVariable('button-background-hover-color');
|
||||||
background-color: getThemifyVariable('button-background-hover-color');
|
background-color: getThemifyVariable('button-background-hover-color');
|
||||||
color: getThemifyVariable('button-hover-color');
|
color: getThemifyVariable('button-hover-color');
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('button-hover-color');
|
fill: getThemifyVariable('button-hover-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +98,7 @@
|
||||||
border-color: getThemifyVariable('button-background-active-color');
|
border-color: getThemifyVariable('button-background-active-color');
|
||||||
background-color: getThemifyVariable('button-background-active-color');
|
background-color: getThemifyVariable('button-background-active-color');
|
||||||
color: getThemifyVariable('button-active-color');
|
color: getThemifyVariable('button-active-color');
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('button-active-color');
|
fill: getThemifyVariable('button-active-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,13 +113,13 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-bottom: #{28 / $base-font-size}rem;
|
margin-bottom: #{28 / $base-font-size}rem;
|
||||||
line-height: #{50 / $base-font-size}rem;
|
line-height: #{50 / $base-font-size}rem;
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('modal-button-color');
|
fill: getThemifyVariable('modal-button-color');
|
||||||
}
|
}
|
||||||
&:enabled:hover {
|
&:enabled:hover {
|
||||||
background-color: getThemifyVariable('button-background-hover-color');
|
background-color: getThemifyVariable('button-background-hover-color');
|
||||||
color: getThemifyVariable('button-hover-color');
|
color: getThemifyVariable('button-hover-color');
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('button-hover-color');
|
fill: getThemifyVariable('button-hover-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,8 @@ $themes: (
|
||||||
nav-border-color: $middle-light,
|
nav-border-color: $middle-light,
|
||||||
error-color: $p5js-pink,
|
error-color: $p5js-pink,
|
||||||
table-row-stripe-color: $medium-light,
|
table-row-stripe-color: $medium-light,
|
||||||
codefold-icon-open: url(../images/triangle-arrow-down.svg),
|
codefold-icon-open: url(../images/triangle-arrow-down.svg?byUrl),
|
||||||
codefold-icon-closed: url(../images/triangle-arrow-right.svg),
|
codefold-icon-closed: url(../images/triangle-arrow-right.svg?byUrl),
|
||||||
|
|
||||||
primary-button-color: $lightest,
|
primary-button-color: $lightest,
|
||||||
primary-button-background-color: $p5js-pink,
|
primary-button-background-color: $p5js-pink,
|
||||||
|
@ -163,8 +163,8 @@ $themes: (
|
||||||
nav-border-color: $middle-dark,
|
nav-border-color: $middle-dark,
|
||||||
error-color: $p5js-pink,
|
error-color: $p5js-pink,
|
||||||
table-row-stripe-color: $dark,
|
table-row-stripe-color: $dark,
|
||||||
codefold-icon-open: url(../images/triangle-arrow-down-white.svg),
|
codefold-icon-open: url(../images/triangle-arrow-down-white.svg?byUrl),
|
||||||
codefold-icon-closed: url(../images/triangle-arrow-right-white.svg),
|
codefold-icon-closed: url(../images/triangle-arrow-right-white.svg?byUrl),
|
||||||
|
|
||||||
primary-button-color: $lightest,
|
primary-button-color: $lightest,
|
||||||
primary-button-background-color: $p5js-pink,
|
primary-button-background-color: $p5js-pink,
|
||||||
|
@ -236,8 +236,8 @@ $themes: (
|
||||||
nav-border-color: $middle-dark,
|
nav-border-color: $middle-dark,
|
||||||
error-color: $p5-contrast-pink,
|
error-color: $p5-contrast-pink,
|
||||||
table-row-stripe-color: $dark,
|
table-row-stripe-color: $dark,
|
||||||
codefold-icon-open: url(../images/triangle-arrow-down-white.svg),
|
codefold-icon-open: url(../images/triangle-arrow-down-white.svg?byUrl),
|
||||||
codefold-icon-closed: url(../images/triangle-arrow-right-white.svg),
|
codefold-icon-closed: url(../images/triangle-arrow-right-white.svg?byUrl),
|
||||||
|
|
||||||
primary-button-color: $lightest,
|
primary-button-color: $lightest,
|
||||||
primary-button-background-color: $p5js-pink,
|
primary-button-background-color: $p5js-pink,
|
||||||
|
|
|
@ -96,3 +96,15 @@ textarea:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 0 1px $outline-color;
|
box-shadow: 0 0 0 1px $outline-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// screen reader only class
|
||||||
|
// from https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html#hiding-content-visually
|
||||||
|
.sr-only:not(:focus):not(:active) {
|
||||||
|
clip: rect(0 0 0 0);
|
||||||
|
clip-path: inset(50%);
|
||||||
|
height: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
font-size: #{21 / $base-font-size}rem;
|
font-size: #{21 / $base-font-size}rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.api-key-list {
|
.api-key-list {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
|
@ -58,7 +59,7 @@
|
||||||
position: initial;
|
position: initial;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
& g {
|
& g, & path {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
fill: getThemifyVariable('icon-color');
|
fill: getThemifyVariable('icon-color');
|
||||||
}
|
}
|
||||||
|
@ -67,7 +68,7 @@
|
||||||
|
|
||||||
.api-key-list__delete-button:hover {
|
.api-key-list__delete-button:hover {
|
||||||
@include themify() {
|
@include themify() {
|
||||||
& g {
|
& g, & path {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
fill: getThemifyVariable('icon-hover-color');
|
fill: getThemifyVariable('icon-hover-color');
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
height:#{25 / $base-font-size}rem;
|
height:#{25 / $base-font-size}rem;
|
||||||
|
|
||||||
@include themify() {
|
@include themify() {
|
||||||
& polygon {
|
& polygon, & path {
|
||||||
fill: getThemifyVariable('inactive-text-color');
|
fill: getThemifyVariable('inactive-text-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,12 +143,12 @@
|
||||||
@include icon();
|
@include icon();
|
||||||
@include themify() {
|
@include themify() {
|
||||||
// icon graphic
|
// icon graphic
|
||||||
polygon {
|
path {
|
||||||
fill: getThemifyVariable('table-button-color');
|
fill: getThemifyVariable('table-button-color');
|
||||||
}
|
}
|
||||||
|
|
||||||
// icon background circle
|
// icon background circle
|
||||||
path {
|
path:first-child {
|
||||||
fill: getThemifyVariable('table-button-background-color');
|
fill: getThemifyVariable('table-button-background-color');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +159,11 @@
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
&:focus {
|
&:focus {
|
||||||
polygon {
|
path {
|
||||||
fill: getThemifyVariable('table-button-hover-color');
|
fill: getThemifyVariable('table-button-hover-color');
|
||||||
}
|
}
|
||||||
|
|
||||||
path {
|
path:first-child {
|
||||||
fill: getThemifyVariable('table-button-background-hover-color');
|
fill: getThemifyVariable('table-button-background-hover-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,8 @@
|
||||||
@include icon();
|
@include icon();
|
||||||
@include themify() {
|
@include themify() {
|
||||||
& g,
|
& g,
|
||||||
& polygon {
|
& polygon,
|
||||||
|
& path {
|
||||||
fill: getThemifyVariable('secondary-text-color');
|
fill: getThemifyVariable('secondary-text-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +73,8 @@
|
||||||
@include icon();
|
@include icon();
|
||||||
@include themify() {
|
@include themify() {
|
||||||
& g,
|
& g,
|
||||||
& polygon {
|
& polygon,
|
||||||
|
& path {
|
||||||
fill: getThemifyVariable('secondary-text-color');
|
fill: getThemifyVariable('secondary-text-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ button.editable-input__label {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editable-input__icon svg {
|
.editable-input__icon {
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,12 +211,12 @@ pre.CodeMirror-line {
|
||||||
|
|
||||||
// Previous button
|
// Previous button
|
||||||
.CodeMirror-search-button.prev::after {
|
.CodeMirror-search-button.prev::after {
|
||||||
background-image: url(../images/up-arrow.svg)
|
background-image: url(../images/up-arrow.svg?byUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next button
|
// Next button
|
||||||
.CodeMirror-search-button.next::after {
|
.CodeMirror-search-button.next::after {
|
||||||
background-image: url(../images/down-arrow.svg)
|
background-image: url(../images/down-arrow.svg?byUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -247,7 +247,7 @@ pre.CodeMirror-line {
|
||||||
|
|
||||||
@include icon();
|
@include icon();
|
||||||
|
|
||||||
background: transparent url(../images/exit.svg) no-repeat;
|
background: transparent url(../images/exit.svg?byUrl) no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// foldgutter
|
// foldgutter
|
||||||
|
@ -391,3 +391,7 @@ pre.CodeMirror-line {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editor__unsaved-changes {
|
||||||
|
margin-left: #{2 / $base-font-size}rem;
|
||||||
|
}
|
||||||
|
|
|
@ -48,7 +48,8 @@
|
||||||
padding-left: #{15 / $base-font-size}rem;
|
padding-left: #{15 / $base-font-size}rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav__item-header-triangle polygon {
|
.nav__item-header-triangle polygon,
|
||||||
|
.nav__item-header-triangle path {
|
||||||
@include themify() {
|
@include themify() {
|
||||||
fill: getThemifyVariable('icon-color');
|
fill: getThemifyVariable('icon-color');
|
||||||
}
|
}
|
||||||
|
@ -67,7 +68,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav__item-header-triangle polygon {
|
.nav__item-header-triangle polygon,
|
||||||
|
.nav__item-header-triangle path {
|
||||||
@include themify() {
|
@include themify() {
|
||||||
fill: getThemifyVariable('nav-hover-color');
|
fill: getThemifyVariable('nav-hover-color');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
.quick-add-wrapper {
|
.quick-add-wrapper {
|
||||||
min-width: #{600 / $base-font-size}rem;
|
min-width: #{600 / $base-font-size}rem;
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quick-add {
|
.quick-add {
|
||||||
|
@ -43,12 +44,12 @@
|
||||||
@include icon();
|
@include icon();
|
||||||
@include themify() {
|
@include themify() {
|
||||||
// icon graphic
|
// icon graphic
|
||||||
polygon {
|
path {
|
||||||
fill: getThemifyVariable('table-button-color');
|
fill: getThemifyVariable('table-button-color');
|
||||||
}
|
}
|
||||||
|
|
||||||
// icon background circle
|
// icon background circle
|
||||||
path {
|
path:first-child {
|
||||||
fill: getThemifyVariable('table-button-background-color');
|
fill: getThemifyVariable('table-button-background-color');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,15 +68,15 @@
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quick-add__icon--in-collection .quick-add__in-icon svg {
|
.quick-add__icon--in-collection .quick-add__in-icon {
|
||||||
@include themify() {
|
@include themify() {
|
||||||
// icon graphic
|
// icon graphic
|
||||||
polygon {
|
& path {
|
||||||
fill: getThemifyVariable('table-button-active-color');
|
fill: getThemifyVariable('table-button-active-color');
|
||||||
}
|
}
|
||||||
|
|
||||||
// icon background circle
|
// icon background circle
|
||||||
path {
|
& path:first-child {
|
||||||
fill: getThemifyVariable('table-button-background-active-color');
|
fill: getThemifyVariable('table-button-background-active-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,14 +91,12 @@
|
||||||
.quick-add__item-toggle:focus {
|
.quick-add__item-toggle:focus {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@include themify() {
|
@include themify() {
|
||||||
.quick-add__icon {
|
& .quick-add__icon path {
|
||||||
polygon {
|
fill: getThemifyVariable('table-button-hover-color');
|
||||||
fill: getThemifyVariable('table-button-hover-color');
|
}
|
||||||
}
|
|
||||||
|
|
||||||
path {
|
& .quick-add__icon path:first-child {
|
||||||
fill: getThemifyVariable('table-button-background-hover-color');
|
fill: getThemifyVariable('table-button-background-hover-color');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ div.searchbar__button {
|
||||||
height: #{27 / $base-font-size}rem;
|
height: #{27 / $base-font-size}rem;
|
||||||
transform: scaleX(-1);
|
transform: scaleX(-1);
|
||||||
padding-top: #{3 / $base-font-size}rem;
|
padding-top: #{3 / $base-font-size}rem;
|
||||||
|
}
|
||||||
|
& path {
|
||||||
@include themify() {
|
@include themify() {
|
||||||
fill: getThemifyVariable('input-text-color');
|
fill: getThemifyVariable('input-text-color');
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,17 +188,17 @@
|
||||||
height: #{25 / $base-font-size}rem;
|
height: #{25 / $base-font-size}rem;
|
||||||
width: #{49 / $base-font-size}rem;
|
width: #{49 / $base-font-size}rem;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
& svg {
|
display: flex;
|
||||||
height: #{25 / $base-font-size}rem;
|
justify-content: center;
|
||||||
}
|
align-items: center;
|
||||||
@include themify() {
|
@include themify() {
|
||||||
background-color: getThemifyVariable("toolbar-button-background-color");
|
background-color: getThemifyVariable("toolbar-button-background-color");
|
||||||
& polygon {
|
& polygon, & path {
|
||||||
fill: getThemifyVariable("toolbar-button-color");
|
fill: getThemifyVariable("toolbar-button-color");
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: getThemifyVariable("button-background-hover-color");
|
background-color: getThemifyVariable("button-background-hover-color");
|
||||||
& polygon {
|
& polygon, & path {
|
||||||
fill: getThemifyVariable("button-hover-color");
|
fill: getThemifyVariable("button-hover-color");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@
|
||||||
cursor: e-resize;
|
cursor: e-resize;
|
||||||
}
|
}
|
||||||
.sidebar--contracted & {
|
.sidebar--contracted & {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@
|
||||||
.sidebar__folder-icon {
|
.sidebar__folder-icon {
|
||||||
padding: #{4 / $base-font-size}rem 0;
|
padding: #{4 / $base-font-size}rem 0;
|
||||||
margin-right: #{5 / $base-font-size}rem;
|
margin-right: #{5 / $base-font-size}rem;
|
||||||
& g {
|
& path {
|
||||||
@include themify() {
|
@include themify() {
|
||||||
fill: map-get($theme-map, 'primary-text-color');
|
fill: map-get($theme-map, 'primary-text-color');
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@
|
||||||
.sidebar__file-item-icon {
|
.sidebar__file-item-icon {
|
||||||
padding: #{4 / $base-font-size}rem 0;
|
padding: #{4 / $base-font-size}rem 0;
|
||||||
margin-right: #{5 / $base-font-size}rem;
|
margin-right: #{5 / $base-font-size}rem;
|
||||||
& g {
|
& path {
|
||||||
@include themify() {
|
@include themify() {
|
||||||
fill: getThemifyVariable('secondary-text-color');
|
fill: getThemifyVariable('secondary-text-color');
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
height: #{32 / $base-font-size}rem;
|
height: #{32 / $base-font-size}rem;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
@include themify() {
|
@include themify() {
|
||||||
background-color: getThemifyVariable('background-color');
|
background-color: getThemifyVariable('background-color');
|
||||||
}
|
}
|
||||||
|
@ -100,7 +101,7 @@
|
||||||
width:#{25 / $base-font-size}rem;
|
width:#{25 / $base-font-size}rem;
|
||||||
height:#{25 / $base-font-size}rem;
|
height:#{25 / $base-font-size}rem;
|
||||||
@include themify() {
|
@include themify() {
|
||||||
& polygon {
|
& polygon, & path {
|
||||||
fill: getThemifyVariable('inactive-text-color');
|
fill: getThemifyVariable('inactive-text-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,18 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding: 0 0 0 #{3 / $base-font-size}rem;
|
||||||
&--selected {
|
&--selected {
|
||||||
@extend %toolbar-button--selected;
|
@extend %toolbar-button--selected;
|
||||||
}
|
}
|
||||||
&:disabled {
|
&:disabled {
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('button-border-color');
|
fill: getThemifyVariable('button-border-color');
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: getThemifyVariable('toolbar-button-background-color');
|
background-color: getThemifyVariable('toolbar-button-background-color');
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('button-border-color');
|
fill: getThemifyVariable('button-border-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +43,7 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-right: #{15 / $base-font-size}rem;
|
margin-right: #{15 / $base-font-size}rem;
|
||||||
|
padding: 0;
|
||||||
&--selected {
|
&--selected {
|
||||||
@extend %toolbar-button--selected;
|
@extend %toolbar-button--selected;
|
||||||
}
|
}
|
||||||
|
@ -61,13 +63,11 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
line-height: #{52 / $base-font-size}rem;
|
padding: 0;
|
||||||
&--selected {
|
&--selected {
|
||||||
@extend %toolbar-button--selected;
|
@extend %toolbar-button--selected;
|
||||||
line-height: #{52 / $base-font-size}rem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
line-height: #{52 / $base-font-size}rem;
|
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
& span {
|
& span {
|
||||||
padding-left: #{1 / $base-font-size}rem;
|
padding-left: #{1 / $base-font-size}rem;
|
||||||
|
@ -82,7 +82,7 @@
|
||||||
.toolbar__logo {
|
.toolbar__logo {
|
||||||
margin-right: #{30 / $base-font-size}rem;
|
margin-right: #{30 / $base-font-size}rem;
|
||||||
@include themify() {
|
@include themify() {
|
||||||
& g {
|
& g, & path {
|
||||||
fill: getThemifyVariable('logo-color');
|
fill: getThemifyVariable('logo-color');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,11 +152,8 @@
|
||||||
.toolbar__edit-name-button {
|
.toolbar__edit-name-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
width: #{18 / $base-font-size}rem;
|
||||||
height: #{18 / $base-font-size}rem;
|
height: #{18 / $base-font-size}rem;
|
||||||
& svg {
|
|
||||||
width: #{18 / $base-font-size}rem;
|
|
||||||
height: #{18 / $base-font-size}rem;
|
|
||||||
}
|
|
||||||
@include themify() {
|
@include themify() {
|
||||||
& path {
|
& path {
|
||||||
fill: getThemifyVariable('secondary-text-color');
|
fill: getThemifyVariable('secondary-text-color');
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||||
|
|
||||||
/*eslint-disable*/
|
/*eslint-disable*/
|
||||||
|
var p5_javascript_template = require("./p5-keywords");
|
||||||
|
var p5FunctionKeywords = p5_javascript_template.p5FunctionKeywords;
|
||||||
|
var p5VariableKeywords = p5_javascript_template.p5VariableKeywords;
|
||||||
|
|
||||||
(function(mod) {
|
(function(mod) {
|
||||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
mod(require("codemirror"));
|
mod(require("codemirror"));
|
||||||
|
@ -25,8 +29,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||||
function kw(type) {return {type: type, style: "keyword"};}
|
function kw(type) {return {type: type, style: "keyword"};}
|
||||||
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
|
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
|
||||||
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
|
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
|
||||||
var p5Function = {type: "variable", style: "p5-function"};
|
|
||||||
var p5Variable = {type: "variable", style: "p5-variable"};
|
|
||||||
|
|
||||||
var jsKeywords = {
|
var jsKeywords = {
|
||||||
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
||||||
|
@ -41,85 +43,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||||
"await": C, "async": kw("async")
|
"await": C, "async": kw("async")
|
||||||
};
|
};
|
||||||
|
|
||||||
var p5FunctionKeywords = {
|
|
||||||
'alpha': p5Function, 'blue': p5Function, 'brightness': p5Function, 'color': p5Function, 'green': p5Function, 'hue': p5Function,
|
|
||||||
'lerpColor': p5Function, 'lightness': p5Function, 'red': p5Function, 'saturation': p5Function, 'background': p5Function, 'clear': p5Function,
|
|
||||||
'colorMode': p5Function, 'fill': p5Function, 'noFill': p5Function, 'noStroke': p5Function, 'stroke': p5Function, 'arc': p5Function,
|
|
||||||
'ellipse': p5Function, 'circle': p5Function, 'line': p5Function, 'point': p5Function, 'quad': p5Function, 'rect': p5Function,
|
|
||||||
'square': p5Function, 'triangle': p5Function, 'ellipseMode': p5Function, 'noSmooth': p5Function, 'rectMode': p5Function, 'smooth': p5Function,
|
|
||||||
'strokeCap': p5Function, 'strokeJoin': p5Function, 'strokeWeight': p5Function, 'bezier': p5Function, 'bezierDetail': p5Function, 'bezierPoint': p5Function,
|
|
||||||
'bezierTangent': p5Function, 'curve': p5Function, 'curveDetail': p5Function, 'curveTightness': p5Function, 'curvePoint': p5Function, 'curveTangent': p5Function,
|
|
||||||
'beginContour': p5Function, 'beginShape': p5Function, 'bezierVertex': p5Function, 'curveVertex': p5Function, 'endContour': p5Function, 'endShape': p5Function,
|
|
||||||
'quadraticVertex': p5Function, 'vertex': p5Function, 'print': p5Function, 'cursor': p5Function, 'frameRate': p5Function, 'noCursor': p5Function,
|
|
||||||
'windowResized': p5Function, 'fullscreen': p5Function, 'pixelDensity': p5Function, 'displayDensity': p5Function, 'getURL': p5Function, 'getURLPath': p5Function,
|
|
||||||
'getURLParams': p5Function, 'preload': p5Function, 'setup': p5Function, 'draw': p5Function, 'remove': p5Function, 'createCanvas': p5Function,
|
|
||||||
'resizeCanvas': p5Function, 'noCanvas': p5Function, 'createGraphics': p5Function, 'blendMode': p5Function, 'noLoop': p5Function, 'loop': p5Function,
|
|
||||||
'push': p5Function, 'pop': p5Function, 'redraw': p5Function, 'applyMatrix': p5Function, 'resetMatrix': p5Function, 'rotate': p5Function,
|
|
||||||
'rotateX': p5Function, 'rotateY': p5Function, 'rotateZ': p5Function, 'scale': p5Function, 'shearX': p5Function, 'shearY': p5Function,
|
|
||||||
'translate': p5Function, 'createStringDict': p5Function, 'createNumberDict': p5Function, 'setMoveThreshold': p5Function, 'setShakeThreshold': p5Function,
|
|
||||||
'deviceTurned': p5Function, 'deviceShaken': p5Function, 'keyPressed': p5Function, 'keyReleased': p5Function, 'keyTyped': p5Function, 'keyIsDown': p5Function,
|
|
||||||
'mouseMoved': p5Function, 'mouseDragged': p5Function, 'mousePressed': p5Function, 'mouseReleased': p5Function, 'mouseClicked': p5Function, 'doubleClicked': p5Function,
|
|
||||||
'mouseWheel': p5Function, 'touchStarted': p5Function, 'touchMoved': p5Function, 'touchEnded': p5Function, 'createImage': p5Function, 'saveCanvas': p5Function,
|
|
||||||
'saveFrames': p5Function, 'loadImage': p5Function, 'image': p5Function, 'tint': p5Function, 'noTint': p5Function, 'imageMode': p5Function,
|
|
||||||
'blend': p5Function, 'copy': p5Function, 'filter': p5Function, 'get': p5Function, 'loadPixels': p5Function, 'set': p5Function,
|
|
||||||
'updatePixels': p5Function, 'loadJSON': p5Function, 'loadStrings': p5Function, 'loadTable': p5Function, 'loadXML': p5Function, 'loadBytes': p5Function,
|
|
||||||
'httpGet': p5Function, 'httpPost': p5Function, 'httpDo': p5Function, 'createWriter': p5Function, 'save': p5Function, 'saveJSON': p5Function,
|
|
||||||
'saveStrings': p5Function, 'saveTable': p5Function, 'abs': p5Function, 'ceil': p5Function, 'constrain': p5Function, 'dist': p5Function,
|
|
||||||
'exp': p5Function, 'floor': p5Function, 'lerp': p5Function, 'log': p5Function, 'mag': p5Function, 'map': p5Function,
|
|
||||||
'max': p5Function, 'min': p5Function, 'norm': p5Function, 'pow': p5Function, 'round': p5Function, 'sq': p5Function,
|
|
||||||
'sqrt': p5Function, 'createVector': p5Function, 'noise': p5Function, 'noiseDetail': p5Function, 'noiseSeed': p5Function, 'randomSeed': p5Function,
|
|
||||||
'random': p5Function, 'randomGaussian': p5Function, 'acos': p5Function, 'asin': p5Function, 'atan': p5Function, 'atan2': p5Function,
|
|
||||||
'cos': p5Function, 'sin': p5Function, 'tan': p5Function, 'degrees': p5Function, 'radians': p5Function, 'angleMode': p5Function,
|
|
||||||
'textAlign': p5Function, 'textLeading': p5Function, 'textSize': p5Function, 'textStyle': p5Function, 'textWidth': p5Function, 'textAscent': p5Function,
|
|
||||||
'textDescent': p5Function, 'loadFont': p5Function, 'text': p5Function, 'textFont': p5Function, 'append': p5Function, 'arrayCopy': p5Function,
|
|
||||||
'concat': p5Function, 'reverse': p5Function, 'shorten': p5Function, 'shuffle': p5Function, 'sort': p5Function, 'splice': p5Function,
|
|
||||||
'subset': p5Function, 'float': p5Function, 'int': p5Function, 'str': p5Function, 'boolean': p5Function, 'byte': p5Function,
|
|
||||||
'char': p5Function, 'unchar': p5Function, 'hex': p5Function, 'unhex': p5Function, 'join': p5Function, 'match': p5Function,
|
|
||||||
'matchAll': p5Function, 'nf': p5Function, 'nfc': p5Function, 'nfp': p5Function, 'nfs': p5Function, 'split': p5Function,
|
|
||||||
'splitTokens': p5Function, 'trim': p5Function, 'day': p5Function, 'hour': p5Function, 'minute': p5Function, 'millis': p5Function,
|
|
||||||
'month': p5Function, 'second': p5Function, 'year': p5Function, 'plane': p5Function, 'box': p5Function, 'sphere': p5Function,
|
|
||||||
'cylinder': p5Function, 'cone': p5Function, 'ellipsoid': p5Function, 'torus': p5Function, 'orbitControl': p5Function, 'debugMode': p5Function,
|
|
||||||
'noDebugMode': p5Function, 'ambientLight': p5Function, 'directionalLight': p5Function, 'pointLight': p5Function, 'loadModel': p5Function,
|
|
||||||
'loadShader': p5Function, 'createShader': p5Function, 'shader': p5Function, 'normalMaterial': p5Function, 'texture': p5Function,
|
|
||||||
'ambientMaterial': p5Function, 'specularMaterial': p5Function, 'camera': p5Function, 'perspective': p5Function, 'ortho': p5Function,
|
|
||||||
'setCamera': p5Function, 'setAttributes': p5Function, 'select': p5Function, 'selectAll': p5Function, 'removeElements': p5Function, 'changed': p5Function,
|
|
||||||
'input': p5Function, 'createDiv': p5Function, 'createP': p5Function, 'createSpan': p5Function, 'createImg': p5Function, 'createA': p5Function,
|
|
||||||
'createSlider': p5Function, 'createButton': p5Function, 'createCheckbox': p5Function, 'createSelect': p5Function, 'createRadio': p5Function,
|
|
||||||
'createColorPicker': p5Function, 'textureMode': p5Function, 'createCamera': p5Function, 'model': p5Function,
|
|
||||||
'createInput': p5Function, 'createFileInput': p5Function, 'createVideo': p5Function, 'createAudio': p5Function, 'createCapture': p5Function,
|
|
||||||
'createElement': p5Function, 'deviceMoved': p5Function,
|
|
||||||
'sampleRate': p5Function, 'freqToMidi': p5Function, 'midiToFreq': p5Function, 'soundFormats': p5Function, 'saveSound': p5Function,
|
|
||||||
};
|
|
||||||
|
|
||||||
var p5VariableKeywords = {
|
|
||||||
'P2D': p5Variable, 'WEBGL': p5Variable, 'ARROW': p5Variable, 'CROSS': p5Variable, 'HAND': p5Variable,
|
|
||||||
'MOVE': p5Variable, 'TEXT': p5Variable,
|
|
||||||
'WAIT': p5Variable, 'HALF_PI': p5Variable, 'PI': p5Variable, 'QUARTER_PI': p5Variable,
|
|
||||||
'TAU': p5Variable, 'TWO_PI': p5Variable, 'DEGREES': p5Variable,
|
|
||||||
'RADIANS': p5Variable, 'CORNER': p5Variable, 'CORNERS': p5Variable, 'RADIUS': p5Variable,
|
|
||||||
'RIGHT': p5Variable, 'LEFT': p5Variable, 'CENTER': p5Variable, 'TOP': p5Variable, 'BOTTOM': p5Variable,
|
|
||||||
'BASELINE': p5Variable, 'POINTS': p5Variable, 'LINES': p5Variable, 'LINE_STRIP': p5Variable, 'LINE_LOOP': p5Variable,
|
|
||||||
'TRIANGLES': p5Variable, 'TRIANGLE_FAN': p5Variable, 'TRIANGLE_STRIP': p5Variable, 'QUADS': p5Variable,
|
|
||||||
'QUAD_STRIP': p5Variable, 'CLOSE': p5Variable, 'OPEN': p5Variable, 'CHORD': p5Variable, 'PIE': p5Variable,
|
|
||||||
'PROJECT': p5Variable, 'SQUARE': p5Variable, 'ROUND': p5Variable, 'BEVEL': p5Variable, 'MITER': p5Variable,
|
|
||||||
'RGB': p5Variable, 'HSB': p5Variable, 'HSL': p5Variable, 'AUTO': p5Variable, 'BLEND': p5Variable, 'ADD': p5Variable,
|
|
||||||
'DARKEST': p5Variable, 'LIGHTEST': p5Variable, 'DIFFERENCE': p5Variable, 'EXCLUSION': p5Variable, 'MULTIPLY': p5Variable,
|
|
||||||
'SCREEN': p5Variable, 'REPLACE': p5Variable, 'OVERLAY': p5Variable, 'HARD_LIGHT': p5Variable, 'SOFT_LIGHT': p5Variable,
|
|
||||||
'DODGE': p5Variable, 'BURN': p5Variable, 'THRESHOLD': p5Variable, 'GRAY': p5Variable, 'OPAQUE': p5Variable,
|
|
||||||
'INVERT': p5Variable, 'POSTERIZE': p5Variable, 'DILATE': p5Variable, 'ERODE': p5Variable, 'BLUR': p5Variable,
|
|
||||||
'NORMAL': p5Variable, 'ITALIC': p5Variable, 'BOLD': p5Variable, 'BOLDITALIC': p5Variable, 'LANDSCAPE': p5Variable,
|
|
||||||
'PORTRAIT': p5Variable, 'GRID': p5Variable, 'AXES': p5Variable, 'frameCount': p5Variable, 'focused': p5Variable,
|
|
||||||
'displayWidth': p5Variable, 'displayHeight': p5Variable, 'windowWidth': p5Variable, 'windowHeight': p5Variable,
|
|
||||||
'width': p5Variable, 'height': p5Variable, 'deviceOrientation': p5Variable, 'accelerationX': p5Variable,
|
|
||||||
'accelerationY': p5Variable, 'accelerationZ': p5Variable, 'pAccelerationX': p5Variable, 'pAccelerationY': p5Variable,
|
|
||||||
'pAccelerationZ': p5Variable, 'rotationX': p5Variable, 'rotationY': p5Variable, 'rotationZ': p5Variable,
|
|
||||||
'pRotationX': p5Variable, 'pRotationY': p5Variable, 'pRotationZ': p5Variable, 'turnAxis': p5Variable,
|
|
||||||
'keyIsPressed': p5Variable, 'key': p5Variable, 'keyCode': p5Variable, 'mouseX': p5Variable, 'mouseY': p5Variable,
|
|
||||||
'pmouseX': p5Variable, 'pmouseY': p5Variable, 'winMouseX': p5Variable, 'winMouseY': p5Variable,
|
|
||||||
'pwinMouseX': p5Variable, 'pwinMouseY': p5Variable, 'mouseButton': p5Variable,
|
|
||||||
'mouseIsPressed': p5Variable, 'touches': p5Variable, 'pixels': p5Variable, 'VIDEO': p5Variable, 'AUDIO': p5Variable
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var attr in p5FunctionKeywords) {
|
for (var attr in p5FunctionKeywords) {
|
||||||
jsKeywords[attr] = p5FunctionKeywords[attr];
|
jsKeywords[attr] = p5FunctionKeywords[attr];
|
||||||
}
|
}
|
||||||
|
|
8
client/utils/p5-keywords.js
Normal file
8
client/utils/p5-keywords.js
Normal file
File diff suppressed because one or more lines are too long
6093
package-lock.json
generated
6093
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -20,6 +20,7 @@
|
||||||
"fetch-examples:prod": "cross-env NODE_ENV=production node ./dist/fetch-examples.bundle.js",
|
"fetch-examples:prod": "cross-env NODE_ENV=production node ./dist/fetch-examples.bundle.js",
|
||||||
"fetch-examples-gg:prod": "cross-env NODE_ENV=production node ./dist/fetch-examples-gg.bundle.js",
|
"fetch-examples-gg:prod": "cross-env NODE_ENV=production node ./dist/fetch-examples-gg.bundle.js",
|
||||||
"fetch-examples-ml5:prod": "cross-env NODE_ENV=production node ./dist/fetch-examples-ml5.bundle.js",
|
"fetch-examples-ml5:prod": "cross-env NODE_ENV=production node ./dist/fetch-examples-ml5.bundle.js",
|
||||||
|
"update-syntax-highlighting": "node ./server/scripts/update-syntax-highlighting.js",
|
||||||
"heroku-postbuild": "touch .env; npm run build",
|
"heroku-postbuild": "touch .env; npm run build",
|
||||||
"storybook": "start-storybook -p 6006",
|
"storybook": "start-storybook -p 6006",
|
||||||
"build-storybook": "build-storybook"
|
"build-storybook": "build-storybook"
|
||||||
|
@ -76,6 +77,7 @@
|
||||||
"@storybook/addon-links": "^5.3.6",
|
"@storybook/addon-links": "^5.3.6",
|
||||||
"@storybook/addons": "^5.3.6",
|
"@storybook/addons": "^5.3.6",
|
||||||
"@storybook/react": "^5.3.6",
|
"@storybook/react": "^5.3.6",
|
||||||
|
"@svgr/webpack": "^5.4.0",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
"babel-eslint": "^9.0.0",
|
"babel-eslint": "^9.0.0",
|
||||||
"babel-jest": "^24.9.0",
|
"babel-jest": "^24.9.0",
|
||||||
|
@ -176,7 +178,7 @@
|
||||||
"react-dom": "^16.12.0",
|
"react-dom": "^16.12.0",
|
||||||
"react-helmet": "^5.1.3",
|
"react-helmet": "^5.1.3",
|
||||||
"react-hot-loader": "^4.12.19",
|
"react-hot-loader": "^4.12.19",
|
||||||
"react-inlinesvg": "^0.7.5",
|
"react-inlinesvg": "^1.2.0",
|
||||||
"react-redux": "^5.1.2",
|
"react-redux": "^5.1.2",
|
||||||
"react-router": "^3.2.5",
|
"react-router": "^3.2.5",
|
||||||
"react-split-pane": "^0.1.89",
|
"react-split-pane": "^0.1.89",
|
||||||
|
|
48
server/scripts/update-syntax-highlighting.js
Normal file
48
server/scripts/update-syntax-highlighting.js
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const process = require('process');
|
||||||
|
const request = require('request');
|
||||||
|
|
||||||
|
request('https://p5js.org/reference/data.json', (err, res) => {
|
||||||
|
if (!err) {
|
||||||
|
const result = res.toJSON();
|
||||||
|
const data = JSON.parse(result.body);
|
||||||
|
|
||||||
|
const arr = data.classitems;
|
||||||
|
const p5VariableKeywords = {};
|
||||||
|
const p5FunctionKeywords = {};
|
||||||
|
|
||||||
|
arr.forEach((obj) => {
|
||||||
|
if (obj.class === 'p5' && obj.module !== 'Foundation') {
|
||||||
|
if (obj.itemtype === 'property') {
|
||||||
|
p5VariableKeywords[`${obj.name}`] = 'p5Variable';
|
||||||
|
}
|
||||||
|
if (obj.itemtype === 'method') {
|
||||||
|
p5FunctionKeywords[`${obj.name}`] = 'p5Function';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let p5VariablePart = JSON.stringify(p5VariableKeywords);
|
||||||
|
let p5FunctionPart = JSON.stringify(p5FunctionKeywords);
|
||||||
|
p5VariablePart = p5VariablePart.replace(/"p5Variable"/g, 'p5Variable');
|
||||||
|
p5FunctionPart = p5FunctionPart.replace(/"p5Function"/g, 'p5Function');
|
||||||
|
|
||||||
|
let generatedCode = '/* eslint-disable */ \n';
|
||||||
|
generatedCode += '/* generated: do not edit! helper file for syntax highlighting. generated by update-syntax-highlighting script */ \n';
|
||||||
|
generatedCode += 'var p5Function = {type: "variable", style: "p5-function"};\n';
|
||||||
|
generatedCode += 'var p5Variable = {type: "variable", style: "p5-variable"};\n';
|
||||||
|
generatedCode += `let p5VariableKeywords = ${p5VariablePart}; \n`;
|
||||||
|
generatedCode += `let p5FunctionKeywords = ${p5FunctionPart}; \n`;
|
||||||
|
generatedCode += 'exports.p5FunctionKeywords = p5FunctionKeywords;\n';
|
||||||
|
generatedCode += 'exports.p5VariableKeywords = p5VariableKeywords;\n';
|
||||||
|
fs.writeFile(`${process.cwd()}/client/utils/p5-keywords.js`, generatedCode, (error) => {
|
||||||
|
if (error) {
|
||||||
|
console.log("Error!! Couldn't write to the file", error);
|
||||||
|
} else {
|
||||||
|
console.log('Syntax highlighting files updated successfully');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("Error!! Couldn't fetch the data.json file");
|
||||||
|
}
|
||||||
|
});
|
|
@ -69,7 +69,7 @@ module.exports = {
|
||||||
use: ['style-loader', 'css-loader', 'sass-loader']
|
use: ['style-loader', 'css-loader', 'sass-loader']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(svg|mp3)$/,
|
test: /\.(mp3)$/,
|
||||||
use: 'file-loader'
|
use: 'file-loader'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -83,9 +83,30 @@ module.exports = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /fonts\/.*\.(eot|svg|ttf|woff|woff2)$/,
|
test: /fonts\/.*\.(eot|ttf|woff|woff2)$/,
|
||||||
use: 'file-loader'
|
use: 'file-loader'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /\.svg$/,
|
||||||
|
oneOf: [
|
||||||
|
{
|
||||||
|
resourceQuery: /byUrl/,
|
||||||
|
use: 'file-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
use: {
|
||||||
|
loader: '@svgr/webpack',
|
||||||
|
options: {
|
||||||
|
svgoConfig: {
|
||||||
|
plugins: {
|
||||||
|
removeViewBox: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /_console-feed.scss/,
|
test: /_console-feed.scss/,
|
||||||
use: {
|
use: {
|
||||||
|
|
|
@ -80,10 +80,6 @@ module.exports = [{
|
||||||
exclude: /node_modules/,
|
exclude: /node_modules/,
|
||||||
use: 'babel-loader'
|
use: 'babel-loader'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.(svg|mp3)$/,
|
|
||||||
use: 'file-loader'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
test: /\.(png)$/,
|
test: /\.(png)$/,
|
||||||
use: {
|
use: {
|
||||||
|
@ -95,9 +91,34 @@ module.exports = [{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /fonts\/.*\.(eot|svg|ttf|woff|woff2)$/,
|
test: /\.mp3$/,
|
||||||
use: 'file-loader'
|
use: 'file-loader'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
test: /fonts\/.*\.(eot|ttf|woff|woff2)$/,
|
||||||
|
use: 'file-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.svg$/,
|
||||||
|
oneOf: [
|
||||||
|
{
|
||||||
|
resourceQuery: /byUrl/,
|
||||||
|
use: 'file-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
use: {
|
||||||
|
loader: '@svgr/webpack',
|
||||||
|
options: {
|
||||||
|
svgoConfig: {
|
||||||
|
plugins: {
|
||||||
|
removeViewBox: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /_console-feed.scss/,
|
test: /_console-feed.scss/,
|
||||||
use: {
|
use: {
|
||||||
|
|
Loading…
Reference in a new issue