let storage = new Storage();
class SearchBar extends React.Component {
constructor(props) {
super(props);
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSnapshotToggle = this.handleSnapshotToggle.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleInputChange(event) {
this.props.onSearchInput(event.target.value);
}
handleSnapshotToggle(event) {
this.props.onSnapshotToggle(event);
}
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 'link':
return (
{this.props.message}
)
break;
case 'error':
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 (
)
}
}
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 Prometheus 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: '',
snapshotToggle: false,
messages: [],
appName: null,
apps: storage.getData(),
ws: null,
resourceQuota: {
used: 0,
hard: 0,
}
};
this.handleSearchInput = this.handleSearchInput.bind(this);
this.handleSnapshotToggle = this.handleSnapshotToggle.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});
}
handleSnapshotToggle(event) {
this.setState({snapshotToggle: !this.state.snapshotToggle})
}
handleSearchSubmit(event) {
event.preventDefault();
let query = this.state.searchInput;
if (query.length == 0) {
return;
}
try {
let url = new URL(query);
if (this.state.snapshotToggle) {
url.searchParams.append('altsnap', "true");
}
this.search(url.toString());
} catch (e) {
console.log(e);
}
}
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" || message.action === "error" || message.action === "failure") {
// 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
ws.send(JSON.stringify({"action": "connect"}))
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() {
window.addEventListener("beforeunload", this.onUnload);
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);
}
}
}
onUnload() {
if (this.state.ws) {
console.log("Closing socket");
this.state.ws.close();
}
}
componentWillUnmount() {
window.removeEventListener("beforeunload", this.onUnload);
}
render() {
let messages;
let searchClass;
if (this.state.appName != null) {
messages =
searchClass = null;
} else {
messages = [];
searchClass = 'search-center';
}
return (
);
}
}
ReactDOM.render(
,
document.getElementById('container')
);