Skip to content

Commit

Permalink
feat(cockpit): make editor resizable
Browse files Browse the repository at this point in the history
  • Loading branch information
jrainville committed Nov 8, 2018
1 parent a714e07 commit 1030607
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 28 deletions.
5 changes: 5 additions & 0 deletions embark-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions embark-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"prop-types": "^15.6.2",
"qs": "^6.5.2",
"raf": "3.4.0",
"re-resizable": "^4.9.3",
"react": "^16.4.2",
"react-blockies": "^1.4.0",
"react-bootstrap-typeahead": "^3.2.4",
Expand Down
5 changes: 3 additions & 2 deletions embark-ui/src/components/FileExplorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const style = (theme) => ({
top: 0,
bottom: '40px',
left: 0,
right: 0
right: 0,
minWidth: '175px'
},
node: {
base: {
Expand Down Expand Up @@ -214,7 +215,7 @@ class FileExplorer extends React.Component {
style={style(this.props.theme)}
/>

<Label className="hidden-toogle mb-0 pt-2 pr-2 pb-1 border-top text-right">
<Label className="hidden-toggle mb-0 pt-2 pr-2 pb-1 border-top text-right">
<span className="mr-2 align-top" style={{"fontSize": "12px"}}>Show hidden files</span>
<AppSwitch color="success" variant="pill" size="sm" onChange={this.props.toggleShowHiddenFiles}/>
</Label>
Expand Down
10 changes: 9 additions & 1 deletion embark-ui/src/components/TextEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class TextEditor extends React.Component {
});
}

componentWillUnmount() {
window.removeEventListener("resize", this.handleResize);
}

handleResize = () => editor.layout();


Expand Down Expand Up @@ -134,6 +138,10 @@ class TextEditor extends React.Component {
this.handleResize();
}

addEditorTabs(e, file) {
e.preventDefault(); this.props.addEditorTabs(file);
}

renderTabs() {
return (
<ul className="list-inline m-0 p-0">
Expand All @@ -144,7 +152,7 @@ class TextEditor extends React.Component {
})}>
<a
href="#switch-tab"
onClick={() => this.props.addEditorTabs(file)}
onClick={(e) => this.addEditorTabs(e, file)}
className="p-2 text-muted"
>
{file.name}
Expand Down
4 changes: 4 additions & 0 deletions embark-ui/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ export const DEPLOYMENT_PIPELINES = {
embark: 'embark'
};
export const DEFAULT_HOST = process.env.NODE_ENV === 'development' ? 'localhost:8000' : window.location.host;
export const OPERATIONS = {
MORE: 1,
LESS: -1
};
13 changes: 9 additions & 4 deletions embark-ui/src/containers/EditorContainer.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
margin-top: -1.5rem !important;
}

.hidden-toogle {
.hidden-toggle {
position: absolute;
bottom: 0;
right: 0;
left: 0;
height: 40px;
}

.text-editor__debuggerLine {
Expand All @@ -34,8 +35,12 @@
.editor-aside {
position: relative;
}
}

.aside-opened .text-editor-container {
max-height: 500px;
}
.resizer-handle {
width: 15px !important;
}

.resize-handle-horizontal {
height: 15px !important;
}
144 changes: 126 additions & 18 deletions embark-ui/src/containers/EditorContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,51 @@ import TextEditorToolbarContainer from './TextEditorToolbarContainer';
import {fetchEditorTabs as fetchEditorTabsAction} from '../actions';
import {getCurrentFile} from '../reducers/selectors';
import classnames from 'classnames';
import Resizable from 're-resizable';
import {OPERATIONS} from '../constants';

import './EditorContainer.css';

class EditorContainer extends React.Component {
constructor(props) {
super(props);
this.state = {currentAsideTab: {}, showHiddenFiles: false, currentFile: this.props.currentFile};
this.DEFAULT_EDITOR_WIDTH = 85;
this.DEFAULT_EDITOR_WIDTH_SMALL = 75;
this.DEFAULT_HEIGHT = 500;
this.SMALL_SIZE = 768;
this.windowWidth = window.innerWidth;

this.state = {
currentAsideTab: {}, showHiddenFiles: false, currentFile: this.props.currentFile,
editorHeight: this.DEFAULT_HEIGHT,
editorWidth: ((this.windowWidth < this.SMALL_SIZE) ? this.DEFAULT_EDITOR_WIDTH_SMALL : this.DEFAULT_EDITOR_WIDTH) + '%',
asideHeight: '100%', asideWidth: '25%',
isSmallSize: (this.windowWidth < this.SMALL_SIZE)
};
}

componentDidMount() {
this.props.fetchEditorTabs();
window.addEventListener("resize", this.updateDimensions.bind(this));
}

componentWillUnmount() {
window.removeEventListener("resize", this.updateDimensions.bind(this));
}

updateDimensions() {
this.windowWidth = window.innerWidth;

const isSmallSize = (this.windowWidth < this.SMALL_SIZE);
if (this.state.isSmallSize !== isSmallSize) {
this.setState({isSmallSize});
this.changeEditorWidth(isSmallSize ? OPERATIONS.MORE : OPERATIONS.LESS);
this.editor.handleResize();
}
}

componentDidUpdate(prevProps) {
if(this.props.currentFile.path !== prevProps.currentFile.path) {
if (this.props.currentFile.path !== prevProps.currentFile.path) {
this.setState({currentFile: this.props.currentFile});
}
}
Expand All @@ -43,38 +73,116 @@ class EditorContainer extends React.Component {
}

openAsideTab(newTab) {
if (!this.state.isSmallSize) {
this.changeEditorWidth((!this.state.currentAsideTab.label) ? OPERATIONS.LESS : OPERATIONS.MORE);
}
if (newTab.label === this.state.currentAsideTab.label) {
this.editor.handleResize();
return this.setState({currentAsideTab: {}});
}

this.setState({currentAsideTab: newTab});
}

textEditorMdSize() {
return this.state.currentAsideTab.label ? 7 : 10;
changeEditorWidth(operation) {
this.setState({
editorWidth: (parseFloat(this.state.editorWidth) + (operation * parseFloat(this.state.asideWidth))) + '%'
});
}

renderTextEditor() {
const height = !!(this.state.isSmallSize && this.state.currentAsideTab.label) ? this.state.editorHeight : 'auto';
return (
<Resizable
size={{width: this.state.editorWidth, height: height}}
minWidth="20%" maxWidth="90%"
handleClasses={{left: 'resizer-handle', right: 'resizer-handle', bottom: 'resize-handle-horizontal'}}
onResizeStop={(e, direction, ref, d) => {
this.setState({
editorWidth: ref.style.width,
editorHeight: this.state.editorHeight + d.height
});
this.editor.handleResize();
}}
className="text-editor-container border-left"
enable={{
top: false,
right: false,
bottom: !!(this.state.isSmallSize && this.state.currentAsideTab.label),
left: true,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false
}}>
<TextEditorContainer
ref={instance => {
this.editor = instance ? instance.getWrappedInstance().editor : null;
}}
currentFile={this.props.currentFile}
onFileContentChange={(newContent) => this.onFileContentChange(newContent)}/>
</Resizable>
);
}

renderAside() {
const aside = (
<div className="editor-aside">
<TextEditorAsideContainer currentAsideTab={this.state.currentAsideTab}
currentFile={this.props.currentFile}/>
</div>
);

if (this.windowWidth < this.SMALL_SIZE) {
return (<Col sm={12} className="border-left-0 relative">
{aside}
</Col>);
}

return (
<Resizable defaultSize={{width: this.state.asideWidth, height: 'auto'}}
maxWidth='60%' minWidth='17%'
handleClasses={{left: 'resizer-handle', right: 'resizer-handle'}}
className="border-left-0 relative"
enable={{
top: false,
right: false,
bottom: false,
left: true,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false
}}
onResize={(e, direction, ref, _d) => {
this.setState({
editorWidth: this.DEFAULT_EDITOR_WIDTH - parseFloat(ref.style.width) + '%'
});
}}>
{aside}
</Resizable>
);
}

render() {
return (
<Row noGutters className={classnames('h-100', 'editor--grid', {'aside-opened': this.state.currentAsideTab.label})}>
<Row noGutters
className={classnames('h-100', 'editor--grid', {'aside-opened': this.state.currentAsideTab.label})}>
<Col xs={12}>
<TextEditorToolbarContainer openAsideTab={(newTab) => this.openAsideTab(newTab)}
isContract={this.isContract()}
currentFile={this.props.currentFile}
activeTab={this.state.currentAsideTab}/>
</Col>
<Col sm={4} md={2} xl={2} lg={2} className="border-right">
<FileExplorerContainer showHiddenFiles={this.state.showHiddenFiles} toggleShowHiddenFiles={() => this.toggleShowHiddenFiles()} />
</Col>
<Col sm={8} md={this.textEditorMdSize()} className="text-editor-container">
<TextEditorContainer currentFile={this.props.currentFile} onFileContentChange={(newContent) => this.onFileContentChange(newContent)} />

<Col className="border-right">
<FileExplorerContainer showHiddenFiles={this.state.showHiddenFiles}
toggleShowHiddenFiles={() => this.toggleShowHiddenFiles()}/>
</Col>
{this.state.currentAsideTab.label &&
<Col sm={12} md={3} className="border-left-0 relative">
<div className="editor-aside">
<TextEditorAsideContainer currentAsideTab={this.state.currentAsideTab}
currentFile={this.props.currentFile}/>
</div>
</Col>}

{this.renderTextEditor()}

{this.state.currentAsideTab.label && this.renderAside()}
</Row>
);
}
Expand All @@ -95,6 +203,6 @@ EditorContainer.propTypes = {

export default connect(
mapStateToProps,
{fetchEditorTabs: fetchEditorTabsAction.request},
{fetchEditorTabs: fetchEditorTabsAction.request}
)(EditorContainer);

11 changes: 8 additions & 3 deletions embark-ui/src/containers/TextEditorContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ class TextEditorContainer extends React.Component {
addEditorTabs={this.props.addEditorTabs}
debuggerLine={this.props.debuggerLine}
onFileContentChange={this.props.onFileContentChange}
theme={this.props.theme} />
theme={this.props.theme}
ref={instance => {
if (instance) this.editor = instance;
}}/>
);
}
}
Expand All @@ -45,7 +48,7 @@ TextEditorContainer.propTypes = {
onFileContentChange: PropTypes.func,
toggleBreakpoints: PropTypes.func,
breakpoints: PropTypes.array,
toggleBreakpoint: PropTypes.object,
toggleBreakpoint: PropTypes.func,
fetchEditorTabs: PropTypes.func,
removeEditorTabs: PropTypes.func,
addEditorTabs: PropTypes.func,
Expand All @@ -57,9 +60,11 @@ TextEditorContainer.propTypes = {
export default connect(
mapStateToProps,
{
toggleBreakpoint,
toggleBreakpoint: toggleBreakpoint.request,
fetchEditorTabs: fetchEditorTabsAction.request,
removeEditorTabs: removeEditorTabsAction.request,
addEditorTabs: addEditorTabsAction.request
},
null,
{ withRef: true }
)(TextEditorContainer);

0 comments on commit 1030607

Please sign in to comment.