mirror of https://github.com/embarklabs/embark.git
WIP: style fiddle
This commit is contained in:
parent
de901b73fc
commit
ea9939c03a
|
@ -0,0 +1,4 @@
|
||||||
|
.fiddle--grid {
|
||||||
|
margin-left: -30px;
|
||||||
|
margin-right: -30px;
|
||||||
|
}
|
|
@ -1,28 +1,27 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {Row, Col} from 'reactstrap';
|
||||||
Page,
|
import TextEditorAsideContainer from '../containers/TextEditorAsideContainer';
|
||||||
Grid
|
|
||||||
} from "tabler-react";
|
|
||||||
|
|
||||||
import ApplicationPreviewContainer from '../containers/ApplicationPreviewContainer';
|
|
||||||
import TextEditorContainer from '../containers/TextEditorContainer';
|
import TextEditorContainer from '../containers/TextEditorContainer';
|
||||||
import FileExplorerContainer from '../containers/FileExplorerContainer';
|
import FileExplorerContainer from '../containers/FileExplorerContainer';
|
||||||
|
|
||||||
|
import './FiddleLayout.css';
|
||||||
|
|
||||||
|
const DEFAULT_FILE = {name: 'newContract.sol', content: ''};
|
||||||
|
|
||||||
class FiddleLayout extends React.Component {
|
class FiddleLayout extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Page.Content title="Fiddle">
|
<Row noGutters className="h-100 fiddle--grid">
|
||||||
<Grid.Row className="my-5">
|
<Col sm={4} md={2}>
|
||||||
<Grid.Col md={3}>
|
|
||||||
<Page.Title>Fiddle</Page.Title>
|
|
||||||
<FileExplorerContainer />
|
<FileExplorerContainer />
|
||||||
</Grid.Col>
|
</Col>
|
||||||
<Grid.Col md={9}>
|
<Col sm={8} md={6}>
|
||||||
<TextEditorContainer />
|
<TextEditorContainer defaultFile={DEFAULT_FILE} />
|
||||||
</Grid.Col>
|
</Col>
|
||||||
</Grid.Row>
|
<Col sm={12} md={4}>
|
||||||
<ApplicationPreviewContainer />
|
<TextEditorAsideContainer defaultFile={DEFAULT_FILE} />
|
||||||
</Page.Content>
|
</Col>
|
||||||
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,85 @@ import PropTypes from 'prop-types';
|
||||||
import {Treebeard, decorators} from 'react-treebeard';
|
import {Treebeard, decorators} from 'react-treebeard';
|
||||||
import {Form} from 'tabler-react';
|
import {Form} from 'tabler-react';
|
||||||
|
|
||||||
|
const style = {
|
||||||
|
tree: {
|
||||||
|
base: {
|
||||||
|
height: '100%',
|
||||||
|
listStyle: 'none',
|
||||||
|
backgroundColor: '#1C1C1C',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
color: '#9DA5AB',
|
||||||
|
fontFamily: 'lucida grande ,tahoma,verdana,arial,sans-serif',
|
||||||
|
fontSize: '14px'
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
base: {
|
||||||
|
position: 'relative'
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
cursor: 'pointer',
|
||||||
|
position: 'relative',
|
||||||
|
padding: '0px 5px',
|
||||||
|
display: 'block'
|
||||||
|
},
|
||||||
|
activeLink: {
|
||||||
|
background: '#31363F'
|
||||||
|
},
|
||||||
|
toggle: {
|
||||||
|
base: {
|
||||||
|
position: 'relative',
|
||||||
|
display: 'inline-block',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
marginLeft: '-5px',
|
||||||
|
height: '24px',
|
||||||
|
width: '24px'
|
||||||
|
},
|
||||||
|
wrapper: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
margin: '-7px 0 0 -7px',
|
||||||
|
height: '14px'
|
||||||
|
},
|
||||||
|
height: 14,
|
||||||
|
width: 14,
|
||||||
|
arrow: {
|
||||||
|
fill: '#9DA5AB',
|
||||||
|
strokeWidth: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
base: {
|
||||||
|
display: 'inline-block',
|
||||||
|
verticalAlign: 'top',
|
||||||
|
color: '#9DA5AB'
|
||||||
|
},
|
||||||
|
connector: {
|
||||||
|
width: '2px',
|
||||||
|
height: '12px',
|
||||||
|
borderLeft: 'solid 2px black',
|
||||||
|
borderBottom: 'solid 2px black',
|
||||||
|
position: 'absolute',
|
||||||
|
top: '0px',
|
||||||
|
left: '-21px'
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
lineHeight: '24px',
|
||||||
|
verticalAlign: 'middle'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subtree: {
|
||||||
|
listStyle: 'none',
|
||||||
|
paddingLeft: '19px'
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
color: '#E2C089'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const Header = ({style, node}) => {
|
const Header = ({style, node}) => {
|
||||||
const iconType = node.children ? 'folder' : 'file';
|
const iconType = node.children ? 'folder' : 'file';
|
||||||
const iconClass = `fe fe-${iconType}`;
|
const iconClass = `fe fe-${iconType}`;
|
||||||
|
@ -104,6 +183,7 @@ class FileExplorer extends React.Component {
|
||||||
data={this.filterHidden(this.props.files)}
|
data={this.filterHidden(this.props.files)}
|
||||||
decorators={decorators}
|
decorators={decorators}
|
||||||
onToggle={this.onToggle.bind(this)}
|
onToggle={this.onToggle.bind(this)}
|
||||||
|
style={style}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
|
@ -66,7 +66,7 @@ const Layout = ({children, logout, credentials, location}) => (
|
||||||
<AppSidebarMinimizer />
|
<AppSidebarMinimizer />
|
||||||
</AppSidebar>
|
</AppSidebar>
|
||||||
<main className="main">
|
<main className="main">
|
||||||
<Container fluid>
|
<Container fluid className="h-100">
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -2,37 +2,15 @@ import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Form, Button} from 'tabler-react';
|
import {Form, Button} from 'tabler-react';
|
||||||
|
|
||||||
class ApplicationPreviewContainer extends React.Component {
|
class Preview extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
previewUrl: this.props.previewHomepage
|
previewUrl: this.props.previewUrl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Form.Group>
|
|
||||||
<Form.InputGroup>
|
|
||||||
<Form.Input placeholder="URL"
|
|
||||||
value={this.state.previewUrl}
|
|
||||||
className="form-control"
|
|
||||||
onChange={(e) => this.handlePreviewUrlChange(e)} />
|
|
||||||
<Form.InputGroupAppend>
|
|
||||||
<Button color="primary" onClick={(e) => this.handlePreviewGo(e)}>Go</Button>
|
|
||||||
</Form.InputGroupAppend>
|
|
||||||
</Form.InputGroup>
|
|
||||||
<iframe width="100%"
|
|
||||||
height="500"
|
|
||||||
title="Preview"
|
|
||||||
ref={(iframe) => this.previewIframe = iframe}
|
|
||||||
onLoad={(e) => this.handlePreviewChange(e)} src={this.props.previewHomepage}>
|
|
||||||
</iframe>
|
|
||||||
</Form.Group>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePreviewUrlChange(ev) {
|
handlePreviewUrlChange(ev) {
|
||||||
this.setState({previewUrl: ev.target.value});
|
this.setState({previewUrl: ev.target.value});
|
||||||
}
|
}
|
||||||
|
@ -41,23 +19,43 @@ class ApplicationPreviewContainer extends React.Component {
|
||||||
try {
|
try {
|
||||||
let url = ev.target.contentWindow.location.toString();
|
let url = ev.target.contentWindow.location.toString();
|
||||||
this.setState({previewUrl: url});
|
this.setState({previewUrl: url});
|
||||||
} catch(e) {
|
} catch(e) {}
|
||||||
// Nothing here.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePreviewGo() {
|
handlePreviewGo() {
|
||||||
this.previewIframe.src = this.state.previewUrl;
|
this.previewIframe.src = this.state.previewUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Form.Group className='h-100'>
|
||||||
|
<Form.InputGroup>
|
||||||
|
<Form.Input placeholder="URL"
|
||||||
|
value={this.state.previewUrl}
|
||||||
|
className="form-control"
|
||||||
|
onChange={(e) => this.handlePreviewUrlChange(e)} />
|
||||||
|
<Form.InputGroupAppend>
|
||||||
|
<Button color="primary" onClick={(e) => this.handlePreviewGo(e)}>Go</Button>
|
||||||
|
</Form.InputGroupAppend>
|
||||||
|
</Form.InputGroup>
|
||||||
|
<iframe width="100%"
|
||||||
|
height="100%"
|
||||||
|
title="Preview"
|
||||||
|
ref={(iframe) => this.previewIframe = iframe}
|
||||||
|
onLoad={(e) => this.handlePreviewChange(e)} src={this.state.previewUrl}>
|
||||||
|
</iframe>
|
||||||
|
</Form.Group>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationPreviewContainer.propTypes = {
|
Preview.propTypes = {
|
||||||
previewHomepage: PropTypes.string
|
previewUrl: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
ApplicationPreviewContainer.defaultProps = {
|
Preview.defaultProps = {
|
||||||
previewHomepage: window.location.protocol + '//' + window.location.host
|
previewUrl: window.location.protocol + '//' + window.location.host
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ApplicationPreviewContainer;
|
export default Preview;
|
||||||
|
|
|
@ -27,8 +27,13 @@ class TextEditor extends React.Component {
|
||||||
const value = editor.getValue();
|
const value = editor.getValue();
|
||||||
this.props.onFileContentChange(value);
|
this.props.onFileContentChange(value);
|
||||||
});
|
});
|
||||||
|
editor.layout();
|
||||||
|
window.addEventListener('resize', this.handleResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleResize = () => editor.layout();
|
||||||
|
|
||||||
|
|
||||||
getLanguage() {
|
getLanguage() {
|
||||||
const extension = this.props.file.name.split('.').pop();
|
const extension = this.props.file.name.split('.').pop();
|
||||||
return SUPPORTED_LANGUAGES[SUPPORTED_LANGUAGES.indexOf(extension)] || DEFAULT_LANGUAGE;
|
return SUPPORTED_LANGUAGES[SUPPORTED_LANGUAGES.indexOf(extension)] || DEFAULT_LANGUAGE;
|
||||||
|
@ -77,11 +82,10 @@ class TextEditor extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const style = {
|
const style = {
|
||||||
width: "800px",
|
height: "100%"
|
||||||
height: "600px"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return <div ref={this.assignRef} style={style} id={EDITOR_ID} />;
|
return <div style={style} id={EDITOR_ID} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* eslint multiline-ternary: "off" */
|
||||||
|
/* eslint operator-linebreak: "off" */
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
currentFile as currentFileAction,
|
||||||
|
} from '../actions';
|
||||||
|
import {getCurrentFile} from '../reducers/selectors';
|
||||||
|
import Preview from '../components/Preview';
|
||||||
|
|
||||||
|
class TextEditorAsideContainer extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {currentFile: this.props.currentFile};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.fetchCurrentFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
if(this.props.currentFile.path !== prevProps.currentFile.path) {
|
||||||
|
this.setState({currentFile: this.props.currentFile});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isContract() {
|
||||||
|
return this.state.currentFile.name.endsWith('.sol');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return this.isContract() ? <React.Fragment>hello</React.Fragment> : <Preview />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state, props) {
|
||||||
|
const currentFile = getCurrentFile(state) || props.defaultFile
|
||||||
|
|
||||||
|
return {
|
||||||
|
currentFile,
|
||||||
|
loading: state.loading,
|
||||||
|
error: state.errorMessage
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditorAsideContainer.propTypes = {
|
||||||
|
currentFile: PropTypes.object,
|
||||||
|
fetchCurrentFile: PropTypes.func,
|
||||||
|
loading: PropTypes.bool,
|
||||||
|
error: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
{
|
||||||
|
fetchCurrentFile: currentFileAction.request,
|
||||||
|
},
|
||||||
|
)(TextEditorAsideContainer);
|
|
@ -3,7 +3,6 @@
|
||||||
import React, {Component} from 'react';
|
import React, {Component} from 'react';
|
||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {Grid} from 'tabler-react';
|
|
||||||
import TextEditor from '../components/TextEditor';
|
import TextEditor from '../components/TextEditor';
|
||||||
import TextEditorContractErrors from '../components/TextEditorContractErrors';
|
import TextEditorContractErrors from '../components/TextEditorContractErrors';
|
||||||
import TextEditorContractWarnings from '../components/TextEditorContractWarnings';
|
import TextEditorContractWarnings from '../components/TextEditorContractWarnings';
|
||||||
|
@ -20,8 +19,6 @@ import {
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
import {getCurrentFile, getContractCompile, getContractDeploys} from '../reducers/selectors';
|
import {getCurrentFile, getContractCompile, getContractDeploys} from '../reducers/selectors';
|
||||||
|
|
||||||
const DEFAULT_FILE = {name: 'newContract.sol', content: ''};
|
|
||||||
|
|
||||||
class TextEditorContainer extends Component {
|
class TextEditorContainer extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -62,7 +59,7 @@ class TextEditorContainer extends Component {
|
||||||
|
|
||||||
remove() {
|
remove() {
|
||||||
this.props.removeFile(this.state.currentFile);
|
this.props.removeFile(this.state.currentFile);
|
||||||
this.setState({currentFile: DEFAULT_FILE});
|
this.setState({currentFile: this.props.defaultFile});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderContractFooter() {
|
renderContractFooter() {
|
||||||
|
@ -103,21 +100,15 @@ class TextEditorContainer extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
|
||||||
<Grid.Row className="my-2">
|
|
||||||
{this.renderToolbar()}
|
|
||||||
</Grid.Row>
|
|
||||||
<TextEditor file={this.state.currentFile}
|
<TextEditor file={this.state.currentFile}
|
||||||
contractCompile={this.props.contractCompile}
|
contractCompile={this.props.contractCompile}
|
||||||
onFileContentChange={(newContent) => this.onFileContentChange(newContent)} />
|
onFileContentChange={(newContent) => this.onFileContentChange(newContent)} />
|
||||||
{this.renderContractFooter()}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state, props) {
|
||||||
const currentFile = getCurrentFile(state) || DEFAULT_FILE;
|
const currentFile = getCurrentFile(state) || props.defaultFile;
|
||||||
const contractCompile = getContractCompile(state, currentFile) || {};
|
const contractCompile = getContractCompile(state, currentFile) || {};
|
||||||
const contractName = contractCompile.result && Object.keys(contractCompile.result)[0];
|
const contractName = contractCompile.result && Object.keys(contractCompile.result)[0];
|
||||||
const contractDeploys = getContractDeploys(state, contractName);
|
const contractDeploys = getContractDeploys(state, contractName);
|
||||||
|
|
Loading…
Reference in New Issue