Skip to content

Instantly share code, notes, and snippets.

@mattborn
Last active December 18, 2015 20:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattborn/cc3db479098981f9f505 to your computer and use it in GitHub Desktop.
Save mattborn/cc3db479098981f9f505 to your computer and use it in GitHub Desktop.
Command Center Flat Prototype

Flat Markup and Styles

@import "https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css";
* {
box-sizing: border-box;
}
html {
color: #515e5f;
font: 14px/1 "proxima-nova", sans-serif;
font-smoothing: antialiased;
letter-spacing: .02em;
}
body {
margin: 0;
}
/* static */
.CCHead {
height: 90px;
padding: 20px 30px;
}
.CCModule {
color: #c8cccc;
float: left;
height: 50%;
padding: 10px;
position: relative;
text-align: center;
width: calc(100% / 3);
}
.CCModuleBottom {
bottom: 30px;
left: 0;
position: absolute;
width: 100%;
}
.CCModuleCenter {
position: relative;
top: 50%;
transform: translateY(-50%);
}
.CCModuleInset {
background: #f3f4f4;
background-position: center;
background-size: contain;
border: 10px solid rgba(255,255,255,0);
border-radius: 5px;
height: 100%;
padding: 20px 0;
transition: background .5s, border-color .5s;
}
.CCModuleInset .fa {
font-size: 24px;
margin-bottom: 10px;
}
.CCModules {
height: calc(100vh - 90px);
padding: 0 20px 20px;
}
.CCModuleTop {
top: 30px;
left: 0;
position: absolute;
width: 100%;
}
.Clear {
clear: both;
}
.DateTime {
color: #929a9b;
letter-spacing: 1px;
text-transform: uppercase;
}
.LargeNumber {
color: #59cb59;
font-size: 120px;
font-weight: 600;
position: relative;
transition: color .5s;
}
.Left {
float: left;
}
.Persona {
font-size: 40px;
font-weight: 600;
text-transform: uppercase;
}
.Right {
float: right;
}
.SideBySide {
display: inline-block;
padding: 0 40px;
vertical-align: middle;
}
.Smallcaps {
font-size: 13px;
letter-spacing: .1em;
position: relative;
text-transform: uppercase;
}
.SproutLeaf {
background: url(http://resumator.s3.amazonaws.com/customer_20130701155547_HON8RRIUSAA3VYK2/social_icons/20150727193736_sprout-social-leaf-400x400.png) center / cover;
height: 70px;
position: absolute;
right: 10px;
top: 10px;
width: 70px;
}
/* stateful */
.CCModuleLoading {
font-size: 30px !important;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
}
.CCModule .CCModuleCenter,
.CCModule .CCModuleBottom {
opacity: 0;
}
.CCMessages,
.CCResponseTime,
.CCTasks,
.CCTrendingHashtags,
.CCTrendingTopics {
cursor: pointer;
}
.CCTrendingTopics .CCTrendingWord,
.CCTrendingTopics .CCTrendingNumber {
color: #59cb59;
}
.CCTrendingHashtags .CCTrendingWord,
.CCTrendingHashtags .CCTrendingNumber {
color: #0797ae;
}
.CCTrendingRow {
padding: .2em;
white-space: nowrap;
}
.CCTrendingRow .fa {
font-size: 20px;
margin: 0 2px;
}
.CCTrendingWord {
font-size: 40px;
margin-right: 10px;
}
.CCTrendingNumber {
font-size: 50px;
font-weight: bold;
}
.CCResponseTime .CCModuleCenter .fa {
font-size: 40px;
margin-right: 10px;
vertical-align: middle;
}
.CCTasksPriority {
/*display: none;*/
}
.Normal .CCModuleInset {
border-color: #59cb59;
}
.Danger .CCModuleInset {
background: #f04;
border-color: #f04;
color: #fff;
}
.PassiveDanger .LargeNumber {
color: #f04;
}
.Danger .LargeNumber {
color: #fff;
}
.fa-twitter {
color: #55acee;
}
.fa-facebook-official {
color: #3b5998;
}
.fa-instagram {
color: #3f729b;
}
/* chart styles */
.CCVolumeChart {
margin-left: -1em;
position: absolute !important;
top: 50%;
transform: translateY(-50%);
width: calc(100% + 2em);
}
.c3-grid .c3-ygrid {
stroke: #e8eaea;
}
.c3-line {
stroke-width: 10px;
}
/* smaller displays */
@media (max-width: 1700px) {
.LargeNumber { font-size: 60px; }
.CCTrendingRow .fa { font-size: 16px; }
.CCTrendingWord { font-size: 20px; }
.CCTrendingNumber { font-size: 30px; }
.SideBySide { padding: 0 20px; }
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Command Center Flat Prototype</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css">
<link rel="stylesheet" href="global.css">
<script src="https://use.typekit.net/kdf2bga.js"></script>
<script>try{Typekit.load({ async: true });}catch(e){}</script>
</head>
<body>
<div class="CCHead">
<div class="Persona">Customer Care</div>
<div class="DateTime"></div>
<div class="SproutLeaf"></div>
</div>
<div class="CCModules">
<div class="CCModule CCVolume">
<div class="CCModuleInset">
<div class="CCModuleLoading">
<i class="fa fa-refresh fa-spin"></i>
</div>
<div class="CCModuleTop">
<i class="fa fa-bar-chart"></i>
<div class="Smallcaps">Inbound Message Volume</div>
</div>
<div class="CCModuleCenter">
<div class="CCVolumeChart"></div>
<div class="LargeNumber"></div>
<div class="Smallcaps">since 6:00am</div>
</div>
<div class="CCModuleBottom">last updated just now</div>
</div>
</div>
<div class="CCModule CCMessages">
<div class="CCModuleInset">
<div class="CCModuleLoading">
<i class="fa fa-refresh fa-spin"></i>
</div>
<div class="CCModuleTop">
<i class="fa fa-envelope"></i>
<div class="Smallcaps">Messages</div>
</div>
<div class="CCModuleCenter">
<div class="SideBySide">
<div class="LargeNumber">211</div>
<div class="Smallcaps">remaining</div>
</div>
<div class="SideBySide">
<div class="LargeNumber">806</div>
<div class="Smallcaps">completed</div>
</div>
</div>
<div class="CCModuleBottom">last updated just now</div>
</div>
</div>
<div class="CCModule CCTrendingTopics">
<div class="CCModuleLoading">
<i class="fa fa-refresh fa-spin"></i>
</div>
<div class="CCModuleTop">
<div class="Smallcaps">Current Topics</div>
</div>
<div class="CCModuleCenter">
<div class="Table">
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">star wars</span>
<i class="fa fa-twitter"></i>
<i class="fa fa-facebook-official"></i>
<i class="fa fa-instagram"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">18</span>
</div>
<div class="Clear"></div>
</div>
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">costume</span>
<i class="fa fa-twitter"></i>
<i class="fa fa-instagram"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">17</span>
</div>
<div class="Clear"></div>
</div>
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">light saber</span>
<i class="fa fa-facebook-official"></i>
<i class="fa fa-instagram"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">12</span>
</div>
<div class="Clear"></div>
</div>
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">force awakens</span>
<i class="fa fa-twitter"></i>
<i class="fa fa-facebook-official"></i>
<i class="fa fa-instagram"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">5</span>
</div>
<div class="Clear"></div>
</div>
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">tonight</span>
<i class="fa fa-twitter"></i>
<i class="fa fa-facebook-official"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">4</span>
</div>
<div class="Clear"></div>
</div>
</div>
</div>
</div>
<div class="CCModule CCResponseTime">
<div class="CCModuleInset">
<div class="CCModuleLoading">
<i class="fa fa-refresh fa-spin"></i>
</div>
<div class="CCModuleTop">
<i class="fa fa-clock-o"></i>
<div class="Smallcaps">Average Response Time</div>
</div>
<div class="CCModuleCenter">
<div class="SideBySide">
<div class="LargeNumber">40</div>
<div class="Smallcaps">minutes</div>
</div>
<div class="SideBySide">
<div class="LargeNumber"><i class="fa fa-caret-down"></i>0%</div>
<div class="Smallcaps">since last hour</div>
</div>
</div>
<div class="CCModuleBottom">updates every hour</div>
</div>
</div>
<div class="CCModule CCTasks">
<div class="CCModuleInset">
<div class="CCModuleLoading">
<i class="fa fa-refresh fa-spin"></i>
</div>
<div class="CCModuleTop">
<i class="fa fa-thumb-tack"></i>
<div class="Smallcaps">Tasks</div>
</div>
<div class="CCModuleCenter">
<div class="SideBySide">
<div class="LargeNumber">21</div>
<div class="Smallcaps">open</div>
</div>
<div class="SideBySide CCTasksPriority">
<div class="LargeNumber">1</div>
<div class="Smallcaps">high<br>priority</div>
</div>
</div>
<div class="CCModuleBottom">last updated just now</div>
</div>
</div>
<div class="CCModule CCTrendingHashtags">
<div class="CCModuleLoading">
<i class="fa fa-refresh fa-spin"></i>
</div>
<div class="CCModuleTop">
<div class="Smallcaps">Current Hashtags</div>
</div>
<div class="CCModuleCenter">
<div class="Table">
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">#millenniumfalcon</span>
<i class="fa fa-twitter"></i>
<i class="fa fa-facebook-official"></i>
<i class="fa fa-instagram"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">18</span>
</div>
<div class="Clear"></div>
</div>
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">#darthvader</span>
<i class="fa fa-twitter"></i>
<i class="fa fa-instagram"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">17</span>
</div>
<div class="Clear"></div>
</div>
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">#jedi</span>
<i class="fa fa-facebook-official"></i>
<i class="fa fa-instagram"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">12</span>
</div>
<div class="Clear"></div>
</div>
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">#maytheforcebewithyou</span>
<i class="fa fa-twitter"></i>
<i class="fa fa-facebook-official"></i>
<i class="fa fa-instagram"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">5</span>
</div>
<div class="Clear"></div>
</div>
<div class="CCTrendingRow">
<div class="Left">
<span class="CCTrendingWord">#fomo</span>
<i class="fa fa-twitter"></i>
<i class="fa fa-facebook-official"></i>
</div>
<div class="Right">
<span class="CCTrendingNumber">4</span>
</div>
<div class="Clear"></div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="script.js"></script>
</body>
</html>
'use strict';
var response_timer, tasks_timer;
var toggleStyles = {
paddingLeft: 'toggle',
paddingRight: 'toggle',
width: 'toggle',
};
$('.CCModule').each(function (key, el) {
setTimeout(function () {
$(el).find('.CCModuleLoading').fadeOut();
$(el).find('.CCModuleCenter, .CCModuleBottom').animate({
opacity: 1,
});
}, _.random(3000));
});
$('.CCResponseTime').click(function () {
var $this = $(this);
var $number = $(this).find('.LargeNumber:eq(0)');
var current = parseInt($number.text());
var selector = '.CCResponseTime .LargeNumber';
if (current <= 60) {
var above = _.random(30) + 60;
$this.addClass('Danger');
interpolate_number(selector, above);
update_response_percentage(current, above);
response_timer = setTimeout(function () {
$this.removeClass('Danger').addClass('PassiveDanger');
}, 5000);
} else {
var below = _.random(59);
clearTimeout(response_timer);
$this.removeClass('Danger PassiveDanger');
interpolate_number(selector, below);
update_response_percentage(current, below);
goldilocks_pulse($this);
}
});
$('.CCTasks').click(function () {
var $this = $(this);
$this.toggleClass('Danger');
$this.find('.CCTasksPriority').animate(toggleStyles);
if ($this.hasClass('Danger')) {
task_added();
}
});
window.chart = c3.generate({
bindto: '.CCVolumeChart',
data: {
x: 'x',
xFormat: '%S',
columns: [],
colors: {
volume: '#e8eaea',
},
},
axis: {
x: {
show: false,
type: 'timeseries',
tick: {
format: '%S',
},
},
y: {
show: false,
},
},
// grid: {
// y: {
// show: true,
// },
// },
legend: {
show: false,
},
tooltip: {
show: false,
},
size: {
height: 300,
},
});
window.columns = [];
window.data = [[],[]];
window.volume = 0;
(function every_second () {
var now = moment().format('MMMM D, YYYY · h:mm:ss a');
$('.DateTime').text(now);
update_volume_chart();
setTimeout(every_second, 1000);
})();
function every_minute () {
setTimeout(function () {
$('.CCResponseTime').click();
}, _.random(10));
}
setInterval(every_minute, 30000);
var $tasks = $('.CCTasks');
var $inset = $tasks.find('.CCModuleInset');
var $number = $tasks.find('.LargeNumber:eq(0)');
function task_added () {
$number.text(parseInt($number.text()) + 1);
$inset.css({
backgroundImage: 'none',
borderWidth: 10,
});
}
// 1 task is added every 20 seconds
setInterval(task_added, 20000);
function task_completed () {
var tasks = parseInt($number.text());
if (tasks > 0) {
$number.text(tasks - 1);
if (tasks === 1) {
$inset.css({
backgroundImage: 'url(http://i.imgur.com/26ZCou0.gif)',
borderWidth: 0,
});
}
}
if ($tasks.hasClass('Danger')) {
$tasks.click();
}
goldilocks_pulse($tasks);
// at least 1 task is completed every 40 seconds
clearTimeout(tasks_timer);
tasks_timer = setTimeout(task_completed, _.random(40000));
}
// complete first task after 10 seconds
setTimeout(task_completed, 10000);
function goldilocks_pulse ($this) {
$this.addClass('Normal');
setTimeout(function () {
$this.removeClass('Normal');
}, 2000);
}
function update_volume_chart () {
var sawtooth = [0,0,0,0,_.random(5),_.random(20),0,0,_.random(200),_.random(20)];
var posix = moment().format('x');
volume += sawtooth[posix.charAt(9)];
data[0].unshift(parseInt(posix));
data[1].unshift(volume);
columns[0] = data[0].slice(0,20);
columns[0].unshift('x');
columns[1] = data[1].slice(0,20);
columns[1].unshift('volume');
d3.select('.CCVolume .LargeNumber')
.transition()
.duration(1000)
.tween('volume', function () {
var current =+ this.textContent.replace(/,/g, '');
var interpolator = d3.interpolateRound(current, volume);
return function (t) {
this.textContent = d3.format(',')(interpolator(t));
};
});
chart.load({columns: columns});
}
function interpolate_number (selector, value) {
d3.select(selector)
.transition()
.duration(1000)
.tween('interpolate_number', function () {
var current =+ this.textContent;
var interpolator = d3.interpolateRound(current, value);
return function (t) {
this.textContent = interpolator(t);
};
});
}
function update_response_percentage (previous, current) {
var difference = current - previous;
var percentage = Math.round((difference / previous) * 100);
var icon = percentage > 0 ? '<i class="fa fa-caret-up"></i>' : '<i class="fa fa-caret-down"></i>';
$('.CCResponseTime .LargeNumber:eq(1)').html(icon + Math.abs(percentage) + '%');
}
$(function () {
var now = moment().format('h:mm a');
$('.CCVolume .CCModuleCenter .Smallcaps').text('since '+ now);
$('.CCTasksPriority').animate(toggleStyles);
window.CCTasks = $('.CCTasks');
$('.CCTasks').data('updated', moment().format('x'));
});
(function increment_completed () {
var $remaining = $('.CCMessages .LargeNumber:eq(0)');
var $completed = $('.CCMessages .LargeNumber:eq(1)');
$remaining.text(parseInt($remaining.text()) - 1);
$completed.text(parseInt($completed.text()) + 1);
setTimeout(increment_completed, _.random(2000) + 500);
})();
(function increment_remaining () {
var $remaining = $('.CCMessages .LargeNumber:eq(0)');
var increment = parseInt($remaining.text()) + _.random(3);
interpolate_number('.CCMessages .LargeNumber', increment);
setTimeout(increment_remaining, _.random(5000));
})();
document.addEventListener('keydown', function (e) {
if (e.which === 38) {
task_added();
} else if (e.which === 40) {
task_completed();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment