happs-tutorial 0.1 → 0.2
raw patch · 22 files changed
+482/−1 lines, 22 filesbinary-added
Files
- happs-tutorial.cabal +22/−1
- runServer.sh +1/−0
- static/HAppSTutorialLogo.png binary
- static/tutorial.css +80/−0
- templates/base.st +9/−0
- templates/basic-url-handling.st +54/−0
- templates/favoriteAnimal.st +3/−0
- templates/footer.st +6/−0
- templates/googleanalytics.st +9/−0
- templates/header.st +41/−0
- templates/home.st +24/−0
- templates/home_interpersonal.st +42/−0
- templates/login.st +22/−0
- templates/main-function.st +33/−0
- templates/moreFavoriteAnimals.st +5/−0
- templates/myhomepage.st +11/−0
- templates/prerequisites.st +22/−0
- templates/run-tutorial-locally.st +24/−0
- templates/start-happs-on-boot.st +18/−0
- templates/start-tutorial.st +25/−0
- templates/understanding-happs-types.st +28/−0
- templates/using-templates.st +3/−0
happs-tutorial.cabal view
@@ -1,5 +1,5 @@ Name: happs-tutorial-Version: 0.1+Version: 0.2 Synopsis: A HAppS Tutorial that is is own demo Description: A nice way to learn how to build web sites with HAppS @@ -21,6 +21,27 @@ Stability: Experimental Category: Web Build-type: Simple+Extra-Source-Files:+ runServer.sh+ templates/basic-url-handling.st templates/googleanalytics.st+ templates/run-tutorial-locally.st+ templates/home.st+ templates/understanding-happs-types.st+ templates/start-tutorial.st+ templates/base.st+ templates/login.st+ templates/home_interpersonal.st+ templates/myhomepage.st+ templates/start-happs-on-boot.st+ templates/moreFavoriteAnimals.st+ templates/footer.st+ templates/main-function.st+ templates/header.st+ templates/prerequisites.st+ templates/using-templates.st+ templates/favoriteAnimal.st+ static/tutorial.css+ static/HAppSTutorialLogo.png Cabal-Version: >= 1.2
+ runServer.sh view
@@ -0,0 +1,1 @@+time ghc -isrc --make src/Main.hs; ./src/Main
+ static/HAppSTutorialLogo.png view
binary file changed (absent → 23598 bytes)
+ static/tutorial.css view
@@ -0,0 +1,80 @@+html,body{margin:0;padding:0}++body{font: 85% arial,sans-serif}++/* p{margin:0 10px 10px} */++a{color: #006}++div#header{position:relative}+div#header h1{+ height:70px;line-height:70px;margin:0;+ padding-left:10px;background: #EEE;color: #79B30B}+div#header h4{ + margin:0;+ padding-left:120px;background: #EEE;}+div#header a{background: #EEE;height:80px} ++/* div#content p{line-height:1.4} */++div#content+{+ background-color: white;+ /* padding-left: 10px; */+}+div#content p{+ padding-left: 10px +}+div#content h3{+ padding-left: 5px;+}++div#dealform{+ background:#B9CAFF;+ float:left;+ width:40%;++}+++/* div#dealform{float:left;width:50%} */++div#suggestions{background:#FF8539}+div#suggestions{float:left;width:59.9%}++div#footer{background: #333;color: #FFF}++/* div#footer p{margin:0 0 0 0;padding:5px 10px} */++div#footer a{display:inline;padding:0;color: #C6D5FD}+div#footer{clear:left;width:100%}+++/* .pbox {+ /* border: 2px solid #73a1ca; */+ margin-left:20px; + border-collapse: collapse;+ /*margin: 0 5px 10px 5px;*/+ /*width: 285px;+ padding: 5px;+ float: left;*/+} */++/*+++.dealform { margin: 0px; padding: 0px; }+.dealform table { border-collapse: collapse; }+.dealform td { white-space: nowrap; }+.dealform input.logtxt { color:black; width: 135px}+.dealform td.right { text-align: right}+.dealform button.btn { margin: 0px; padding: 2px 3px 2px 3px}+.dealform a { padding-left: 1em }+++*/++.iform button {background-color:#e9e9e9; border: 1px solid #336699; vertical-align: bottom} +.btn { background-color:#e9e9e9;+ border: 1px solid #336699; + margin: 0 5px 0 5px; vertical-align: bottom }
+ templates/base.st view
@@ -0,0 +1,9 @@+$ header() $+ <div id="content"> + $ contentarea $ + </div> ++$ googleanalytics() $ ++$ footer() $+
+ templates/basic-url-handling.st view
@@ -0,0 +1,54 @@+<h3>Basic Request Handling in HAppS</h3>++<p>One of the most basic functions of a web framework is to give you a way of controlling what happens when a web browser makes an http request.</p>++<p>$! Before explaining the theory of request handling in HAppS, !$ Let's look at some simple examples.</p>++<!-- who cares about MVC?... <p>In the <a href="tk">FIX LINK... MVC paradigm</a> employed by Ruby on Rails and other popular frameworks, this is the task of the Controller. </p> -->++<ol>+ <li> Read the source code of the simpleHandlers function in <a href="/src/ControllerBasic.hs">ControllerBasic.hs</a> to see how urls are handled in HAppS. <b>Pay attention to the comments!</b>+ <li>Follow the urls below by clicking on them. Match what happens when you click on a link with the code in <a href="/src/ControllerBasic.hs">ControllerBasic.hs</a></li>+</ol>++<ul>+ <li>introduction to handlers: <a href="/helloworld">hello world</a></li>++ <li>exactdir and msgToSp (subdirectories of the path argument do not match):+ <a href="/exactdir-with-msgtosp">exactdir-with-msgtosp</a> ... + <a href="/exactdir-with-msgtosp/subdir">exactdir-with-msgtosp/subdir</a> ... ++ </li>+ <li>introduction to dir and msgToSp -- subdirectories *do* match:+ <a href="/dir-with-msgtosp">dir-with-msgtosp</a> ...+ <a href="/dir-with-msgtosp/subdir">dir-with-msgtosp/subdir</a>+ </li>+ <li>gluing handlers together / handlers as monoids: + <a href="/handleraddition1">handleraddition1</a> ... + <a href="/handleraddition2">handleraddition2</a> ...+ <a href="/handleraddition3">handleraddition3</a> ...+ <a href="/handleraddition4">handleraddition4</a> ...+ <a href="/handleraddition5">handleraddition5</a>+ </li>++ <li>the "empty" handler:+ <a href="/nohandle1">nohandle1</a> ...+ <a href="/nohandle2">nohandle2</a>+ </li>++ <li>IO in the response: <a href="/ioaction">IO Response</a> ... + <a href="/ioaction2">Another IO Response</a+ </li>+ <li>Formatted html: <a href="/htmlAttemptWrong">First attempt at formatted html (wrong)</a> ... + <a href="/htmlAttemptRight">Second attempt at formatted html (right)</a>+ </li>++ <li>Serving static files: <a href="/templates/base.st">Using dir and fileserve "templates", we can view templates</a> ... + <a href="/templates/basic-url-handling.st">The template that was used to generate this page</a>+ </li>++</ul> ++<p>The static file serving example above hints at the templating system used by this tutorial to put together web pages behind the scenes.</p>++<p>We learn about <a href="/tutorial/using-templates">using-templates</a> next.</p>
+ templates/favoriteAnimal.st view
@@ -0,0 +1,3 @@+Again, my favorite animal is a $ favoriteAnimal $. (set in another template)+<p>+If I forget to set an attribute (favoriteMammal), it just doesn't display: $ favoriteMammal $
@@ -0,0 +1,6 @@+ <div id="footer">+ <!-- {% block footer %}+ {% endblock %} -->+ </div>+</body>+</html>
+ templates/googleanalytics.st view
@@ -0,0 +1,9 @@+<script type="text/javascript">+var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");+document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));+</script>+<script type="text/javascript">+var pageTracker = _gat._getTracker("UA-4801425-2");+pageTracker._initData();+pageTracker._trackPageview();+</script>
+ templates/header.st view
@@ -0,0 +1,41 @@+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+<head>+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />+ <title> HAppS Tutorial </title>+ <link rel="stylesheet" href="/static/tutorial.css" type="text/css" />+</head>++<body>++ <div id="header">+ <img src="/static/HAppSTutorialLogo.png" alt="HAppS Tutorial">+ <a href="http://h-master.net/web2.0/"><font size=1>logo created by the web 2.0 logo generator</font></a+ <!-- <h1>HAppS Tutorial</h1> -->+ <h4> <a href="/tutorial/home" class="leftitem">Home</a>+ <!-- |<a href="/tutorial/about">About</a>+ |<a href="/tutorial/faq">FAQ</a> + |<a href="/tutorial/contact">Contact</a> -->+ |<a href="/tutorial/login">Login</a>+ |<a href="/view">Logged in as</a>+ |<a href="/list">View all users</a>+ <!-- |<a href="/market/">Marketplace</a>+ |<a href="/market/sendmoney">Send Money Abroad</a> -->+ </h4>+ <h4>+ <!-- {% if userNode %}+ Logged in as: {{ userNode.username|escape}}+ |<a href="/summary/" class="leftitem">Summary</a>+ |<a href="/accounts/">Credit Relationships</a>+ |<a href="/payments/">Payments</a>+ |<a href="/profile/">Profile</a>+ |<a href="/inbox/"> <img src="/site_media/inbox-nomail.png"> </a>+ |<a href="/logout/">Log out</a>+ {% else %}+ <a href="/login/" class="leftitem">Log in</a>+ |<a href="/register/">Sign up</a> + {% endif %} -->+ + </h4>+ </div>
+ templates/home.st view
@@ -0,0 +1,24 @@+<h3>Why another HAppS Tutorial?</h3>++<p><a href="http://www.haskell.org">Haskell</a> is a <a href="http://www.google.com/search?hl=en&q=why+haskell">great way to program</a>.</p>++<p>And <a href="http://www.happs.org">HAppS</a> is a great way to build web applications.</p>++$! <p>Unfortunately, the HAppS documentation is sorely lacking. Without good documentation, even something as trivial as <a href="http://www.google.com/search?hl=en&q=hello+world+happs">hello world</a> can seem to take a Ph.D. in HAppSology.</p>++<p>I created this tutorial to show that this isn't so, and to popularize the use of my favorite language,+haskell, in web applications. </p> !$++<p>I created this tutorial to popularize the use of my favorite language, haskell, in web applications. </p>++<p>This tutorial is its own demo. For best results, you should <a href="/tutorial/run-tutorial-locally">install and run</a> it in a local environment where you have control. Then, when you are done learning, you can use the tutorial code as a template for your own HAppS applications.</p>++<p>If you use Ruby on Rails, Django, Perl Catalyst, PHP, or some other popular web framework, but+have programmed in haskell and would like to use the world's greatest language for your next web project,+this tutorial will give you all the knowledge you need.</p>++$! <p>No Ph.D. required. <sup>®</sup></p> !$++<p><a href="/tutorial/prerequisites/">Prerequisites</p>+<p><a href="/tutorial/start-tutorial">Start The Tutorial.</a></p>+<p><a href="http://code.haskell.org/happs-examples">Browse The Source</a></p>
+ templates/home_interpersonal.st view
@@ -0,0 +1,42 @@+{% extends "base.html" %}+{% block content %}+++ <p>RippleDeals is a marketplace where you buy on credit+ granted by people who trust you. Or you sell on credit, which+ is guaranteed by people you trust. Credit is used in a+ person-to-person <a href="/creditpath">credit path</a> which can be many people+ long.</p><!--+ <p>Instead of letting the banking system determine your credit, you trust the people in your life w+ ho have earned it.</p>-->++ <p>Since RippleDeals doesn't depend on the banking system,+ you can do deals without using credit cards, writing a check,+ or handling cash.</p>++ <p>You also have a simple way to start doing business in+ emerging currencies such as community currencies and digital+ gold, or even online gaming currencies. Of course, dollars,+ euro, and other mainstream national currencies are fine+ too.</p><!--+++ <p>Since credit flows along a trust chain, where each link has a high degree of confidence in the next,+ scams that are common in other online marketplaces simply won't work here. </p>+ -->++ <p>RippleDeals is free.</p>+++ {% include "dealsearch.html" %}++{% endblock %}+++++{% block footer %}+ <!-- users: {{ num_users }}<br>+ accounts: {{ num_accounts }}<br>+ payments: {{ num_payments }}<br> -->+{% endblock %}
+ templates/login.st view
@@ -0,0 +1,22 @@+<div id="create">+<h1>Register</h1>+<form action="/newuser" method="post">+<label>Username:<input type="textfield" name="username"/></label>+<br/>+<label>Password:<input type="textfield" name="password"/></label>+<br/>+<label>Verify Password:<input type="textfield" name="password2"/></label>+<br/>+<input type="submit" name="create" value="Create Account">+</form>+</div>+<div id="login">+<h1>Log In</h1>+<form action="/login" method="post">+<label>Username:<input type="textfield" name="username"/></label>+<br/>+<label>Password:<input type="textfield" name="password"/></label>+<br/>+<input type="submit" name="create" value="Log in">+</form>+</div>
+ templates/main-function.st view
@@ -0,0 +1,33 @@+<h3>Where it all begins: the function main</h3>++<p>Have a look at <a href="/src/Main.hs">main</a> function at the core of this web application.</p>++<p>Two bits of code that should jump out at you as being important are "entrypoint" and "controller".</p>++<p>So, open this file in ghci: cd src; ghci Main.hs and have a look at these functions using ghci :i .</p>++<p>*Main> :info entryPoint+<br>entryPoint :: HAppS.Data.Proxy.Proxy Session.State+<br> -- Defined at <a href="/src/Model.hs">Model.hs</a>...+<br>*Main> :i controller+<br>controller :: [ServerPartT IO Response]+<br> -- Defined at <a href="/src/Controller.hs">Controller.hs</a>...+</p>++<p>The entrypoint function has to do with the HAppS state system, and we'll pospone learning about it for later.</p>++<p>The controller function is a list of ServerPartTs, which are basically handlers that+accept an HTTP request and return a response. We look at what is going on in the controller code in+<a href="/tutorial/basic-url-handling">basic url handling</a>, next.+</p>++$! +<p>Now you have a choice about what to read next.</p>++<p>If you are in a hurry to write a HAppS application without delving too much into what's going on behind the scenes,+read , which looks at what's happening in the controller code.</p>++<p>If you want to understand the HAppS type system in more detail, read <a href="understanding-happs-types">understanding HAppS types</a>.+</p>+!$+
+ templates/moreFavoriteAnimals.st view
@@ -0,0 +1,5 @@+More Favorite Animals: +<p>+$ favoriteAnimals $+<p>+<a href="myHomepage.html">Back to my homepage</a>
+ templates/myhomepage.st view
@@ -0,0 +1,11 @@+<html>+ This is my homepage.+ <p>+ It is generated using HStringTemplate.+ <p>+ My favorite animal is a: $ favoriteAnimal $ (set with setAttribute)+ <p>+ $ favoriteAnimal() $ + <p>+ <a href="moreFavoriteAnimals.html">More Favorite Animals</a>+</html>
+ templates/prerequisites.st view
@@ -0,0 +1,22 @@+<h3>Prerequisites</h3>++<p>For best results with this tutorial, you hopefully have the following.</p>++<ul>+ <li>Basic knowledge of haskell and html.</li>+ <li>A somewhat modern computer. I have a PIII laptop with 512M of ram. </li>+ <li>A modern operating system. You should be able to develop haskell applications using windows, mac, or linux. For the record, I work with the latest <a href="http://www.ubuntu.com">ubuntu</a> linux distribution, which is currently hardy heron.</li>+ <li>If you want to create a public web site based on the materials here, I recommend getting either a private server (more expensive) or a virtual private server (less expensive) which gives you admin priviliges to install the packages and software you need. I use the cheapest virtual private server plan at <a href="http://www.linode.com">linode</a> to host this tutorial publicly. I wouldn't try hosting a HappS project publicly using a shared hoster like <a href="http://www.dreamhost.com">dreamhost</a> that doesn't give you root powers to administer your server. (Dreamhost is great for other things, like cheap storage for online images.)</li>+ <li>More requirements are described in the instructions for+ <a href="/tutorial/run-tutorial-locally">installing and running this tutorial locally</a>.+ However, if you have the basics ingredients above you should be okay.+ </li>+ <li>Please let me know -- or patch the tutorial -- if I forgot something. I hate getting stuck on some finicky aspect of installation when I am trying to learn something.</li>+</ul>++<p><a href="/tutorial/start-tutorial">Get started!</a></p>+++ ++</ul>
+ templates/run-tutorial-locally.st view
@@ -0,0 +1,24 @@+<h3>Run This Tutorial Locally</h3>++<p> Before going further, you may want to inform yourself about the <a href=/tutorial/prerequisites>basic prerequisites</a>, both knowledge and equipment, you need to make the best use of this tutorial </p>++<p>This tutorial is cabalized. You can install and run it simply by doing: sudo cabal install happs-tutorial. You should then be able to run the resulting binary and view the tutorial offline at http://localhost:5001.</p>++<p>The cabal installation may take up to an hour, mainly because the HAppS-Server installation is slow, but it should succeed in one shot. Incidentally, the fact that installing HAppS takes this long is arguably a <a href="http://code.google.com/p/happs/issues/detail?id=29">bug</a>. Hopefully this situation will be remedied as HAppS matures and, eventually, has an official release</p>++<p>If you've never used cabal install or need more detailed info....</p>++<ul>+ <li>Haskell: You need at least ghc 6.8.2 to install HAppS. I installed this with with apt-get install haskell (works for ubuntu hardy heron), and then <a href="http://www.haskell.org/ghc/download.html">upgraded to ghc 6.8.3</a> as this is supposed to have fixed some bugs.</li> + <li>Dependency chasing haskell package installers: you should have the latest versions of cabal and cabal install from <a href="http://hackage.haskell.org/packages/archive/pkg-list.html">hackage</a>. These are already included in the latest version of ghc, or they will be soon. Another reason to upgrade to ghc 6.8.3.</li>+ <li>If you want to check out the latest version of this tutorial, install <a href="http://www.darcs.net">Darcs</a> and check out the repo with darcs get http://code.haskell.org/happs-examples</li>+ <li>cabal installs the tutorial at /home/yourdir/.cabal/bin/happs-tutorial. In practice, I usually recompile and run changed code by executing ./runServer.sh, in the top project directory.</li>+ <li>You should now be able to browse this tutorial offline by running the executable, and opening http://localhost:5001 in your browser.</li>+ <li>You may also want to <a href="start-happs-on-boot">start HAppS on boot</a>.</li>+ </ul>++<p><a href="/tutorial/start-tutorial">Get started!</a></p>++++
+ templates/start-happs-on-boot.st view
@@ -0,0 +1,18 @@+<h3>Start HAppS Automatically At Boot Time</h3>++<p>What happens if your HAppS deployment server experiences a power outage?</p>++<p>The following instructions are one way to get your HAppS application to start up automatially when the machine is booted.</p>++<p>cp /etc/init.d/ssh /etc/init.d/happs-app</p>++<p>edit that to do the right thing with Main.exe executable.</p>++<p>install it into the linux init with</p>++<p>sudo update-rc.d happs-app multiuser</p>++<p>this is all +++<p>These instructions are valid (at least) for debian/ubuntu, loosely following instructions at the <a href="http://www.debian.org/doc/debian-policy/ch-opersys.html#s9.3.3">debian policy manual</a>.</p>
+ templates/start-tutorial.st view
@@ -0,0 +1,25 @@+<h3>Get Started Learning HAppS</h3>++<p>Like the <a href="/tutorial/home">home</a> page says, the best way to learn how to use use HAppS with this tutorial is to actually <a href="/tutorial/run-tutorial-locally">install and run</a> it in a local environment.</p>++<p>So, step 1 is to <a href="/tutorial/run-tutorial-locally">install and run this tutorial locally</a></p>++<p>Getting on with the tutorial proper, our first lesson examines the <a href="/tutorial/main-function">main function</a> in a HAppS program.++<p>The second lesson explains how to do <a href="/tutorial/basic-url-handling">basic url handling</a>.</p>++<p>The third lesson covers <a href="/tutorial/using-templates">using templates</a>.</p>++<p>More lessons are planned. This is a work in progress. Stay tuned.</p>++$! <p>Lesson 2 is <a href="/tutorial/using-templates">using templates</a</p> !$+ +$! <p>Lesson 3 is <a href="/tutorial/managing-state">managing state</a></p> !$++++++++
+ templates/understanding-happs-types.st view
@@ -0,0 +1,28 @@++<p>I find it helpful to have ghci tell me about the types in the code I am reading. Here is a snip of ghci output.</p>++<p>+<br>*Main>:i simpleHTTP+<br>simpleHTTP :: (ToMessage a) => Conf -> [ServerPartT IO a] -> IO ()+<br> -- Defined in HAppS.Server.SimpleHTTP+<br>*Main>:i Conf+<br>data Conf = Conf {port :: Int}+<br> -- Defined in HAppS.Server.HTTP.Types+<br>*Main> :i ServerPartT+<br>newtype ServerPartT m a+<br> = ServerPartT {unServerPartT :: Request -> WebT m a}+<br> -- Defined in HAppS.Server.SimpleHTTP+<br>instance [overlap ok] (Monad m) => Monad (ServerPartT m)+<br> -- Defined in HAppS.Server.SimpleHTTP+<br>*Main> :i WebT+<br>newtype WebT m a = WebT {unWebT :: m (Result a)}+<br> -- Defined in HAppS.Server.SimpleHTTP+<br>instance [overlap ok] (Monad m) => Monad (WebT m)+<br> -- Defined in HAppS.Server.SimpleHTTP+</p>++<p>So basically what this tells you is that the meat of a HAppS application is a list of ServerParts, which themselves are a wrapper over a function that takes an HTTP request to a response.</p>++<p>I use ghci info a lot, and you should too as you are learning HAppS. This kind of comfort with the HAppS type system is particularly important at the present time, when the HAppS documentation is relatively sparse</p>++<p>... also read read TK happs-tutorial2 for a more in-depth look at HAppS and the HAppS type system. </p>
+ templates/using-templates.st view
@@ -0,0 +1,3 @@+<ul>+ <li><a href="/usingtemplates/testtgio">my favorite animal</li></li>+</ul>