From ee2c58ffae301f4040aeff15131dd60ae98d7463 Mon Sep 17 00:00:00 2001
From: Tom Willemse
Date: Wed, 24 Jul 2013 23:46:16 +0200
Subject: Change manner of assignment
Instead of having an input in which an assignee's email address can be
entered, show the gravatar of the assignee, or a question mark if no
assignee has been specified, and upon clicking it show a modal dialog
where this information can be changed.
---
scrumli.lisp | 9 +++++
static/js/main.js | 109 ++++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 94 insertions(+), 24 deletions(-)
diff --git a/scrumli.lisp b/scrumli.lisp
index 362f4a5..df6b442 100644
--- a/scrumli.lisp
+++ b/scrumli.lisp
@@ -221,3 +221,12 @@
(set-assignee 'story id assignee)
(encode-json-to-string '((status . "ok"))))
403))
+
+(define-route scrumli-task-set-assignee ("tasks/assignee"
+ :content-type "json"
+ :method :post)
+ (if (logged-in-p)
+ (with-post-parameters ("id" "assignee")
+ (set-assignee 'task id assignee)
+ (encode-json-to-string '((status . "ok"))))
+ 403))
diff --git a/static/js/main.js b/static/js/main.js
index 169448d..201c332 100644
--- a/static/js/main.js
+++ b/static/js/main.js
@@ -34,10 +34,8 @@ var AssigneeIcon = React.createClass({
title={this.props.assignee}
alt={this.props.assignee} />;
else
- icon = (
-
-
- );
+ icon = ;
return icon;
}
@@ -68,6 +66,12 @@ var StoryTaskRow = React.createClass({
this.props.onMoved(-1);
}.bind(this));
}),
+ handleAssigneeClick: React.autoBind(function(event) {
+ this.props.onAssigneeClicked({url: "/tasks/assignee",
+ id: this.props.task.id,
+ assignee: this.props.task.assignee,
+ md5: this.props.task.md5});
+ }),
render: function() {
return (
@@ -78,8 +82,11 @@ var StoryTaskRow = React.createClass({
onClick={this.moveDown}>
-
+
|
@@ -100,7 +107,8 @@ var StoryTaskTable = React.createClass({
render: function() {
var taskNodes = this.props.tasks.map(function (task) {
return ;
+ onMoved={this.props.onTaskMoved}
+ onAssigneeClicked={this.props.onAssigneeClicked} />;
}.bind(this));
return (
@@ -167,26 +175,16 @@ var StoryData = React.createClass({
handleTaskMoved: React.autoBind(function(direction) {
this.loadStoryFromServer();
}),
- handleAssigned: React.autoBind(function(event) {
- $.post("/story/assignee", {id: this.state.data.id,
- assignee: event.target.value})
- .fail(function() {
- event.target.value = "";
- }.bind(this));
- }),
render: function() {
if (this.state.data) {
return (
{this.state.data.title}
- Assignee:
-
{this.state.data.content}
+ onTaskMoved={this.handleTaskMoved}
+ onAssigneeClicked={this.props.onAssigneeClicked} />
);
}
@@ -196,6 +194,12 @@ var StoryData = React.createClass({
});
var StoryRow = React.createClass({
+ handleAssigneeClick: React.autoBind(function(event) {
+ this.props.onAssigneeClicked({url: "/story/assignee",
+ id: this.props.story.id,
+ assignee: this.props.story.assignee,
+ md5: this.props.story.md5});
+ }),
render: function() {
return (
@@ -206,8 +210,11 @@ var StoryRow = React.createClass({
onClick={this.moveDown}>
-
+
|
@@ -265,7 +272,8 @@ var StoryTable = React.createClass({
render: function() {
var storyNodes = this.props.data.map(function (story) {
return ;
+ onTitleClicked={this.handleSelected}
+ onAssigneeClicked={this.props.onAssigneeClicked} />;
}.bind(this));
return (
@@ -275,6 +283,49 @@ var StoryTable = React.createClass({
}
});
+var AssignmentForm = React.createClass({
+ handleChanged: React.autoBind(function() {
+ var assignee = this.refs.assignee.getDOMNode().value;
+
+ $.post(this.state.url,
+ {id: this.state.id, assignee: assignee})
+ .done(function (data) {
+ if (data.status == "ok") {
+ this.refs.assignee.getDOMNode().value = '';
+ $(".assignModal").modal('hide');
+ }
+ }.bind(this));
+ }),
+ setInfo: React.autoBind(function(info) {
+ this.setState(info);
+ }),
+ getInitialState: function () {
+ return {id: 0, assignee: "", url: "", md5: ""};
+ },
+ render: function() {
+ return (
+
+ );
+ }
+});
+
var StoryForm = React.createClass({
handleSubmit: React.autoBind(function() {
var role = this.refs.role.getDOMNode().value.trim();
@@ -383,18 +434,28 @@ var StoryPage = React.createClass({
this.refs.data.setData(data);
}.bind(this), 'json');
}),
+ handleAssigneeClicked: React.autoBind(function (info) {
+ var form = this.refs.assignmentForm;
+
+ form.setInfo(info);
+
+ $(".assignModal").modal();
+ }),
render: function() {
return (
+ onStorySelected={this.handleStorySelected}
+ onAssigneeClicked={this.handleAssigneeClicked} />
+
+ pollInterval={this.props.pollInterval}
+ onAssigneeClicked={this.handleAssigneeClicked} />
);
--
cgit v1.2.3-54-g00ecf
| |