Skip to content

Commit 62ad55c

Browse files
Merge pull request #39 from OneBusAway/reports
Redesign reports page with secondary sidebar and Tailwind forms
2 parents 628400f + ce940d8 commit 62ad55c

41 files changed

Lines changed: 705 additions & 1165 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<%@ tag pageEncoding="UTF-8" %>
2+
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
3+
<%@ attribute name="title" required="true" %>
4+
<%@ attribute name="message" required="false" %>
5+
<div class="flex h-full items-center justify-center px-6 py-24">
6+
<div class="text-center max-w-sm">
7+
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24"
8+
stroke-width="1.5" stroke="currentColor" aria-hidden="true">
9+
<path stroke-linecap="round" stroke-linejoin="round"
10+
d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"/>
11+
</svg>
12+
<h3 class="mt-4 text-base font-semibold text-gray-900">${title}</h3>
13+
<c:if test="${not empty message}">
14+
<p class="mt-1 text-sm text-gray-500">${message}</p>
15+
</c:if>
16+
</div>
17+
</div>

transitclockWebapp/src/main/webapp/WEB-INF/tags/layout.tag

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<%@ tag pageEncoding="UTF-8" import="org.transitclock.db.webstructs.WebAgency" %>
22
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
33
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
4+
<%@ taglib prefix="fn" uri="jakarta.tags.functions" %>
45
<%@ attribute name="title" required="false" %>
56
<%@ attribute name="head" fragment="true" required="false" %>
67
<%-- bare="true" skips the default p-8 padding wrapper around the body — for
@@ -20,8 +21,10 @@
2021
<c:set var="onMapFor" value="${path == '/maps/map.jsp' and not showUnassigned}"/>
2122
<c:set var="onMapIncl" value="${path == '/maps/map.jsp' and showUnassigned}"/>
2223
<c:set var="onSchAdhMap" value="${path == '/maps/schAdhMap.jsp'}"/>
23-
<c:set var="onReports" value="${path == '/reports/index.jsp'}"/>
24-
<c:set var="onApi" value="${path == '/reports/apiCalls/index.jsp'}"/>
24+
<c:set var="onApi" value="${fn:startsWith(path, '/reports/apiCalls/')}"/>
25+
<%-- Any /reports/* page (except the API calls section) keeps the
26+
Reports nav highlighted so subpages don't appear unrooted. --%>
27+
<c:set var="onReports" value="${fn:startsWith(path, '/reports/') and not onApi}"/>
2528
<c:set var="onActiveBlocks" value="${path == '/status/activeBlocks.jsp'}"/>
2629
<c:set var="onServerStatus" value="${path == '/status/serverStatus.jsp'}"/>
2730
<c:set var="onDbDiskSpace" value="${path == '/status/dbDiskSpace.jsp'}"/>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<%@ tag pageEncoding="UTF-8" %>
2+
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
3+
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
4+
<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
5+
<%@ attribute name="title" required="false" %>
6+
<%@ attribute name="head" fragment="true" required="false" %>
7+
<%-- bare="true" so the inner sidebar+content flex container can fill
8+
the main pane itself; the default p-8 wrapper would double-pad. --%>
9+
<t:layout title="${title}" bare="true">
10+
<jsp:attribute name="head">
11+
<jsp:invoke fragment="head"/>
12+
</jsp:attribute>
13+
<jsp:body>
14+
<div class="flex h-full">
15+
<t:reportsSidebar/>
16+
<div class="flex-1 overflow-y-auto">
17+
<jsp:doBody/>
18+
</div>
19+
</div>
20+
</jsp:body>
21+
</t:layout>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<%@ tag pageEncoding="UTF-8" %>
2+
<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
3+
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
4+
<%@ attribute name="title" required="false" %>
5+
<%@ attribute name="heading" required="true" %>
6+
<%@ attribute name="action" required="true" %>
7+
<%@ attribute name="select2" required="false" type="java.lang.Boolean" %>
8+
<%@ attribute name="head" fragment="true" required="false" %>
9+
<c:set var="useSelect2" value="${select2 ne false}"/>
10+
<c:set var="effectiveTitle" value="${empty title ? heading : title}"/>
11+
<t:reportsLayout title="${effectiveTitle}">
12+
<jsp:attribute name="head">
13+
<c:if test="${useSelect2}">
14+
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet"/>
15+
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
16+
</c:if>
17+
<jsp:invoke fragment="head"/>
18+
</jsp:attribute>
19+
<jsp:body>
20+
<header class="border-b border-gray-200 px-6 py-4">
21+
<h1 class="text-xl font-semibold text-gray-900">${heading}</h1>
22+
</header>
23+
<div class="px-6 py-6">
24+
<form action="${action}" method="POST" class="max-w-2xl space-y-5">
25+
<input type="hidden" name="a" value="${param.a}">
26+
<jsp:doBody/>
27+
</form>
28+
</div>
29+
</jsp:body>
30+
</t:reportsLayout>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<%@ tag pageEncoding="UTF-8" %>
2+
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
3+
<%@ taglib prefix="fmt" uri="jakarta.tags.fmt" %>
4+
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
5+
<c:set var="qs" value="?a=${param.a}"/>
6+
<c:set var="path" value="${pageContext.request.servletPath}"/>
7+
<c:set var="active" value="bg-indigo-50 text-indigo-700 font-medium"/>
8+
<c:set var="inactive" value="text-gray-700 hover:bg-gray-100 hover:text-gray-900"/>
9+
<aside class="hidden md:flex md:flex-col w-64 lg:w-72 shrink-0 border-r border-gray-200 bg-gray-50">
10+
<div class="px-5 py-4 border-b border-gray-200">
11+
<h2 class="text-base font-semibold text-gray-900">Reports</h2>
12+
</div>
13+
<nav class="flex-1 overflow-y-auto px-3 py-4 space-y-6">
14+
<div>
15+
<h3 class="px-2 mb-1 text-xs font-semibold text-gray-500 uppercase tracking-wider"><fmt:message key="div.pa"/></h3>
16+
<ul class="space-y-0.5">
17+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/predAccuracyRangeParams.jsp' ? active : inactive}" href="${ctx}/reports/predAccuracyRangeParams.jsp${qs}" title="Shows percentage of predictions that were accurate to within the specified limits."><fmt:message key="div.prediction"/></a></li>
18+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/predAccuracyIntervalsParams.jsp' ? active : inactive}" href="${ctx}/reports/predAccuracyIntervalsParams.jsp${qs}" title="Shows average prediction accuracy for each prediction length, with upper and lower bounds."><fmt:message key="div.PredictionAccuracyIntervalChart"/></a></li>
19+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/predAccuracyScatterParams.jsp' ? active : inactive}" href="${ctx}/reports/predAccuracyScatterParams.jsp${qs}" title="Shows each individual datapoint for prediction accuracy. Useful for finding specific issues with predictions."><fmt:message key="div.predictionscatter"/></a></li>
20+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/predAccuracyCsvParams.jsp' ? active : inactive}" href="${ctx}/reports/predAccuracyCsvParams.jsp${qs}" title="Download prediction accuracy data in CSV format."><fmt:message key="div.csv"/></a></li>
21+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/routePerformanceTable.jsp' ? active : inactive}" href="${ctx}/reports/routePerformanceTable.jsp${qs}" title="Shows route performance: number of on-time predictions over total predictions for a given route."><fmt:message key="div.RoutePerformanceTable"/></a></li>
22+
</ul>
23+
</div>
24+
<div>
25+
<h3 class="px-2 mb-1 text-xs font-semibold text-gray-500 uppercase tracking-wider"><fmt:message key="div.ar"/></h3>
26+
<ul class="space-y-0.5">
27+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/avlMap.jsp' ? active : inactive}" href="${ctx}/reports/avlMap.jsp${qs}" title="Display historic AVL data for a vehicle on a map."><fmt:message key="div.AVLDataInMap"/></a></li>
28+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/avlMapParams.jsp' ? active : inactive}" href="${ctx}/reports/avlMapParams.jsp${qs}" title="Display historic AVL data for a vehicle on a map (with parameters)."><fmt:message key="div.AVLDataInMapParametersPage"/></a></li>
29+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/lastAvlReport.jsp' ? active : inactive}" href="${ctx}/reports/lastAvlReport.jsp${qs}" title="Show the last time each vehicle reported its GPS position over the last 24 hours."><fmt:message key="div.lastgpsreports"/></a></li>
30+
</ul>
31+
</div>
32+
<div>
33+
<h3 class="px-2 mb-1 text-xs font-semibold text-gray-500 uppercase tracking-wider"><fmt:message key="div.EventReports"/></h3>
34+
<ul class="space-y-0.5">
35+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/vehicleEventParams.jsp' ? active : inactive}" href="${ctx}/reports/vehicleEventParams.jsp${qs}" title="View all events for a vehicle."><fmt:message key="div.EventForVehicle"/></a></li>
36+
</ul>
37+
</div>
38+
<div>
39+
<h3 class="px-2 mb-1 text-xs font-semibold text-gray-500 uppercase tracking-wider"><fmt:message key="div.sar"/></h3>
40+
<ul class="space-y-0.5">
41+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/schAdhByRouteParams.jsp' ? active : inactive}" href="${ctx}/reports/schAdhByRouteParams.jsp${qs}" title="Schedule adherence by route, in a bar chart. Can compare multiple routes."><fmt:message key="div.scheduleroutr"/></a></li>
42+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/schAdhByStopParams.jsp' ? active : inactive}" href="${ctx}/reports/schAdhByStopParams.jsp${qs}" title="Schedule adherence for each stop on a route, in a bar chart."><fmt:message key="div.schedulebystop"/></a></li>
43+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/schAdhByTimeParams.jsp' ? active : inactive}" href="${ctx}/reports/schAdhByTimeParams.jsp${qs}" title="Schedule adherence for a route grouped by how early or late."><fmt:message key="div.earlylate"/></a></li>
44+
</ul>
45+
</div>
46+
<div>
47+
<h3 class="px-2 mb-1 text-xs font-semibold text-gray-500 uppercase tracking-wider"><fmt:message key="div.mr"/></h3>
48+
<ul class="space-y-0.5">
49+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/scheduleHorizStopsParams.jsp' ? active : inactive}" href="${ctx}/reports/scheduleHorizStopsParams.jsp${qs}" title="Display the schedule for a specified route in a table."><fmt:message key="div.schedulefor"/></a></li>
50+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/reports/scheduleVertStopsParams.jsp' ? active : inactive}" href="${ctx}/reports/scheduleVertStopsParams.jsp${qs}" title="Schedule for a route with stops listed vertically. Useful when there are few trips per day."><fmt:message key="div.sfrvss"/></a></li>
51+
</ul>
52+
</div>
53+
<div>
54+
<h3 class="px-2 mb-1 text-xs font-semibold text-gray-500 uppercase tracking-wider"><fmt:message key="div.sr"/></h3>
55+
<ul class="space-y-0.5">
56+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/status/activeBlocks.jsp' ? active : inactive}" href="${ctx}/status/activeBlocks.jsp${qs}" title="How many block assignments are currently active and which have assigned vehicles."><fmt:message key="div.acbiveblock"/></a></li>
57+
<li><a class="block px-2 py-1.5 text-sm rounded ${path == '/status/serverStatus.jsp' ? active : inactive}" href="${ctx}/status/serverStatus.jsp${qs}" title="How well the system is running, including the AVL feed."><fmt:message key="div.ss"/></a></li>
58+
</ul>
59+
</div>
60+
</nav>
61+
</aside>

transitclockWebapp/src/main/webapp/css/general.css

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,50 @@ a:hover {
7575
padding: 4px;
7676
}
7777

78-
/* Make input widgets use different color and larger font */
79-
input, select {
78+
/* Pre-Tailwind input chrome. Scoped to .param so it doesn't bleed onto
79+
.form-control or partials that have already migrated to Tailwind
80+
(jsonXmlFormat.jsp, submitApiCall.jsp). /reports/apiCalls/* pages
81+
render hybrid until they're fully ported. */
82+
.param > input, .param > select {
8083
background-color: #f8f8f8;
8184
font-size: large;
8285
}
8386

87+
.form-control {
88+
display: block;
89+
border: 0;
90+
border-radius: 0.5rem;
91+
background-color: #fff;
92+
padding: 0.5rem 0.75rem;
93+
font-size: 1rem;
94+
line-height: 1.5rem;
95+
color: #171717;
96+
box-shadow: inset 0 0 0 1px #d4d4d4, 0 1px rgba(0, 0, 0, 0.05);
97+
outline: none;
98+
}
99+
.form-control::placeholder { color: #737373; }
100+
.form-control:focus {
101+
outline: none;
102+
box-shadow: inset 0 0 0 2px #525252, 0 1px rgba(0, 0, 0, 0.05);
103+
}
104+
@media (min-width: 640px) {
105+
.form-control { font-size: 0.875rem; line-height: 1.25rem; }
106+
}
107+
.form-control[disabled] {
108+
cursor: not-allowed;
109+
background-color: #f5f5f5;
110+
}
111+
112+
select.form-control:not([multiple]) {
113+
appearance: none;
114+
-webkit-appearance: none;
115+
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23737373' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
116+
background-position: right 0.75rem center;
117+
background-repeat: no-repeat;
118+
background-size: 1.25em 1.25em;
119+
padding-right: 2.5rem;
120+
}
121+
84122
.earlyColor {
85123
background: #f2b7cd;
86124
border-radius: 4px;
Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,9 @@
1-
<t:layout>
2-
<jsp:attribute name="title"><fmt:message key="div.SpecifyParameters" /></jsp:attribute>
3-
<jsp:attribute name="head">
4-
<!-- Load in Select2 files so can create fancy route selector -->
5-
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
6-
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
7-
8-
<link href="params/reportParams.css" rel="stylesheet"/>
9-
</jsp:attribute>
1+
<t:reportsParamsForm action="avlMap.jsp">
2+
<jsp:attribute name="title"><fmt:message key="div.SpecifyParameters"/></jsp:attribute>
3+
<jsp:attribute name="heading"><fmt:message key="div.spdavld"/></jsp:attribute>
104
<jsp:body>
11-
<div id="title">
12-
<fmt:message key="div.spdavld" />
13-
</div>
14-
15-
<div id="mainDiv">
16-
<form action="avlMap.jsp" method="POST">
17-
<%-- For passing agency param to the report --%>
18-
<input type="hidden" name="a" value="${param.a}">
19-
20-
<jsp:include page="params/routeSingle.jsp" />
21-
22-
<jsp:include page="params/fromDateNumDaysTime.jsp" />
23-
24-
<jsp:include page="params/submitReport.jsp" />
25-
</form>
26-
</div>
5+
<jsp:include page="params/routeSingle.jsp"/>
6+
<jsp:include page="params/fromDateNumDaysTime.jsp"/>
7+
<jsp:include page="params/submitReport.jsp"/>
278
</jsp:body>
28-
</t:layout>
9+
</t:reportsParamsForm>
Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,15 @@
1-
<t:layout>
2-
<jsp:attribute name="title"><fmt:message key="div.SpecifyParameters" /></jsp:attribute>
3-
<jsp:attribute name="head">
4-
<!-- Load in Select2 files so can create fancy route selector -->
5-
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
6-
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
7-
8-
<link href="params/reportParams.css" rel="stylesheet"/>
9-
</jsp:attribute>
1+
<t:reportsParamsForm action="avlMap.jsp">
2+
<jsp:attribute name="title"><fmt:message key="div.SpecifyParameters"/></jsp:attribute>
3+
<jsp:attribute name="heading"><fmt:message key="div.spdavlbv"/></jsp:attribute>
104
<jsp:body>
11-
<div id="title">
12-
<fmt:message key="div.spdavlbv" />
13-
</div>
14-
15-
<div id="mainDiv">
16-
<form action="avlMap.jsp" method="POST">
17-
<%-- For passing agency param to the report --%>
18-
<input type="hidden" name="a" value="${param.a}">
19-
20-
<jsp:include page="params/vehicle.jsp" />
21-
22-
<jsp:include page="params/fromDateNumDaysTime.jsp" />
23-
24-
<jsp:include page="params/routeOptional.jsp" />
25-
<script>
26-
// Make selector label more appropriate
27-
$("#routesDiv label").text("Route to Display:");
28-
</script>
29-
30-
<jsp:include page="params/submitReport.jsp" />
31-
</form>
32-
</div>
5+
<jsp:include page="params/vehicle.jsp"/>
6+
<jsp:include page="params/fromDateNumDaysTime.jsp"/>
7+
<jsp:include page="params/routeOptional.jsp"/>
8+
<%-- Override the shared "Route" label to clarify intent next to the vehicle picker. --%>
9+
<script>
10+
$("#routesDiv label").text("Route to Display:");
11+
</script>
12+
13+
<jsp:include page="params/submitReport.jsp"/>
3314
</jsp:body>
34-
</t:layout>
15+
</t:reportsParamsForm>
Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,10 @@
1-
<t:layout>
2-
<jsp:attribute name="title">Specify Parameters</jsp:attribute>
3-
<jsp:attribute name="head">
4-
<!-- Load in Select2 files so can create fancy route selector -->
5-
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
6-
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
7-
8-
<link href="params/reportParams.css" rel="stylesheet"/>
9-
</jsp:attribute>
1+
<t:reportsParamsForm action="avlMap.jsp">
2+
<jsp:attribute name="title"><fmt:message key="div.SpecifyParameters"/></jsp:attribute>
3+
<jsp:attribute name="heading"><fmt:message key="div.SelectParametersForDisplayingAVLDataInMap"/></jsp:attribute>
104
<jsp:body>
11-
<div id="title">
12-
<fmt:message key="div.SelectParametersForDisplayingAVLDataInMap" />
13-
</div>
14-
15-
<div id="mainDiv">
16-
<form action="avlMap.jsp" method="POST">
17-
<%-- For passing agency param to the report --%>
18-
<input type="hidden" name="a" value="${param.a}">
19-
20-
<jsp:include page="params/vehicle.jsp" />
21-
22-
<jsp:include page="params/fromDateNumDaysTime.jsp" />
23-
24-
<jsp:include page="params/routeSingle.jsp" />
25-
26-
<jsp:include page="params/submitReport.jsp" />
27-
</form>
28-
</div>
5+
<jsp:include page="params/vehicle.jsp"/>
6+
<jsp:include page="params/fromDateNumDaysTime.jsp"/>
7+
<jsp:include page="params/routeSingle.jsp"/>
8+
<jsp:include page="params/submitReport.jsp"/>
299
</jsp:body>
30-
</t:layout>
10+
</t:reportsParamsForm>

0 commit comments

Comments
 (0)