Commits

Maciej Fijalkowski committed 35b4c8e Draft

implement most of the web iface

Comments (0)

Files changed (6)

 
         parse_contents(0, self.render().encode('utf-8'))
 
+    def add_comment(self, comment):
+        self.comments.append(comment)
+        # a bit tricky since we have to append to _rawsource
+        if hasattr(self, '_rawsource'):
+            self._rawsource += '\n\n' + comment.render()
+
     def render(self):
         if hasattr(self, '_rawsource'):
             return self._rawsource

trakker/server.py

 runtrakker <directory>
 """
 
-from flask import Flask
+from flask import Flask, request
 from flask import render_template
 
 from docutils.core import publish_parts
 
 from trakker.storage import Storage
+from trakker.model import Comment
+
+from datetime import datetime
 
 SETTINGS = {'no_doctype': True,
             'embed_stylesheet': False}
     def __init__(self, raw_issue):
         self.title = raw_issue.title
         self.full_body = self.render(raw_issue.render())
+        self.author = raw_issue.fields.get('author', 'unknown')
+        self.date = raw_issue.fields.get('date', 'unknown')
+        self.num = raw_issue.num
 
     def render(self, txt):
         return publish_parts(txt, writer_name='html4css1',
     
     def __init__(self, storage):
         self.storage = storage
+        self.list_issues()
     
     def index(self):
         return render_template('index.html')
         if self.rendered_issues:
             return self.rendered_issues
         issues = []
+        issue_map = {}
         for i, issue in enumerate(self.storage.issues):
-            issues.append((i, RenderedIssue(issue)))
+            issues.append(RenderedIssue(issue))
+            issue_map[issue.num] = i, issue
         self.rendered_issues = issues
+        self.issue_map = issue_map
         return issues
 
+    def post_comment(self):
+        comment = request.form['comment']
+        num = int(request.form['num'])
+        author = request.form['author']
+        now = datetime.now().strftime('%Y-%M-%d %H:%m')
+        index, issue = self.issue_map[num]
+        issue.add_comment(Comment(author, now, comment))
+        self.rendered_issues[index] = RenderedIssue(issue)
+        return self.rendered_issues[index].full_body
+
     def render_list_issues(self):
         return render_template('listissues.html', issues=self.list_issues())
 
     server = Server(Storage(argv[0]))
     app.route("/")(server.index)
     app.route("/listissues")(server.render_list_issues)
+    app.route("/post_comment", methods=['POST'])(server.post_comment)
     app.run(debug=True, use_reloader=False)
     return 0

trakker/static/main.js

+
+current = -1;
 
 function filter(elem, search_val)
 {
 
 function openissue(num)
 {
-    $("#issue" + num).toggle()
+    if (current != -1 && num != current) {
+        $("#issue" + current).toggle();
+    }
+    $("#issue" + num).toggle();
+    if (num != current) {
+        var pos = $("#issue" + num).position().top - 50;
+        $.scrollTo(pos, 200, {axis: 'y'});
+        current = num;
+    }
+}
+
+function post(num)
+{
+    var new_comment = $("#txt" + num).val();
+    var new_author = $("#author" + num).val();
+    $.post("/post_comment",
+           {'num': num, 'comment': new_comment, 'author': new_author},
+           function (res) {
+               $("#issuebody" + num).html(res);
+               $("#txt" + num).val("");
+           });
 }
 
 $(document).ready(function () {
     $.get("listissues", function (data) {
+        var loc = window.location.href;
+        var num = parseInt((loc.substr(loc.lastIndexOf('/') + 2)));
         $("#list").html(data);
+        if (num) {
+            openissue(num);
+        }
         $("#searchbox").focus();
     });
     $("#searchbox").keydown(function () {

trakker/static/style.css

+
+body {
+    font: 16px Helvetica;
+}
 
 #main {
     margin-top: 50px;
     width: 80%;
 }
 
+.literal-block {
+    border: 1px solid black;
+    padding: 20px;
+    font-size: 10pt;
+    font-family: Monaco, "DejaVu Sans Mono", "Bitstream Vera Sans Mono", monospace;
+}
+
+.banner {
+    margin-top: 5px;
+}
+
+.author {
+    color: #922;
+    display: inline;
+}
+
+.date {
+    color: #292;
+    display: inline;
+    margin-left: 100px;
+}
+
+.txtarea {
+    width: 100%;
+}
+
+.submit {
+    padding: 5px;
+}
+
 .issuepreview {
 //    height: 30px;
     padding: 10px;
     border-bottom: 1px solid #ccc;
+    background: #f5f5f5;
+    font-size: 10pt;
 }
 
 .issuepreview:hover {
     background: #eee;
+    cursor: pointer;
+}
+
+.issuethumb:hover {
+    color: blue;
 }
 
 #searchboxcontainer {
 
 #searchbox {
     font: 20px Helvetica;
+    margin-right: 50px;
 }
 
 .issuelist {
     list-style-type: none;
+    padding-left: 30px;
 }
 
 .issuethumb {
     font: 20px Helvetica;
     margin: 0px;
-}
+}

trakker/templates/index.html

 <head>
    <link rel="stylesheet" type="text/css" href="/static/style.css"/>
    <script src="/static/jquery.min.js"></script>
+   <script src="/static/jquery.scrollTo-1.4.2-min.js"></script>
    <script src="/static/main.js"></script>
 </head>
 <body>
   <div id="main">
-    <div id="searchboxcontainer"><input id="searchbox" size="50" type="text"></input></div>
+    <div id="searchboxcontainer">Search: <input id="searchbox" size="50" type="text"></input><a href="#">Help</a></div>
     <div id="list"></div>
   </div>
 </body>

trakker/templates/listissues.html

 <ul class="issuelist">
-  {% for i, issue in issues %}
+  {% for issue in issues %}
      <li class="issuepreview">
-       <p class="issuethumb">
-         <a href="#{{ i }}" onclick="openissue({{ i }})">
-           {{ issue.title }}
-         </a>
+       <p class="issuethumb" onclick="openissue({{ issue.num }})">
+         {{ issue.title }}
        </p>
-       <div id="issue{{ i }}" style="display: none">
+       <div id="issue{{ issue.num }}" style="display: none">
+         <div class="banner">
+         <p class="author">{{ issue.author }}</p>
+         <p class="date">{{ issue.date }}</p>
+         </div>
+         <div id="issuebody{{ issue.num }}">
          {{ issue.full_body|safe }}
+         </div>
+         <div>
+           <textarea id="txt{{ issue.num }}" class="txtarea" rows="15"></textarea>
+           <div class="submit" >
+             Author: <input id="author{{ issue.num }}" class="authorinput"></input>
+             <a href="#" onclick="post({{ issue.num }}); return false;">submit</a>
+           </div>
+         </div>
        </div>
      </li>
   {% endfor %}