WAComponent subclass: #SLCommentViewer
instanceVariableNames: 'story '
classVariableNames: ''
poolDictionaries: ''
category: 'SBlogLite-UI'!
!SLCommentViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:18'!
addComment
| comment |
comment _ SLComment parent: story.
(self call: (SLCommentEditor new story: story; comment: comment))
ifTrue: [comment post]! !
!SLCommentViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:19'!
renderAddCommentLinkOn: html
html spanClass: 'blogStamp' with: [html anchorWithAction: [self addComment] text: 'add']! !
!SLCommentViewer methodsFor: 'as yet unclassified' stamp: 'lr 10/26/2003 10:40'!
renderComment: aComment on: html
html divClass: 'commentStamp' with: [
html text: aComment author.
aComment email isEmptyOrNil ifFalse: [
self renderEmail: aComment email on: html ].
html text: ', '.
html text: aComment timeStamp.
].
html divClass: 'commentBody' with: [ html blogText: aComment text ].! !
!SLCommentViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:19'!
renderContentOn: html
story hasComments ifFalse: [^ self].
html divClass: 'commentTitle' with: [
html text: 'Comments '.
self renderAddCommentLinkOn: html
].
story comments do: [:ea | self renderComment: ea on: html].! !
!SLCommentViewer methodsFor: 'as yet unclassified' stamp: 'lr 10/26/2003 10:31'!
renderEmail: aString on: html
| stream |
stream _ aString withBlanksTrimmed readStream.
html text: ' ('; text: (stream upTo: $@).
stream atEnd ifFalse: [
html text: ' AT '; text: stream upToEnd ].
html text: ')' ! !
!SLCommentViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:28'!
story: aStory
story _ aStory! !
SLCommentViewer subclass: #SLCommentEditor
instanceVariableNames: 'comment '
classVariableNames: ''
poolDictionaries: ''
category: 'SBlogLite-UI'!
!SLCommentEditor methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 12:44'!
comment: aComment
comment _ aComment! !
!SLCommentEditor methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:19'!
renderAddCommentLinkOn: html
! !
!SLCommentEditor methodsFor: 'as yet unclassified' stamp: 'lr 10/26/2003 10:36'!
renderContentOn: html
super renderContentOn: html.
html divClass: 'commentBody' with: [
html divClass: 'commentTitle' with: 'Add Comment'.
html cssClass: 'addComment'; form: [
html layoutTableOfWidth: '100%' do: [
html tableRowWith: 'Author:' with: [html textInputOn: #author of: comment].
html tableRowWith: 'Email: ' with: [html textInputOn: #email of: comment].
html tableRowWith: [
html cssClass: 'commentTextArea'; textAreaOn: #text of: comment.
] span: 2.
html attributes alignCenter.
html tableRowWith: [
html submitButtonWithAction: [self answer: true] text: 'Save'.
html space.
html submitButtonWithAction: [self answer: false] text: 'Cancel'.
] span: 2.
]
]
]! !
Object subclass: #SLCss
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'SBlogLite-UI'!
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
SLCss class
instanceVariableNames: ''!
!SLCss class methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 17:15'!
blaineCss
^'BODY {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BACKGROUND: #f6f6f6; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #000000; PADDING-TOP: 0px; FONT-FAMILY: "Trebuchet MS",Trebuchet,Verdana,Sans-Serif
}
A {
COLOR: #800080
}
A:hover {
COLOR: #e0ad12
}
DIV.title {
PADDING-RIGHT: 0px; BORDER-TOP: #800000 1px solid; PADDING-LEFT: 0px; BACKGROUND: #800080; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: white; PADDING-TOP: 0px; BORDER-BOTTOM: #800000 1px dotted
}
DIV.titleDescription {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BACKGROUND: none transparent scroll repeat 0% 0%; PADDING-BOTTOM: 0px; MARGIN: 7px 12% 7px 5%; FONT: bold 85% Verdana,Sans-Serif; COLOR: #ffde80; PADDING-TOP: 0px
}
DIV.mainContent {
float: right ; width: 60%; PADDING-RIGHT: 7%; PADDING-LEFT: 3%; PADDING-BOTTOM: 10px; BORDER-LEFT: #800000 1px dotted; PADDING-TOP: 30px
}
.title A {
COLOR: #f5deb3; TEXT-DECORATION: none ;
}
DIV.sideBar {
float: left ; PADDING-RIGHT: 4px; PADDING-LEFT: 10px; PADDING-BOTTOM: 0px; MARGIN: 20px 0px 0px 0px; PADDING-TOP: 0px; TEXT-ALIGN: left
}
P.blogPostTitle {
FONT-WEIGHT: bold;
}
.blogStamp {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 90%; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #444444; PADDING-TOP: 0px
}
.blogStamp A {
COLOR: #800000; BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; TEXT-DECORATION: none; BORDER-BOTTOM-STYLE: none
}
.blogStamp A:hover {
TEXT-DECORATION: underline
}
H1 {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
H2 {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
H3 {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
H4 {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
H5 {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
H6 {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
H1 {
PADDING-RIGHT: 0px; PADDING-LEFT: 5%; BACKGROUND: #800080; PADDING-BOTTOM: 10px; FONT: bold 175% Verdana,Sans-Serif; COLOR: #f5deb3; PADDING-TOP: 25px; BORDER-BOTTOM: #ffde80 1px solid; LETTER-SPACING: -2px
}
H2 {
FONT-WEIGHT: bold; COLOR: #9e5205; FONT-FAMILY: Verdana,Sans-Serif; LETTER-SPACING: -1px
}
H3 {
FONT-SIZE: 100%; MARGIN: 10px 0px 0px; COLOR: #700070
}
H4 {
COLOR: #aa0033
}
H6 {
FONT-SIZE: 100%; COLOR: #800080
}
.blogPost {
FONT-SIZE: 80%; MARGIN: 0px 0px 30px
}
.blogPost STRONG {
FONT-WEIGHT: bold; COLOR: #000000
}
#sideBar UL {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 85%; PADDING-BOTTOM: 0px; MARGIN: 0px 0px 33px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none
}
#sideBar LI {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 85%; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none
}
#sideBar UL A {
PADDING-RIGHT: 2px; PADDING-LEFT: 2px; PADDING-BOTTOM: 2px; MARGIN: 1px; COLOR: #999999; BORDER-TOP-STYLE: none; PADDING-TOP: 2px; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; TEXT-DECORATION: none; BORDER-BOTTOM-STYLE: none
}
#sideBar UL A:link {
COLOR: #800000
}
#sideBar UL A:visited {
COLOR: #800000
}
#sideBar UL A:active {
COLOR: #ff0000
}
#sideBar UL A:hover {
COLOR: #de7008; TEXT-DECORATION: none
}
PRE {
COLOR: #999999
}
CODE {
COLOR: #999999
}
STRIKE {
COLOR: #999999
}
.syndicate {
FONT-SIZE: 90%; COLOR: #800080 ; PADDING-LEFT: 8px;
}
.recentEntries {
FONT-SIZE: 100%; COLOR: #800080
}
.archiveEntries {
FONT-SIZE: 100%; COLOR: #800080
}
Div.calendar {
PADDING-BOTTOM: 20px ; PADDING-TOP: 15px; COLOR: #800000;
}
.calendar {
font-size: 80%
}
.calendarCaption {
FONT-SIZE: 100%; FONT-WEIGHT: bold; COLOR: #800080
}
tr.calendarTitle {
FONT-SIZE: 90%; COLOR: #800080
}
.calendar td {
font-size: 80% ; TEXT-ALIGN: center ;
}
.calendarTitle td {
}
td.calendarArchiveDate {
BACKGROUND: lightGrey ; font-size: 80% ; TEXT-ALIGN: center ;
}
.commentTitle {
PADDING-TOP: 10px; COLOR: #800000;
}
.commentStamp {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 90%; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #444444; PADDING-TOP: 0px
}
textArea.commentTextArea {
width : 100%;
height: 200px;;
}
'! !
!SLCss class methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 17:28'!
defaultCss
^ self standardCss! !
!SLCss class methodsFor: 'as yet unclassified' stamp: 'lr 10/26/2003 10:14'!
standardCss
^'BODY {
BACKGROUND: #eee; MARGIN: 20px
}
A {
FONT-WEIGHT: bold; COLOR: #003366; TEXT-DECORATION: none
}
A:link {
COLOR: #003366; TEXT-DECORATION: none
}
A:visited {
COLOR: #003366; TEXT-DECORATION: none
}
A:active {
COLOR: #ffcc66
}
A:hover {
COLOR: #ffcc66
}
H1 {
FONT-SIZE: x-large; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
H2 {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
H3 {
PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px
}
DIV.title {
BORDER-RIGHT: #fff 1px solid; PADDING-RIGHT: 15px; BORDER-TOP: #fff 1px solid; PADDING-LEFT: 15px; FONT-WEIGHT: bold; FONT-SIZE: x-large; BACKGROUND: #003366; PADDING-BOTTOM: 15px; BORDER-LEFT: #fff 1px solid; COLOR: #fff; PADDING-TOP: 15px; FONT-FAMILY: georgia, verdana, arial, sans-serif
}
.title A {
FONT-SIZE: x-large; COLOR: #fff; FONT-FAMILY: georgia, verdana, arial, sans-serif; TEXT-DECORATION: none
}
.title A:link {
FONT-SIZE: x-large; COLOR: #fff; FONT-FAMILY: georgia, verdana, arial, sans-serif; TEXT-DECORATION: none
}
.title A:visited {
FONT-SIZE: x-large; COLOR: #fff; FONT-FAMILY: georgia, verdana, arial, sans-serif; TEXT-DECORATION: none
}
.title A:active {
FONT-SIZE: x-large; COLOR: #fff; FONT-FAMILY: georgia, verdana, arial, sans-serif; TEXT-DECORATION: none
}
.title A:hover {
FONT-SIZE: x-large; COLOR: #fff; FONT-FAMILY: georgia, verdana, arial, sans-serif; TEXT-DECORATION: none
}
DIV.titleDescription {
FONT-WEIGHT: bold; FONT-SIZE: x-small; BACKGROUND: #003366; TEXT-TRANSFORM: none; COLOR: #fff; FONT-FAMILY: verdana, arial, sans-serif
}
DIV.mainContent {
PADDING-RIGHT: 15px; PADDING-LEFT: 15px; BACKGROUND: #fff; PADDING-BOTTOM: 15px; PADDING-TOP: 15px; BORDER-RIGHT: #fff 1px solid; BORDER-TOP: #fff 1px solid; BACKGROUND: #fff; FLOAT: left; MARGIN-BOTTOM: 20px; BORDER-LEFT: #fff 1px solid; WIDTH: 60%; MARGIN-RIGHT: 15px; BORDER-BOTTOM: #fff 1px solid; POSITION: relative;
}
DIV.mainBody {
BACKGROUND: white
}
DIV.sideBar {
BORDER-RIGHT: #fff 1px solid; PADDING-RIGHT: 15px; BORDER-TOP: #fff 1px solid; PADDING-LEFT: 15px; BACKGROUND: #999; PADDING-BOTTOM: 15px; BORDER-LEFT: #fff 1px solid; PADDING-TOP: 15px; BORDER-BOTTOM: #fff 1px solid
}
P.blogPostTitle {
FONT-WEIGHT: bold;
}
.blogStamp {
PADDING-TOP 16px; FONT-SIZE: x-small; MARGIN-BOTTOM: 25px; COLOR: #000000; FONT-FAMILY: verdana, arial, sans-serif
}
.blogPost {
PADDING-BOTTOM: 15px; FONT-WEIGHT: normal; FONT-SIZE: small; BACKGROUND: #fff; COLOR: #666; LINE-HEIGHT: 150%; FONT-FAMILY: georgia, verdana, arial, sans-serif
}
.blogPost A {
FONT-WEIGHT: normal; TEXT-DECORATION: underline
}
.blogPost A:link {
FONT-WEIGHT: normal; TEXT-DECORATION: underline
}
.blogPost A:visited {
FONT-WEIGHT: normal; TEXT-DECORATION: underline
}
.blogPost A:active {
FONT-WEIGHT: normal; TEXT-DECORATION: underline
}
.blogPost A:hover {
FONT-WEIGHT: normal; TEXT-DECORATION: underline
}
.blogDate {
FONT-WEIGHT: bold; FONT-SIZE: small; MARGIN-BOTTOM: 10px; COLOR: #666; BORDER-BOTTOM: #999 1px solid; FONT-FAMILY: georgia, verdana, arial, sans-serif
}
.blogPostTitle {
FONT-SIZE: small; TEXT-TRANSFORM: uppercase; COLOR: #000000; FONT-FAMILY: verdana, arial, sans-serif
}
.posted {
FONT-SIZE: x-small; MARGIN-BOTTOM: 25px; COLOR: #000000; FONT-FAMILY: verdana, arial, sans-serif
}
.recentEntries {
PADDING-RIGHT: 2px; MARGIN-TOP: 10px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; FONT-SIZE: small; BACKGROUND: #999; PADDING-BOTTOM: 2px; COLOR: #fff; PADDING-TOP: 2px; BORDER-BOTTOM: #fff 1px dotted; FONT-FAMILY: georgia, verdana, arial, sans-serif; LETTER-SPACING: 0.1em; TEXT-ALIGN: center
}
.archiveEntries {
PADDING-RIGHT: 2px; MARGIN-TOP: 10px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; FONT-SIZE: small; BACKGROUND: #999; PADDING-BOTTOM: 2px; COLOR: #fff; PADDING-TOP: 2px; BORDER-BOTTOM: #fff 1px dotted; FONT-FAMILY: georgia, verdana, arial, sans-serif; LETTER-SPACING: 0.1em; TEXT-ALIGN: center
}
.syndicate {
PADDING-RIGHT: 2px; MARGIN-TOP: 10px; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: xx-small; BACKGROUND: #ccc; PADDING-BOTTOM: 2px; LINE-HEIGHT: 140%; PADDING-TOP: 2px; FONT-FAMILY: verdana, arial, sans-serif; TEXT-ALIGN: center
}
DIV.sideEntry {
MARGIN-LEFT: 10px; PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; FONT-SIZE: small; BACKGROUND: #999; PADDING-BOTTOM: 2px; COLOR: #333; LINE-HEIGHT: 140%; PADDING-TOP: 2px; FONT-FAMILY: verdana, arial, sans-serif
}
#sideBar UL {
PADDING-RIGHT: 0px; PADDING-LEFT: 10px; FONT-SIZE: 85%; PADDING-BOTTOM: 0px; MARGIN: 0px 0px 33px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none
}
.calendar {
TEXT-ALIGN: center; MARGIN-LEFT: 10px; PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; FONT-SIZE: 85%; BACKGROUND: #999; PADDING-BOTTOM: 2px; COLOR: #333; LINE-HEIGHT: 140%; PADDING-TOP: 16px; FONT-FAMILY: verdana, arial, sans-serif
}
.calendarCaption {
PADDING-RIGHT: 2px; MARGIN-TOP: 10px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; BACKGROUND: #999; PADDING-BOTTOM: 2px; COLOR: #fff; PADDING-TOP: 2px; BORDER-BOTTOM: #fff 1px dotted; FONT-FAMILY: georgia, verdana, arial, sans-serif; LETTER-SPACING: 0.1em; TEXT-ALIGN: center
}
.calendar table {
margin-left: auto;
margin-right: auto;
}
tr.calendarTitle {
font-size: 90%; COLOR: #003366; TEXT-DECORATION: none ; FONT-WEIGHT: bold
}
.calendar td {
TEXT-ALIGN: center; MARGIN-LEFT: 10px; PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; FONT-SIZE: 80%; BACKGROUND: #999; PADDING-BOTTOM: 2px; COLOR: #333; LINE-HEIGHT: 140%; PADDING-TOP: 2px; FONT-FAMILY: verdana, arial, sans-serif
}
.calendarTitle td {
font-size: 75%; COLOR: #003366; TEXT-DECORATION: none ; FONT-WEIGHT: bold
}
.calendarArchiveDate {
TEXT-ALIGN: center; MARGIN-LEFT: 10px; PADDING-RIGHT: 2px; PADDING-LEFT: 2px; FONT-WEIGHT: normal; FONT-SIZE: 80%; BACKGROUND: lightgrey; PADDING-BOTTOM: 2px; COLOR: #333; LINE-HEIGHT: 140%; PADDING-TOP: 2px; FONT-FAMILY: verdana, arial, sans-serif
}
.commentBody {
PADDING-BOTTOM: 15px; FONT-WEIGHT: normal; FONT-SIZE: small; BACKGROUND: #fff; COLOR: #666; LINE-HEIGHT: 150%; FONT-FAMILY: georgia, verdana, arial, sans-serif
}
.commentBody td {
PADDING-BOTTOM: 15px; FONT-WEIGHT: normal; FONT-SIZE: small; BACKGROUND: #fff; COLOR: #666; LINE-HEIGHT: 150%; FONT-FAMILY: georgia, verdana, arial, sans-serif
}
.commentTitle {
FONT-WEIGHT: bold; FONT-SIZE: small; MARGIN-BOTTOM: 10px; COLOR: #666; BORDER-BOTTOM: #999 1px solid; FONT-FAMILY: georgia, verdana, arial, sans-serif
}
.commentStamp {
PADDING-TOP 16px; FONT-SIZE: x-small; MARGIN-BOTTOM: 8px; FONT-FAMILY: verdana, arial, sans-serif
}
textArea.commentTextArea {
width : 100%;
height: 200px;;
}
.newStory {
TEXT-ALIGN: left ; PADDING-RIGHT: 15px;
}
.newStory A {
COLOR: darkgreen ; TEXT-DECORATION: underline
}
.configure {
TEXT-ALIGN: left;
}
.configure A {
COLOR: darkgreen ; TEXT-DECORATION: underline
}
.login A {
COLOR: #003366; ; TEXT-DECORATION: underline
}
.editStory {
PADDING-BOTTOM: 15px; FONT-WEIGHT: normal; FONT-SIZE: small; BACKGROUND: #fff; COLOR: #666; LINE-HEIGHT: 150%; FONT-FAMILY: georgia, verdana, arial, sans-serif
}
'! !
WAComponent subclass: #SLFrame
instanceVariableNames: 'main blog '
classVariableNames: ''
poolDictionaries: ''
category: 'SBlogLite-UI'!
!SLFrame methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:55'!
blogName
| url |
url _ self session initialRequest path allButFirst: self session basePath size.
^ (url findTokens: $/) first! !
!SLFrame methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:52'!
initialize
(SLBlogStore current blogs includesKey: self blogName) ifFalse: [self noSuchBlog].
blog _ SLBlogStore current blogNamed: self blogName.
main _ SLFrontPage new blog: blog.
main processRequest: self session initialRequest.! !
!SLFrame methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 22:48'!
renderContentOn: html
html title: blog title.
html divClass: 'title' with: [
html anchorWithUrl: self session basePath do: blog title.
html divClass: 'titleDescription' with: blog description.
].
html divClass: 'mainBody' with: main! !
!SLFrame methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 14:33'!
style
^ SLCss defaultCss! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
SLFrame class
instanceVariableNames: ''!
!SLFrame class methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:49'!
initialize
self registerAsApplication: 'blog'! !
WAComponent subclass: #SLFrontPage
instanceVariableNames: 'blog calendar storyList '
classVariableNames: ''
poolDictionaries: ''
category: 'SBlogLite-UI'!
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'mas 10/26/2003 19:35'!
baseUrl
^ (self session initialRequest headers at: 'host'), (self session basePath)! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:31'!
blog: aBlog
blog _ aBlog! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 17:06'!
chooseDate: aDate
storyList storyBlock: [blog storiesOnDate: aDate].
self session addToPath: (self pathForDate: aDate)
! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:56'!
chooseStory: aStory
self session addToPath: blog name, '/', aStory id asString.
calendar date: nil.
storyList storyBlock: [Array with: aStory]! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'mas 10/25/2003 20:16'!
displayAllRss
| response xml |
response _ WAGenericResponse new.
xml _ String streamContents: [:s | SLRssWriter writeBlog: blog on: s].
response contentType: 'text/xml'.
response nextPutAll: xml.
self session returnResponse: response.! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'mas 10/26/2003 01:56'!
displayRss
| response xml |
response _ WAGenericResponse new.
xml _ String streamContents: [:s | SLRssWriter writeBlog: blog stories: storyList stories on: s withBaseUrl: self baseUrl].
response contentType: 'text/xml'.
response nextPutAll: xml.
self session returnResponse: response.! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:34'!
initialize
storyList _ SLStoryList new
storyBlock: [blog recentStories];
selectBlock: [:story | self chooseStory: story].
calendar _ SLMiniCalendar new
canSelectBlock: [:date | blog hasStoriesOnDate: date];
selectBlock: [:date | self chooseDate: date]! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 14:43'!
login
(self call: (SLLoginPage new validateBlock: [:u :p | blog checkUsername: u password: p]))
ifTrue: [self session isolate: [self call: (SLAdminPage new blog: blog)]]! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:57'!
pathForDate: aDate
^ blog name, '/', (aDate printFormat: #(3 2 1 $/ 1 1 2))! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:56'!
processRequest: aRequest
| url tokens |
url _ aRequest path allButFirst: self session basePath size.
tokens _ url findTokens: '/'.
[
tokens size = 4 ifTrue: [self requestDay: tokens fourth month: tokens third year: tokens second].
tokens size = 3 ifTrue: [tokens second = 'rss' ifTrue: [self requestFeed: tokens third]].
tokens size = 2 ifTrue: [self requestStory: tokens second].
tokens size = 1 ifTrue: [self session addToPath: blog name].
] on: Error do: []! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 14:35'!
renderContentOn: html
html divClass: 'mainContent' with: storyList.
html divClass: 'sideBar' with: [self renderSideBarOn: html].! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:57'!
renderLoginOn: html
html divClass: 'login' with: [html anchorWithAction: [self login] text: 'login']! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:58'!
renderSideBarOn: html
html render: calendar.
html cssClass: 'syndicate'; paragraph: [
html anchorWithUrl: (self session basePath, '/', blog name, '/rss/recent.xml') do:
[html attributes border: 0.
html image: 'http://www.scripting.com/images/xml.gif' altText: 'xml'].
].
self renderLoginOn: html.! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:29'!
requestDay: dayString month: monthString year: yearString
| date |
date _ Date
newDay: dayString asNumber
monthNumber: monthString asNumber
year: yearString asNumber.
calendar select: date! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:39'!
requestFeed: feedName
feedName = 'recent.xml' ifTrue: [self displayRss].
feedName = 'all.xml' ifTrue: [self displayAllRss].! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:29'!
requestStory: idString
| id |
id _ UUID fromString: idString.
self chooseStory: (blog storyWithId: id)! !
!SLFrontPage methodsFor: 'as yet unclassified' stamp: 'mas 10/26/2003 01:36'!
setBaseUrl
baseUrl _ self session basePath.
self halt.
! !
WAComponent subclass: #SLMiniCalendar
instanceVariableNames: 'month date canSelectBlock selectBlock '
classVariableNames: ''
poolDictionaries: ''
category: 'SBlogLite-UI'!
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 14:38'!
canSelect: aDate
^ canSelectBlock notNil and: [canSelectBlock value: aDate]! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 15:16'!
canSelectBlock: aBlock
canSelectBlock _ aBlock! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 15:25'!
date
^ date contents! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 17:40'!
date: aDate
date contents: aDate! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 22:56'!
initialize
month _ WAStateHolder new contents: Date today month.
date _ WAStateHolder new.! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 22:56'!
month
^ month contents! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 22:56'!
month: aMonth
^ month contents: aMonth! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 22:56'!
monthHeading
^ self month name, ' ', self month year asString! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:14'!
renderCellForDate: aDate on: html
html tableData: [
aDate month = self month ifTrue:
[html cssClass: (self date = aDate ifTrue: ['calendarArchiveDate']).
html span: [
(self canSelect: aDate)
ifTrue: [html anchorWithAction: [self select: aDate] text: aDate dayOfMonth]
ifFalse: [html text: aDate dayOfMonth]
]]
]! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 11:35'!
renderContentOn: html
html divClass: 'calendar' with: [
html spanClass: 'calendarCaption' with: self monthHeading.
html table: [
html cssClass: 'calendarTitle'; tableRow: [
self weekDays do: [:ea | html tableData: ea].
].
self month eachWeekDo: [:week | self renderRowForWeek: week on: html].
].
self renderMonthNavigationOn: html.
]! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:14'!
renderMonthNavigationOn: html
html spanClass: 'calendarPrevious' with: [
html
anchorWithAction: [self month: self month previous]
text: (self month previous name first: 3).
].
html space.
html spanClass: 'calendarNext' with: [
html
anchorWithAction: [self month: self month next]
text: (self month next name first: 3).
]
! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 14:23'!
renderRowForWeek: aWeek on: html
html tableRow: [
aWeek do: [:ea | self renderCellForDate: ea on: html].
]! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 17:40'!
select: aDate
self date: aDate.
selectBlock ifNotNil: [selectBlock value: aDate]! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 17:39'!
selectBlock: aBlock
selectBlock _ aBlock! !
!SLMiniCalendar methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 14:25'!
weekDays
^ (1 to: 7) collect: [:i | (Date nameOfDay: i) first: 3]! !
WAComponent subclass: #SLStoryList
instanceVariableNames: 'storyBlock selectBlock storyViewers '
classVariableNames: ''
poolDictionaries: ''
category: 'SBlogLite-UI'!
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:14'!
initialize
storyBlock _ WAStateHolder new.
storyViewers _ Dictionary new.! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 12:31'!
renderContentOn: html
self storiesByDate do:
[:group |
self renderStoryGroup: group on: html]! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 15:46'!
renderDateHeader: aDate on: html
html divClass: 'blogDate' with: aDate! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:14'!
renderStoryGroup: aCollection on: html
self renderDateHeader: aCollection anyOne date on: html.
aCollection do:
[:ea |
html render: (self storyViewerFor: ea)].! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:25'!
select: aStory
selectBlock ifNotNil: [selectBlock value: aStory]! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:25'!
selectBlock: aBlock
selectBlock _ aBlock! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 14:18'!
stories
^ storyBlock contents value! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/23/2003 13:52'!
storiesByDate
| dictionary |
dictionary _ self stories groupBy: [:ea | ea date] having: [:ea | true].
^ dictionary keys asSortedCollection reversed collect: [:ea | dictionary at: ea]! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 13:21'!
storyBlock: aBlock
storyBlock contents: aBlock! !
!SLStoryList methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:26'!
storyViewerFor: aStory
^ storyViewers at: aStory ifAbsentPut: [SLStoryViewer new list: self; story: aStory]! !
WAComponent subclass: #SLStoryViewer
instanceVariableNames: 'story list commentViewer showComments '
classVariableNames: ''
poolDictionaries: ''
category: 'SBlogLite-UI'!
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 16:54'!
addComment
self showComments: true.
self commentViewer addComment.! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 16:43'!
commentInfo
^ self showComments
ifFalse: [story comments size asString, ' comments, last by ', story comments last author]
ifTrue: ['hide comments']! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:27'!
commentViewer
^ commentViewer ifNil: [commentViewer _ SLCommentViewer new story: story]! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:20'!
initialize
showComments _ WAStateHolder new contents: false! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:12'!
list: aStoryList
list _ aStoryList! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 16:51'!
renderCommentInfoOn: html
story hasComments
ifTrue: [html anchorWithAction: [self toggleComments] text: self commentInfo]
ifFalse: [html anchorWithAction: [self addComment] text: 'add comment'].! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'lr 10/26/2003 10:41'!
renderContentOn: html
html divClass: 'blogPost' with: [
self renderTitleOn: html.
html blogText: story text.
self renderStampOn: html.
self showComments ifTrue: [html render: self commentViewer].
]! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/25/2003 23:57'!
renderPermalinkOn: html
html anchorWithUrl: self session basePath, '/', story blog name, '/', story id asString title: story title do: 'link'.
! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 16:50'!
renderStampOn: html
html divClass: 'blogStamp' with: [
self renderPermalinkOn: html.
html space.
html text: story time.
html space.
self renderCommentInfoOn: html.
].
! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:22'!
renderTitleOn: html
html cssClass: 'blogPostTitle'; paragraph: [
html anchorWithAction: [self select] text: story title.
].
! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:12'!
select
list select: story! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:06'!
selectBlock: aBlock
selectBlock _ aBlock! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:20'!
showComments
^ showComments contents! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 16:54'!
showComments: aBoolean
showComments contents: aBoolean! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 15:06'!
story: aStory
story _ aStory! !
!SLStoryViewer methodsFor: 'as yet unclassified' stamp: 'avi 10/24/2003 16:54'!
toggleComments
self showComments: self showComments not! !
SLFrame initialize!