in server/src/main/scala/com/twitter/server/view/IndexView.scala [37:128]
def render(title: String, uri: String, nav: Seq[Entry], contents: Reader[Buf]): Reader[Buf] = {
def renderNav(ls: Seq[Entry], sb: StringBuilder = new StringBuilder): String = ls match {
case Seq() => sb.toString
case Link(id, href, Post) +: rest =>
// Spaces are replaced with '-' since HTML IDs do not permit whitespace
val formattedId = id.replace(' ', '-')
val selected = if (href == uri) "selected" else ""
sb ++= s"""
<form method="post" id="${formattedId}-form" action="${href}">
<a href="#" onclick="document.getElementById('${formattedId}-form').submit()">
<li id="${formattedId}" class="selectable $selected">
${id}
</li>
</a>
</form>
"""
renderNav(rest, sb)
case Link(id, href, Get) +: rest =>
// Spaces are replaced with '-' since HTML IDs do not permit whitespace
val formattedId = id.replace(' ', '-')
val selected = if (href == uri) "selected" else ""
sb ++= s"""
<a href="${href}">
<li id="${formattedId}" class="selectable $selected">
${escapeHtml(id)}
</li>
</a>
"""
renderNav(rest, sb)
case Group(id, links) +: rest =>
val isChild = links exists {
// Instead of strictly checking for href == uri,
// we are a bit more liberal to allow for "catch-all"
// endpoints (ex. /admin/clients/).
case Link(_, href, _) => !href.stripPrefix(uri).contains("/")
case _ => false
}
val active = if (isChild) "active" else ""
val collapse = if (isChild) "glyphicon-collapse-up" else ""
sb ++= s"""
<li class="subnav $active">
<div class="subnav-title selectable">
<span class="glyphicon glyphicon-expand $collapse"></span>
<span>${escapeHtml(id)}</span>
</div>
<ul>${renderNav(links)}</ul>
</li>"""
renderNav(rest, sb)
}
Reader.concat(
Reader.fromBuf(
Buf.Utf8(
s"""<!DOCTYPE html>
<html>
<head>
<title>${title} · Twitter Server Admin</title>
<!-- css -->
<link type="text/css" href="/admin/files/css/bootstrap.min.css" rel="stylesheet"/>
<link type="text/css" href="/admin/files/css/index.css" rel="stylesheet"/>
<link type="text/css" href="/admin/files/css/client-registry.css" rel="stylesheet"/>
<!-- js -->
<script type="application/javascript" src="//www.google.com/jsapi"></script>
<script type="application/javascript" src="/admin/files/js/jquery.min.js"></script>
<script type="application/javascript" src="/admin/files/js/bootstrap.min.js"></script>
<script type="application/javascript" src="/admin/files/js/index.js"></script>
<script type="application/javascript" src="/admin/files/js/utils.js"></script>
</head>
<body>
<div id="wrapper">
<nav id="sidebar">
<ul>${renderNav(nav)}</ul>
</nav>
<div id="toggle"><span class="glyphicon glyphicon-chevron-left"></span></div>
<div id="contents" class="container-fluid">
<div class="row">
<div class="col-md-12">"""
)
)
+:: contents
+:: AsyncStream.of(Reader.fromBuf(Buf.Utf8("""</div>
</div>
</div>
</div>
</body>
</html>""")))
)
}