Commit 5e28a159 authored by Christian Wulf's avatar Christian Wulf

user stories can now be added

parents 3d0fe1ea 94d4b473
......@@ -10,7 +10,7 @@ modules = {
resource url:'/less/main.less'
resource url:'/less/elements.less'
resource url: '/less/backlogs.less'
resource url:'/css/dummy.css'
}
......
......@@ -51,6 +51,7 @@ class BootStrap {
userStoryInBacklog.author = ffi
userStoryInBacklog.editor = ffi
userStoryInBacklog.points = 3
userStoryInBacklog.status = UserStoryStatus.IN_BACKLOG
userStoryInBacklog.color = new Color(250,60,0)
productBacklog.addToUserstories(userStoryInBacklog)
......
package scrumboard
import org.apache.shiro.SecurityUtils
import scrumboard.shiro.User
class UserStoryController {
def show(int id) {
def userStory = UserStory.get(id)
def storyPointMapping = userStory.project.storyPointMapping.entrySet()
render ( template:"showUserStory", model: [userStory : userStory, storyPointMapping: storyPointMapping])
Project project = Project.find {true} // TODO get current project; do not search in db
def currentUser = User.findByUsername(SecurityUtils.subject?.principal)
def userStory = UserStory.get(id) ?: new UserStory(currentUser, project.productBacklog)
render ( template:"create", model: [userStory : userStory, storyPointMapping: project.storyPointMapping])
}
def create(id) {
def userStory = new UserStory(params)
userStory.save()
def create() {
Project project = Project.find {true} // TODO get current project; do not search in db
def userStory = new UserStory()
userStory.title = params.title
userStory.description = params.description
userStory.shortId = params.shortId
userStory.points = Double.valueOf(params.points)
userStory.status = UserStoryStatus.IN_BACKLOG
userStory.color = Color.DEFAULT
userStory.author = User.findByUsername(params.author)
userStory.editor = User.findByUsername(params.editor)
userStory.productBacklog = project.productBacklog
userStory.save(failOnError:true)
}
def move(int id, String to) {
......
......@@ -14,9 +14,15 @@ class Color {
static belongsTo = UserStory
static DEFAULT = new Color(100,100,100)
Color(red, green, blue) {
this.red = red
this.green = green
this.blue = blue
}
def toHex() {
"#${String.format("%02X", red)}${String.format("%02X", green)}${String.format("%02X", blue)}"
}
}
......@@ -3,7 +3,7 @@ package scrumboard
class ProductBacklog {
static hasMany = [ userstories: UserStory ]
static belongsTo = Project
static belongsTo = [project: Project]
static constraints = {
}
......
......@@ -11,7 +11,7 @@ class UserStory implements Comparable {
double points
UserStoryStatus status = UserStoryStatus.IN_BACKLOG
UserStoryStatus status
Color color
......@@ -25,6 +25,17 @@ class UserStory implements Comparable {
assignedToSprint nullable: true
}
UserStory(User user, ProductBacklog productBacklog) {
this.shortId = "Type in your short identifier"
this.title = "Type in your title"
this.description = "Type in your description"
this.status = UserStoryStatus.IN_BACKLOG
this.color = Color.DEFAULT
this.author = user
this.editor = user
this.productBacklog = productBacklog
}
UserStory(String shortId, String title) {
this.shortId = shortId
this.title = title
......
......@@ -15,17 +15,22 @@ class NoteTagLib {
userStories.eachWithIndex { UserStory item, index ->
if (index % attrs["columnlength"].toInteger() == attrs["columnindex"].toInteger()) {
def colorClass = determineColor(item, productBacklog)
out << """<div class='ui-widget ui-corner-all'>
out << getNewUserStoryString(item, productBacklog)
}
}
}
private static getNewUserStoryString(item, productBacklog) {
def colorClass = determineColor(item, productBacklog)
def style = (productBacklog) ? "" : "background: ${item.color.toHex()} !important;"
"""<div class='ui-widget ui-corner-all'>
<div class='hidden'>${item.id}</div>
<div class='ui-widget-header ui-corner-top ${colorClass}'>${item}</div>
<div class='ui-widget-header ui-corner-top ${colorClass}' style='${style}'>${item}</div>
<div class='ui-widget-content ui-corner-bottom' >${item.getShortDescription()}</div>
</div> """
}
}
}
private determineColor(UserStory userStory, productBacklog) {
private static determineColor(UserStory userStory, productBacklog) {
if (productBacklog) {
if (!userStory.assignedToSprint) {
return "notAssignedToSprint"
......
......@@ -16,17 +16,17 @@ class ShowUserStoryDialogTagLib {
height: 500,
width: 650,
modal: true,
buttons: {
'Save': function() {
var bValid = true;
if ( bValid ) {
\$( this ).dialog( 'close' );
}
},
Cancel: function() {
\$( this ).dialog( 'close' );
}
},
// buttons: {
// 'Save': function() {
// var bValid = true;
// if ( bValid ) {
// \$( this ).dialog( 'close' );
// }
// },
// Cancel: function() {
// \$( this ).dialog( 'close' );
// }
// },
close: function() {
}
});"""
......
<!doctype html>
<html>
<head>
<meta name="layout" content="main">
<style>
.ui-widget-header .ui-icon { float: right; }
.ui-sortable-placeholder { border: 1px dotted gray; visibility: visible !important; height: 50px !important; }
.ui-sortable-placeholder * { visibility: hidden; }
</style>
<meta name="layout" content="main">
<style>
.ui-widget-header .ui-icon {
float: right;
}
.ui-sortable-placeholder {
border: 1px dotted gray;
visibility: visible !important;
height: 50px !important;
}
.ui-sortable-placeholder * {
visibility: hidden;
}
</style>
</head>
<body>
<h1 id="backloglabel"><img id="AddUserStory" style="cursor: pointer;" alt="Add" src="/scrumboard/images/add.png"></img>&nbsp;&nbsp;&nbsp;Backlog</h1>
<hr id="boarddivider" width="1px" size="768px" class="centerVerticalLine"></hr>
<h1 id="sprintbackloglabel"><img id="AddSprint" style="cursor: pointer;" alt="Add" src="/scrumboard/images/add.png"></img>&nbsp;&nbsp;&nbsp;<g:select name="sprints"
from="${sprints}" style="margin-top:-6px;"/>&nbsp;&nbsp;&nbsp;<a href="/scrumboard/sprint/show?id=0"><img id="ShowSprint" alt="show" src="/scrumboard/images/east-mini.png"></img></a>
<h1 id="backloglabel">
<img id="AddUserStory" style="cursor: pointer;" alt="Add"
src="/scrumboard/images/add.png"></img>&nbsp;&nbsp;&nbsp;Backlog
</h1>
<div id="backlog">
<div id="columnbacklogone" class="column">
<g:note userStories="${backlogUserStories}" columnindex="0" columnlength="4" productBacklog="true" />
</div>
<div id="columnbacklogtwo" class="column">
<g:note userStories="${backlogUserStories}" columnindex="1" columnlength="4" productBacklog="true" />
</div>
<div id="columnbacklogthree" class="column">
<g:note userStories="${backlogUserStories}" columnindex="2" columnlength="4" productBacklog="true" />
</div>
<div id="columnbacklogfour" class="column">
<g:note userStories="${backlogUserStories}" columnindex="3" columnlength="4" productBacklog="true" />
</div>
</div>
<div id="sprintbacklog">
<div id="columnsprintbacklogone" class="column">
<g:note userStories="${sprintUserStories}" columnindex="0" columnlength="4" />
</div>
<div id="columnsprintbacklogtwo" class="column">
<g:note userStories="${sprintUserStories}" columnindex="1" columnlength="4" />
</div>
<div id="columnsprintbacklogthree" class="column">
<g:note userStories="${sprintUserStories}" columnindex="2" columnlength="4" />
</div>
<div id="columnsprintbacklogfour" class="column">
<g:note userStories="${sprintUserStories}" columnindex="3" columnlength="4" />
</div>
<div id="dialog-addSprint" title="Create new sprint">
<form>
<fieldset>
<label for="name">Name</label>
<input type="text" name="name" id="name" class="text ui-widget-content ui-corner-all" />
</fieldset>
</form>
</div>
</div>
<div id="dialog-showUserStory" title="Show User Story">
</div>
<script type="text/javascript">
$(function() {
<g:movableColumn name="column"/>
$( ".ui-widget" )
.find( ".ui-widget-header" )
.prepend( "<span class='icon'>+</span>")
.end();
$( ".ui-widget-header .ui-icon" ).click(function() {
alert("x");
});
<g:showUserStoryDialog />
$( "#dialog-addSprint" ).dialog({
autoOpen: false,
height: 300,
width: 350,
modal: true,
buttons: {
"Create new sprint": function() {
var bValid = true;
allFields.removeClass( "ui-state-error" );
if ( bValid ) {
$( this ).dialog( "close" );
<hr id="boarddivider" width="1px" size="768px"
class="centerVerticalLine"></hr>
<h1 id="sprintbackloglabel">
<img id="AddSprint" style="cursor: pointer;" alt="Add"
src="/scrumboard/images/add.png"></img>&nbsp;&nbsp;&nbsp;
<g:select name="sprints" from="${sprints}" style="margin-top:-6px;" />
&nbsp;&nbsp;&nbsp;<a href="/scrumboard/sprint/show?id=0"><img
id="ShowSprint" alt="show" src="/scrumboard/images/east-mini.png"></img></a>
</h1>
<div id="backlog">
<div id="columnbacklogone" class="column">
<g:note userStories="${backlogUserStories}" columnindex="0"
columnlength="4" productBacklog="true" />
</div>
<div id="columnbacklogtwo" class="column">
<g:note userStories="${backlogUserStories}" columnindex="1"
columnlength="4" productBacklog="true" />
</div>
<div id="columnbacklogthree" class="column">
<g:note userStories="${backlogUserStories}" columnindex="2"
columnlength="4" productBacklog="true" />
</div>
<div id="columnbacklogfour" class="column">
<g:note userStories="${backlogUserStories}" columnindex="3"
columnlength="4" productBacklog="true" />
</div>
</div>
<div id="sprintbacklog">
<div id="columnsprintbacklogone" class="column">
<g:note userStories="${sprintUserStories}" columnindex="0"
columnlength="4" />
</div>
<div id="columnsprintbacklogtwo" class="column">
<g:note userStories="${sprintUserStories}" columnindex="1"
columnlength="4" />
</div>
<div id="columnsprintbacklogthree" class="column">
<g:note userStories="${sprintUserStories}" columnindex="2"
columnlength="4" />
</div>
<div id="columnsprintbacklogfour" class="column">
<g:note userStories="${sprintUserStories}" columnindex="3"
columnlength="4" />
</div>
<div id="dialog-addSprint" title="Create new sprint">
<form>
<fieldset>
<label for="name">Name</label> <input type="text" name="name"
id="name" class="text ui-widget-content ui-corner-all" />
</fieldset>
</form>
</div>
</div>
<div id="dialog-showUserStory" title="Show User Story"></div>
<script type="text/javascript">
$(function() {
<g:movableColumn name="column"/>
$(".ui-widget").find(".ui-widget-header").prepend(
"<span class='icon'>+</span>").end();
$(".ui-widget-header .ui-icon").click(function() {
alert("x");
});
<g:showUserStoryDialog />
$("#dialog-addSprint").dialog({
autoOpen : false,
height : 300,
width : 350,
modal : true,
buttons : {
"Create new sprint" : function() {
var bValid = true;
allFields.removeClass("ui-state-error");
if (bValid) {
$(this).dialog("close");
}
},
Cancel : function() {
$(this).dialog("close");
}
},
close : function() {
allFields.val("").removeClass("ui-state-error");
}
},
Cancel: function() {
$( this ).dialog( "close" );
}
},
close: function() {
allFields.val( "" ).removeClass( "ui-state-error" );
}
});
$( "#AddSprint" ).click(function() {
$( "#dialog-addSprint" ).dialog( "open" );
});
$( "#AddUserStory" ).click(function() {
$( "#dialog-addSprint" ).dialog( "open" );
});
});
</script>
});
$("#AddSprint").click(function() {
$("#dialog-addSprint").dialog("open");
});
$("#AddUserStory").click(function() {
$.ajax({
url: "/scrumboard/userStory/show?id=" + (-1)
}).done(function ( data ) {
$( "#dialog-showUserStory" ).html(data);
$( "#dialog-showUserStory" ).dialog( "open" );
});
})
});
</script>
</body>
</html>
<table>
<tbody>
<tr>
<td>Title:</td>
<td><input name="title"></td>
</tr>
<tr>
<td>Description:</td>
<td><input name="description"></td>
</tr>
<tr>
<td>Points:</td>
<td><g:select name="points" from="${storyPointMapping }" optionKey="key" optionValue="value" value="${storyPointMapping.1 }" /></td>
</tr>
<tr>
<td>Status:</td>
<td>${UserStoryStatus.IN_BACKLOG}</td>
</tr>
<tr>
<td>Author:</td>
<td>
<input name="author" value="${SecurityUtils.subject.name }">
</td>
</tr>
<tr>
<td>Editor:</td>
<td>
<input name="editor" value="${SecurityUtils.subject.name }">
</td>
</tr>
<tbody>
</table>
\ No newline at end of file
<g:form >
<table>
<tbody>
<tr>
<td>Short ID:</td>
<td><input id="shortId" name="shortId" value="${userStory.shortId}">
</td>
</tr>
<tr>
<td>Title:</td>
<td><input name="title" value="${userStory.title}"></td>
</tr>
<tr>
<td>Description:</td>
<td><input name="description" value="${userStory.description}"></td>
</tr>
<tr>
<td>Points:</td>
<td><g:select name="points" from="${storyPointMapping }"
keys="${0..storyPointMapping.size()-1}"
value="${userStory.points}" /></td>
</tr>
<tr>
<td>Status:</td>
<td>
${userStory.status.name}
<%-- <input name="status" value="${userStory.status}" class="hidden" />--%>
</td>
</tr>
<%-- <tr class="hidden">--%>
<%-- <td><input name="color" value="${userStory.color}"/></td>--%>
<%-- </tr>--%>
<tr>
<td>Author:</td>
<td><input name="author" value="${userStory.author}" disabled="disabled"></td>
</tr>
<tr>
<td>Editor:</td>
<td><input name="editor" value="${userStory.editor}" disabled="disabled"></td>
</tr>
<tbody>
</table>
<g:submitToRemote url="[action:'create']" value="Create" after="jQuery(document).closeAndUpdate()" />
<input type="button" value="Cancel" onclick="$(document).close();" />
</g:form>
<script type="text/javascript">
( function($) {
jQuery(document).ready(function() {
jQuery.fn.close = function() {
$('#dialog-showUserStory').dialog('close');
}
jQuery.fn.closeAndUpdate = function() {
$(document).close()
location.reload()
}
$("#shortId").focus(function(){
this.select();
});
});
} ) ( jQuery );
</script>
\ No newline at end of file
.assignedToSprint {
background-color: #90F790;
background-color: #90F790 !important;
}
.notAssignedToSprint {
background-color: grey;
background-color: grey !important;
}
......@@ -181,11 +181,10 @@
}
.ui-widget-header {
color: #315fa0;
//color: #315fa0;
font-weight: normal;
font-family: Cambria, Arial, Trebuchet MS;
font-size: 13pt;
background: #90F790;
padding-left: 10px;
border: 1px solid #DDDDDD;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment