/** @jsx React.DOM */
/* scrumli --- A simple scrum web application
Copyright (C) 2013 Tom Willemse
scrumli is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
scrumli 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with scrumli. If not, see . */
var StateIcon = React.createClass({
render: function() {
var icon_names = {"TODO": "icon-check-empty",
"DOING": "icon-sign-blank",
"DONE": "icon-check"};
return ;
}
});
var AssigneeIcon = React.createClass({
render: function() {
var icon;
if (this.props.assignee)
icon = ;
else
icon = ;
return icon;
}
});
var StoryTaskRow = React.createClass({
changeState: React.autoBind(function(event) {
$.post(baseUrl + "tasks/state", {'id': this.props.task.id})
.done(function (data, textStatus, jqXHR) {
if (data.status == "ok")
this.setState({state: data.state});
}.bind(this));
}),
getInitialState: function () {
return {state: this.props.task.state};
},
moveUp: React.autoBind(function(event) {
$.post(baseUrl + "tasks/up", {'id': this.props.task.id})
.done(function (data) {
if (data.status == "ok")
this.props.onMoved(1);
}.bind(this));
}),
moveDown: React.autoBind(function(event) {
$.post(baseUrl + "tasks/down", {'id': this.props.task.id})
.done(function (data) {
if (data.status == "ok")
this.props.onMoved(-1);
}.bind(this));
}),
handleAssigneeClick: React.autoBind(function(event) {
this.props.onAssigneeClicked({url: baseUrl + "task/assignee",
id: this.props.task.id,
assignee: this.props.task.assignee,
md5: this.props.task.md5});
}),
render: function() {
return (
{" "}
{this.state.state}
{this.props.task.description}
);
}
});
var StoryTaskTable = React.createClass({
render: function() {
var taskNodes = this.props.tasks.map(function (task) {
return ;
}.bind(this));
return (
);
}
});
var StoryTaskForm = React.createClass({
handleSubmit: React.autoBind(function() {
var text = this.refs.text.getDOMNode().value.trim();
this.props.onTaskSubmit({description: text,
storyId: this.state.storyId});
$(".taskModal").modal('hide');
this.refs.text.getDOMNode().value = '';
return false;
}),
getInitialState: function() {
return {storyId: null};
},
setStoryId: React.autoBind(function(id) {
this.setState({storyId: id});
}),
render: function() {
return (
);
}
});
var StoryData = React.createClass({
loadStoryFromServer: function() {
$.get(baseUrl + "stories/" + this.state.data.id)
.done(this.setData.bind(this));
},
componentWillMount: function() {
setInterval(
this.loadStoryFromServer.bind(this),
this.props.pollInterval
);
},
getInitialState: function() {
return {data: null};
},
setData: function(data) {
this.setState({data: null});
this.setState({data: data});
},
handleTaskMoved: React.autoBind(function(direction) {
this.loadStoryFromServer();
}),
render: function() {
if (this.state.data) {
return (
{this.state.data.title}
{this.state.data.content}
);
}
return
;
}
});
var StoryRow = React.createClass({
handleAssigneeClick: React.autoBind(function(event) {
this.props.onAssigneeClicked({url: baseUrl + "story/assignee",
id: this.props.story.id,
assignee: this.props.story.assignee,
md5: this.props.story.md5});
}),
render: function() {
return (
{" "}
{this.state.state}
As a {this.props.story.role}, I
{this.props.story.necessity} to
{this.props.story.title}
);
},
getInitialState: function() {
return {state: this.props.story.state,
content: null};
},
handleClick: React.autoBind(function(event) {
this.props.onTitleClicked(this.props.story.id);
}),
changeState: React.autoBind(function(event) {
$.post(baseUrl + "stories/state", {'id': this.props.story.id})
.done(function(data, textStatus, jqXHR) {
if (data.status == "ok")
this.setState({state: data.state});
}.bind(this));
}),
moveUp: React.autoBind(function(event) {
$.post(baseUrl + "stories/up", {'id': this.props.story.id})
.done(function (data, textStatus, jqXHR) {
if (data.status == "ok")
this.props.onMoved(1);
}.bind(this));
}),
moveDown: React.autoBind(function(event) {
$.post(baseUrl + "stories/down", {'id': this.props.story.id})
.done(function (data) {
if (data.status == "ok")
this.props.onMoved(-1);
}.bind(this));
})
});
var StoryTable = React.createClass({
render: function() {
var storyNodes = this.props.data.map(function (story) {
return ;
}.bind(this));
return (
);
}
});
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();
var necessity = this.refs.necessity.getDOMNode().value.trim();
var headline = this.refs.headline.getDOMNode().value.trim();
var content = this.refs.content.getDOMNode().value.trim();
$(".newTaskModal").modal('hide');
this.props.onStorySubmit({role: role,
necessity: necessity,
headline: headline,
content: content});
this.refs.role.getDOMNode().value = '';
this.refs.necessity.getDOMNode().value = '';
this.refs.headline.getDOMNode().value = '';
this.refs.content.getDOMNode().value = '';
return false;
}),
render: function() {
return (
);
}
});
var StoryPage = React.createClass({
loadStoriesFromServer: function() {
$.get(this.state.url)
.done(function(data) {
this.setState({data: []});
this.setState({data: data});
}.bind(this));
},
getInitialState: function() {
return {data: [], url: this.props.url};
},
setUrl: React.autoBind(function(url) {
this.setState({url: url});
}),
componentWillMount: function() {
this.loadStoriesFromServer();
setInterval(
this.loadStoriesFromServer.bind(this),
this.props.pollInterval
);
},
handleStoryMoved: React.autoBind(function (direction) {
this.loadStoriesFromServer();
}),
handleStorySubmit: React.autoBind(function (story) {
$.post(baseUrl + "stories/new", story)
.done(function (data, textStatus, jqXHR) {
if (data.status == "ok")
this.loadStoriesFromServer();
}.bind(this))
.fail(function (jqXHR, textStatus, errorThrown) {
alert("error: " + errorThrown);
}.bind(this));
}),
handleStorySelected: React.autoBind(function (storyId) {
$.get(baseUrl + 'stories/' + storyId)
.done(function (data, textStatus, jqXHR) {
this.refs.data.setData(data);
this.refs.taskForm.setStoryId(data.id);
}.bind(this), 'json');
}),
handleAssigneeClicked: React.autoBind(function (info) {
var form = this.refs.assignmentForm;
form.setInfo(info);
$(".assignModal").modal();
}),
handleTaskSubmit: React.autoBind(function (task) {
$.post(baseUrl + "stories/tasks/new", task)
.done(function(data) {
if (data.status == "ok")
this.refs.data.loadStoryFromServer();
}.bind(this));
}),
render: function() {
return (
);
}
});
var StoryFilter = React.createClass({
getInitialState: function() {
return {filter: 'all'};
},
handleClick: React.autoBind(function(event) {
this.setState({filter: (this.state.filter != 'all'
? 'all' : 'user')});
scrumli_page.setUrl(baseUrl + (this.state.filter == "all"
? "stories" : "stories/mine"));
}),
render: function() {
var classes = {all: ['icon-group', 'All'],
user: ['icon-user', 'Mine']};
return (
{" "} {classes[this.state.filter][1]}
);
}
});
var scrumli_page = ;
React.renderComponent(
scrumli_page,
document.getElementById('content')
);
React.renderComponent(
,
document.getElementById('filter')
);