aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--defmodule.lisp3
-rw-r--r--pg-datastore.lisp7
-rw-r--r--scrumli.lisp6
-rw-r--r--static/js/main.js37
-rw-r--r--templates/scrumli.tmpl1
5 files changed, 51 insertions, 3 deletions
diff --git a/defmodule.lisp b/defmodule.lisp
index 3ca601a..9381d31 100644
--- a/defmodule.lisp
+++ b/defmodule.lisp
@@ -25,6 +25,9 @@
(define-method get-all-stories ()
"Get all of the stories in the datastore.")
+ (define-method get-stories-for (username)
+ "Get all of the storiess for USERNAME.")
+
(define-method get-story (id)
"Get a story from the datastore.")
diff --git a/pg-datastore.lisp b/pg-datastore.lisp
index 39e2646..5505de1 100644
--- a/pg-datastore.lisp
+++ b/pg-datastore.lisp
@@ -60,6 +60,13 @@
(query (:order-by (:select :* (:as (:md5 'assignee) 'md5)
:from 'story) 'priority) :alists)))
+(defmethod datastore-get-stories-for ((datastore pg-datastore) username)
+ (with-connection (connection-spec datastore)
+ (query (:order-by (:select :* (:as (:md5 'assignee) 'md5)
+ :from 'story
+ :where (:= 'assignee username))
+ 'priority) :alists)))
+
(defmethod datastore-get-story ((datastore pg-datastore) id)
(with-connection (connection-spec datastore)
(append (query (:select :* (:as (:md5 'assignee) 'md5) :from 'story
diff --git a/scrumli.lisp b/scrumli.lisp
index df6b442..14a2cdd 100644
--- a/scrumli.lisp
+++ b/scrumli.lisp
@@ -102,6 +102,12 @@
(encode-json-to-string (get-all-stories))
403))
+(define-route my-stories-json ("stories/mine" :content-type "text/json")
+ (if (logged-in-p)
+ (encode-json-to-string (get-stories-for
+ (hunchentoot:session-value :username)))
+ 403))
+
(defmacro with-post-parameters (parameters &body body)
`(let ,(mapcar (lambda (p)
(list (intern (string-upcase p))
diff --git a/static/js/main.js b/static/js/main.js
index c20c615..457bd6f 100644
--- a/static/js/main.js
+++ b/static/js/main.js
@@ -393,15 +393,18 @@ var StoryForm = React.createClass({
var StoryPage = React.createClass({
loadStoriesFromServer: function() {
- $.get(this.props.url)
+ $.get(this.state.url)
.done(function(data) {
this.setState({data: []});
this.setState({data: data});
}.bind(this));
},
getInitialState: function() {
- return {data: []};
+ return {data: [], url: this.props.url};
},
+ setUrl: React.autoBind(function(url) {
+ this.setState({url: url});
+ }),
componentWillMount: function() {
this.loadStoriesFromServer();
setInterval(
@@ -456,7 +459,35 @@ var StoryPage = React.createClass({
}
});
+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((this.state.filter == "all"
+ ? "/stories" : "/stories/mine"));
+ }),
+ render: function() {
+ var classes = {all: ['icon-group', 'All'],
+ user: ['icon-user', 'Mine']};
+
+ return (<a onClick={this.handleClick}>
+ <i class={classes[this.state.filter][0] + ' icon-light'}></i>
+ {" "} {classes[this.state.filter][1]}
+ </a>);
+ }
+});
+
+var scrumli_page = <StoryPage url="/stories" pollInterval={5000} />;
+
React.renderComponent(
- <StoryPage url="/stories" pollInterval={5000} />,
+ scrumli_page,
document.getElementById('content')
);
+
+React.renderComponent(
+ <StoryFilter />,
+ document.getElementById('filter')
+);
diff --git a/templates/scrumli.tmpl b/templates/scrumli.tmpl
index 62e8eec..b86c4be 100644
--- a/templates/scrumli.tmpl
+++ b/templates/scrumli.tmpl
@@ -43,6 +43,7 @@
</span>
</li>
<li class="divider-vertical"></li>
+ <li id="filter"></li>
<li><a href="{$ulogout}">Logout</a></li>
<li class="divider-vertical"></li>
</ul>