* Got the basis covered, now I need to style all this * Corrected and upgraded Share window * Changed the routes again, and set correct design * Made some of the requested changes * Removed PreviewFrame errors * Redesigned Preview Header * Corrected style of the FullView * Corrected most of the css mistakes * Corrected logo size
This commit is contained in:
parent
f4ff0b1c34
commit
996a1b988a
16 changed files with 137 additions and 31 deletions
37
client/components/PreviewNav.jsx
Normal file
37
client/components/PreviewNav.jsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router';
|
||||||
|
import InlineSVG from 'react-inlinesvg';
|
||||||
|
|
||||||
|
const logoUrl = require('../images/p5js-logo-small.svg');
|
||||||
|
const editorUrl = require('../images/code.svg');
|
||||||
|
|
||||||
|
const PreviewNav = ({ owner, project }) => (
|
||||||
|
<nav className="nav">
|
||||||
|
<div className="nav__items-left">
|
||||||
|
<div className="nav__item-logo">
|
||||||
|
<InlineSVG src={logoUrl} alt="p5.js logo" />
|
||||||
|
</div>
|
||||||
|
<Link className="nav__item" to={`/${owner.username}/sketches/${project.id}`}>{project.name}</Link>
|
||||||
|
<p className="toolbar__project-owner">by</p>
|
||||||
|
<Link className="nav__item" to={`/${owner.username}/sketches/`}>{owner.username}</Link>
|
||||||
|
</div>
|
||||||
|
<div className="nav__items-right">
|
||||||
|
<Link to={`/${owner.username}/sketches/${project.id}`}>
|
||||||
|
<InlineSVG className="preview-nav__editor-svg" src={editorUrl} />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
|
||||||
|
PreviewNav.propTypes = {
|
||||||
|
owner: PropTypes.shape({
|
||||||
|
username: PropTypes.string.isRequired
|
||||||
|
}).isRequired,
|
||||||
|
project: PropTypes.shape({
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PreviewNav;
|
8
client/images/code.svg
Normal file
8
client/images/code.svg
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generated by IcoMoon.io -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="16" viewBox="0 0 20 16">
|
||||||
|
<path d="M13 11.5l1.5 1.5 5-5-5-5-1.5 1.5 3.5 3.5z"></path>
|
||||||
|
<path d="M7 4.5l-1.5-1.5-5 5 5 5 1.5-1.5-3.5-3.5z"></path>
|
||||||
|
<path d="M10.958 2.352l1.085 0.296-3 11-1.085-0.296 3-11z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 513 B |
|
@ -31,7 +31,8 @@ class CopyableInput extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
label,
|
label,
|
||||||
value
|
value,
|
||||||
|
hasPreviewLink
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="copyable-input">
|
<div className="copyable-input">
|
||||||
|
@ -42,7 +43,12 @@ class CopyableInput extends React.Component {
|
||||||
onMouseLeave={this.onMouseLeaveHandler}
|
onMouseLeave={this.onMouseLeaveHandler}
|
||||||
>
|
>
|
||||||
<label className="copyable-input__label" htmlFor={`copyable-input__value-${label}`}>
|
<label className="copyable-input__label" htmlFor={`copyable-input__value-${label}`}>
|
||||||
{label}
|
<div className="copyable-input__label-container">
|
||||||
|
{label} {hasPreviewLink &&
|
||||||
|
<a target="_blank" href={value}>
|
||||||
|
Open
|
||||||
|
</a>}
|
||||||
|
</div>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="copyable-input__value"
|
className="copyable-input__value"
|
||||||
|
@ -60,7 +66,12 @@ class CopyableInput extends React.Component {
|
||||||
|
|
||||||
CopyableInput.propTypes = {
|
CopyableInput.propTypes = {
|
||||||
label: PropTypes.string.isRequired,
|
label: PropTypes.string.isRequired,
|
||||||
value: PropTypes.string.isRequired
|
value: PropTypes.string.isRequired,
|
||||||
|
hasPreviewLink: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
|
CopyableInput.defaultProps = {
|
||||||
|
hasPreviewLink: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CopyableInput;
|
export default CopyableInput;
|
||||||
|
|
|
@ -317,8 +317,9 @@ class PreviewFrame extends React.Component {
|
||||||
|
|
||||||
renderSketch() {
|
renderSketch() {
|
||||||
const doc = this.iframeElement;
|
const doc = this.iframeElement;
|
||||||
|
const localFiles = this.injectLocalFiles();
|
||||||
if (this.props.isPlaying) {
|
if (this.props.isPlaying) {
|
||||||
srcDoc.set(doc, this.injectLocalFiles());
|
srcDoc.set(doc, localFiles);
|
||||||
if (this.props.endSketchRefresh) {
|
if (this.props.endSketchRefresh) {
|
||||||
this.props.endSketchRefresh();
|
this.props.endSketchRefresh();
|
||||||
}
|
}
|
||||||
|
@ -331,6 +332,7 @@ class PreviewFrame extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<iframe
|
<iframe
|
||||||
|
id="canvas_frame"
|
||||||
className="preview-frame"
|
className="preview-frame"
|
||||||
aria-label="sketch output"
|
aria-label="sketch output"
|
||||||
role="main"
|
role="main"
|
||||||
|
|
|
@ -17,11 +17,12 @@ class ShareModal extends React.PureComponent {
|
||||||
</h3>
|
</h3>
|
||||||
<CopyableInput
|
<CopyableInput
|
||||||
label="Embed"
|
label="Embed"
|
||||||
value={`<iframe src="${hostname}/embed/${projectId}"></iframe>`}
|
value={`<iframe src="${hostname}/${ownerUsername}/embed/${projectId}"></iframe>`}
|
||||||
/>
|
/>
|
||||||
<CopyableInput
|
<CopyableInput
|
||||||
label="Fullscreen"
|
label="Fullscreen"
|
||||||
value={`${hostname}/full/${projectId}`}
|
hasPreviewLink
|
||||||
|
value={`${hostname}/${ownerUsername}/full/${projectId}`}
|
||||||
/>
|
/>
|
||||||
<CopyableInput
|
<CopyableInput
|
||||||
label="Edit"
|
label="Edit"
|
||||||
|
|
|
@ -1,24 +1,38 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import Helmet from 'react-helmet';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import PreviewFrame from '../components/PreviewFrame';
|
import PreviewFrame from '../components/PreviewFrame';
|
||||||
|
import PreviewNav from '../../../components/PreviewNav';
|
||||||
import { getHTMLFile, getJSFiles, getCSSFiles } from '../reducers/files';
|
import { getHTMLFile, getJSFiles, getCSSFiles } from '../reducers/files';
|
||||||
import * as ProjectActions from '../actions/project';
|
import * as ProjectActions from '../actions/project';
|
||||||
|
|
||||||
|
|
||||||
class FullView extends React.Component {
|
class FullView extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.getProject(this.props.params.project_id);
|
this.props.getProject(this.props.params.project_id);
|
||||||
|
document.body.className = this.props.theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUpdate(nextProps) {
|
||||||
|
if (nextProps.theme !== this.props.theme) {
|
||||||
|
document.body.className = nextProps.theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ident = () => {}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="fullscreen-preview">
|
<div className="fullscreen-preview">
|
||||||
<h1 className="fullscreen-preview__title">
|
<Helmet>
|
||||||
{this.props.project.name} {this.props.project.owner ? `by ${this.props.project.owner.username}` : ''}
|
<title>{this.props.project.name}</title>
|
||||||
</h1>
|
</Helmet>
|
||||||
<div className="fullscreen-preview__frame-wrapper">
|
<PreviewNav
|
||||||
|
owner={{ username: this.props.project.owner ? `${this.props.project.owner.username}` : '' }}
|
||||||
|
project={{ name: this.props.project.name, id: this.props.params.project_id }}
|
||||||
|
/>
|
||||||
|
<div className="preview-frame-holder">
|
||||||
<PreviewFrame
|
<PreviewFrame
|
||||||
htmlFile={this.props.htmlFile}
|
htmlFile={this.props.htmlFile}
|
||||||
jsFiles={this.props.jsFiles}
|
jsFiles={this.props.jsFiles}
|
||||||
|
@ -29,6 +43,16 @@ class FullView extends React.Component {
|
||||||
}
|
}
|
||||||
fullView
|
fullView
|
||||||
isPlaying
|
isPlaying
|
||||||
|
isAccessibleOutputPlaying={false}
|
||||||
|
textOutput={false}
|
||||||
|
gridOutput={false}
|
||||||
|
soundOutput={false}
|
||||||
|
dispatchConsoleEvent={this.ident}
|
||||||
|
endSketchRefresh={this.ident}
|
||||||
|
previewIsRefreshing={false}
|
||||||
|
setBlobUrl={this.ident}
|
||||||
|
stopSketch={this.ident}
|
||||||
|
expandConsole={this.ident}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,6 +61,7 @@ class FullView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
FullView.propTypes = {
|
FullView.propTypes = {
|
||||||
|
theme: PropTypes.string.isRequired,
|
||||||
params: PropTypes.shape({
|
params: PropTypes.shape({
|
||||||
project_id: PropTypes.string
|
project_id: PropTypes.string
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
@ -72,6 +97,7 @@ FullView.propTypes = {
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
user: state.user,
|
user: state.user,
|
||||||
|
theme: state.preferences.theme,
|
||||||
htmlFile: getHTMLFile(state.files),
|
htmlFile: getHTMLFile(state.files),
|
||||||
jsFiles: getJSFiles(state.files),
|
jsFiles: getJSFiles(state.files),
|
||||||
cssFiles: getCSSFiles(state.files),
|
cssFiles: getCSSFiles(state.files),
|
||||||
|
|
|
@ -33,6 +33,7 @@ const routes = store => (
|
||||||
component={NewPasswordView}
|
component={NewPasswordView}
|
||||||
/>
|
/>
|
||||||
<Route path="/projects/:project_id" component={IDEView} />
|
<Route path="/projects/:project_id" component={IDEView} />
|
||||||
|
<Route path="/:username/full/:project_id" component={FullView} />
|
||||||
<Route path="/full/:project_id" component={FullView} />
|
<Route path="/full/:project_id" component={FullView} />
|
||||||
<Route path="/sketches" component={IDEView} />
|
<Route path="/sketches" component={IDEView} />
|
||||||
<Route path="/assets" component={IDEView} />
|
<Route path="/assets" component={IDEView} />
|
||||||
|
|
|
@ -30,6 +30,7 @@ $themes: (
|
||||||
toolbar-button-background-color: #f4f4f4,
|
toolbar-button-background-color: #f4f4f4,
|
||||||
button-background-hover-color: $p5js-pink,
|
button-background-hover-color: $p5js-pink,
|
||||||
button-background-active-color: #f10046,
|
button-background-active-color: #f10046,
|
||||||
|
button-nav-inactive-color: #a0a0a0,
|
||||||
button-hover-color: $white,
|
button-hover-color: $white,
|
||||||
button-active-color: $white,
|
button-active-color: $white,
|
||||||
modal-background-color: #f4f4f4,
|
modal-background-color: #f4f4f4,
|
||||||
|
@ -77,6 +78,7 @@ $themes: (
|
||||||
toolbar-button-background-color: #424242,
|
toolbar-button-background-color: #424242,
|
||||||
button-background-hover-color: $p5js-pink,
|
button-background-hover-color: $p5js-pink,
|
||||||
button-background-active-color: #f10046,
|
button-background-active-color: #f10046,
|
||||||
|
button-nav-inactive-color: #a0a0a0,
|
||||||
button-hover-color: $white,
|
button-hover-color: $white,
|
||||||
button-active-color: $white,
|
button-active-color: $white,
|
||||||
modal-background-color: #444,
|
modal-background-color: #444,
|
||||||
|
@ -122,6 +124,7 @@ $themes: (
|
||||||
toolbar-button-background-color: #C1C1C1,
|
toolbar-button-background-color: #C1C1C1,
|
||||||
button-background-hover-color: $yellow,
|
button-background-hover-color: $yellow,
|
||||||
button-background-active-color: #f10046,
|
button-background-active-color: #f10046,
|
||||||
|
button-nav-inactive-color: #a0a0a0,
|
||||||
button-hover-color: #333333,
|
button-hover-color: #333333,
|
||||||
button-active-color: #333333,
|
button-active-color: #333333,
|
||||||
modal-background-color: #444,
|
modal-background-color: #444,
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.copyable-input__label-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
.copyable-input {
|
.copyable-input {
|
||||||
padding-bottom: #{30 / $base-font-size}rem;
|
padding-bottom: #{30 / $base-font-size}rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
.nav {
|
.nav {
|
||||||
width: calc(100% - #{10 / $base-font-size}rem);
|
|
||||||
height: #{42 / $base-font-size}rem;
|
height: #{42 / $base-font-size}rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -225,4 +224,3 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
client/styles/components/_preview-nav.scss
Normal file
14
client/styles/components/_preview-nav.scss
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
.preview-nav__editor-svg {
|
||||||
|
& svg {
|
||||||
|
width: #{22 / $base-font-size}rem;
|
||||||
|
height: #{22 / $base-font-size}rem;
|
||||||
|
@include themify() {
|
||||||
|
fill: getThemifyVariable('button-nav-inactive-color');
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
@include themify() {
|
||||||
|
fill: getThemifyVariable('button-background-hover-color');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,15 +3,7 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
|
@include themify() {
|
||||||
|
background-color: getThemifyVariable('background-color');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fullscreen-preview__title {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fullscreen-preview__frame-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
flex: 1 0 0%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
@import 'components/p5-contrast-codemirror-theme';
|
@import 'components/p5-contrast-codemirror-theme';
|
||||||
@import 'components/editor';
|
@import 'components/editor';
|
||||||
@import 'components/nav';
|
@import 'components/nav';
|
||||||
|
@import 'components/preview-nav';
|
||||||
@import 'components/toolbar';
|
@import 'components/toolbar';
|
||||||
@import 'components/preferences';
|
@import 'components/preferences';
|
||||||
@import 'components/reset-password';
|
@import 'components/reset-password';
|
||||||
|
|
|
@ -3,7 +3,7 @@ import * as EmbedController from '../controllers/embed.controller';
|
||||||
|
|
||||||
const router = new Router();
|
const router = new Router();
|
||||||
|
|
||||||
|
router.get('/:username/embed/:project_id', EmbedController.serveProject);
|
||||||
router.get('/embed/:project_id', EmbedController.serveProject);
|
router.get('/embed/:project_id', EmbedController.serveProject);
|
||||||
router.get('/full/:project_id', EmbedController.serveProject);
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
@ -32,10 +32,17 @@ router.get('/:username/sketches/:project_id', (req, res) => {
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/:username/full/:project_id', (req, res) => {
|
||||||
|
projectForUserExists(req.params.username, req.params.project_id, exists => (
|
||||||
|
exists ? res.send(renderIndex()) : get404Sketch(html => res.send(html))
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
// router.get('/full/:project_id', (req, res) => {
|
router.get('/full/:project_id', (req, res) => {
|
||||||
// res.send(renderIndex());
|
projectExists(req.params.project_id, exists => (
|
||||||
// });
|
exists ? res.send(renderIndex()) : get404Sketch(html => res.send(html))
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
router.get('/login', (req, res) => {
|
router.get('/login', (req, res) => {
|
||||||
if (req.user) {
|
if (req.user) {
|
||||||
|
|
Loading…
Reference in a new issue