/* appjet:version 0.1 */
import("storage", "quickforms");
import("lib-datestrings");

// Database
if (! storage.posts) { storage.posts = new StorableCollection(); }
if (! storage.seed) { storage.seed = Math.floor(Math.random() * 1e9); }

// favicon.ico
page.head.write(toHTML(
    LINK({rel: "shortcut icon",
          href: "http://appjet.com/favicon.ico"})));

// Redefine print to print into a contentDiv
var contentDiv = DIV({'class': "content"});
var realprint = print;
var print = function() { 
    contentDiv.push.apply(contentDiv, Array.prototype.slice.call(arguments));
}

import("lib-start");
import("lib-admin");
import("lib-atom");

// For adding/editing a ChangeLog entry.
function ChangeLogInputForm(prop) {
    var form = new QuickForm({action: "/clmod", method: "post"});
    form.addHeading("h", (prop && prop.id ? "Edit CL" : "Add a new CL"));
    form.addInputTextArea("summary", {label: "Summary", cols: 60, rows: 3,
                                      value: (prop ? prop.summary : undefined)});
    form.addInputTextArea("diff", {label: "Changes", cols: 60, rows: 30,
                                   value: (prop ? prop.diff : undefined)});
    if (prop && prop.id) {
        form.addInputHidden("modid", prop.id);
    }
    form.addSubmit("submit", "Submit");
    return form;
}

// Object for displaying a changelog entry.
function ChangeLogDisplay(obj, f) {
    var n = (typeof(f) == 'function' ? f(obj) : obj);
    this.toHTML = function() {
        return supplant(n, """
<div class="cl">
<div class="cldate"><a href="/change?id={id}">{date}</a></div>
<div class="cldiff">{diff}</div>
<div class="edit">{edit}</div>
</div>""");
    }
}

// Takes a StorableObject and converts it to the format the ChangeLogDisplay expects
function CLConverter(obj) {
    var ret = {
        id: obj.id,
        date: (new Date(obj.date)).toLocaleDateString(),
        diff: obj.diff,
        summary: obj.summary
    };
    if (isAdmin()) {
        ret.edit = toHTML(A({href: "/edit?id="+obj.id }, "edit"));
    } else {
        ret.edit = ""
    }
    return ret;
}

// Page display
function printHeading() {
    print(
        DIV({id: "head"},
            A({href: "/", id: "headlink"},
              IMG({src: "http://appjet.com/img/aug/frontlogo.gif",
                   height: 60 })),
            SPAN({id: "headtitle"}, "Recent Changes")),
        DIV({className: "clearfloats"}, html("<!-- -->")),
        DIV({id: "secondHead"},
             DIV({id: "backlink"},
                 A({href: "http://appjet.com/"}, html("&laquo; Back to AppJet"))),
             DIV({id: "rsslink"},
                 A({href: "/feed", style: "text-decoration: none;"},
                   IMG({src: "http://www.blogsmithmedia.com/www.engadget.com/media/feedicon_small.gif"}),
                   html("&nbsp;&nbsp;RSS Feed")))),
        DIV({className: "clearfloats"}, html("<!-- -->")));
}

function printFirstN(n) {
    page.head.write(toHTML(LINK({rel: "alternate", title: "AppJet ChangeLog Atom Feed", 
                                 href: "http://changelog.appjet.com/feed", 
                                 type: "application/atom+xml"})));
    printHeading();
    var dateSorted = storage.posts.sortBy("-date")
    dateSorted.limit(n).forEach(function(obj) {
        print(new ChangeLogDisplay(obj, CLConverter));
    });
    dateSorted.skip(n).forEach(function(obj) {
        print(DIV({className: 'cl'},
                  A({href: "/change?id="+obj.id, className: 'cllink'},
                    "Earlier change on "+obj.date.toLocaleDateString()+
                    " at "+obj.date.toLocaleTimeString())));
    });
    if (isAdmin()) {
        print(ChangeLogInputForm());
    }
}

// Index
function get_() {
    printFirstN(10);
}

function get_all() {
    printFirstN(10000);
}   

function post_clmod() {
    if(! isAdmin())
        response.redirect("/");
    if (request.params.modid) {
        var o = getStorable(request.params.modid);
        o.summary = request.params.summary;
        o.diff = request.params.diff;
    } else {
        storage.posts.add({date: new Date(), summary: request.params.summary,
                           diff: request.params.diff});
    }
    response.redirect("/");
}

function get_edit() {
    storage.posts.sortBy("-date").forEach(function(obj) {
        if (obj.id == request.params.id) {
            print(new ChangeLogInputForm(CLConverter(obj)));
        } else {
            print(new ChangeLogDisplay(obj, CLConverter));
        }
    });
}

function get_change() {
    printHeading();
    var o = getStorable(request.params.id);
    if (! o)
        response.notFound();
    print(new ChangeLogDisplay(o, CLConverter));
}

function get_atom() {
    var entries = { 
        base: storage.posts.sortBy("-date"),
        i: 0,
        forEach: function(f) {
            this.base.forEach(function(n) {
                return f({
                    author: "AppJet",
                    title: "Change on "+n.date.toLocaleDateString()+
                           " at "+n.date.toLocaleTimeString(),
                    link: "http://changelog.appjet.com/change?id="+n.id,
                    id: "tag:changelog.appjet.com,2008:obj/"+n.id,
                    updated: n.date,
                    summary: n.summary,
                    content: n.diff
            })})}
        }
    page.setMode("plain");
    response.setHeader("Content-Type", "application/atom+xml");
    realprint(raw(getMainFeed("AppJet ChangeLog",
                              "http://changelog.appjet.com/atom",
                              "tag:changelog.appjet.com,2008:/1",
                              storage.posts.sortBy("-date").first().date, entries)));
    response.stop(true);
}

function get_feed() {
    response.redirect("http://feeds.feedburner.com/AppjetChangelog");
}

function get_summary() {
    var max = 3;
    storage.posts.sortBy("-date").forEach(function(obj) {
        if (obj.summary) {
            realprint(B(A({href: "/change?id="+obj.id, target: "_top"},
                           shortMon[obj.date.getMonth()], " ", obj.date.getDate(), " ", obj.date.getFullYear()),
                      ""), raw(obj.summary));
        }
        if (max-- <= 0) return false;
    });
    response.stop(true);
}
        

if ((! storage.adminpassword) && request.path != "/start") {
    response.redirect("/start");
} else {
    dispatch();
}

realprint(contentDiv);
realprint(raw("""
<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-4373620-2");
pageTracker._initData();
pageTracker._trackPageview();
</script>
"""));

/* appjet:css */

body {
    font-family: sans-serif;
    background: #eee;
}
img { border: 0px; }
div#head { 
    text-align: center;
    font-weight: bold; 
    font-size: 200%;
    font-family: serif;
    color: #333;
}
div#head img { vertical-align: middle; }
a#headlink { color: black; text-decoration: underline; }
span#headtitle {
    margin-left: 1em;
}
div#secondHead { margin-top: 1em; margin-bottom: 4em; }
div#backlink { float: left; }
div#rsslink {
    float: right;
    text-align: left;
    font-size: 100%;
    text-align: right;
}

div.clearfloats { clear: both; }
div.content {
    border: 1px solid #aaa;
    background: white;
    padding: 1em;
    width: 700px;
    margin-right: auto;
    margin-left: auto;
}
.surroundtext { float: right; color: red; }

.cldate {
    border-bottom: 1px solid gray;
    margin-bottom: 1em;
    font-size: 120%;
}
.cldate A {
    text-decoration: none;
    color: gray;
}
h3 { font-size: 100%; }
.cl { padding: 0.5em 0; font-size: 90%; }
.cl ul li { line-height: 150%; margin-bottom: 1.0em; }
.cllink { font-size: 90%; color: gray; }
div#appjetfooter { width: 700px; margin-left: auto; margin-right: auto; padding: 0 1em; }
code { font-family: monospace; font-size: 9pt; }
pre { 
  line-height: 120%;
  font: 8pt monospace;
  padding: 8px;
  border: 1px dashed #999;
  background-color: #fff3cc;
}








© Copyright 2007-2008 AppJet Inc.