Building a Bug Tracker: Filtering by Status
Along with filtering by severity, and viewing one’s own bug reports, it is also important to be able to filter by status. This allows developers to see what still needs to be worked on, and allows users to see what may still be open and what may already be fixed.
For this purpose, we’ll use the same methods that we used in the article on Filtering by Severity.
There are times when using one template with conditionals makes a lot of sense, and other times when it makes no sense. In this case, we already have a filter_by template, only now we want to filter by status rather than severity. To that end, we’ll see how we can do that on one template.
We know that we want to filter by severity if segment 3 contains the word “severity”. So, open up bug_tracker/filter_by and surround the weblog entries tag with a conditional testing segment 3; it will look like this:
{if segment_3 == "severity"}
{exp:weblog:entries weblog="{bug_tracker_weblog}" limit="30" status="Open|New|Confirmed|Unconfirmed|External|Resolved" sort="desc" search:bug_tracker_{segment_3}="={segment_4}" dynamic="off"}
{if no_results}
No bugs of {segment_4} {segment_3}.
{/if}
{if count == "1"}
<h3>Filtering by {segment_4} {segment_3}</h3>
<table>
<tr>
<th>ID</th>
<th>Status</th>
<th>Version</th>
<th>Description</th>
</tr>
{/if}
<tr>
<td>{entry_id}</td>
<td>{status}</td>
<td>{bug_tracker_version}</td>
<td>{title}</td>
</tr>
{if count == total_results}
</table>
{/if}
{/exp:weblog:entries}
{/if}
Now we’re going to add the same weblog entries tag inside a conditional testing segment 3 for the word “status”. However, we’re going to modify this tag to make status= segment 4, and get rid of the search: parameter, as we won’t need it in this instance:
{if segment_3 == "status"}
{exp:weblog:entries weblog="{bug_tracker_weblog}" limit="30" status="{segment_4}" sort="desc" dynamic="off"}
{if no_results}
No bugs of {segment_4} {segment_3}.
{/if}
{if count == "1"}
<h3>Filtering by {segment_4} {segment_3}</h3>
<table>
<tr>
<th>ID</th>
<th>Status</th>
<th>Version</th>
<th>Description</th>
</tr>
{/if}
<tr>
<td>{entry_id}</td>
<td>{status}</td>
<td>{bug_tracker_version}</td>
<td>{title}</td>
</tr>
{if count == total_results}
</table>
{/if}
{/exp:weblog:entries}
{/if}
As before, we’re passing what to filter by (status) and its value (any of the Statuses we previously set up) via the URL, in segment 3 and segment 4 respectively.
Now, all that is left to do is create our links, with the appropriate status, so that the filters are easy to access. Open up inc/.leftnav. Replace
<li><a href="#">Status</a></li>
with:
<li>Status</li>
<ul>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/New"}">New</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/Confirmed"}">Confirmed</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/Unconfirmed"}">Unconfirmed</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/External"}">External</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/Resolved"}">Resolved</a></li>
</ul>
Because we had already set up the basic concept, it was very easy to add a new filtering method for our Bug Tracker users.
Here are the two templates that we worked on this time. The full code, first, for our navigation in inc/.leftnav:
<div id="leftnav">
<h3>Filter By</h3>
<ul>
<li>Status</li>
<ul>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/New"}">New</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/Confirmed"}">Confirmed</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/Unconfirmed"}">Unconfirmed</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/External"}">External</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by/status/Resolved"}">Resolved</a></li>
</ul>
<li>Severity</li>
<ul>
<li><a href="{path="{bug_tracker_template_group}/filter_by"}severity/Trivial/">Trivial</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by"}severity/Minor/">Minor</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by"}severity/Major/">Major</a></li>
<li><a href="{path="{bug_tracker_template_group}/filter_by"}severity/Critical">Critical</a></li>
</ul>
<li><a href="#">Version</a></li>
<li><a href="#">Category</a></li>
<li><a href="#">Reported by</a></li>
<li><a href="#">Assigned To</a></li>
</ul>
<h3>Search and Report</h3>
<ul>
<li><a href="#">Search</a></li>
<li><a href="{path="{bug_tracker_template_group}/submit_bug"}">Report</a></li>
<li><a href="{path="{bug_tracker_template_group}/by_author}{logged_in_username}"}">View My Bugs</a></li>
</ul>
<h3>Subscribe</h3>
<ul>
<li><a href="#">RSS</a></li>
<li><a href="#">Atom</a></li>
</ul>
</div>
and our code for the bug_tracker/filter_by template:
{html_begin}
{embed="inc/.head" title="Bug Tracker - {segment_4} {segment_3}"}
<body>
<div id="container">
{embed="inc/.banner"}
{embed="inc/.leftnav"}
<div id="content">
{!-- Filter Reported Bugs by Severity --}
{if segment_3 == "severity"}
{exp:weblog:entries weblog="{bug_tracker_weblog}" limit="30" status="Open|New|Confirmed|Unconfirmed|External|Resolved" sort="desc" search:bug_tracker_{segment_3}="={segment_4}" dynamic="off"}
{if no_results}
No bugs of {segment_4} {segment_3}.
{/if}
{if count == "1"}
<h3>Filtering by {segment_4} {segment_3}</h3>
<table>
<tr>
<th>ID</th>
<th>Status</th>
<th>Version</th>
<th>Description</th>
</tr>
{/if}
<tr>
<td>{entry_id}</td>
<td>{status}</td>
<td>{bug_tracker_version}</td>
<td>{title}</td>
</tr>
{if count == total_results}
</table>
{/if}
{/exp:weblog:entries}
{/if}
{!-- Filter Reported Bugs by Status --}
{if segment_3 == "status"}
{exp:weblog:entries weblog="{bug_tracker_weblog}" limit="30" status="{segment_4}" sort="desc" dynamic="off"}
{if no_results}
No bugs of {segment_4} {segment_3}.
{/if}
{if count == "1"}
<h3>Filtering by {segment_4} {segment_3}</h3>
<table>
<tr>
<th>ID</th>
<th>Status</th>
<th>Version</th>
<th>Description</th>
</tr>
{/if}
<tr>
<td>{entry_id}</td>
<td>{status}</td>
<td>{bug_tracker_version}</td>
<td>{title}</td>
</tr>
{if count == total_results}
</table>
{/if}
{/exp:weblog:entries}
{/if}
{!-- End Bug List --}
</div>
{embed="inc/.footer"}
</div>
{html_end}
With this kind of ground-work, we can keep the templates on focus with their intended usage, quickly deploy new filtering methodologies, and have a nice, comfortable compromise between number of templates and complexity of those templates.


