Use server timestamps for interval start and end.
[?]
Aug 20, 2020, 4:15 AM
J6S23MDGHVSCVVIRB6XRNSY3EGTDNWFJHV7RYLIEHBUK5KU63CFQCDependencies
- [2]
ZIG57EE6Fix project selection, end log end on project switch. - [3]
JXG3FCXYUpgrade ps + halogen versions. - [4]
Y3LIJ5USAdd handler for CreatePaymentRequest - [5]
B6HWAPDPModularize & update to recent haskoin. - [6]
EFSXYZPOAutoformat everything with brittany. - [7]
WRPIYG3EUse project listing functionality to check for whether we have a cookie. - [8]
BFZN4SUAMake timeline component work. - [9]
QU5FW67RAdd project selection to time tracker. - [10]
NJNMO72SAdd zcash.com submodule and update client to modern halogen. - [11]
RN7EI6INUpdate database layer to use CreditTo - [*]
IZEVQF62Work in progress replacing sqlite with postgres.
Change contents
- replacement in client/src/Aftok/Project.purs at line 6
import Control.Monad.Except.Trans (ExceptT, runExceptT, except)import Control.Monad.Except.Trans (ExceptT, runExceptT, except, withExceptT) - edit in client/src/Aftok/Project.purs at line 15
import Data.JSDate as JSDate - replacement in client/src/Aftok/Project.purs at line 27
import Aftok.Types (APIError(..))import Aftok.Types (APIError(..), parseDate) - replacement in client/src/Aftok/Project.purs at line 149
jsDate <- lift $ JSDate.parse p.inceptionDatepdate <- except $ note (ParseFailure json "Could not parse inception date")(JSDate.toDateTime jsDate)pdate <- withExceptT (ParseFailure json) $ parseDate p.inceptionDate - edit in client/src/Aftok/Timeline.purs at line 6
import Control.Monad.Error.Class (throwError)import Control.Monad.Except.Trans (except, withExceptT, runExceptT) - edit in client/src/Aftok/Timeline.purs at line 12
import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:), (.:?)) - replacement in client/src/Aftok/Timeline.purs at line 15
import Data.Either (Either(..))import Data.Foldable (any)import Data.Either (Either(..), note)import Data.Foldable (class Foldable, any, foldMapDefaultR) - replacement in client/src/Aftok/Timeline.purs at line 21
import Data.Traversable (traverse_)import Data.Traversable (class Traversable, traverse_, traverse) - replacement in client/src/Aftok/Timeline.purs at line 57
import Aftok.Types (APIError(..))import Aftok.Types (APIError(..), parseDate) - replacement in client/src/Aftok/Timeline.purs at line 59
import Effect.Class.Console (log)import Effect.Class.Console as C - edit in client/src/Aftok/Timeline.purs at line 88
instance showTimelineError :: Show TimelineError whereshow = case _ ofLogFailure e -> show e - edit in client/src/Aftok/Timeline.purs at line 187
log $ "Active: " <> show active <> "; " <> show ((_.projectName) <<< unwrap <$> currentProject)log $ "Selected: " <> show ((_.projectName) <<< unwrap $ p) - replacement in client/src/Aftok/Timeline.purs at line 189
H.modify_ (_ { selectedProject = Just p })H.modify_ (_ { selectedProject = Just p, history = [] }) - replacement in client/src/Aftok/Timeline.purs at line 207
Left _ -> log "Failed to start timer."Left err -> C.log $ "Failed to start timer: " <> show err - replacement in client/src/Aftok/Timeline.purs at line 214
Left _ -> log "Failed to stop timer."Left err -> C.log $ "Failed to stop timer: " <> show err - replacement in client/src/Aftok/Timeline.purs at line 242
toPct n = pct (100.0 * n / maxWidth)toPct n = 100.0 * n / maxWidth - replacement in client/src/Aftok/Timeline.purs at line 248
left (toPct ileft)width (toPct iwidth)left (pct $ toPct ileft)width (pct $ max (toPct iwidth) 0.5) - edit in client/src/Aftok/Timeline.purs at line 262
data Event i= StartEvent i| StopEvent iderive instance eventFunctor :: Functor Eventinstance eventFoldable :: Foldable Event wherefoldr f b = case _ ofStartEvent a -> f a bStopEvent a -> f a bfoldl f b = case _ ofStartEvent a -> f b aStopEvent a -> f b afoldMap = foldMapDefaultRinstance eventTraversable :: Traversable Event wheretraverse f = case _ ofStartEvent a -> StartEvent <$> f aStopEvent a -> StopEvent <$> f asequence = traverse identityinstance decodeJsonEvent :: DecodeJson (Event String) wheredecodeJson json = doobj <- decodeJson jsonevent <- obj .: "event"start' <- traverse (_ .: "eventTime") =<< event .:? "start"stop' <- traverse (_ .: "eventTime") =<< event .:? "stop"note "Only 'stop' and 'start' events are supported." $ (StartEvent <$> start') <|> (StopEvent <$> stop') - replacement in client/src/Aftok/Timeline.purs at line 319
case result ofLeft err -> pure <<< Left <<< LogFailure $ Error { status: Nothing, message: printError err }liftEffect <<< runExceptT $ case result ofLeft err -> throwError <<< LogFailure $ Error { status: Nothing, message: printError err } - replacement in client/src/Aftok/Timeline.purs at line 322
StatusCode 403 -> pure <<< Left <<< LogFailure $ ForbiddenStatusCode 200 -> Right <$> liftEffect nowother -> pure <<< Left <<< LogFailure $ Error { status: Just other, message: r.statusText }StatusCode 403 ->throwError $ LogFailure ForbiddenStatusCode 200 ->withExceptT (LogFailure <<< ParseFailure r.body) $ doevent <- except $ decodeJson r.bodytimeEvent <- traverse parseDate eventcase timeEvent ofStartEvent t -> pure $ fromDateTime tStopEvent _ -> throwError $ "Expected start event, got stop."other ->throwError <<< LogFailure $ Error { status: Just other, message: r.statusText } - replacement in client/src/Aftok/Timeline.purs at line 338
case result ofLeft err -> pure <<< Left <<< LogFailure $ Error { status: Nothing, message: printError err }liftEffect <<< runExceptT $ case result ofLeft err -> throwError <<< LogFailure $ Error { status: Nothing, message: printError err } - replacement in client/src/Aftok/Timeline.purs at line 341
StatusCode 403 -> pure <<< Left <<< LogFailure $ ForbiddenStatusCode 200 -> Right <$> liftEffect nowother -> pure <<< Left <<< LogFailure $ Error { status: Just other, message: r.statusText }StatusCode 403 ->throwError $ LogFailure ForbiddenStatusCode 200 ->withExceptT (LogFailure <<< ParseFailure r.body) $ doevent <- except $ decodeJson r.bodytimeEvent <- traverse parseDate eventcase timeEvent ofStartEvent _ -> throwError $ "Expected stop event, got start."StopEvent t -> pure $ fromDateTime tother ->throwError <<< LogFailure $ Error { status: Just other, message: r.statusText } - edit in client/src/Aftok/Types.purs at line 2
import Preludeimport Control.Monad.Trans.Class (lift)import Control.Monad.Except.Trans (ExceptT, except) - replacement in client/src/Aftok/Types.purs at line 8
import Data.Argonaut.Core (Json)import Data.Argonaut.Core (Json, stringify)import Data.Argonaut.Decode (decodeJson)import Data.DateTime (DateTime)import Data.Either (note)import Data.JSDate as JSDate - edit in client/src/Aftok/Types.purs at line 14
import Effect (Effect) - edit in client/src/Aftok/Types.purs at line 23
instance showAPIError :: Show APIError whereshow = case _ ofForbidden -> "Forbidden"ParseFailure js e -> "ParseFailure (" <> show (stringify js) <> ") " <> show eError r -> "Error { status: " <> show r.status <> ", message: " <> r.message <> "}"parseJsonDate :: Json -> ExceptT String Effect DateTimeparseJsonDate json = dostr <- except $ decodeJson jsonparseDate str - edit in client/src/Aftok/Types.purs at line 34[3.7645]
parseDate :: String -> ExceptT String Effect DateTimeparseDate str = dojsDate <- lift $ JSDate.parse strexcept $ note ("Unable to convert date " <> show jsDate <> " to a valid DateTime value.")(JSDate.toDateTime jsDate) - replacement in lib/Aftok/Database/PostgreSQL.hs at line 145
creditToParser' mode f v =letcreditToParser' mode f v = dotn <- typename fif tn /= "credit_to_t"then returnError Incompatible f "column was not of type credit_to_t"else maybe empty (pure . parser . decodeUtf8) vwhere - replacement in lib/Aftok/Database/PostgreSQL.hs at line 152
parser "credit_to_address" =CreditToCurrency <$> (addressParser mode <* nullField <* nullField)parser "credit_to_user" =CreditToUser <$> (nullField *> nullField *> idParser UserId <* nullField)parser "credit_to_project" =CreditToProject<$> (nullField *> nullField *> nullField *> idParser ProjectId)parser _ = emptyindotn <- typename fif tn /= "credit_to_t"then returnError Incompatible f "column was not of type credit_to_t"else maybe empty (pure . parser . decodeUtf8) vparser = \case"credit_to_address" -> CreditToCurrency <$> (addressParser mode <* nullField <* nullField)"credit_to_user" -> CreditToUser <$> (nullField *> nullField *> idParser UserId <* nullField)"credit_to_project" -> CreditToProject <$> (nullField *> nullField *> nullField *> idParser ProjectId)_ -> empty