let storage = new Storage(); class SearchBar extends React.Component { constructor(props) { super(props); this.handleInputChange = this.handleInputChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleInputChange(event) { this.props.onSearchInput(event.target.value); } handleSubmit(event) { this.props.onSearchSubmit(event); } render() { let btn = Generate if (this.props != null && this.props.appName != null) { btn = } return ( {btn} ); } } class DeleteAppButton extends React.Component { render() { return ( Delete {this.props.appName} ) } } class Message extends React.Component { render() { var variants = { "status": "info", "progress": "info", "failure": "danger", "done": "success" } switch (this.props.action) { case 'done': case 'failure': case 'status': return ( {this.props.message} ) break; case 'progress': return ( {this.props.message} ) break; case 'choose': const items = JSON.parse(this.props.message); return ( Choose a Dump

Multiple cluster dumps were found, please pick one:


{items.map((item, index) => { let url = new URL(window.location.href); url.searchParams.set('search', item); return (

{item}

) })}
) case 'kubeconfig': var encodedKubeconfig = "data:text/yaml;charset=utf-8;base64,"+ btoa(this.props.message); return ( Kubeconfig Download kubeconfig
{this.props.message}
) break; case 'link': return ( {this.props.message} ) break; default: return ( ) } } } class ResourceQuotaStatus extends React.Component { render() { if (this.props === null || this.props.resourceQuota === null) { return ( ) } let used = this.props.resourceQuota.used; let hard = this.props.resourceQuota.hard; if (typeof used == "undefined" || typeof hard == "undefined") { return ( ) } return (
Current resource quota
) } } class Status extends React.Component { render() { if (this.props.messages.length == 0) { return ( ); } else { return(
{ this.props.messages.map(item => ) }
); } } } class AppsList extends React.Component { render() { let appCount = Object.keys(this.props.apps).length; if (appCount === 0) { return false; } let header =

Currently running KAS instances

let apps = Object.keys(this.props.apps).map(k => { return ( {k} { this.props.onDeleteApp(k) }} appName={k} /> ) }) return
{header} {apps}
} } class SearchForm extends React.Component { constructor(props) { super(props); this.state = { querySearch: '', searchInput: '', messages: [], appName: null, apps: storage.getData(), ws: null, resourceQuota: { used: 0, hard: 0, } }; this.handleSearchInput = this.handleSearchInput.bind(this); this.handleSearchSubmit = this.handleSearchSubmit.bind(this); this.handleDeleteAppInternal = this.handleDeleteAppInternal.bind(this); this.handleDeleteApp = this.handleDeleteApp.bind(this); this.handleDeleteCurrentApp = this.handleDeleteCurrentApp.bind(this); this.addMessage = this.addMessage.bind(this); this.sendWSMessage = this.sendWSMessage.bind(this); this.connect = this.connect.bind(this); this.check = this.check.bind(this); this.search = this.search.bind(this); } handleSearchInput(searchInput) { this.setState({searchInput: searchInput}); } handleSearchSubmit(event) { event.preventDefault(); if (this.state.searchInput.length == 0) { return; } this.search(this.state.searchInput); } sendWSMessage(message) { // add messages to queue if connection is not ready if (!this.state.ws || this.state.ws.readyState != WebSocket.OPEN) { if (this.state.ws) { console.log("ws.readyState " + this.state.ws.readyState); } if (!this.ws_msgs) this.ws_msgs = [] console.log("Added message " + message + " to queue"); this.ws_msgs.push(message) } else { console.log("Sending message " + message); this.state.ws.send(message) } } search(input) { try { this.state.messages = []; this.sendWSMessage(JSON.stringify({ 'action': 'new', 'message': input, })); } catch (error) { console.log(error); } } handleDeleteApp(appName) { console.log(appName) if (this.state.appName === appName) { this.handleDeleteCurrentApp() } else { this.handleDeleteAppInternal(appName) } } handleDeleteCurrentApp() { this.handleDeleteAppInternal(this.state.appName) // Remove message with app-label from the list let newMessages = this.state.messages.slice(1, this.state.messages.length) this.setState(state => ({ messages: newMessages, appName: null, })) } handleDeleteAppInternal(appName) { try { this.sendWSMessage(JSON.stringify({ 'action': 'delete', 'message': appName })) storage.removeInstance(appName) this.setState(state => ({ apps: storage.getData(), })) } catch (error) { console.log(error) } } addMessage(message) { this.setState(state => ({ messages: [...state.messages, message] })) if (message.action === "app-label") { this.setState(state => ({appName: message.message})) } if (message.action === "done") { // Remove message with progress from the list let newMessages = this.state.messages.filter(function(message){ return message.action != "progress"; }); this.setState(state => ({ messages: newMessages })) if (message.data != null) { storage.addInstance(message.data.hash, message.data.url) } this.setState(state => ({apps: storage.getData()})) } if (message.action === "rquota") { let rquotaStatus = JSON.parse(message.message) this.setState(state => ({ resourceQuota: { used: rquotaStatus.used, hard: rquotaStatus.hard, } })) } } check () { const { ws } = this.state; if (!ws || ws.readyState == WebSocket.CLOSED) this.connect(); //check if websocket instance is closed, if so call `connect` function. }; connect () { var loc = window.location; var ws_uri; if (loc.protocol === "https:") { ws_uri = "wss:"; } else { ws_uri = "ws:"; } ws_uri += "//" + loc.host; ws_uri += "/ws/status"; var ws = new WebSocket(ws_uri); let that = this; var connectInterval; // websocket onopen event listener ws.onopen = () => { console.log("websocket connected"); that.setState({ ws: ws }); that.timeout = 250; // reset timer to 250 on open of websocket connection clearTimeout(connectInterval); // clear Interval on on open of websocket connection // Send messages if there's a queue while (that.ws_msgs && that.ws_msgs.length > 0) { ws.send(that.ws_msgs.pop()) } }; // websocket onclose event listener ws.onclose = e => { console.log( `Socket is closed. Reconnect will be attempted in ${Math.min( 10000 / 1000, (that.timeout + that.timeout) / 1000 )} second.`, e.reason ); that.timeout = that.timeout + that.timeout; //increment retry interval connectInterval = setTimeout(this.check, Math.min(10000, that.timeout)); //call check function after timeout }; // websocket onerror event listener ws.onerror = err => { console.error( "Socket encountered error: ", err.message, "Closing socket" ); ws.close(); }; ws.onmessage = evt => { console.log("Received " + evt.data); const message = JSON.parse(evt.data); this.addMessage(message) } this.setState({ ws: ws }); } componentDidMount() { this.check(); this.timeout = 0; if (!this.state.searchInput) { let params = (new URL(window.location)).searchParams; let searchInput = params.get('search'); if (searchInput && searchInput != this.state.querySearch) { this.state.querySearch = searchInput; this.handleSearchInput(searchInput); this.search(searchInput); } } } render() { let messages; let searchClass; if(this.state.appName != null) { messages = searchClass = null; } else { messages = []; searchClass = 'search-center'; } return (

KAS as a service


{messages}
); } } ReactDOM.render( , document.getElementById('container') );