From 16f58323aabf7e187d281794b08bd948440d44a1 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 23 Sep 2025 11:11:49 +0200 Subject: [PATCH] Create contact book model --- src/ContactBook/Contact.class.st | 54 +++++++++++++++++++ src/ContactBook/ContactBook.class.st | 44 +++++++++++++++ src/ContactBook/ContactBookTest.class.st | 40 ++++++++++++++ src/ContactBook/ContactTest.class.st | 26 +++++++++ src/ContactBook/TBHeaderComponent.class.st | 23 ++++++++ src/ContactBook/TBScreenComponent.class.st | 36 +++++++++++++ src/ContactBook/WAContactBook.class.st | 62 ++++++++++++++++++++++ src/ContactBook/package.st | 1 + 8 files changed, 286 insertions(+) create mode 100644 src/ContactBook/Contact.class.st create mode 100644 src/ContactBook/ContactBook.class.st create mode 100644 src/ContactBook/ContactBookTest.class.st create mode 100644 src/ContactBook/ContactTest.class.st create mode 100644 src/ContactBook/TBHeaderComponent.class.st create mode 100644 src/ContactBook/TBScreenComponent.class.st create mode 100644 src/ContactBook/WAContactBook.class.st create mode 100644 src/ContactBook/package.st diff --git a/src/ContactBook/Contact.class.st b/src/ContactBook/Contact.class.st new file mode 100644 index 0000000..29dfd3e --- /dev/null +++ b/src/ContactBook/Contact.class.st @@ -0,0 +1,54 @@ +" +I represent a person with a name and an email address. I'm usually +part of a contact book. +" +Class { + #name : #Contact, + #superclass : #Object, + #instVars : [ + 'fullname', + 'email' + ], + #category : #ContactBook +} + +{ #category : #'instance creation' } +Contact class >> newNamed: aNameString email: anEmailString [ + ^ self new + fullname: aNameString; + email: anEmailString; + yourself +] + +{ #category : #accessing } +Contact >> email [ + + ^ email +] + +{ #category : #accessing } +Contact >> email: anObject [ + + email := anObject +] + +{ #category : #accessing } +Contact >> fullname [ + + ^ fullname +] + +{ #category : #accessing } +Contact >> fullname: aString [ + + fullname := aString +] + +{ #category : #accessing } +Contact >> printOn: aStream [ + aStream + nextPutAll: self fullname; + nextPutAll: ' <'; + nextPutAll: self email; + nextPutAll: '>' +] diff --git a/src/ContactBook/ContactBook.class.st b/src/ContactBook/ContactBook.class.st new file mode 100644 index 0000000..20af36d --- /dev/null +++ b/src/ContactBook/ContactBook.class.st @@ -0,0 +1,44 @@ +Class { + #name : #ContactBook, + #superclass : #Object, + #instVars : [ + 'contacts' + ], + #category : #ContactBook +} + +{ #category : #demos } +ContactBook class >> createDefault [ + ^ self new + addContact: (Contact newNamed: 'Damien Cassou' email: 'damien@cassou.me'); + addContact: (Contact newNamed: 'Marcus Denker' email: 'marcus.denker@inria.fr'); + addContact: (Contact newNamed: 'Tudor Girba' email: 'tudor@tudorgirba.com'); + addContact: (Contact newNamed: 'Clara Allende' email: 'clari.allende@gmail.com'); + yourself +] + +{ #category : #writing } +ContactBook >> addContact: aContact [ + self contacts add: aContact +] + +{ #category : #reading } +ContactBook >> contacts [ + ^ contacts +] + +{ #category : #initialization } +ContactBook >> initialize [ + super initialize. + contacts := OrderedCollection new +] + +{ #category : #deleting } +ContactBook >> removeContact: aContact [ + self contacts remove: aContact +] + +{ #category : #initialization } +ContactBook >> size [ + ^ contacts size +] diff --git a/src/ContactBook/ContactBookTest.class.st b/src/ContactBook/ContactBookTest.class.st new file mode 100644 index 0000000..80d3bb0 --- /dev/null +++ b/src/ContactBook/ContactBookTest.class.st @@ -0,0 +1,40 @@ +Class { + #name : #ContactBookTest, + #superclass : #TestCase, + #instVars : [ + 'blog', + 'post' + ], + #category : #ContactBook +} + +{ #category : #running } +ContactBookTest >> setUp [ + blog := ContactBook new. + blog addContact: (Contact newNamed: 'Tudor Girba' email: 'tudor@tudorgirba.com'). + + post := Contact newNamed: 'Clara Allende' email: 'clari.allende@gmail.com' +] + +{ #category : #tests } +ContactBookTest >> testAddContact [ + blog addContact: post. + self assert: blog size equals: 2 +] + +{ #category : #tests } +ContactBookTest >> testContacts [ + blog addContact: post. + self assert: blog contacts size equals: 2 +] + +{ #category : #tests } +ContactBookTest >> testRemoveContact [ + blog removeContact: blog contacts first. + self assert: blog size equals: 0 +] + +{ #category : #tests } +ContactBookTest >> testSize [ + self assert: blog size equals: 1 +] diff --git a/src/ContactBook/ContactTest.class.st b/src/ContactBook/ContactTest.class.st new file mode 100644 index 0000000..c3e21c3 --- /dev/null +++ b/src/ContactBook/ContactTest.class.st @@ -0,0 +1,26 @@ +Class { + #name : #ContactTest, + #superclass : #TestCase, + #category : #ContactBook +} + +{ #category : #tests } +ContactTest >> testCreation [ + + | contact | + contact := Contact + newNamed: 'Marcus Denker' + email: 'marcus.denker@inria.fr'. + self assert: contact fullname equals: 'Marcus Denker'. + self assert: contact email equals: 'marcus.denker@inria.fr' +] + +{ #category : #tests } +ContactTest >> testPrinting [ + + | contact | + contact := Contact + newNamed: 'Marcus Denker' + email: 'marcus.denker@inria.fr'. + self assert: contact asString equals: 'Marcus Denker ' +] diff --git a/src/ContactBook/TBHeaderComponent.class.st b/src/ContactBook/TBHeaderComponent.class.st new file mode 100644 index 0000000..74d7391 --- /dev/null +++ b/src/ContactBook/TBHeaderComponent.class.st @@ -0,0 +1,23 @@ +Class { + #name : #TBHeaderComponent, + #superclass : #WAComponent, + #category : #ContactBook +} + +{ #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 + ] + ] +] diff --git a/src/ContactBook/TBScreenComponent.class.st b/src/ContactBook/TBScreenComponent.class.st new file mode 100644 index 0000000..d72bcfc --- /dev/null +++ b/src/ContactBook/TBScreenComponent.class.st @@ -0,0 +1,36 @@ +Class { + #name : #TBScreenComponent, + #superclass : #WAComponent, + #instVars : [ + 'header' + ], + #category : #ContactBook +} + +{ #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." + ^ ContactBook current +] + +{ #category : #acccessing } +TBScreenComponent >> children [ + ^ { header } +] + +{ #category : #initialization } +TBScreenComponent >> createHeaderComponent [ + ^ TBHeaderComponent new +] + +{ #category : #initialization } +TBScreenComponent >> initialize [ + super initialize. + header := self createHeaderComponent +] + +{ #category : #acccessing } +TBScreenComponent >> renderContentOn: html [ + html render: header +] diff --git a/src/ContactBook/WAContactBook.class.st b/src/ContactBook/WAContactBook.class.st new file mode 100644 index 0000000..4555250 --- /dev/null +++ b/src/ContactBook/WAContactBook.class.st @@ -0,0 +1,62 @@ +Class { + #name : #WAContactBook, + #superclass : #WAComponent, + #instVars : [ + 'contactBook' + ], + #category : #ContactBook +} + +{ #category : #initialization } +WAContactBook class >> initialize [ + WAAdmin register: self asApplicationAt: 'contacts'. +] + +{ #category : #accessing } +WAContactBook >> contactBook [ + ^ contactBook ifNil: [ contactBook := ContactBook createDefault ] +] + +{ #category : #accessing } +WAContactBook >> contacts [ + ^ self contactBook contacts +] + +{ #category : #iterating } +WAContactBook >> contactsDo: aBlock [ + self contacts do: aBlock +] + +{ #category : #rendering } +WAContactBook >> renderContact: aContact on: html [ + html tableRow: [ + html + tableData: aContact fullname; + tableData: aContact email ] +] + +{ #category : #rendering } +WAContactBook >> renderContactsOn: html [ + html table: [ + html tableHead: [ + html + tableHeading: 'Name'; + tableHeading: 'Email' ]. + self contactsDo: [ :contact | self renderContact: contact on: html ] ] +] + +{ #category : #rendering } +WAContactBook >> renderContentOn: html [ + "Main entry point of the view. Render both a title and the list of contacts." + + html heading + level: 1; + with: 'My Contact Book'. + self renderContactsOn: html +] + +{ #category : #updating } +WAContactBook >> updateRoot: anHtmlRoot [ + super updateRoot: anHtmlRoot. + anHtmlRoot title: 'Contact Book' +] diff --git a/src/ContactBook/package.st b/src/ContactBook/package.st new file mode 100644 index 0000000..9b6cb2b --- /dev/null +++ b/src/ContactBook/package.st @@ -0,0 +1 @@ +Package { #name : #ContactBook }