1. Rufus Pollock
  2. commentonit

Commits

Rufus Pollock  committed d3a23b7

[show/edit,show/view,lists/index,tests][l]: implement basic view and index action for document and improve edit (esp look and feel).

  • Participants
  • Parent commits 9ff330f
  • Branches couchdb

Comments (0)

Files changed (8)

File _attachments/style/master.css

View file
   line-height: 24px;
 }
 
+#content .entry-title {
+  margin-bottom: 20px;
+}
+
+form.doc-edit input, form.doc-edit textarea {
+  width: 80%;
+}
+
+textarea.doc-body {
+  height: 400px;
+}

File couchapp.json

View file
 {
-    "name": "CommentOnIt",
+    "name": "Comment On It",
     "description": "Inline Commenting on Stuff",
-    "index" : "_show/edit"
+    "index" : "_list/index/recent-items"
 }

File lists/index.js

View file
+function(head, req) {
+	var ddoc = this;
+	var Mustache = require("vendor/couchapp/lib/mustache");
+	var List = require("vendor/couchapp/lib/list");
+	var path = require("vendor/couchapp/lib/path").init(req);
+	var Atom = require("vendor/couchapp/lib/atom");
+
+	var indexPath = path.list('index','recent-posts',{descending:true, limit:10});
+	var feedPath = path.list('index','recent-posts',{descending:true, limit:10, format:"atom"});
+
+	var path_parts = req.path;
+	// The provides function serves the format the client requests.
+	// The first matching format is sent, so reordering functions changes 
+	// thier priority. In this case HTML is the preferred format, so it comes first.
+	provides("html", function() {
+		var key = "";
+		// render the html head using a template
+		var stash = {
+			header : {
+				index : indexPath,
+				blogName : ddoc.couchapp.name,
+				feedPath : feedPath,
+			},
+			scripts : {},
+			db : req.path[0],
+			design : req.path[2],
+			feedPath : feedPath,
+			newPostPath : path.show("edit"),
+			assets : path.asset(),
+			posts : List.withRows(function(row) {
+				var post = row.value;
+				key = row.key;
+				return {
+					title : post.title,
+					author : post.author,
+					date : post.created_at,
+					link : path.show('view', post._id),
+					has_tags : post.tags ? true : false,
+					tags : post.tags && post.tags.map ? post.tags.map(function(tag) {
+						var t = tag.toLowerCase();
+						return {
+							tag : tag,
+							link : path.list("index", "tags", {
+								descending : true, 
+								reduce : false, 
+								startkey : [t, {}], 
+								endkey : [t]
+							})
+						}
+					}) : []
+				};
+			}),
+			older : function() {
+				return path.older(key);
+			},
+			"5" : path.limit(5),
+			"10" : path.limit(10),
+			"25" : path.limit(25)
+		};
+		return Mustache.to_html(ddoc.templates.index, stash, ddoc.templates.partials, List.send);
+	});
+
+	// if the client requests an atom feed and not html, 
+	// we run this function to generate the feed.
+	provides("atom", function() {		
+		var path = require("vendor/couchapp/lib/path").init(req);
+		var markdown = require("vendor/couchapp/lib/markdown");
+
+		// we load the first row to find the most recent change date
+		var row = getRow();
+		
+		// generate the feed header
+		var feedHeader = Atom.header({
+			updated : (row ? new Date(row.value.created_at) : new Date()),
+			title : ddoc.blog.title,
+			feed_id : path.absolute(indexPath),
+			feed_link : path.absolute(feedPath),
+		});
+		
+		// send the header to the client
+		send(feedHeader);
+
+		// loop over all rows
+		if (row) {
+			do {
+				if (row.value.format == "markdown") {
+					var html = markdown.encode(row.value.body);
+				} else {
+					var html = Mustache.escape(row.value.html);
+				}
+				// generate the entry for this row
+				var feedEntry = Atom.entry({
+					entry_id : path.absolute('/'+encodeURIComponent(req.info.db_name)+'/'+encodeURIComponent(row.id)),
+					title : row.value.title,
+					content : html,
+					updated : new Date(row.value.created_at),
+					author : row.value.author,
+					alternate : path.absolute(path.show('post', row.id))
+				});
+				// send the entry to client
+				send(feedEntry);
+			} while (row = getRow());
+		}
+
+		// close the loop after all rows are rendered
+		return "</feed>";
+	});
+};

File shows/view.js

View file
+function(doc, req) {
+	var ddoc = this;
+	var Mustache = require("vendor/couchapp/lib/mustache");
+	var path = require("vendor/couchapp/lib/path").init(req);
+	var markdown = require("vendor/couchapp/lib/markdown");
+
+	var editPath = path.show('edit', doc._id);
+
+	var data = {
+		header : {
+			blogName : ddoc.couchapp.name,
+		},
+		scripts : {},
+		pageTitle : "View: "+doc.title,
+		assets : path.asset(),
+		editLink: editPath
+	};
+	
+	data.doc = JSON.stringify(doc);
+	data.title = doc.title;
+	if (doc.format == "markdown") {
+		var html = markdown.encode(doc.body);
+	} else {
+		var html = doc.body;
+	}
+	data.body = html;
+	data.tags = doc.tags.join(", ");
+
+	return Mustache.to_html(ddoc.templates.view, data, ddoc.templates.partials);
+}

File templates/edit.html

View file
     {{>header}}
 
-    <h1>{{pageTitle}}</h1>
+    <h1 class="entry-title">{{pageTitle}}</h1>
     <!-- form to create a post -->
-    <form id="new-post" action="new.html" method="post">
-        <p><label>Title</label>
-          <input type="text" name="title" value="{{title}}"></p>
-      <p><label for="body">Body</label>
-      <textarea name="body">{{body}}</textarea></p>
-      <p>
+    <form id="new-post" action="new.html" method="post" class="doc-edit">
+      <dl>
+        <dt>
+          <label>Title</label>
+        </dt>
+        <dd>
+          <input type="text" name="title" value="{{title}}" class="doc-title" />
+        </dd>
+        <dt>
+          <label for="body">Body</label>
+        </dt>
+        <dd>
+          <textarea name="body" class="doc-body">{{body}}</textarea></p>
+        </dd>
+        <dt>
         <label for="tags">Click tags to add them. (split by ',')</label>
+        </dt>
+        <dd>
         <input type="text" name="tags" value="{{tags}}">
-      </p>
-      <p>
-        <input id="preview" type="button" value="Preview"/>
-        <input type="submit" value="Save &rarr;"/> 
-        <span id="saved" style="display:none;">Saved</span>
-      </p>
+        </dd>
+      </dl>
+      <input id="preview" type="button" value="Preview"/>
+      <input type="submit" value="Save &rarr;"/> 
+      <span id="saved" style="display:none;">Saved</span>
     </form>
     <a target="_new" href="http://warpedvisions.org/projects/markdown-cheat-sheet/">Markdown help</a>
     <div id="show-preview"></div>
         if (!postDoc.created_at) {
           postDoc.created_at = new Date();
         }
-        if (!postDoc._id) {
-          postDoc._id = postDoc.title;
-        }
         app.db.saveDoc(postDoc, {
           success : function(resp) {
             $("#saved").text("Saved _rev: "+resp.rev).fadeIn(500).fadeOut(6000);
-            $('h1').html('Editing <a href="'+path.show('doc',resp.id)+'">'+resp.id+'</a> by '+postDoc.author);
+            console.log(resp);
+            alert(resp);
+            $('h1.entry-title').html('Updated successfully. <a href="'+path.show('view',resp.id)+'">View document</a>.');
           }
         });
         return false;

File templates/index.html

View file
+    {{>header}}
+
+    <h1>Recently...</h1>
+    <ul id="posts">
+      {{#posts}}
+        <li>
+          <h3><a href="{{ link }}">{{ title }}</a></h3>
+          {{#has_tags}}
+            <div class="tags">
+              {{#tags}}
+                <a href="{{link}}">{{tag}}</a>
+              {{/tags}}
+            </div>
+          {{/has_tags}}
+          <div class="by">
+            <span class="date">{{ date }}</span> 
+            by {{author}}
+          </div>
+        </li>
+      {{/posts}}
+    </ul>
+    <div class="paginate">
+      <a href="{{ older }}">Older entries</a>
+      <a href="{{5}}">5</a>
+      <a href="{{10}}">10</a>
+      <a href="{{25}}">25</a>      
+    </div>
+
+  {{>footer}}
+
+  {{>scripts}}
+</html>

File templates/view.html

View file
+    {{>header}}
+
+    <h1>{{title}} [<a href="{{editLink}}">Edit</a>]</h1>
+
+    <div class="document-body">
+      {{{body}}}
+    </div>
+
+    <div class="tags">
+      {{tags}}
+    </div>
+
+  {{>footer}}
+
+  {{>scripts}}
+</html>

File tests/test-edit.html

View file
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:5984/" />
+<title>test-edit</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">test-edit</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/commentonit/_design/commentonit/_show/edit</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>title</td>
+	<td>Test Document 1</td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>itsalltext_generated_id_body_1</td>
+	<td>Some test text</td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>tags</td>
+	<td>onetag, twotag</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//input[@value='Save →']</td>
+	<td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>