OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openproject/app/assets/javascripts/backlogs/backlog.js

186 lines
5.6 KiB

//-- copyright
// OpenProject Backlogs Plugin
//
// Copyright (C)2013-2014 the OpenProject Foundation (OPF)
// Copyright (C)2011 Stephan Eckardt, Tim Felgentreff, Marnen Laibow-Koser, Sandro Munda
// Copyright (C)2010-2011 friflaj
// Copyright (C)2010 Maxime Guilbot, Andrew Vit, Joakim Kolsjö, ibussieres, Daniel Passos, Jason Vasquez, jpic, Emiliano Heyns
// Copyright (C)2009-2010 Mark Maglana
// Copyright (C)2009 Joe Heck, Nate Lowrie
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3.
//
// OpenProject Backlogs is a derivative work based on ChiliProject Backlogs.
// The copyright follows:
// Copyright (C) 2010-2011 - Emiliano Heyns, Mark Maglana, friflaj
// Copyright (C) 2011 - Jens Ulferts, Gregor Schmidt - Finn GmbH - Berlin, Germany
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
/******************************************
BACKLOG
A backlog is a visual representation of
a sprint and its stories. It is not a
sprint. Imagine it this way: A sprint is
a start and end date, and a set of
objectives. A backlog is something you
would draw up on the board or a spread-
sheet (or in Redmine Backlogs!) to
visualize the sprint.
******************************************/
RB.Backlog = (function ($) {
return RB.Object.create({
initialize: function (el) {
this.$ = $(el);
this.el = el;
// Associate this object with the element for later retrieval
this.$.data('this', this);
// Make the list sortable
this.getList().sortable({
connectWith: '.stories',
dropOnEmpty: true,
start: this.dragStart,
stop: this.dragStop,
update: this.dragComplete,
receive: this.dragChanged,
remove: this.dragChanged,
containment: $('#backlogs_container'),
scroll: true,
helper: function(event, ui){
var $clone = $(ui).clone();
$clone .css('position','absolute');
return $clone.get(0);
}
});
// Observe menu items
this.$.find('.add_new_story').click(this.handleNewStoryClick);
if (this.isSprintBacklog()) {
RB.Factory.initialize(RB.Sprint, this.getSprint());
this.burndown = RB.Factory.initialize(RB.Burndown, this.$.find('.show_burndown_chart'));
this.burndown.setSprintId(this.getSprint().data('this').getID());
}
// Initialize each item in the backlog
this.getStories().each(function (index) {
// 'this' refers to an element with class="story"
RB.Factory.initialize(RB.Story, this);
});
if (this.isSprintBacklog()) {
this.refresh();
}
},
dragChanged: function (e, ui) {
$(this).parents('.backlog').data('this').refresh();
},
dragComplete: function (e, ui) {
var isDropTarget = (ui.sender === null || ui.sender === undefined);
// jQuery triggers dragComplete of source and target.
// Thus we have to check here. Otherwise, the story
// would be saved twice.
if (isDropTarget) {
ui.item.data('this').saveDragResult();
}
},
dragStart: function (e, ui) {
ui.item.addClass("dragging");
},
dragStop: function (e, ui) {
ui.item.removeClass("dragging");
// FIXME: workaround for IE7
if ($.browser.msie && $.browser.version <= 7) {
ui.item.css("z-index", 0);
}
},
getSprint: function () {
return $(this.el).find(".model.sprint").first();
},
getStories: function () {
return this.getList().children(".story");
},
getList: function () {
return this.$.children(".stories").first();
},
handleNewStoryClick: function (e) {
var toggler = $(this).parents('.header').find('.toggler');
if (toggler.hasClass('closed')){
toggler.click();
}
e.preventDefault();
$(this).parents('.backlog').data('this').newStory();
},
// return true if backlog has an element with class="sprint"
isSprintBacklog: function () {
return $(this.el).find('.sprint').length === 1;
},
newStory: function () {
var story, o;
story = $('#story_template').children().first().clone();
this.getList().prepend(story);
o = RB.Factory.initialize(RB.Story, story[0]);
o.edit();
story.find('.editor').first().focus();
},
refresh : function () {
this.recalcVelocity();
this.recalcOddity();
},
recalcVelocity: function () {
var total;
if (!this.isSprintBacklog()) {
return true;
}
total = 0;
this.getStories().each(function (index) {
total += $(this).data('this').getPoints();
});
this.$.children('.header').children('.velocity').text(total);
},
recalcOddity : function () {
this.$.find('.story:even').removeClass('odd').addClass('even');
this.$.find('.story:odd').removeClass('even').addClass('odd');
}
});
}(jQuery));