mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2009-07-26 07:31 pm

[dw-free] New logged-in homepage

[commit: http://hg.dwscoalition.org/dw-free/rev/12c5f516dea2]

http://bugs.dwscoalition.org/show_bug.cgi?id=445

New logged in homepage. It's static-ish for now, can't change the boxes,
but it's a huge step up from what we have today.

Patch by [personal profile] afuna.

Files modified:
  • bin/upgrading/en.dat
  • cgi-bin/DW/Panel.pm
  • cgi-bin/DW/Widget/AccountStatistics.pm
  • cgi-bin/DW/Widget/CommunityManagement.pm
  • cgi-bin/DW/Widget/LatestInbox.pm
  • cgi-bin/DW/Widget/LatestNews.pm
  • cgi-bin/DW/Widget/QuickUpdate.pm
  • cgi-bin/DW/Widget/ReadingList.pm
  • cgi-bin/DW/Widget/UserTagCloud.pm
  • cgi-bin/LJ/Comment.pm
  • cgi-bin/LJ/Event.pm
  • cgi-bin/LJ/Event/ImportStatus.pm
  • cgi-bin/LJ/Event/JournalNewComment.pm
  • cgi-bin/LJ/Event/JournalNewEntry.pm
  • cgi-bin/LJ/Event/NewUserpic.pm
  • cgi-bin/LJ/Event/OfficialPost.pm
  • cgi-bin/LJ/Event/UserMessageRecvd.pm
  • cgi-bin/LJ/Event/UserMessageSent.pm
  • cgi-bin/LJ/Event/XPostFailure.pm
  • cgi-bin/LJ/Event/XPostSuccess.pm
  • cgi-bin/LJ/NotificationItem.pm
  • cgi-bin/LJ/Widget/FriendBirthdays.pm
  • cgi-bin/LJ/Widget/SiteMessages.pm
  • cgi-bin/weblib.pl
  • doc/config-private.pl.txt
  • htdocs/stc/blueshift/blueshift.css
  • htdocs/stc/celerity/celerity.css
  • htdocs/stc/gradation/gradation-vertical.css
  • htdocs/stc/widgets/latestinbox.css
  • htdocs/stc/widgets/quickupdate.css
  • htdocs/stc/widgets/sitemessages.css
--------------------------------------------------------------------------------
diff -r bce79d7b087a -r 12c5f516dea2 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat	Sun Jul 26 19:02:20 2009 +0000
+++ b/bin/upgrading/en.dat	Sun Jul 26 19:31:11 2009 +0000
@@ -3863,6 +3863,22 @@ web.postto.btn=Switch
 
 web.postto.label=Post to:
 
+widget.accountstatistics.expires_on=[[type]], expiring [[date]]
+
+widget.accountstatistics.comments=[[num_received]] [[?num_received|comment|comments]] received; [[num_posted]] [[?num_received|comment|comments]] posted
+
+widget.accountstatistics.entries=[[num]] [[?num|entry|entries]]
+
+widget.accountstatistics.last_updated=Last updated [[date]]
+
+widget.accountstatistics.member_since=Member since [[date]]
+
+widget.accountstatistics.memories=[[num]] <a [[aopts]]>Memories</a>
+
+widget.accountstatistics.tags=[[num]] <a [[aopts]]>Tags</a>
+
+widget.accountstatistics.title=Account Stats
+
 widget.addqotd.extratext=Extra Text (optional):
 
 widget.addqotd.extratext.note=HTML allowed
@@ -4123,7 +4139,7 @@ widget.feeds.title=Feeds
 
 widget.feeds.viewall=view all
 
-widget.friendbirthdays.friends_link=View all friends' birthdays
+widget.friendbirthdays.friends_link=View birthdays for everyone in your circle
 
 widget.friendbirthdays.gift=Gift
 
@@ -4293,6 +4309,22 @@ widget.journaltitles.title=1. Edit Title
 
 widget.journaltitles.title_nonum=Edit Titles
 
+widget.latestinbox.links.compose=Create New Message
+
+widget.latestinbox.links.inbox=View More Messages
+
+widget.latestinbox.links.manage=Manage Settings
+
+widget.latestinbox.title=Inbox
+
+widget.latestnews.comments=[[num_comments]] [[?num_comments|comment|comments]]
+
+widget.latestnews.more=(Read more...)
+
+widget.latestnews.subscribe=<a [[aopts]]>Add</a> [[news]] to your reading list
+
+widget.latestnews.title=[[sitename]] News
+
 widget.layoutchooser.layout.apply=Apply Layout
 
 widget.layoutchooser.title=3. Choose a Page Setup
@@ -4451,6 +4483,28 @@ widget.qotdresponses.read.your.friends.p
 
 widget.qotdresponses.there.are.no.answers=There are no answers to this Writer's Block.
 
+widget.quickupdate.entry=Entry
+
+widget.quickupdate.moreopts=More Options
+
+widget.quickupdate.subject=Subject
+
+widget.quickupdate.title=Quick Update
+
+widget.quickupdate.update=Update Journal
+
+widget.readinglist.breakdown.communities=[[num]] communities
+
+widget.readinglist.breakdown.feeds=[[num]] feeds
+
+widget.readinglist.breakdown.header=You are currently reading:
+
+widget.readinglist.breakdown.personal=[[num]] personal journals
+
+widget.readinglist.readpage=Check out recent updates on your <a [[aopts]]>reading list</a>!
+
+widget.readinglist.title=Reading List
+
 widget.recentcomments.anon=Somebody
 
 widget.recentcomments.commentheading=[[poster]] in [[entry]]
@@ -4598,6 +4652,8 @@ widget.shopitemoptions.price=[[num]] [[?
 widget.shopitemoptions.price=[[num]] [[?num|month|months]] for [[price]]
 
 widget.shopitemoptions.price.seed=Forever for [[price]]
+
+widget.sitemessages.title=[[sitename]] Plugs In
 
 widget.support.submit.button=Submit Request
 
@@ -4685,6 +4741,8 @@ widget.themenav.switchtos1=Switch to old
 
 widget.themenav.title=2. Select a New Theme
 
+widget.usertagcloud.title=Tag Cloud
+
 xpost.delete.error=Error deleting crossposted entry at [[username]]@[[server]]:  [[error]]
 
 xpost.delete.success=Crossposted entry at [[username]]@[[server]] deleted.
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/DW/Panel.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Panel.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,137 @@
+#!/usr/bin/perl
+#
+# DW::Panel - Generic movable container which wraps around an object of 
+# class LJ::Widget, and remembers state and position.
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself. For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+
+package DW::Panel;
+
+=head1 NAME
+
+DW::Panel - Generic movable container which wraps around an object of 
+class LJ::Widget, and remembers state and position.
+
+=head1 SYNOPSIS
+
+  use DW::Panel;
+
+  my $panels = DW::Panel->init( u => $remote );  
+  $panels->render_primary;
+  $panels->render_secondary;
+
+=cut
+
+use strict;
+use warnings;
+
+use fields qw( primary secondary );
+
+=head1 API
+
+=head2 C<< $class->init( [ u => $u] ) >>
+Class method; initializes the panels with their settings, etc, for this user.
+=cut
+
+sub init {
+    my ( $class, %opts ) = @_;
+    # my $dbh = LJ::get_db_reader();
+
+    my $u = $opts{u} || LJ::get_remote();
+    return unless $u;
+
+    my $ret = fields::new( $class );
+
+    # TODO: store/retrieve user settings from database
+    # possible settings: display or not, position, possibly per-widget config
+    $ret->{primary} = [
+        "DW::Widget::LatestNews",
+        "DW::Widget::QuickUpdate",
+        "DW::Widget::LatestInbox",
+        # "LJ::Widget::RecentComments",
+    ];
+
+    $ret->{secondary} = [
+        "DW::Widget::ReadingList",
+        "LJ::Widget::FriendBirthdays",
+        "DW::Widget::AccountStatistics",
+        "LJ::Widget::SiteMessages",
+        "DW::Widget::UserTagCloud",
+        # "DW::Widget::CommunityManagement",
+        "LJ::Widget::CurrentTheme",
+    ];
+
+    return $ret;
+}
+
+=head2 C<< $object->render_primary >>
+Render the widgets that belong in the primary column
+=cut
+
+sub render_primary {
+    my $self = shift;
+    
+    my $ret;
+    foreach my $widget ( @{ $self->{primary} } ) {
+        $ret .= DW::Panel->_render( $widget );
+    }
+
+    return $ret;
+}
+
+=head2 C<< $object->render_secondary >>
+Render the widgets that belong in the secondary column
+=cut
+
+sub render_secondary {
+    my $self = shift;
+    
+    my $ret;
+    foreach my $widget ( @{ $self->{secondary} } ) {
+        $ret .= DW::Panel->_render( $widget );
+    }
+
+    return $ret;
+}
+
+=head2 C<< $object->_render( widgetname ) >>
+Render the widget and its container.
+=cut
+
+sub _render {
+    my ( $object, $widget ) = @_;
+
+    eval "use $widget; 1"  or return "";
+
+    my $widget_body = $widget->render;
+    return "" unless $widget_body;
+
+    my $css_subclass = lc $widget->subclass;
+    # TODO: this can contain the non-js controls to enable customization of display
+    return "<div class='panel' id='panel-$css_subclass' >$widget_body</div>";
+}
+
+=head1 BUGS
+
+=head1 AUTHORS
+
+Afuna <coder.dw@afunamatata.com>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2009 by Dreamwidth Studios, LLC.
+
+This program is free software; you may redistribute it and/or modify it under
+the same terms as Perl itself. For a copy of the license, please reference
+'perldoc perlartistic' or 'perldoc perlgpl'.
+
+=cut
+
+1;
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/DW/Widget/AccountStatistics.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Widget/AccountStatistics.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,57 @@
+#!/usr/bin/perl
+#
+# DW::Widget::AccountStatistics
+#
+# User's account statistics, similar to those on the profile page.
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Widget::AccountStatistics;
+
+use strict;
+use base qw/ LJ::Widget /;
+
+sub should_render { 1; }
+
+sub render_body {
+    my ( $class, %opts ) = @_;
+
+    my $remote = LJ::get_remote()
+        or return;
+
+    my $tags_count = scalar keys %{ $remote->tags || {} };
+    my $memories_count = LJ::Memories::count( $remote->id ) || 0;
+
+    my $accttype = DW::Pay::get_account_type_name( $remote );
+    my $accttype_string;
+    if ( $accttype ) {
+        my $expire_time = DW::Pay::get_account_expiration_time( $remote );
+        $accttype_string = $expire_time > 0 
+                ? BML::ml( 'widget.accountstatistics.expires_on', { type => $accttype, date => DateTime->from_epoch( epoch => $expire_time )->date } ) 
+                : $accttype;
+    }
+
+    my $ret = "<h2>" . $class->ml( 'widget.accountstatistics.title' ) . "</h2>";
+    $ret .= "<ul>";
+    $ret .= "<li>" . $class->ml( 'widget.accountstatistics.member_since', { date => LJ::mysql_time( $remote->timecreate ) } ) . "</li>";
+    $ret .= "<li>" . $class->ml( 'widget.accountstatistics.entries', { num => LJ::commafy( $remote->number_of_posts ) } ) . "</li>";
+    $ret .= "<li>" . $class->ml( 'widget.accountstatistics.last_updated', { date =>         LJ::mysql_time( $remote->timeupdate ) } ) . "</li>";
+    $ret .= "<li>" . $class->ml( 'widget.accountstatistics.comments', { num_received => LJ::commafy( $remote->num_comments_received ), num_posted => LJ::commafy( $remote->num_comments_posted ) } ) . "</li>";
+    $ret .= "<li>" . $class->ml( 'widget.accountstatistics.memories', { num => LJ::commafy( $memories_count ), aopts => "href='$LJ::SITEROOT/tools/memories.bml?user=" . $remote->user . "'", } );
+    $ret .= ", " . $class->ml( 'widget.accountstatistics.tags', { num => $tags_count, aopts => 'href="' . $remote->journal_base . '/tag/"' } ) . "</li>";
+    $ret .= "<li>" . $accttype_string . "</li>";
+    $ret .= "</ul>";
+    
+    return $ret;
+}
+
+1;
+
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/DW/Widget/CommunityManagement.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Widget/CommunityManagement.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,39 @@
+#!/usr/bin/perl
+#
+# DW::Widget::CommunityManagement
+#
+# List the user's communities which require attention.
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Widget::CommunityManagement;
+
+use strict;
+use base qw/ LJ::Widget /;
+
+sub should_render { 1; }
+
+# requires attention are: 
+# * has pending join requests
+# * has pending entries in the queue
+sub render_body {
+    my ( $class, %opts ) = @_;
+
+    my $remote = LJ::get_remote()
+        or return;
+
+    # TODO: everything!
+    my $ret = "";
+    return $ret;
+}
+
+1;
+
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/DW/Widget/LatestInbox.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Widget/LatestInbox.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,76 @@
+#!/usr/bin/perl
+#
+# DW::Widget::LatestInbox
+#
+# Latest inbox messages
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Widget::LatestInbox;
+
+use strict;
+use base qw/ LJ::Widget /;
+
+sub need_res {
+    qw( stc/widgets/latestinbox.css );
+}
+
+sub render_body {
+    my ( $class, %opts ) = @_;
+
+    my $remote = LJ::get_remote()
+        or return "";
+
+    my $limit = $opts{limit} || 5;
+
+    my $ret = "<h2>" . $class->ml( 'widget.latestinbox.title' ) . "</h2>";
+
+    $ret .= "<div class='sidebar'><ul>";
+    $ret .= "<li><a href='/inbox/'>" . $class->ml( 'widget.latestinbox.links.inbox' ). "</a></li>";
+    $ret .= "<li><a href='/inbox/compose'>" . $class->ml( 'widget.latestinbox.links.compose' ) . "</a></li>";
+    $ret .= "<li><a href='/manage/settings/?cat=notifications'>" . $class->ml( 'widget.latestinbox.links.manage' ) . "</a></li>";
+    $ret .= "</ul></div>";
+
+    $ret .= "<div class='contents'>";
+
+    # get the user's inbox
+    my $error;
+    my $inbox = $remote->notification_inbox
+        or $error = LJ::error_list( $class->ml( 'inbox.error.couldnt_retrieve_inbox', { 'user' => $remote->{user} } ) );
+
+    if ( $error  ) {
+        $ret .= $error;
+    } else {
+        my @inbox_items = reverse $inbox->all_items;
+
+        if ( @inbox_items ) {
+            # TODO: summary mode?
+            foreach my $item ( splice( @inbox_items, 0, $limit ) ) {
+                $ret .= "<div class='item'>";
+                $ret .= "<div class='title'>" . $item->title . "</div>";
+
+                my $summary = $item->as_html_summary;
+                $ret .= "<div class='summary'>$summary</div>" if $summary;
+
+                $ret .= "</div>";
+            }
+        } else {
+            # TODO: test this
+            $ret .= $class->ml( 'widget.latestinbox.empty' );
+        }
+    }
+
+    $ret .= "</div>";
+    return $ret;
+}
+
+1;
+
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/DW/Widget/LatestNews.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Widget/LatestNews.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+#
+# DW::Widget::LatestNews
+#
+# The latest site news.
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Widget::LatestNews;
+
+use strict;
+use base qw/ LJ::Widget /;
+
+# define the news journal in your site config
+sub should_render { $LJ::NEWS_JOURNAL ? 1 : 0; }
+
+sub render_body {
+    my ( $class, %opts ) = @_;
+
+    my $remote = LJ::get_remote()
+        or return;
+
+    my $news_journal = LJ::load_user( $LJ::NEWS_JOURNAL )
+        or return;
+
+    my $ret = "<h2>" . $class->ml( 'widget.latestnews.title', { sitename => $LJ::SITENAMESHORT } ) . "</h2>";
+
+    # do getevents request
+    my %res = ();
+    LJ::do_request( { mode => 'getevents',
+                      selecttype => 'one',
+                      ver => $LJ::PROTOCOL_VER,
+                      user => $news_journal->user,
+                      itemid => -1 },
+                      \%res,
+                      { noauth => 1 }
+                   );
+
+    return unless $res{success} eq 'OK';
+
+    my $entry = LJ::Entry->new( $news_journal, ditemid => ( $res{events_1_itemid} << 8) + $res{events_1_anum} );
+
+    $ret .= "<div class='sidebar'>";
+    $ret .= "<p><a href='" . $entry->url . "#comments'>" . $class->ml( 'widget.latestnews.comments', { num_comments => $entry->reply_count } ) . "</a></p>";
+    $ret .= "<p>" . $class->ml( 'widget.latestnews.subscribe', { 
+        aopts => "href='$LJ::SITEROOT/manage/circle/add.bml?user=" . $news_journal->user. "&action=subscribe'",
+        news => LJ::ljuser( $news_journal ) } ) . "</p>";
+    $ret .= "</div>";
+
+    $ret .= "<div class='contents'>";
+    $ret .= "<p><a href='" . $entry->url . "'>" . $entry->subject_html . "</a></p>";
+    $ret .= "<p>" . $entry->event_html_summary( 300 ) . "</p>";
+    $ret .= "<p><a href='" . $entry->url . "'>" . $class->ml( 'widget.latestnews.more' ) . "</a></p>";
+    $ret .= "</div>";
+
+    return $ret;
+}
+
+1;
+
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/DW/Widget/QuickUpdate.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Widget/QuickUpdate.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,74 @@
+#!/usr/bin/perl
+#
+# DW::Widget::QuickUpdate
+#
+# Quick update form
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Widget::QuickUpdate;
+
+use strict;
+use base qw/ LJ::Widget /;
+
+sub need_res { qw( stc/widgets/quickupdate.css ) }
+
+sub render_body {
+    my ( $class, %opts ) = @_;
+
+    my $remote = LJ::get_remote()
+        or return;
+
+    my $ret = "<h2>" . $class->ml( 'widget.quickupdate.title' ) . "</h2>";
+    $ret .= "<div class='sidebar'>" . LJ::run_hook( 'entryforminfo', $remote->user, $remote ) . "</div>";
+    $ret .= "<div class='contents'>";
+
+    # not using the LJ::Widget form of the HTML methods, because we're directing this to update.bml
+    $ret .= $class->start_form( action => "/update.bml" );
+    $ret .= LJ::entry_form_date_widget();
+    $ret .= LJ::entry_form_xpost_widget( $remote );
+
+    $ret .= LJ::labelfy( "subject", $class->ml( 'widget.quickupdate.subject' ) );
+    $ret .= LJ::entry_form_subject_widget();
+    $ret .= LJ::labelfy( "event", $class->ml( 'widget.quickupdate.entry' ) );
+    $ret .= LJ::entry_form_entry_widget();
+
+    $ret .= "<div class='metadata'>";
+    $ret .= "<div class='form-input'>";
+    $ret .= LJ::labelfy( "usejournal", $class->ml( 'entryform.postto' ) );
+    $ret .= LJ::entry_form_postto_widget( $remote ) || "";
+    $ret .= "</div>";
+    $ret .= "<div class='form-input'>";
+    $ret .= LJ::labelfy( "security", $class->ml( 'entryform.security' ) );
+    $ret .= LJ::entry_form_security_widget();
+    $ret .= "</div>";
+    $ret .= "<div class='form-input'>";
+    $ret .= LJ::labelfy( "prop_picture_keyword", $class->ml( 'entryform.userpic' ) );
+    $ret .= LJ::entry_form_usericon_widget( $remote );
+    $ret .="</div>";
+    $ret .= "<div class='form-input'>";
+    $ret .= LJ::labelfy( "prop_taglist", $class->ml( 'entryform.tags' ) );
+    $ret .= LJ::entry_form_tags_widget();
+    $ret .= "</div>";
+    $ret .= "</div>";
+
+    $ret .= "<div class='submit'>";
+    $ret .= LJ::html_submit( $class->ml( 'widget.quickupdate.update' ) );
+    $ret .= LJ::html_submit( 'moreoptsbtn', $class->ml( 'widget.quickupdate.moreopts' ) );
+    $ret .= "</div>";
+    $ret .= $class->end_form;
+    $ret .= "</div>";
+
+    return $ret;
+}
+
+1;
+
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/DW/Widget/ReadingList.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Widget/ReadingList.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,43 @@
+#!/usr/bin/perl
+#
+# DW::Widget::ReadingList
+#
+# Breakdown of the user's reading list
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Widget::ReadingList;
+
+use strict;
+use base qw/ LJ::Widget /;
+
+sub render_body {
+    my ( $class, %opts ) = @_;
+
+    my $remote = LJ::get_remote()
+        or return;
+
+    my %count;
+    my @watched = $remote->watched_users;
+    $count{$_->journaltype_readable}++ foreach @watched;
+
+    my $ret = "<h2>" . $class->ml( 'widget.readinglist.title' ) . "</h2>";
+    $ret .= "<p>" . $class->ml( 'widget.readinglist.readpage', { aopts => "href='" . $remote->journal_base. "/read'" } ) . "</p>";
+    $ret .= "<p>" . $class->ml( 'widget.readinglist.breakdown.header' ) . "</p>";
+    $ret .= "<ul><li>" . $class->ml( 'widget.readinglist.breakdown.personal', { num => $count{personal} } ) . "</li>";
+    $ret .= "<li>" . $class->ml( 'widget.readinglist.breakdown.communities', { num => $count{community} } ) . "</li>";
+    $ret .= "<li>" . $class->ml( 'widget.readinglist.breakdown.feeds', { num => $count{syndicated} } ) . "</li></ul>";
+
+    return $ret;
+}
+
+1;
+
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/DW/Widget/UserTagCloud.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Widget/UserTagCloud.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+#
+# DW::Widget::UserTagCloud
+#
+# User's tag cloud
+#
+# Authors:
+#      Afuna <coder.dw@afunamatata.com>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Widget::UserTagCloud;
+
+use strict;
+use base qw/ LJ::Widget /;
+
+sub render_body {
+    my ( $class, %opts ) = @_;
+
+    my $remote = LJ::get_remote()
+        or return "";
+
+    my $tags = $remote->tags;
+    return "" unless $tags;
+
+    my $limit = $opts{limit} || 10;
+    my $ret = "<h2>" . $class->ml( 'widget.usertagcloud.title' ) . "</h2>";
+
+    my @by_size = sort { $tags->{$b}->{uses} <=> $tags->{$a}->{uses} } keys %$tags;
+    @by_size = splice @by_size, 0, $limit;
+    my %popular_tags = map { $_ => 1 } @by_size;
+
+    my $tag_items;
+    my $tag_base_url = $remote->journal_base . "/tag/";
+    while ( my ( $id, $tag ) = each %$tags ) {
+        next unless $popular_tags{$id};
+        $tag_items->{$tag->{name}} = {
+            url => $tag_base_url. LJ::eurl( $tag->{name} ),
+            value => $tag->{uses},
+        };
+    }
+
+    $ret .= LJ::tag_cloud( $tag_items );
+    return $ret;
+}
+
+1;
+
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Comment.pm
--- a/cgi-bin/LJ/Comment.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Comment.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -790,6 +790,12 @@ sub body_html {
     my $body = $self->body_raw;
     LJ::CleanHTML::clean_comment(\$body, $opts) if $body;
     return $body;
+}
+
+# comement body, but trimmed to $char_max
+sub body_html_summary {
+    my ( $self, $char_max ) = @_;
+    return LJ::html_trim( $self->body_html, $char_max );
 }
 
 # comment body, plaintext
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event.pm
--- a/cgi-bin/LJ/Event.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -106,6 +106,8 @@ sub always_checked { 0 }
 
 # Override this with HTML containing the actual event
 sub content { '' }
+# Override this with HTML containing a summary of the event text (may be left blank)
+sub content_summary { '' }
 
 # Override this to provide details, method for XMLRPC::getinbox
 sub raw_info {
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/ImportStatus.pm
--- a/cgi-bin/LJ/Event/ImportStatus.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/ImportStatus.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -134,6 +134,11 @@ sub content {
     return '';
 }
 
+# short enough that we can just use this the normal content as the summary
+sub content_summary {
+    return $_[0]->content( @_ );
+}
+
 # load our options hashref
 sub _optsref {
     my $self = $_[0];
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/JournalNewComment.pm
--- a/cgi-bin/LJ/Event/JournalNewComment.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/JournalNewComment.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -185,15 +185,21 @@ sub as_sms {
     return $msg . $self->comment->body_text;
 }
 
+sub _can_view_content {
+    my ( $self, $comment, $target ) = @_;
+
+    return undef unless $comment && $comment->valid;
+    return undef unless $comment->entry && $comment->entry->valid;
+    return undef unless $comment->visible_to( $target );
+    return undef if $comment->is_deleted;
+
+    return 1;
+}
 sub content {
     my ($self, $target) = @_;
 
     my $comment = $self->comment;
-
-    return undef unless $comment && $comment->valid;
-    return undef unless $comment->entry && $comment->entry->valid;
-    return undef unless $comment->visible_to($target);
-    return undef if $comment->is_deleted;
+    return undef unless $self->_can_view_content( $comment, $target );
 
     LJ::need_res('js/commentmanage.js');
 
@@ -233,6 +239,20 @@ sub content {
     $ret .= qq {
         </script>
         };
+    $ret .= $self->as_html_actions;
+
+    return $ret;
+}
+
+sub content_summary {
+    my ( $self, $target ) = @_;
+
+    my $comment = $self->comment;
+    return undef unless $self->_can_view_content( $comment, $target );
+
+    my $body_summary = $comment->body_html_summary( 300 );
+    my $ret = $body_summary;
+    $ret .= "..." if $comment->body_html ne $body_summary;
     $ret .= $self->as_html_actions;
 
     return $ret;
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/JournalNewEntry.pm
--- a/cgi-bin/LJ/Event/JournalNewEntry.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/JournalNewEntry.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -54,14 +54,35 @@ sub matches_filter {
     return LJ::u_equals($subscr->journal, $evtju);
 }
 
+sub _can_view_content {
+    my ( $self, $entry, $target ) = @_;
+    
+    return undef unless $entry && $entry->valid;
+    return undef unless $entry->visible_to( $target );
+
+    return 1;
+}
+
 sub content {
     my ($self, $target) = @_;
     my $entry = $self->entry;
-
-    return undef unless $entry && $entry->valid;
-    return undef unless $entry->visible_to($target);
+    return undef unless $self->_can_view_content( $entry, $target );
 
     return $entry->event_html . $self->as_html_actions;
+}
+
+sub content_summary {
+    my ( $self, $target ) = @_;
+    
+    my $entry = $self->entry;
+    return undef unless $self->_can_view_content( $entry, $target );
+
+    my $event_summary = $entry->event_html_summary( 300 );
+    my $ret = $event_summary;
+    $ret .= "..." if $event_summary ne $entry->event_html;
+    $ret .= $self->as_html_actions;
+
+    return $ret;
 }
 
 sub as_string {
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/NewUserpic.pm
--- a/cgi-bin/LJ/Event/NewUserpic.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/NewUserpic.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -111,6 +111,11 @@ sub content {
     return $up->imgtag;
 }
 
+# short enough that we can just use this the normal content as the summary
+sub content_summary {
+    return $_[0]->content( @_ );
+}
+
 sub as_email_subject {
     my $self = shift;
     return sprintf "%s uploaded a new userpic!", $self->event_journal->display_username;
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/OfficialPost.pm
--- a/cgi-bin/LJ/Event/OfficialPost.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/OfficialPost.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -20,6 +20,16 @@ sub content {
 sub content {
     my $self = shift;
     return $self->entry->event_html;
+}
+
+sub content_summary {
+    my $entry = $_[0]->entry;
+    my $entry_summary = $entry->event_html_summary( 300 );
+
+    my $ret = $entry_summary;
+    $ret .= "..." if $entry->event_html ne $entry_summary;
+
+    return $ret;
 }
 
 sub is_common { 1 }
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/UserMessageRecvd.pm
--- a/cgi-bin/LJ/Event/UserMessageRecvd.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/UserMessageRecvd.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -161,6 +161,17 @@ sub content {
     return $body . $self->as_html_actions;
 }
 
+sub content_summary {
+    my $msg = $_[0]->load_message;
+    my $body = $msg->body;
+    my $body_summary = LJ::html_trim( $body, 300 );
+
+    my $ret = LJ::html_newlines( $body_summary );
+    $ret .= "..." if $body ne $body_summary;
+    $ret .= $_[0]->as_html_actions;
+    return $ret;
+}
+
 # override parent class sbuscriptions method to always return
 # a subscription object for the user
 sub subscriptions {
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/UserMessageSent.pm
--- a/cgi-bin/LJ/Event/UserMessageSent.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/UserMessageSent.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -62,6 +62,17 @@ sub content {
     $body = LJ::html_newlines($body);
 
     return $body;
+}
+
+sub content_summary {
+    my $msg = $_[0]->load_message;
+    my $body = $msg->body;
+    my $body_summary = LJ::html_trim( $body, 300 );
+
+    my $ret = LJ::html_newlines( $body_summary );
+    $ret .= "..." if $body ne $body_summary;
+    $ret .= $_[0]->as_html_actions;
+    return $ret;
 }
 
 # override parent class sbuscriptions method to always return
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/XPostFailure.pm
--- a/cgi-bin/LJ/Event/XPostFailure.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/XPostFailure.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -65,6 +65,11 @@ sub content {
             } );
 }
 
+# short enough that we can just use this the normal content as the summary
+sub content_summary {
+    return $_[0]->content( @_ );
+}
+
 # the main title for the event
 sub as_html {
     my $self = $_[0];
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Event/XPostSuccess.pm
--- a/cgi-bin/LJ/Event/XPostSuccess.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Event/XPostSuccess.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -38,6 +38,11 @@ sub content {
 sub content {
     my ($self) = @_;
     return BML::ml('event.xpost.success.content', { accountname => $self->account->displayname });
+}
+
+# short enough that we can just use this the normal content as the summary
+sub content_summary {
+    return $_[0]->content( @_ );
 }
 
 # the main title for the event
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/NotificationItem.pm
--- a/cgi-bin/LJ/NotificationItem.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/NotificationItem.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -83,6 +83,13 @@ sub as_html {
     croak "Too many args passed to NotificationItem->as_html" if scalar @_;
     return "(Invalid event)" unless $self->event;
     return eval { $self->event->content($self->u) } || $@;
+}
+
+sub as_html_summary {
+    my $self = shift;
+    croak "Too many args passed to NotificationItem->as_html_summary" if scalar @_;
+    return "(Invalid event)" unless $self->event; 
+    return eval { $self->event->content_summary( $self->u ) } || $@;
 }
 
 # returns the event that this item refers to
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Widget/FriendBirthdays.pm
--- a/cgi-bin/LJ/Widget/FriendBirthdays.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Widget/FriendBirthdays.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -28,7 +28,7 @@ sub render_body {
 
     my $ret;
     $ret .= "<h2><span>" . $class->ml('widget.friendbirthdays.title') . "</span></h2>";
-    $ret .= "<a href='$LJ::SITEROOT/birthdays.bml' class='more-link'>" . $class->ml('widget.friendbirthdays.viewall') . "</a></p>";
+    $ret .= "<a href='$LJ::SITEROOT/birthdays' class='more-link'>" . $class->ml('widget.friendbirthdays.viewall') . "</a></p>";
     $ret .= "<div class='indent_sm'><table>";
 
     foreach my $bday (@bdays) {
@@ -43,14 +43,14 @@ sub render_body {
         $ret .= "<tr>";
         $ret .= "<td>" . $u->ljuser_display . "</td>";
         $ret .= "<td>" . $class->ml('widget.friendbirthdays.userbirthday', {'month' => LJ::Lang::month_short($month), 'day' => $day}) . "</td>";
-        $ret .= "<td><a href='$LJ::SITEROOT/shop/view.bml?item=paidaccount&gift=1&for=" . $u->user . "' class='gift-link'>";
+        $ret .= "<td><a href='$LJ::SITEROOT/shop/account?for=gift&user=" . $u->user . "' class='gift-link'>";
         $ret .= $class->ml('widget.friendbirthdays.gift') . "</a></td>";
         $ret .= "</tr>";
     }
 
     $ret .= "</table></div>";
 
-    $ret .= "<p class='indent_sm'>&raquo; <a href='$LJ::SITEROOT/birthdays.bml'>" .
+    $ret .= "<p class='indent_sm'>&raquo; <a href='$LJ::SITEROOT/birthdays'>" .
             $class->ml('widget.friendbirthdays.friends_link') .
             "</a></p>" if $opts{friends_link};
     $ret .= "<p class='indent_sm'>&raquo; <a href='$LJ::SITEROOT/paidaccounts/friends.bml'>" .
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/LJ/Widget/SiteMessages.pm
--- a/cgi-bin/LJ/Widget/SiteMessages.pm	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/LJ/Widget/SiteMessages.pm	Sun Jul 26 19:31:11 2009 +0000
@@ -4,10 +4,6 @@ use base qw(LJ::Widget);
 use base qw(LJ::Widget);
 use Carp qw(croak);
 use Class::Autouse qw( LJ::SiteMessages );
-
-sub need_res {
-    return qw( stc/widgets/sitemessages.css );
-}
 
 sub render_body {
     my $class = shift;
@@ -16,6 +12,7 @@ sub render_body {
 
     my @messages = LJ::SiteMessages->get_messages;
 
+    $ret .= "<h2>" . $class->ml( "widget.sitemessages.title", { sitename => $LJ::SITENAMESHORT } ) . "</h2>";
     $ret .= "<ul class='nostyle'>";
     foreach my $message (@messages) {
         my $ml_key = $class->ml_key("$message->{mid}.text");
diff -r bce79d7b087a -r 12c5f516dea2 cgi-bin/weblib.pl
--- a/cgi-bin/weblib.pl	Sun Jul 26 19:02:20 2009 +0000
+++ b/cgi-bin/weblib.pl	Sun Jul 26 19:31:11 2009 +0000
@@ -1891,7 +1891,7 @@ sub entry_form_subject_widget {
     if ($class) {
         $class = qq { class="$class" };
     }
-    return qq { <input name="subject" $class/> };
+    return qq { <input name="subject" id="subject" $class/> };
 }
 
 # entry form hidden date field
@@ -1916,7 +1916,7 @@ sub entry_form_entry_widget {
         $class = qq { class="$class" };
     }
 
-    return qq { <textarea cols=50 rows=10 name="event" $class></textarea> };
+    return qq { <textarea cols=50 rows=10 name="event" id="event" $class></textarea> };
 }
 
 
@@ -1947,19 +1947,19 @@ sub entry_form_postto_widget {
     push @journals, $remote->{'user'};
     push @journals, $remote->{'user'};
     @journals = sort @journals;
-    $ret .= LJ::html_select({ 'name' => 'usejournal', 'selected' => $remote->{'user'}}, @journals) . "\n";
+    $ret .= LJ::html_select( { name => 'usejournal', id => 'usejournal', selected => $remote->user }, @journals ) . "\n";
     return $ret;
 }
 
 sub entry_form_security_widget {
     my $ret = '';
 
-    my @secs = ("public", BML::ml('label.security.public'),
-                "private", BML::ml('label.security.private'),
-                "friends", BML::ml('label.security.friends'));
+    my @secs = ( "public", BML::ml( 'label.security.public2' ),
+                 "friends", BML::ml( 'label.security.accesslist' ),
+                 "private", BML::ml( 'label.security.private2' ) );
 
-    $ret .= LJ::html_select({ 'name' => 'security'},
-                            @secs);
+    $ret .= LJ::html_select( { name => 'security', id => 'security' },
+                            @secs );
 
     return $ret;
 }
@@ -1971,11 +1971,71 @@ sub entry_form_tags_widget {
 
     $ret .= LJ::html_text({
                               'name'      => 'prop_taglist',
+                              'id'        => 'prop_taglist',
                               'size'      => '35',
                               'maxlength' => '255',
                           });
     $ret .= LJ::help_icon('addtags');
 
+    return $ret;
+}
+
+sub entry_form_usericon_widget {
+    my $remote = shift;
+    return undef unless LJ::isu( $remote );
+
+    my $ret;
+
+    my %res;
+    LJ::do_request({ mode => "login",
+                     ver => $LJ::PROTOCOL_VER,
+                     user => $remote->user,
+                     getpickws => 1, },
+                     \%res, { noauth => 1, userid => $remote->userid }
+                   );
+
+    if ($res{pickw_count}) {
+
+        my @icons;
+        for ( my $i = 1; $i <= $res{pickw_count}; $i++ ) {
+            push @icons, $res{"pickw_$i"};
+        }
+
+        @icons = sort { lc( $a ) cmp lc( $b ) } @icons;
+        $ret .= LJ::html_select( { name => 'prop_picture_keyword',
+                                   id => 'prop_picture_keyword' },
+                                   ( "", BML::ml( 'entryform.opt.defpic' ),
+                                     map { ( $_, $_ ) } @icons )
+                                );
+    }
+    return $ret;
+}
+
+sub entry_form_xpost_widget {
+    my ( $remote ) = @_;
+    return unless $remote;
+
+    my $ret;
+    my @accounts = DW::External::Account->get_external_accounts( $remote );
+    @accounts = grep { $_->xpostbydefault } @accounts;
+
+    if ( @accounts ) {
+        $ret .= LJ::html_hidden( {
+            name => 'prop_xpost_check', 
+            id => 'prop_xpost_check',
+            value => 1,
+        } );
+
+        foreach my $acct ( @accounts ) {
+            my $acctid = $acct->acctid;
+            $ret .= LJ::html_hidden( {
+                    name => "prop_xpost_$acctid",
+                    id => "prop_xpost_$acctid",
+                    value => 1,
+                } );
+        }
+    }
+    
     return $ret;
 }
 
diff -r bce79d7b087a -r 12c5f516dea2 doc/config-private.pl.txt
--- a/doc/config-private.pl.txt	Sun Jul 26 19:02:20 2009 +0000
+++ b/doc/config-private.pl.txt	Sun Jul 26 19:31:11 2009 +0000
@@ -34,6 +34,9 @@
     %OFFICIAL_JOURNALS = (
         news => 1,
     );
+    
+    # the "news" journal, to be specially displayed on the front page, etc
+    $NEWS_JOURNAL = "news";
 
     # list of alternate domains that point to your site.
     @ALTERNATE_DOMAINS = (
diff -r bce79d7b087a -r 12c5f516dea2 htdocs/stc/blueshift/blueshift.css
--- a/htdocs/stc/blueshift/blueshift.css	Sun Jul 26 19:02:20 2009 +0000
+++ b/htdocs/stc/blueshift/blueshift.css	Sun Jul 26 19:31:11 2009 +0000
@@ -307,54 +307,42 @@ table#table_yourlayers td { padding: .15
     overflow: hidden;
 }
 #content #primary .panel h2 {
-    height: 2em;
     line-height: 2em;
+    border-style: none;
 }
 #content #primary .panel p {
     clear: both;
 }
-#content #secondary .panel h3 {
-    height: 30px;
+#content #secondary .panel h2 {
     line-height: 30px;
+    border-style: none;
+}
+#content .panel .sidebar ul {
+     list-style: none;
+     margin-left: 0;
+}
+#content .panel ul {
+    list-style: circle;
+    margin-left: 1em;
 }
 /**
  * Panels have different styles for different content layouts
  */
 .layout-wide-right-sidebar #primary .panel .sidebar {
     float: left;
-    width: 30%;
+    width: 22%;
 }
 .layout-wide-right-sidebar #primary .panel .contents {
     float: left;
     padding-top: 6px;
     padding-left: 14px;
     border-left: 1px solid #ccc;
-    width: 70%;
+    width: 75%;
     line-height: 1.8;
 }
 .layout-wide-right-sidebar #secondary .panel .contents {
     margin: 0.5em 0;
     line-height: 1.8;
-}
-/**
- * Panels have unique IDs for CSS hooks
- */
-#panel-quick-update .sidebar p {
-    height: 3em;
-    line-height: 3em;
-}
-#panel-quick-update .contents label {
-    display: block;
-    width: 100%;
-    color: #002A82;
-    font-weight: bold;
-}
-#panel-quick-update .contents input,
-#panel-quick-update .contents textarea {
-    width: 95%;
-}
-#panel-quick-update .contents textarea {
-    height: 120px;
 }
 /* panel-first class is added through js */
 #content .panel-first {
diff -r bce79d7b087a -r 12c5f516dea2 htdocs/stc/celerity/celerity.css
--- a/htdocs/stc/celerity/celerity.css	Sun Jul 26 19:02:20 2009 +0000
+++ b/htdocs/stc/celerity/celerity.css	Sun Jul 26 19:31:11 2009 +0000
@@ -334,55 +334,50 @@ table#table_yourlayers td { padding: .15
     margin: 0 0 0.166667em 0;
     overflow: hidden;
 }
+#content .panel .sidebar,
+#content .panel .contents,
+#content .panel .item,
+#content .panel .actions {
+    border-color: #ccc;
+}
 #content #primary .panel h2 {
-    height: 2em;
     line-height: 2em;
+    border-style: none;
 }
 #content #primary .panel p {
     clear: both;
 }
-#content #secondary .panel h3 {
-    height: 30px;
+#content #secondary .panel h2 {
     line-height: 30px;
+    border-style: none;
 }
+#content .panel .sidebar ul {
+     list-style: none;
+     margin-left: 0;
+}
+#content .panel ul {
+    list-style: square;
+    margin-left: 1em;
+}
+
 /**
  * Panels have different styles for different content layouts
  */
 .layout-wide-right-sidebar #primary .panel .sidebar {
     float: left;
-    width: 30%;
+    width: 22%;
 }
 .layout-wide-right-sidebar #primary .panel .contents {
     float: left;
     padding-top: 6px;
     padding-left: 14px;
     border-left: 1px solid #ccc;
-    width: 70%;
+    width: 75%;
     line-height: 1.8;
 }
 .layout-wide-right-sidebar #secondary .panel .contents {
     margin: 0.5em 0;
     line-height: 1.8;
-}
-/**
- * Panels have unique IDs for CSS hooks
- */
-#panel-quick-update .sidebar p {
-    height: 3em;
-    line-height: 3em;
-}
-#panel-quick-update .contents label {
-    display: block;
-    width: 100%;
-    color: #777711;
-    font-weight: bold;
-}
-#panel-quick-update .contents input,
-#panel-quick-update .contents textarea {
-    width: 95%;
-}
-#panel-quick-update .contents textarea {
-    height: 120px;
 }
 /* panel-first class is added through js */
 #content .panel-first {
diff -r bce79d7b087a -r 12c5f516dea2 htdocs/stc/gradation/gradation-vertical.css
--- a/htdocs/stc/gradation/gradation-vertical.css	Sun Jul 26 19:02:20 2009 +0000
+++ b/htdocs/stc/gradation/gradation-vertical.css	Sun Jul 26 19:31:11 2009 +0000
@@ -346,55 +346,50 @@ table#table_yourlayers td { padding: .15
     margin: 0 0 0.155567em 0;
     overflow: hidden;
 }
+#content .panel .sidebar,
+#content .panel .contents,
+#content .panel .item,
+#content .panel .actions {
+    border-color: #ccc;
+}
 #content #primary .panel h2 {
-    height: 2em;
     line-height: 2em;
+    border-style: none;
 }
 #content #primary .panel p {
     clear: both;
 }
-#content #secondary .panel h3 {
-    height: 30px;
+#content #secondary .panel h2 {
     line-height: 30px;
+    border-style: none;
 }
+#content .panel .sidebar ul {
+     list-style: none;
+     margin-left: 0;
+}
+#content .panel ul {
+    list-style: circle;
+    margin-left: 1em;
+}
+
 /**
  * Panels have different styles for different content layouts
  */
 .layout-wide-right-sidebar #primary .panel .sidebar {
     float: left;
-    width: 30%;
+    width: 22%;
 }
 .layout-wide-right-sidebar #primary .panel .contents {
     float: left;
     padding-top: 6px;
     padding-left: 14px;
     border-left: 1px solid #ccc;
-    width: 70%;
+    width: 75%;
     line-height: 1.8;
 }
 .layout-wide-right-sidebar #secondary .panel .contents {
     margin: 0.5em 0;
     line-height: 1.8;
-}
-/**
- * Panels have unique IDs for CSS hooks
- */
-#panel-quick-update .sidebar p {
-    height: 3em;
-    line-height: 3em;
-}
-#panel-quick-update .contents label {
-    display: block;
-    width: 100%;
-    color: #555;
-    font-weight: bold;
-}
-#panel-quick-update .contents input,
-#panel-quick-update .contents textarea {
-    width: 95%;
-}
-#panel-quick-update .contents textarea {
-    height: 120px;
 }
 /* panel-first class is added through js */
 #content .panel-first {
diff -r bce79d7b087a -r 12c5f516dea2 htdocs/stc/widgets/latestinbox.css
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/stc/widgets/latestinbox.css	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,20 @@
+.appwidget-latestinbox h2 {
+  border-bottom-style: none !important;
+}
+.appwidget-latestinbox .contents {
+  padding: 0 !important;
+
+}
+.appwidget-latestinbox .item {
+  border-top: solid 1px;
+  padding: 0.5em 0.5em 0.5em 1em;
+  width: 100%;
+}
+.appwidget-latestinbox .actions {
+  margin-top: 0.4em;
+  font-size: 0.8em;
+}
+
+.appwidget-latestinbox .sidebar {
+  border-top: 1px solid;
+}
diff -r bce79d7b087a -r 12c5f516dea2 htdocs/stc/widgets/quickupdate.css
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/stc/widgets/quickupdate.css	Sun Jul 26 19:31:11 2009 +0000
@@ -0,0 +1,32 @@
+#panel-quickupdate .sidebar p {
+    height: 3em;
+    line-height: 3em;
+}
+#panel-quickupdate .contents label {
+    display: block;
+    width: 100%;
+    color: #555;
+    font-weight: bold;
+}
+#panel-quickupdate .contents .metadata label {
+    display: inline;
+}
+#panel-quickupdate .contents input,
+#panel-quickupdate .contents textarea {
+    width: 95%;
+}
+#panel-quickupdate .contents textarea {
+    height: 120px;
+}
+#panel-quickupdate .metadata .form-input {
+    width: 45%;
+    float: left;
+}
+#panel-quickupdate .metadata input,
+#panel-quickupdate .metadata select {
+     width: 60%;
+}
+
+#panel-quickupdate .submit input {
+     width: auto;
+}
diff -r bce79d7b087a -r 12c5f516dea2 htdocs/stc/widgets/sitemessages.css
--- a/htdocs/stc/widgets/sitemessages.css	Sun Jul 26 19:02:20 2009 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-.homepage-account-right {
-    background: none !important;
-}
--------------------------------------------------------------------------------