Last active
December 5, 2017 20:43
-
-
Save maxchehab/99bccf2d2f630ae69a94c9f22505a56f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import PropTypes from "prop-types"; | |
import { withStyles } from "material-ui/styles"; | |
import AppBar from "material-ui/AppBar"; | |
import Tabs, { Tab } from "material-ui/Tabs"; | |
import Terminal from "../components/Terminal"; | |
let tabCount = 0; | |
let deleting = false; | |
const styles = theme => ({ | |
root: { | |
flexGrow: 1, | |
width: "100%", | |
backgroundColor: theme.palette.background.paper | |
} | |
}); | |
class ScrollableTabsButtonAuto extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
value: 0, | |
tabs: [], | |
terminals: [] | |
}; | |
} | |
handleChange = (event, value) => { | |
this.setState({ value }); | |
}; | |
newTerminal() { | |
deleting = false; | |
let tabs = this.state.tabs.slice(); | |
let terminals = this.state.terminals.slice(); | |
let key = tabCount; | |
tabs.push( | |
<Tab | |
key={key} | |
onClick={e => { | |
const rect = document | |
.getElementById("icon" + key) | |
.getBoundingClientRect(); | |
if ( | |
e.clientX >= rect.x && | |
e.clientX <= rect.width + rect.x && | |
e.clientY >= rect.y && | |
e.clientY <= rect.y + rect.height | |
) { | |
this.removeTerminal(key); | |
e.preventDefault(); | |
} | |
}} | |
style={{ height: 48 }} | |
value={key} | |
label="Terminal" | |
icon={ | |
<div> | |
<i | |
id={"icon" + key} | |
style={{ | |
display: "none", | |
right: 5, | |
position: "absolute", | |
bottom: 14, | |
fontSize: 20 | |
}} | |
className="material-icons" | |
> | |
close | |
</i> | |
</div> | |
} | |
/> | |
); | |
terminals.push( | |
<Terminal key={key} enabled={this.state.value == key} value={key} /> | |
); | |
this.setState({ | |
tabs: tabs, | |
terminals: terminals, | |
value: key | |
}); | |
tabCount++; | |
} | |
removeTerminal(id) { | |
console.log(id); | |
deleting = true; | |
let tabs = this.state.tabs.slice(); | |
let terminals = this.state.terminals.slice(); | |
let index = 0; | |
let lastValue = -1; | |
for (let tab of tabs) { | |
if (tab.props.value == id) { | |
break; | |
} | |
lastValue = tab.props.value; | |
index++; | |
} | |
tabs.splice(index, 1); | |
terminals.slice(index, 1); | |
this.setState({ | |
tabs: tabs, | |
terminals: terminals, | |
value: id == this.state.value ? lastValue : this.state.value | |
}); | |
} | |
render() { | |
const { value } = this.state; | |
console.log(value); | |
return ( | |
<div> | |
<button onClick={() => this.newTerminal()}>new terminal</button> | |
<style global jsx>{` | |
.terminal-cursor { | |
background-color: white; | |
} | |
body { | |
margin: 0; | |
} | |
.docker-browser-console { | |
font-family: monospace; | |
background-color: black; | |
} | |
button:hover .material-icons { | |
display: block !important; | |
} | |
`}</style> | |
<link | |
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500|Material+Icons" | |
rel="stylesheet" | |
/> | |
<AppBar position="static" color="default"> | |
<Tabs | |
value={value} | |
onChange={this.handleChange} | |
indicatorColor="primary" | |
textColor="primary" | |
scrollable | |
scrollButtons="auto" | |
> | |
{this.state.tabs} | |
</Tabs> | |
</AppBar> | |
{this.state.terminals} | |
</div> | |
); | |
} | |
} | |
ScrollableTabsButtonAuto.propTypes = { | |
classes: PropTypes.object.isRequired | |
}; | |
export default withStyles(styles)(ScrollableTabsButtonAuto); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import docker from "docker-browser-console"; | |
import websocket from "websocket-stream"; | |
export default class Terminal extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
width: "0", | |
height: "0" | |
}; | |
this.updateWindowDimensions = this.updateWindowDimensions.bind(this); | |
} | |
componentWillUnmount() { | |
window.removeEventListener("resize", this.updateWindowDimensions); | |
} | |
updateWindowDimensions() { | |
this.setState({ width: window.innerWidth, height: window.innerHeight }); | |
} | |
componentDidMount() { | |
this.updateWindowDimensions(); | |
window.addEventListener("resize", this.updateWindowDimensions); | |
// create a stream for any docker image | |
// use docker({style:false}) to disable default styling | |
// all other options are forwarded to the term.js instance | |
let terminal = docker(); | |
// connect to a docker-browser-console server | |
terminal.pipe(websocket("ws://localhost:8080")).pipe(terminal); | |
// append the terminal to a DOM element | |
terminal.appendTo(this.refs.container); | |
let event = document.createEvent("HTMLEvents"); | |
event.initEvent("resize", true, false); | |
window.dispatchEvent(event); | |
} | |
render() { | |
console.log(this.props.value + ": " + this.props.enabled); | |
return ( | |
<div | |
style={{ | |
height: this.props.enabled ? "auto" : "0", | |
overflow: "hidden" | |
}} | |
> | |
<div | |
style={{ | |
height: this.state.height - 48 | |
}} | |
className={"docker-browser-console"} | |
ref={"container"} | |
/> | |
</div> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment