diff --git a/README.md b/README.md index c6ae9c1..63c94ea 100644 --- a/README.md +++ b/README.md @@ -40,41 +40,49 @@ zu erzwingen. Issue 2 ------- -Neues Feature: Timeline für alle Nutzer. Auf der Seite `All Users` werden alle jemals eingelogten Nutzer angezeigt. Mit einem Klick auf einen Nutzernamen wird man auf die zugehörige `Timeline` weitergeleitet. Auf der Timeline muss erst einmal nichts weiter stehen außer der Titel: "USERNAME's Timeline". +Neues Feature: Timeline für alle Nutzer. Auf der Seite `All Users` sollen alle jemals eingelogten Nutzer angezeigt werden. Mit einem Klick auf einen Nutzernamen wird man auf die zugehörige `Timeline` weitergeleitet. Auf der Timeline muss erst einmal nichts weiter stehen außer der Titel: "USERNAME's Timeline". + +- `config/routes`: Erstellen Sie die folgenden Routen: -- `config/routes`: Erstellen Sie die folgenden Routen. ``` /timeline/#UserId UserTimelineR GET /userList UserListR GET ``` + - `Foundation.hs`: - Ergänzen Sie die Funktionen, in denen auf Routen-Konstruktoren pattern-gematcht wird. - Die Routen `UserListR` und `UserTimelineR` sollen nur für autorisierte (d.h. eingeloggte) Nutzer sichtbar sein. - Sorgen Sie dafür, dass `UserListR` über den Menüpunkt "All Users" erreichbar ist (siehe MenuItem in defaultLayout). -- `src/Handler/`: Legen Sie die Handler-Module `UserTimeline.hs` und `UserList.hs` an. -- `cabal`: Fügen Sie die Handler als `exposed-module` hinzu. -- `src/Application.hs`: Importieren Sie die neuen Handler -- `src/Handler/UserList.hs`/`src/Handler/UserTimeline.hs`: +- `src/Handler/`: + - Kopieren Sie die vorgegebenen Handler-Module `UserTimeline.hs` und `UserList.hs` hier hin. +- `templates/`: Man kann hamlet-Code für Widgets etc. auch in template-Files auslagern. Diese werden hier gespeichert. + - Kopieren Sie die vorgegebenen Template-Dateien `UserTimeline.hamlet` und `UserList.hamlet` hier hin. +- `.cabal`: Fügen Sie die Handler als `exposed-module` hinzu. +- `src/Application.hs`: Importieren Sie die neuen Handler. +- `src/Handler/UserList.hs`/`src/Handler/UserTimeline.hs` bzw. `templates/UserTimeline.hamlet`/`templates/UserList.hamlet`: - - Erstellen Sie für jede `http-Methode`, für die Sie die neue Route definiert haben, eine entsprechende Handler-Funktion in dem neuen Handler-Modul. - - Bennenen Sie ihre Handler-Funktionen gemäß dem Schema: http-Methode + Routenkonstruktor. - - Inhaltlich können Sie sich stark an der Vorlesung orientieren! Schauen Sie sich auch die vorgegeben Handler-Module an. - - Man kann hamlet-Code etc. auch in template-Files auslagern. Sehen Sie sich hierzu beispielsweise `src/Handler/Profile.hs` und das eingebundene Template `templates/profile.hamlet` an. + - Bearbeiten Sie die TODOs zu Issue 2. + - Inhaltlich können Sie sich stark an der Vorlesung orientieren! Issue 3 ------- Neues Feature: Posten auf der eigenen Timeline. Jeder Nutzer soll nun auf seiner eigenen `Timeline`-Seite Nachrichten mit anderen teilen können. -Legen Sie hierfür in `config/routes` die neue Route an: +- Legen Sie hierfür in `config/routes` die neue Route an: + ´´´ /timeline TimelineR GET POST ´´´ -Gehen Sie weiterhin vor wie für `Issue 2`. Die Route `TimelineR` soll für autorisierte Nutzer über einen extra Menüpunkt "Your Timeline" erreichbar sein. Um Nachrichten eingeben und abspeichern zu können, benötigen Sie ein Formular. Auch hier können Sie sich wieder stark an der Vorlesung orientieren. +- Kopieren Sie `Timeline.hs` und `timeline.hamlet` ins Handler- bzw. Templates-Verzeichnis. +- Die Route `TimelineR` soll für autorisierte Nutzer über einen extra Menüpunkt "Your Timeline" erreichbar sein. Führen Sie die nötigen Änderungen in `.cabal`, `Foundation.hs` und `Application.hs` durch. +- Bearbeiten Sie die Aufgaben in `Timeline.hs` und `timeline.hamlet`. -Issue 4: Never gonna give U up, never gonna let ya down – Friendship :D +Issue 4 ------- +Never gonna give U up, never gonna let ya down – Friendship :D + Die Seite `All Users` soll nun auch erlauben, Freundschaftsanfragen abzuschicken, abzulehnen. Auf dieser soll man einem Nutzer eine Freundschaftsanfrage stellen können. Es soll erkenntlich sein, mit wem man bereits befreundet ist. Man soll nur die Timelines befreundeter Nutzer besuchen können. diff --git a/Timeline.hs b/Timeline.hs new file mode 100644 index 0000000..6923ee0 --- /dev/null +++ b/Timeline.hs @@ -0,0 +1,34 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE ScopedTypeVariables #-} +module Handler.Timeline where + +import Import + +getTimelineR :: Handler Html +getTimelineR = do + (uid, user) <- requireAuthPair + posts <- runDB $ selectList [PostUserId ==. uid] [Desc PostCreated] + (postWidget, postEnctype) <- generateFormPost (postForm Nothing uid) + let userName :: Text + userName = userIdent user + defaultLayout $ do + setTitle . toHtml $ userName <> "'s Timeline" + $(widgetFile "timeline") + +-- TODO: Implementieren Sie ein Verhalten zum Speichern des Posts. +-- Nützliche Funktionen: runFormPost. +postTimelineR :: Handler Html +postTimelineR = do + getTimelineR + + +postForm :: Maybe PostId -> UserId -> Form Post +postForm p u = renderDivs $ Post + <$> pure u + <*> areq textField "Post" (Just "Post content") + <*> pure p + <*> lift (liftIO getCurrentTime) diff --git a/UserList.hs b/UserList.hs new file mode 100644 index 0000000..821eedd --- /dev/null +++ b/UserList.hs @@ -0,0 +1,25 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE ScopedTypeVariables #-} +module Handler.UserList where + +import Import + +-- Die Typspezifikation von userlist ist nur notwendig, +-- weil im Folgenden noch keine Verwendung von userlist implementiert ist, +-- aus welcher der TypeChecker den Typ schließen könnte. +-- TODO: (Issue 2) Bearbeiten Sie die Aufgaben im template "userList". +getUserListR :: Handler Html +getUserListR = do + (userlist :: [Entity User]) <- runDB $ selectList [] [] + defaultLayout $ do + setTitle . toHtml $ ("All Users" :: Text) -- setzt den Titel des Browserfensters + $(widgetFile "userList") + + +--TODO: Issue 4 +postUserListR :: Handler Html +postUserListR = undefined \ No newline at end of file diff --git a/UserTimeline.hs b/UserTimeline.hs new file mode 100644 index 0000000..1868dd4 --- /dev/null +++ b/UserTimeline.hs @@ -0,0 +1,19 @@ +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeFamilies #-} +module Handler.UserTimeline where + +import Import + +getUserTimelineR :: UserId -> Handler Html +getUserTimelineR uid = do + mayUser <- runDB $ get uid + posts <- runDB $ selectList [PostUserId ==. uid] [Desc PostCreated] + let userName :: Text + userName = maybe "UnkownUser" userIdent mayUser + defaultLayout $ do + setTitle . toHtml $ show uid <> "'s Timeline" + $(widgetFile "userTimeline") \ No newline at end of file diff --git a/timeline.hamlet b/timeline.hamlet new file mode 100644 index 0000000..60f0b89 --- /dev/null +++ b/timeline.hamlet @@ -0,0 +1,14 @@ +