Skip to content

Instantly share code, notes, and snippets.

@maxchehab
Last active December 5, 2017 20:43
Show Gist options
  • Save maxchehab/99bccf2d2f630ae69a94c9f22505a56f to your computer and use it in GitHub Desktop.
Save maxchehab/99bccf2d2f630ae69a94c9f22505a56f to your computer and use it in GitHub Desktop.
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);
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