Write blog post list component
This commit is contained in:
@@ -1,18 +1,20 @@
|
||||
Class {
|
||||
#name : #TBApplicationRootComponent,
|
||||
#superclass : #WAComponent,
|
||||
#name : 'TBApplicationRootComponent',
|
||||
#superclass : 'WAComponent',
|
||||
#instVars : [
|
||||
'main'
|
||||
],
|
||||
#category : #'TinyBlog-Components'
|
||||
#category : 'TinyBlog-Components-Components',
|
||||
#package : 'TinyBlog-Components',
|
||||
#tag : 'Components'
|
||||
}
|
||||
|
||||
{ #category : #testing }
|
||||
{ #category : 'testing' }
|
||||
TBApplicationRootComponent class >> canBeRoot [
|
||||
^ true
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBApplicationRootComponent class >> initialize [
|
||||
"self initialize"
|
||||
| app |
|
||||
@@ -23,23 +25,29 @@ TBApplicationRootComponent class >> initialize [
|
||||
addLibrary: SBSDeploymentLibrary
|
||||
]
|
||||
|
||||
{ #category : #rendering }
|
||||
{ #category : 'rendering' }
|
||||
TBApplicationRootComponent >> children [
|
||||
^ { main }
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBApplicationRootComponent >> initialize [
|
||||
super initialize.
|
||||
main := TBScreenComponent new
|
||||
main := TBPostsListComponent new
|
||||
]
|
||||
|
||||
{ #category : #rendering }
|
||||
{ #category : 'initialization' }
|
||||
TBApplicationRootComponent >> main: aComponent [
|
||||
|
||||
main := aComponent
|
||||
]
|
||||
|
||||
{ #category : 'rendering' }
|
||||
TBApplicationRootComponent >> renderContentOn: html [
|
||||
html render: main
|
||||
]
|
||||
|
||||
{ #category : #rendering }
|
||||
{ #category : 'rendering' }
|
||||
TBApplicationRootComponent >> updateRoot: anHtmlRoot [
|
||||
super updateRoot: anHtmlRoot.
|
||||
anHtmlRoot beHtml5.
|
27
src/TinyBlog-Components/TBHeaderComponent.class.st
Normal file
27
src/TinyBlog-Components/TBHeaderComponent.class.st
Normal file
@@ -0,0 +1,27 @@
|
||||
Class {
|
||||
#name : 'TBHeaderComponent',
|
||||
#superclass : 'SBSComponent',
|
||||
#category : 'TinyBlog-Components-Components',
|
||||
#package : 'TinyBlog-Components',
|
||||
#tag : 'Components'
|
||||
}
|
||||
|
||||
{ #category : 'rendering' }
|
||||
TBHeaderComponent >> renderBrandOn: html [
|
||||
html navigationBarBrand
|
||||
url: self application url;
|
||||
with: 'TinyBlog'
|
||||
]
|
||||
|
||||
{ #category : 'rendering' }
|
||||
TBHeaderComponent >> renderContentOn: html [
|
||||
| bar |
|
||||
bar := html navigationBar.
|
||||
|
||||
bar background beLight.
|
||||
bar with: [
|
||||
html container: [
|
||||
self renderBrandOn: html
|
||||
]
|
||||
]
|
||||
]
|
43
src/TinyBlog-Components/TBPostComponent.class.st
Normal file
43
src/TinyBlog-Components/TBPostComponent.class.st
Normal file
@@ -0,0 +1,43 @@
|
||||
Class {
|
||||
#name : 'TBPostComponent',
|
||||
#superclass : 'SBSComponent',
|
||||
#instVars : [
|
||||
'post'
|
||||
],
|
||||
#category : 'TinyBlog-Components-Components',
|
||||
#package : 'TinyBlog-Components',
|
||||
#tag : 'Components'
|
||||
}
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostComponent >> date [
|
||||
^ post date
|
||||
]
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostComponent >> initialize [
|
||||
super initialize.
|
||||
post := TBPost new
|
||||
]
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostComponent >> post: aPost [
|
||||
post := aPost
|
||||
]
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostComponent >> renderContentOn: html [
|
||||
html heading level: 2; with: self title.
|
||||
html heading level: 6; with: self date.
|
||||
html text: self text
|
||||
]
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostComponent >> text [
|
||||
^ post text
|
||||
]
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostComponent >> title [
|
||||
^ post title
|
||||
]
|
41
src/TinyBlog-Components/TBPostsListComponent.class.st
Normal file
41
src/TinyBlog-Components/TBPostsListComponent.class.st
Normal file
@@ -0,0 +1,41 @@
|
||||
Class {
|
||||
#name : 'TBPostsListComponent',
|
||||
#superclass : 'TBScreenComponent',
|
||||
#instVars : [
|
||||
'postComponents'
|
||||
],
|
||||
#category : 'TinyBlog-Components-Components',
|
||||
#package : 'TinyBlog-Components',
|
||||
#tag : 'Components'
|
||||
}
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostsListComponent >> children [
|
||||
^ self postComponents, super children
|
||||
]
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostsListComponent >> initialize [
|
||||
super initialize.
|
||||
postComponents := OrderedCollection new
|
||||
]
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostsListComponent >> postComponents [
|
||||
postComponents := self readSelectedPosts
|
||||
collect: [ :each | TBPostComponent new post: each ].
|
||||
^ postComponents
|
||||
]
|
||||
|
||||
{ #category : 'initialization' }
|
||||
TBPostsListComponent >> readSelectedPosts [
|
||||
^ self blog allVisibleBlogPosts
|
||||
]
|
||||
|
||||
{ #category : 'rendering' }
|
||||
TBPostsListComponent >> renderContentOn: html [
|
||||
super renderContentOn: html.
|
||||
html container: [
|
||||
self postComponents do: [ :p |
|
||||
html render: p ] ]
|
||||
]
|
@@ -1,36 +1,38 @@
|
||||
Class {
|
||||
#name : #TBScreenComponent,
|
||||
#superclass : #WAComponent,
|
||||
#name : 'TBScreenComponent',
|
||||
#superclass : 'SBSRootComponent',
|
||||
#instVars : [
|
||||
'header'
|
||||
],
|
||||
#category : #'TinyBlog-Components'
|
||||
#category : 'TinyBlog-Components-Components',
|
||||
#package : 'TinyBlog-Components',
|
||||
#tag : 'Components'
|
||||
}
|
||||
|
||||
{ #category : #acccessing }
|
||||
{ #category : 'acccessing' }
|
||||
TBScreenComponent >> blog [
|
||||
"Return the current blog. In the future we will ask the
|
||||
session to return the blog of the currently logged in user."
|
||||
^ TBBlog current
|
||||
]
|
||||
|
||||
{ #category : #acccessing }
|
||||
{ #category : 'acccessing' }
|
||||
TBScreenComponent >> children [
|
||||
^ { header }
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBScreenComponent >> createHeaderComponent [
|
||||
^ TBHeaderComponent new
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBScreenComponent >> initialize [
|
||||
super initialize.
|
||||
header := self createHeaderComponent
|
||||
]
|
||||
|
||||
{ #category : #acccessing }
|
||||
{ #category : 'acccessing' }
|
||||
TBScreenComponent >> renderContentOn: html [
|
||||
html render: header
|
||||
]
|
1
src/TinyBlog-Components/package.st
Normal file
1
src/TinyBlog-Components/package.st
Normal file
@@ -0,0 +1 @@
|
||||
Package { #name : 'TinyBlog-Components' }
|
@@ -1,13 +1,14 @@
|
||||
Class {
|
||||
#name : #TBBlog,
|
||||
#superclass : #Object,
|
||||
#name : 'TBBlog',
|
||||
#superclass : 'Object',
|
||||
#instVars : [
|
||||
'posts'
|
||||
],
|
||||
#category : #TinyBlog
|
||||
#category : 'TinyBlog',
|
||||
#package : 'TinyBlog'
|
||||
}
|
||||
|
||||
{ #category : #demos }
|
||||
{ #category : 'demos' }
|
||||
TBBlog class >> createDemoPosts [
|
||||
"TBBlog createDemoPosts"
|
||||
self current
|
||||
@@ -29,7 +30,7 @@ TBBlog class >> createDemoPosts [
|
||||
category: 'Pharo') visible: true)
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBBlog class >> current [
|
||||
"answer the instance of the TBRepository"
|
||||
^ self selectAll
|
||||
@@ -37,70 +38,70 @@ TBBlog class >> current [
|
||||
ifEmpty: [ self new save ]
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBBlog class >> initialize [
|
||||
self reset
|
||||
]
|
||||
|
||||
{ #category : #reading }
|
||||
{ #category : 'reading' }
|
||||
TBBlog class >> initializeVoyageOnMemoryDB [
|
||||
VOMemoryRepository new enableSingleton
|
||||
]
|
||||
|
||||
{ #category : #reading }
|
||||
{ #category : 'reading' }
|
||||
TBBlog class >> isVoyageRoot [
|
||||
"Indicates that instances of this class are top level documents in noSQL databases"
|
||||
^ true
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBBlog class >> reset [
|
||||
self initializeVoyageOnMemoryDB.
|
||||
]
|
||||
|
||||
{ #category : #reading }
|
||||
{ #category : 'reading' }
|
||||
TBBlog >> allBlogPosts [
|
||||
^ posts
|
||||
]
|
||||
|
||||
{ #category : #reading }
|
||||
{ #category : 'reading' }
|
||||
TBBlog >> allBlogPostsFromCategory: aCategory [
|
||||
^ posts select: [ :p | p category = aCategory ]
|
||||
]
|
||||
|
||||
{ #category : #reading }
|
||||
{ #category : 'reading' }
|
||||
TBBlog >> allCategories [
|
||||
^ (self allBlogPosts collect: [ :p | p category ]) asSet
|
||||
]
|
||||
|
||||
{ #category : #reading }
|
||||
{ #category : 'reading' }
|
||||
TBBlog >> allVisibleBlogPosts [
|
||||
^ posts select: [ :p | p isVisible ]
|
||||
]
|
||||
|
||||
{ #category : #reading }
|
||||
{ #category : 'reading' }
|
||||
TBBlog >> allVisibleBlogPostsFromCategory: aCategory [
|
||||
^ posts select: [ :p | p category = aCategory and: [ p isVisible ] ]
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBBlog >> initialize [
|
||||
super initialize.
|
||||
posts := OrderedCollection new
|
||||
]
|
||||
|
||||
{ #category : #deleting }
|
||||
{ #category : 'deleting' }
|
||||
TBBlog >> removeAllPosts [
|
||||
posts := OrderedCollection new.
|
||||
self save
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBBlog >> size [
|
||||
^ posts size
|
||||
]
|
||||
|
||||
{ #category : #writing }
|
||||
{ #category : 'writing' }
|
||||
TBBlog >> writeBlogPost: aPost [
|
||||
"Add the blog post in database."
|
||||
self allBlogPosts add: aPost.
|
||||
|
@@ -1,16 +1,18 @@
|
||||
Class {
|
||||
#name : #TBBlogTest,
|
||||
#superclass : #TestCase,
|
||||
#name : 'TBBlogTest',
|
||||
#superclass : 'TestCase',
|
||||
#instVars : [
|
||||
'blog',
|
||||
'post',
|
||||
'first',
|
||||
'previousRepository'
|
||||
],
|
||||
#category : #'TinyBlog-Tests'
|
||||
#category : 'TinyBlog-Tests',
|
||||
#package : 'TinyBlog',
|
||||
#tag : 'Tests'
|
||||
}
|
||||
|
||||
{ #category : #running }
|
||||
{ #category : 'running' }
|
||||
TBBlogTest >> setUp [
|
||||
previousRepository := VORepository current.
|
||||
VORepository setRepository: VOMemoryRepository new.
|
||||
@@ -21,60 +23,60 @@ TBBlogTest >> setUp [
|
||||
post := (TBPost title: 'Another title' text: 'Another text' category: 'Second Category') beVisible
|
||||
]
|
||||
|
||||
{ #category : #running }
|
||||
{ #category : 'running' }
|
||||
TBBlogTest >> tearDown [
|
||||
VORepository setRepository: previousRepository
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testAddBlogPost [
|
||||
blog writeBlogPost: post.
|
||||
self assert: blog size equals: 2
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testAllBlogPosts [
|
||||
blog writeBlogPost: post.
|
||||
self assert: blog allBlogPosts size equals: 2
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testAllBlogPostsFromCategory [
|
||||
self assert: (blog allBlogPostsFromCategory: 'First Category')
|
||||
size equals: 1
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testAllCategories [
|
||||
blog writeBlogPost: post.
|
||||
self assert: blog allCategories size equals: 2
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testAllVisibleBlogPosts [
|
||||
blog writeBlogPost: post.
|
||||
self assert: blog allVisibleBlogPosts size equals: 1
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testAllVisibleBlogPostsFromCategory [
|
||||
blog writeBlogPost: post.
|
||||
self assert: (blog allVisibleBlogPostsFromCategory: 'First Category') size equals: 0.
|
||||
self assert: (blog allVisibleBlogPostsFromCategory: 'Second Category') size equals: 1.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testRemoveAllBlogPosts [
|
||||
blog removeAllPosts.
|
||||
self assert: blog size equals: 0
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testSize [
|
||||
self assert: blog size equals: 1
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBBlogTest >> testUnclassifiedBlogPosts [
|
||||
self assert: (blog allBlogPosts select: [ :p | p isUnclassified ]) size equals: 0
|
||||
]
|
||||
|
@@ -1,23 +0,0 @@
|
||||
Class {
|
||||
#name : #TBHeaderComponent,
|
||||
#superclass : #WAComponent,
|
||||
#category : #'TinyBlog-Components'
|
||||
}
|
||||
|
||||
{ #category : #rendering }
|
||||
TBHeaderComponent >> renderBrandOn: html [
|
||||
html tbsNavbarHeader: [
|
||||
html tbsNavbarBrand
|
||||
url: self application url;
|
||||
with: 'TinyBlog'
|
||||
]
|
||||
]
|
||||
|
||||
{ #category : #rendering }
|
||||
TBHeaderComponent >> renderContentOn: html [
|
||||
html tbsNavbar beDefault; with: [
|
||||
html tbsContainer: [
|
||||
self renderBrandOn: html
|
||||
]
|
||||
]
|
||||
]
|
@@ -1,6 +1,6 @@
|
||||
Class {
|
||||
#name : #TBPost,
|
||||
#superclass : #Object,
|
||||
#name : 'TBPost',
|
||||
#superclass : 'Object',
|
||||
#instVars : [
|
||||
'title',
|
||||
'text',
|
||||
@@ -8,10 +8,11 @@ Class {
|
||||
'category',
|
||||
'visible'
|
||||
],
|
||||
#category : #TinyBlog
|
||||
#category : 'TinyBlog',
|
||||
#package : 'TinyBlog'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
{ #category : 'instance creation' }
|
||||
TBPost class >> title: aTitle text: aText [
|
||||
^ self new
|
||||
title: aTitle;
|
||||
@@ -19,48 +20,48 @@ TBPost class >> title: aTitle text: aText [
|
||||
yourself
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
{ #category : 'instance creation' }
|
||||
TBPost class >> title: aTitle text: aText category: aCategory [
|
||||
^ (self title: aTitle text: aText)
|
||||
category: aCategory;
|
||||
yourself
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
{ #category : 'as yet unclassified' }
|
||||
TBPost class >> unclassifiedTag [
|
||||
^ 'Unclassified'
|
||||
]
|
||||
|
||||
{ #category : #action }
|
||||
{ #category : 'action' }
|
||||
TBPost >> beVisible [
|
||||
self visible: true
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> category [
|
||||
|
||||
^ category
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> category: anObject [
|
||||
|
||||
category := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> date [
|
||||
|
||||
^ date
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> date: anObject [
|
||||
|
||||
date := anObject
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
{ #category : 'initialization' }
|
||||
TBPost >> initialize [
|
||||
super initialize.
|
||||
self category: self class unclassifiedTag.
|
||||
@@ -68,52 +69,52 @@ TBPost >> initialize [
|
||||
self notVisible.
|
||||
]
|
||||
|
||||
{ #category : #testing }
|
||||
{ #category : 'testing' }
|
||||
TBPost >> isUnclassified [
|
||||
^ self category = self class unclassifiedTag
|
||||
]
|
||||
|
||||
{ #category : #testing }
|
||||
{ #category : 'testing' }
|
||||
TBPost >> isVisible [
|
||||
^ self visible
|
||||
]
|
||||
|
||||
{ #category : #action }
|
||||
{ #category : 'action' }
|
||||
TBPost >> notVisible [
|
||||
self visible: false
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> text [
|
||||
|
||||
^ text
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> text: anObject [
|
||||
|
||||
text := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> title [
|
||||
|
||||
^ title
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> title: anObject [
|
||||
|
||||
title := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> visible [
|
||||
|
||||
^ visible
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : 'accessing' }
|
||||
TBPost >> visible: anObject [
|
||||
|
||||
visible := anObject
|
||||
|
@@ -1,10 +1,12 @@
|
||||
Class {
|
||||
#name : #TBPostTest,
|
||||
#superclass : #TestCase,
|
||||
#category : #'TinyBlog-Tests'
|
||||
#name : 'TBPostTest',
|
||||
#superclass : 'TestCase',
|
||||
#category : 'TinyBlog-Tests',
|
||||
#package : 'TinyBlog',
|
||||
#tag : 'Tests'
|
||||
}
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBPostTest >> testPostIsCreatedCorrectly [
|
||||
|
||||
| post |
|
||||
@@ -16,7 +18,7 @@ TBPostTest >> testPostIsCreatedCorrectly [
|
||||
self assert: post text equals: 'TinyBlog is a small blog engine made with Pharo.'.
|
||||
]
|
||||
|
||||
{ #category : #tests }
|
||||
{ #category : 'tests' }
|
||||
TBPostTest >> testWithoutCategoryIsUnclassified [
|
||||
|
||||
| post |
|
||||
|
@@ -1 +1 @@
|
||||
Package { #name : #TinyBlog }
|
||||
Package { #name : 'TinyBlog' }
|
||||
|
Reference in New Issue
Block a user