module
newsGroups
// In this example
newsgroups are created and maintained
// User 0 is the manager of the newsgroup who
can create new newgroups
// All other users can subscribe to such a
newsgroup, commit a message or read news
// (c) mjp 2007
import
StdEnv, iTasks, iDataTrivial, iDataFormlib
import
iTaskUtil
derive
gForm []
derive gUpd []
:: NewsGroups :== [GroupName] // list of newsgroup names
:: GroupName :== String //
Name of the newsgroup
:: NewsGroup :== [News] //
News stored in a news group
:: News :== (Subscriber,Name,Message) //
id, name, and message of the publisher
::
Subscriber :==
Int //
the id of the publisher
:: Name :== String // the login name of the
publisher
::
Message :==
String // the message
::
Subscriptions :==
[Subscription] // newsgroup
subscriptions of user
::
Subscription :==
(GroupName,Index) //
last message read in corresponding group
:: Index :== Int //
0 <= index < length newsgroup
nmessage = 5
Start
world = doHtmlServer (singleUserTask
-1 True (assignWork True welcome account myWork)) world
welcome
= [ Txt "This
is an iTask demo showing how newsgroups can be
created and maintained.",Br,Br
, Txt "Only the site manager can add newsgroups.",Br
, Txt "Any member can subscribe to a
newsgroup, and read or commit news",Br,Br
, Txt "Now please login if you are a
member or make an account and become a member...",Br,Br]
?>> OK
account
v = return_V Void
myWork acc=:(name,unid,_)
| unid == 0 = foreverTask
(newsManager acc) //
for the root
| otherwise = foreverTask (newsReader acc) //
all others
newsManager acc
= chooseTask [("newGroup", addNewsGroup
-||- editTask "Cancel" Void)
,("showGroup", showGroup)
,("readNews", newsReader acc)
]
where
addNewsGroup
= [Txt
"Define name of new news group:",Br,Br]
?>> editTask
"Define" ""
=>> \newName -> readNewsGroups
=>> \oldNames
-> writeNewsGroups
(removeDup (sort [newName:oldNames]))
#>> return_V Void
showGroup
= (readNewsGroups =>> PDMenu)
#>> return_V Void
PDMenu
list
= []
?>> editTask
"OK" (PullDown (1,100) (0,list))
=>> \value -> return_V (toInt value,toString value)
newsReader acc=:(name,unid,_)
= chooseTask [("subscribe", subscribeNewsGroup
unid -||- editTask
"Cancel" Void)
,("showNews", readNews unid)
]
where
subscribeNewsGroup :: Subscriber -> Task Void
subscribeNewsGroup
me
= readNewsGroups
=>> \groups -> PDMenu groups
=>> \(_,group)
-> addSubscription
me (group,0)
#>> [Txt "You have subscribed to news group ", B
[] group,Br,Br]
?>> OK
readNews :: Subscriber -> Task Void
readNews
me
= readSubscriptions me
=>> \mygroups
-> PDMenu
([group \\ (group,_) <- mygroups]
++ ["Cancel"])
=>> \(_,group)
-> readNews`
group
where
readNews` "Cancel" = [Txt "You have
not selected a newgroup you are subscribed on!",Br,Br]
?>> OK
readNews` group = [Txt "You are looking at news group
", B [] group, Br, Br]
?>> foreverTask
( readIndex me
group
=>> \index -> readNewsGroup group
=>> \news -> showNews index (news%(index,index+nmessage-1)) (length
news)
?>> chooseTask
[("<<",readNextNewsItems me (group,index)
(~nmessage) (length news))
,("update", return_V
Void)
,(">>", readNextNewsItems
me (group,index) nmessage
(length news))
,("commitNews",commitItem group me)
]
)
-||-
editTask "leaveGroup"
Void
readNextNewsItems :: Subscriber Subscription Int Int -> Task Void
readNextNewsItems me (group,index) offset length
# nix = index +
offset
# nix = if (nix
< 0) 0 (if (length <= nix) index nix)
= addSubscription
me (group,nix) #>> return_V Void
commitItem :: GroupName Subscriber ->
Task Void
commitItem
group me
= [Txt "Type your message
..."]
?>> editTask
"Commit" (TextArea 4 80 "")
<<@ Submit
=>> \(TextArea _ _ val) -> readNewsGroup group
=>> \news -> writeNewsGroup group (news ++ [(unid,name,val)])
#>> [Txt
"Message commited to news group ",B [] group, Br,Br]
?>> OK
OK ::
Task Void
OK = editTask "OK" Void
//
displaying news groups
showNews ix news nrItems
= [STable [Tbl_Border 1, Tbl_Bgcolor (`Colorname Blue)]
[ [B [] "Message nr:",
B [] "By:", B [] "Contents:"]
: [ [Txt
(showIndex nr),Txt name,Txt (toString info)]
\\ nr <- [ix..]
& (who,name,info) <-
news
]
]
]
where
showIndex
i = ((i+1)
+++> " of ") <+++ nrItems
//
reading and writing of storages
newsGroupsId ::
(DBid NewsGroups)
newsGroupsId = mkDBid
"newsGroups"
readerId :: Int
-> (DBid Subscriptions)
readerId I = mkDBid
("reader" <+++ i)
groupNameId :: String -> (DBid NewsGroup)
groupNameId name = mkDBid
("NewsGroup-" +++ name)
readNewsGroups :: Task NewsGroups
readNewsGroups = readDB
newsGroupsId
writeNewsGroups :: NewsGroups
-> Task NewsGroups
writeNewsGroups newgroups
= writeDB newsGroupsId newgroups
readSubscriptions :: Subscriber -> Task
Subscriptions
readSubscriptions me = readDB
(readerId me)
writeSubscriptions :: Subscriber Subscriptions ->
Task Subscriptions
writeSubscriptions me subscriptions = writeDB (readerId me)
subscriptions
addSubscription :: Subscriber Subscription ->
Task Subscriptions
addSubscription me (groupname,index)
# index = if (index
< 0) 0 index
= readSubscriptions me
=>> \subscriptions -> writeSubscriptions me [(groupname,index):[(group,index) \\ (group,index)
<- subscriptions | group <> groupname]]
readIndex :: Subscriber GroupName
-> Task Index
readIndex me groupname
= readSubscriptions
me
=>> \subscriptions -> return_V (hds
[index \\ (group,index)
<- subscriptions | group == groupname])
where
hds
[x:xs] = x
hds
[] = 0
readNewsGroup :: GroupName
-> Task NewsGroup
readNewsGroup groupname
= readDB (groupNameId groupname)
writeNewsGroup :: GroupName
NewsGroup -> Task NewsGroup
writeNewsGroup groupname
news = writeDB (groupNameId
groupname) news