Compare commits

..

No commits in common. "67d88bd31b2860bd995b461b1974e6939a0da591" and "de60936cd2ae62b2d7869f59fffff7b6958d2df0" have entirely different histories.

9 changed files with 12 additions and 73 deletions

View file

@ -9,8 +9,7 @@ The goal is to provide a minimalistic and fast todo list that is self hostable.
- [ ] write a minimal step by step guide to install with nix,
- [ ] add some css to make it look nicer
- [ ] add htmx to make more agreable without making js manadatory
- [x] make api to allow usage with native app (a way to get every list that has been modified since date $date belonging from the user in a json or similar format)
- [ ] document api to help create clients
- [ ] make api to allow usage with native app (a way to get every list that has been modified since date $date belonging from the user in a json or similar format)
## Version 0.0.3
Simple todo list webapp.
Features :

View file

@ -1 +0,0 @@
:M^¦ÄO2«I†èš³4,pe<70>¿Ôì8Ä·,CI†(q¸¦7/ ÷gGˆuâÍ×¥L'¿(Éœ¡wq1I#ÔpµÌYW»)2L{2—;våÇ_ižËÀ[ÛÈʳ<C38A>ûÕY

View file

@ -8,15 +8,12 @@ TodolistItem
Todolist
groupId GroupId OnDeleteCascade
title Text
lastModified UTCTime
UniqueListPair groupId title
deriving Show
User
name Text
UniqueName name
Group
group Text
lastModified UTCTime
GroupUser
user UserId
groupId GroupId OnDeleteCascade

View file

@ -26,4 +26,3 @@
/delete DeleteGroupR POST
/delete/group/#GroupId DeleteTodolistR POST
/api/#Int ApiR GET

View file

@ -47,7 +47,6 @@ import Handler.Common
import Handler.Group
import Handler.Todolist
import Handler.TodolistItem
import Handler.Api
-- This line actually creates our YesodDispatch instance. It is the second half
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the

View file

@ -12,7 +12,7 @@ module Foundation where
import Import.NoFoundation
import Data.Kind (Type)
import Database.Persist.Sql (ConnectionPool, runSqlPool, rawSql)
import Database.Persist.Sql (ConnectionPool, runSqlPool)
import Text.Hamlet (hamletFile)
import Text.Jasmine (minifym)
import Control.Monad.Logger (LogSource)
@ -208,9 +208,4 @@ dbIfAuth groupId action = do
user <- getUserId
result <- runDB $ selectFirst [GroupUserUser ==. user, GroupUserGroupId ==. groupId] []
if isNothing result then permissionDenied "you are not logged in or you dont have access to this group"
else runDB action
getGroups :: Key User -> Handler [Entity Group]
getGroups userId =
let sql = "SELECT ?? FROM \"group\" JOIN group_user gu ON \"group\".id = gu.group_id WHERE gu.user = ?" in
runDB $ rawSql sql [toPersistValue userId]
else runDB action

View file

@ -1,52 +0,0 @@
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module Handler.Api where
import Import
import Database.Persist.Sql (rawSql)
import Data.Time.Clock.POSIX (posixSecondsToUTCTime, utcTimeToPOSIXSeconds)
import qualified Data.Text as Text
getApiR :: Int -> Handler TypedContent
getApiR time = do
-- TODO: use only one runDB
userId <- getUserId
-- We get all groups no matter what, since else we can't know which groups have been deleted
groups <- getGroups userId
let utcTime = posixSecondsToUTCTime (fromIntegral time)
let sqlLists = "select ?? from todolist join group_user on todolist.group_id = group_user.group_id and group_user.user = ? join \"group\" on todolist.group_id = \"group\".id and \"group\".last_modified > ?;"
lists <- runDB $ rawSql sqlLists [toPersistValue userId, toPersistValue utcTime]
let a = lists :: [Entity Todolist]
let sqlItems = "select ?? from todolist join group_user on todolist.group_id = group_user.group_id and group_user.user = ? join \"group\" on todolist.group_id = \"group\".id and \"group\".last_modified > ? join todolist_item on todolist_item.todolist_id = todolist.id;"
items <- runDB $ rawSql sqlItems [toPersistValue userId, toPersistValue utcTime]
let t = unlines $ map groupToCSV groups <> map todolistToCSV lists <> map todolistItemToCSV items
return $ TypedContent typePlain $ toContent t
todolistItemToCSV :: Entity TodolistItem -> Text
todolistItemToCSV item = "i," <> fieldToText item
todolistToCSV :: Entity Todolist -> Text
todolistToCSV list = "l," <> fieldToText list
groupToCSV :: Entity Group -> Text
groupToCSV group = "g," <> fieldToText group
-- TODO: error management ? (maybe use Either Text Text and then propagate left to handler and send error ?)
fieldToText :: PersistEntity record => Entity record -> Text
fieldToText field = Text.intercalate "," (map persistValueToText $ entityValues field)
persistValueToText :: PersistValue -> Text
persistValueToText (PersistText s) = s
persistValueToText (PersistInt64 i) = Text.pack $ show i
persistValueToText (PersistUTCTime d) = Text.pack $ show $ floor (utcTimeToPOSIXSeconds d)
persistValueToText (PersistBool b) = if b then "T" else "F"
persistValueToText _ = error "Wrong input type"
getText :: Text
getText = do
-- GET EVERY GROUP THAT HAS BEEN MODIFIED SINCE TIMESTAMP FROM USER
-- GET EVERY TODOLIST THAT HAS BEEN MODIFIED SINCE TIMESTAMP
-- GET EVERY ITEM FROM THESE TODOLISTS
-- ENCODE ALL OF THEM IN THE TEXTFILE
-- SEND IT !
-- DONE :)
error "not done yet"

View file

@ -11,7 +11,7 @@ module Handler.Group where
import Import
import Text.Read
import Database.Persist.Sql (fromSqlKey, toSqlKey)
import Database.Persist.Sql (fromSqlKey, toSqlKey, rawSql)
getGroupR :: Handler Html
getGroupR = do
userId <- getUserId
@ -25,8 +25,7 @@ postAddGroupR = do
-- TODO: in a newer version, put insertUnique_
user <- getUserId
_ <- runDB $ do
currentTime <- liftIO getCurrentTime
gId <- insert $ Group g currentTime
gId <- insert $ Group g
success <- insertUnique $ GroupUser user gId
when (isNothing success) $ delete gId
redirect GroupR
@ -55,4 +54,9 @@ postDeleteGroupR = do
let ids = map toSqlKey ints :: [GroupId]
-- TODO: make sure the user has access to it aswell (this only works now for single user), and handle group owned by many
runDB $ deleteWhere [GroupId <-. ids]
redirect EditGroupR
redirect EditGroupR
getGroups :: Key User -> Handler [Entity Group]
getGroups userId =
let sql = "SELECT ?? FROM \"group\" JOIN group_user gu ON \"group\".id = gu.group_id WHERE gu.user = ?" in
runDB $ rawSql sql [toPersistValue userId]

View file

@ -16,8 +16,7 @@ postAddTodolistR :: GroupId -> Handler Html
postAddTodolistR groupId = do
list <- runInputPost $ ireq textField "list"
-- TODO: in a newer version, put insertUnique_
currentTime <- liftIO getCurrentTime
_ <- dbIfAuth groupId (insertUnique $ Todolist groupId list currentTime)
_ <- dbIfAuth groupId (insertUnique $ Todolist groupId list)
redirect $ TodolistR groupId
-- TODO: move this to a new handler file