resources/live/index.html
<!DOCTYPE html>
<html>
<head>
<title>🔥 Rung CLI Hot Server</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<script type="text/javascript" src="./socket.io.slim.js"></script>
<link rel="stylesheet" type="text/css" href="./live.css" />
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
</head>
<body>
<div id="rung-bar">
<img src="./rung-logo.png" draggable="false" id="logo" />
</div>
<div id="rung-alerts"></div>
<div id="rung-timeline">
<button id="rung-timeline-prev" disabled class="rung-timeline-button"><</button>
<div id="rung-timeline-count" title="Time travel">0/0</div>
<button id="rung-timeline-next" disabled class="rung-timeline-button">></button>
</div>
<div id="rung-loading">
<div class="double-bounce-1"></div>
<div class="double-bounce-2"></div>
</div>
<div id="sidebar">
<div id="sidebar-header">
<div id="sidebar-group-name">Rung Developers</div>
<div id="sidebar-card-name"></div>
</div>
<div id="sidebar-body">
<div class="fake-field">
<div class="fake-indicator"></div>
<div class="fake-value"></div>
</div>
<div class="fake-field">
<div class="fake-indicator"></div>
<div class="fake-value"></div>
</div>
<div class="fake-field">
<div class="fake-indicator"></div>
<div class="fake-value"></div>
</div>
<div class="fake-field">
<div class="fake-indicator"></div>
<div class="fake-value"></div>
</div>
<div id="markdown-box" class="custom-scrollbar">
<div id="markdown-robot"></div>
<div id="markdown-content">
<div id="sidebar-comment"></div>
<div id="markdown-resources"></div>
</div>
</div>
</div>
<div id="sidebar-comment-box">
<div id="sidebar-comment-input"></div>
<div id="sidebar-send-button"></div>
</div>
</div>
<div id="rung-error"></div>
</body>
<script type="text/javascript">
const timeline = [];
const DOM = {
sidebarComment: document.querySelector('#sidebar-comment'),
markdownResources: document.querySelector('#markdown-resources'),
sidebarCardName: document.querySelector('#sidebar-card-name'),
rungAlerts: document.querySelector('#rung-alerts'),
loading: document.querySelector('#rung-loading'),
error: document.querySelector('#rung-error'),
timelinePrev: document.querySelector('#rung-timeline-prev'),
timelineNext: document.querySelector('#rung-timeline-next'),
timelineCount: document.querySelector('#rung-timeline-count')
};
function openInSidebar(alert) {
DOM.sidebarComment.innerHTML = alert.comment;
DOM.markdownResources.innerHTML = (alert.resources || []).map(resource =>
`<img src="${resource}" draggable="false">`
).join('');
DOM.sidebarCardName.innerText = alert.title;
}
function render(alerts) {
DOM.error.style.display = 'none';
DOM.rungAlerts.innerHTML = '';
DOM.loading.style.opacity = 0;
const indexes = Object.keys(alerts);
const [first] = indexes;
openInSidebar(alerts[first] || { title: '', comment: '' });
indexes.forEach(index => {
const alert = alerts[index];
const card = document.createElement('div');
card.className = 'card custom-scrollbar';
card.innerHTML = alert.content;
card.onclick = () => openInSidebar(alert);
DOM.rungAlerts.appendChild(card);
});
}
function updateTimeline() {
const { peek } = timeline;
DOM.timelineCount.innerText = `${peek}/${timeline.length}`;
if (peek === 1) {
DOM.timelinePrev.setAttribute('disabled', true);
} else {
DOM.timelinePrev.removeAttribute('disabled');
}
if (peek >= timeline.length) {
DOM.timelineNext.setAttribute('disabled', true);
} else {
DOM.timelineNext.removeAttribute('disabled');
}
}
const timeTravel = functor => () => {
const { peek } = timeline;
const nextState = functor(peek);
timeline.peek = nextState;
updateTimeline();
render(timeline[nextState - 1]);
};
DOM.timelinePrev.onclick = timeTravel(time => time - 1);
DOM.timelineNext.onclick = timeTravel(time => time + 1);
const socket = io.connect(location.origin);
socket.on('update', alerts => {
timeline.push(alerts);
timeline.peek = timeline.length;
render(alerts);
updateTimeline();
});
socket.on('load', () => {
DOM.loading.style.opacity = 1;
});
socket.on('failure', error => {
DOM.loading.style.opacity = 0;
DOM.error.style.display = 'block';
DOM.error.innerText = error;
});
</script>
</html>