Skip to content

Instantly share code, notes, and snippets.

@bmccormack
Created September 18, 2012 17:18
Show Gist options
  • Save bmccormack/3744412 to your computer and use it in GitHub Desktop.
Save bmccormack/3744412 to your computer and use it in GitHub Desktop.
FogBugz Workflow Bugmonkey
#BugBreadcrumbs .breadcrumbs {
overflow: hidden;
margin-left: -2px;
}
#BugBreadcrumbs .breadcrumbs li {
float: left;
padding: 5px 0 5px 30px;
background: #eee;
color: #999;
position: relative;
display: block;
cursor: pointer;
}
#BugBreadcrumbs .breadcrumbs li:after {
content: "";
display: block;
width: 0;
height: 0;
border-top: 30px solid transparent;
border-bottom: 30px solid transparent;
border-left: 15px solid #eee;
position: absolute;
top: 50%;
margin-top: -30px;
left: 100%;
z-index: 2;
}
#BugBreadcrumbs .breadcrumbs li:before {
content: "";
display: block;
width: 0;
height: 0;
border-top: 30px solid transparent;
border-bottom: 30px solid transparent;
border-left: 15px solid white;
position: absolute;
top: 50%;
margin-top: -30px;
margin-left: 2px;
left: 100%;
z-index: 1;
}
#BugBreadcrumbs .breadcrumbs li:first-child {
padding-left: 10px;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
#BugBreadcrumbs .breadcrumbs li:hover {
background-color: #ddd;
color: #666;
}
#BugBreadcrumbs .breadcrumbs li:hover:after {
border-left-color: #ddd;
}
#BugBreadcrumbs .breadcrumbs li.current {
cursor: default;
color: #545a53;
background-color: #e0f1df;
}
#BugBreadcrumbs .breadcrumbs li.current:after {
border-left-color: #e0f1df;
}
#BugBreadcrumbs .breadcrumbs li.current:hover {
background-color: #c0efbd;
color: black;
}
#BugBreadcrumbs .breadcrumbs li.current:hover:after {
border-left-color: #c0efbd;
}
a.actionButton2.next {
cursor: pointer;
}
// controls whether or not the default active status
// is included as a step regardless of it's name
// note: will always be included as the first step
var fIncludeDefaultActive = true;
function stepExtractor(ixCategory) {
var ixStatusDefaultActive = -1;
if (fIncludeDefaultActive) {
var cat = DB.Category.firstMatch(function(cat) {
return cat.ixCategory === ixCategory;
});
if (cat) {
ixStatusDefaultActive = cat.ixStatusDefaultActive;
}
}
return function(status) {
if (status.fDeleted || status.ixCategory !== ixCategory) return null;
var reStep = /\((\d+)\.\s*(.*)\)/ // capture step # and step name
var m = reStep.exec(status.sStatus);
if (m) {
return {
step: parseInt(m[1], 10),
label: m[2],
status: status
};
}
if (ixStatusDefaultActive > 0 && status.ixStatus === ixStatusDefaultActive) {
var label = status.sStatus;
var match = status.sStatus.match(/\((.*)\)/);
if (match) {
label = $.trim(match[1]);
}
return {
step: 0,
label: label,
status: status
}
}
return null;
}
}
function sortByStep(step1, step2) {
if (step1.step === step2.step) {
// defer to FogBugz status ordering
return step1.status.iOrder - step2.status.iOrder;
}
if (step1.step > step2.step) return 1;
return -1;
}
function getCurrentStep(ixStatus) {
var status = DB.Status.firstMatch(function(status) {
return status.ixStatus === ixStatus;
});
if (status) {
return stepExtractor(status.ixCategory)(status);
}
return null;
}
function getSteps(ixCategory) {
return $.map(DB.Status, stepExtractor(ixCategory)).sort(sortByStep);
};
function moveToStep(event) {
if ($('#sEventEdit').length) {
alert('Cannot navigate between steps while editing the case!');
return;
}
var ixStatus = $(event.target).data('ixStatus');
TabManager.clickChangeView(null, 'edit');
var droplist = $('#ixStatus');
droplist.val(ixStatus);
DropListControl.refresh(droplist[0]);
$('#Button_OKEdit').click();
}
function updateUI(steps, currStep, nextStep) {
$('#BugBreadcrumbs ul.breadcrumbs').remove();
$('ul.toolbar.buttons a.next').parent('li').remove();
function decorateStepElement(el, step) {
el
.text(step.label)
.data('ixStatus', step.status.ixStatus)
.attr('title', 'Click to move to this step...')
.click(moveToStep);
return el;
}
var list = $('<ul>').addClass('breadcrumbs');
$.each(steps, function(ix, step) {
var link = decorateStepElement($('<li>'), step);
if (currStep && currStep.step === step.step) {
link
.addClass('current')
.attr('title', 'Currently working on this step')
.unbind(); // no click handler
}
link.appendTo(list);
});
if ($('#BugBreadcrumbs > a.vb').length) {
// add a little spacing if case hierarchy breadcrumbs are present
list.css('margin-top', '0.5em');
}
list.appendTo('#BugBreadcrumbs');
// add a new toolbar option to communicate moving to the next status
if (nextStep !== null && !$('#sEventEdit').length) {
var button = decorateStepElement($('<a>'), nextStep);
button
.addClass('actionButton2 icon-left next')
.appendTo('ul.toolbar.buttons')
.wrap('<li>');
}
}
function statusSteps() {
// this customization only applies to the case page
if (!$('#bugviewContainer').length) return;
//make sure we're dealing with an open and active case
if (goBug.fResolved || !goBug.fOpen) { return; }
var steps = getSteps(goBug.ixCategory);
// we need at least 2 steps for the nav bar to make sense
if (!steps.length || steps.length === 1) { return; }
var nextStep = null;
var currStep = getCurrentStep(goBug.ixStatus, goBug.ixCategory);
if (currStep) {
var currStepIndex = steps.firstMatchIndex(function(s) { return s.step === currStep.step; });
if (currStepIndex !== undefined && currStepIndex + 1 < steps.length) {
nextStep = steps[currStepIndex + 1];
}
}
updateUI(steps, currStep, nextStep);
}
statusSteps();
// run our code when the view changes without a page refresh
$(window).on('BugViewChange', statusSteps);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment