RSF6UAJKG7CEKILSVXI6C4YZXY7PIYZM2EMA2IXKQ7SADKNVSH7QC QMEYU4MWLTSWPWEEOFRLK2IKE64BY3V5X73323WPLCGPP3TPDYGAC EA5BFM5GMM7KNMDLTVOSUKVKMSIDD72TAFVHDVGEOUY5VELECU3QC JXG3FCXYBDKMUD77DOM7RCIJYKB7BILC43OHHDZBE7YQRGAMUCCAC J6S23MDGHVSCVVIRB6XRNSY3EGTDNWFJHV7RYLIEHBUK5KU63CFQC ZIG57EE6RB22JGB3CT33EN2HVYCHCXBT5GROBTBMBLEMDTGQOOBQC QU5FW67RGCWOWT2YFM4NYMJFFHWIRPQANQBBAHBKZUY7UYMCSIMQC BFZN4SUAGYNFFYVAP36BAX32DMO622PK4EPEVQQEAGC2IHTEAAPQC NJNMO72S7VIUV22JXB4IFPZMHWTJAOTP6EC6Z4QSKYIROSXT52MQC AWWC6P5ZVFDQHX3EAYDG4DKTUZ6A5LHQAV3NIUO3VP6FM7JKPK5AC IZEVQF627FA7VV25KJAWYWGGC35LZUUBBQRPN5ZAINTQLPEDRTEAC B6HWAPDPXIWH7CHK5VLMWLL6EQN6NOFZEFYO47BPUY2ZO4SL7VDAC EFSXYZPOGA5M4DN65IEIDO7JK6U34DMQELAPHOIL2UAT6HRC66BAC IPG33FAWXGEQ2PO6OXRT2PWWXHRNMPVUKKADL6UKKN5GD2CNZ25AC A6HKMINBNGQLLX4QJMYWKQ4JAEHVJ4HIRVDKPPDI3FJUO2AAB7OQC 64C6AWH66FDKU6UE6Z6JPX2J2GBM2JOPTH2GL6LHKAIUBGNGDZ5AC HMDM3B557TO5RYP2IGFFC2C2VN6HYZTDQ47CJY2O37BW55DSMFZAC O5FVTOM6YFBLEPF3S576K6IMT6ZZ5VQCSB3YVXNS4CKBITKCRZ7AC 4U7F3CPIDTK6JSEDMNMHVKSR7HOQDLZQD2PPVMDLHO5SFSIMUXZAC RPAJLHMTUJU4AYNBOHVGHGGB4NY2NLY3BVPYN5FMWB3ZIMAUQHCQC 4R7XIYK3BP664CO3YJ2VM64ES2JYN27UTQG5KS34OTEPAIODSZLQC BROSTG5KP3NUNLSYPVQID254TE47E5RKQAKLPIY7PGWETE6JNMTAC HO2PFRABW6BBTE4MUKUTEGXCMJS46WGVBCNWOHO4OL52DVAB4YDAC ADMKQQGCGVSHHIMVQ4XFRDCG544SBJCYALSKZV45CQQBZ4ACUH2AC O722AOKEWXWJPRHGJREU6QPW7HEFPPRETZIAADZ2RMAXHARCNEKAC GCVQD44VRPQVKPZEPIC4AOIXLJIG2ZMV3QI2Y7KALUT6NVUBSGSAC GMYPBCWEB6NKURRILAHR3TJUKDOGR2ZMK5I6MS6P5G2LAGH36P3QC MGOF7IUFGXYQKZOKMM2GGULFFVAULEHLZDSHMUW6B5DBKVXXR74AC module Aftok.Api.Timeline whereimport Preludeimport Control.Alt ((<|>))import Control.Monad.Error.Class (throwError)import Control.Monad.Except.Trans (withExceptT, runExceptT)import Data.Argonaut.Decode (class DecodeJson, decodeJson, (.:), (.:?))import Data.DateTime (DateTime)import Data.DateTime.Instant (Instant)import Data.Either (Either, note)import Data.Foldable (class Foldable, foldMapDefaultR, intercalate, foldr, foldl)import Data.JSDate as JDimport Data.Maybe (Maybe(..))import Data.Newtype (class Newtype)import Data.Traversable (class Traversable, traverse)import Data.UUID as UUIDimport Type.Proxy (Proxy(..))-- import Text.Format as F -- (format, zeroFill, width)import Effect.Aff (Aff)import Effect.Class (liftEffect)import Affjax (get, post)import Affjax.RequestBody as RBimport Affjax.ResponseFormat as RFimport Data.Argonaut.Encode (encodeJson)import Aftok.Project (ProjectId(..), pidStr)import Aftok.Types (APIError, JsonCompose, decompose, parseDatedResponse)data TimelineError= LogFailure (APIError)| Unexpected Stringinstance showTimelineError :: Show TimelineError whereshow = case _ ofLogFailure e -> show eUnexpected t -> tdata Event' i= StartEvent i| StopEvent itype Event = Event' Instantderive instance eventFunctor :: Functor Event'instance 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')newtype Interval' i = Interval{ start :: i, end :: i}derive instance intervalEq :: (Eq i) => Eq (Interval' i)derive instance intervalNewtype :: Newtype (Interval' i) _type Interval = Interval' Instantderive instance intervalFunctor :: Functor Interval'instance intervalFoldable :: Foldable Interval' wherefoldr f b (Interval i) = f i.start (f i.end b)foldl f b (Interval i) = f (f b i.start) i.endfoldMap = foldMapDefaultRinstance intervalTraversable :: Traversable Interval' wheretraverse f (Interval i) = interval <$> f i.start <*> f i.endsequence = traverse identityinstance decodeJsonInterval :: DecodeJson (Interval' String) wheredecodeJson json = doobj <- decodeJson jsoninterval <$> obj .: "start" <*> obj .: "end"interval :: forall i. i -> i -> Interval' iinterval s e = Interval { start: s, end: e }data TimeSpan' t= Before t| During (Interval' t)| After ttype TimeSpan = TimeSpan' DateTimederive instance timeSpanFunctor :: Functor TimeSpan'instance timeSpanFoldable :: Foldable TimeSpan' wherefoldr f b = case _ ofBefore a -> f a bDuring x -> foldr f b xAfter a -> f a bfoldl f b = case _ ofBefore a -> f b aDuring x -> foldl f b xAfter a -> f b afoldMap = foldMapDefaultRinstance timeSpanTraversable :: Traversable TimeSpan' wheretraverse f = case _ ofBefore a -> Before <$> f aDuring x -> During <$> traverse f xAfter a -> After <$> f asequence = traverse identityapiLogStart :: ProjectId -> Aff (Either TimelineError Instant)apiLogStart (ProjectId pid) = dolet requestBody = Just <<< RB.Json <<< encodeJson $ { schemaVersion: "2.0" }response <- post RF.json ("/api/user/projects/" <> UUID.toString pid <> "/logStart") requestBodyliftEffect <<< runExceptT $ doevent <- withExceptT LogFailure $ parseDatedResponse responsecase event ofStartEvent t -> pure tStopEvent _ -> throwError <<< Unexpected $ "Expected start event, got stop."apiLogEnd :: ProjectId -> Aff (Either TimelineError Instant)apiLogEnd (ProjectId pid) = dolet requestBody = Just <<< RB.Json <<< encodeJson $ { schemaVersion: "2.0" }response <- post RF.json ("/api/user/projects/" <> UUID.toString pid <> "/logEnd") requestBodyliftEffect <<< runExceptT $ doevent <- withExceptT LogFailure $ parseDatedResponse responsecase event ofStartEvent _ -> throwError <<< Unexpected $ "Expected stop event, got start."StopEvent t -> pure tnewtype ListIntervalsResponse a = ListIntervalsResponse{ workIndex :: Array ({ intervals :: Array a })}derive instance listIntervalsResponseNewtype :: Newtype (ListIntervalsResponse a) _derive instance listIntervalsResponseFunctor :: Functor ListIntervalsResponseinstance listIntervalsResponseFoldable :: Foldable ListIntervalsResponse wherefoldr f b (ListIntervalsResponse r) = foldr f b (r.workIndex >>= _.intervals)foldl f b (ListIntervalsResponse r) = foldl f b (r.workIndex >>= _.intervals)foldMap = foldMapDefaultRinstance listIntervalsResponseTraversable :: Traversable ListIntervalsResponse wheretraverse f (ListIntervalsResponse r) =let traverseCreditRow r' = ({ intervals: _ }) <$> traverse f r'.intervalsin (ListIntervalsResponse <<< ({ workIndex: _ })) <$> traverse traverseCreditRow r.workIndexsequence = traverse identityinstance listIntervalsResponseDecodeJson :: DecodeJson a => DecodeJson (ListIntervalsResponse a) wheredecodeJson = map ListIntervalsResponse <<< decodeJson_ListIntervalsResponse :: Proxy (JsonCompose ListIntervalsResponse Interval' String)_ListIntervalsResponse = ProxyapiListIntervals :: ProjectId -> TimeSpan -> Aff (Either TimelineError (Array Interval))apiListIntervals pid ts = dots' <- liftEffect $ traverse (JD.toISOString <<< JD.fromDateTime) tslet queryElements = case ts' ofBefore t -> ["before=" <> t]During (Interval x) -> ["after=" <> x.start, "before=" <> x.end]After t -> ["after=" <> t]response <- get RF.json ("/api/user/projects/" <> pidStr pid <> "/workIndex?" <> intercalate "&" queryElements)liftEffect<<< runExceptT<<< map (\(ListIntervalsResponse r) -> r.workIndex >>= (_.intervals))<<< map decompose<<< withExceptT LogFailure$ parseDatedResponse response
import Aftok.Project (Project, Project'(..), ProjectId(..), pidStr)import Aftok.Types (APIError, System, JsonCompose, decompose, parseDatedResponse)data Event' i= StartEvent i| StopEvent itype Event = Event' Instantderive instance eventFunctor :: Functor Event'instance 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')newtype Interval' i = Interval{ start :: i, end :: i}derive instance intervalEq :: (Eq i) => Eq (Interval' i)derive instance intervalNewtype :: Newtype (Interval' i) _type Interval = Interval' Instantderive instance intervalFunctor :: Functor Interval'instance intervalFoldable :: Foldable Interval' wherefoldr f b (Interval i) = f i.start (f i.end b)foldl f b (Interval i) = f (f b i.start) i.endfoldMap = foldMapDefaultRinstance intervalTraversable :: Traversable Interval' wheretraverse f (Interval i) = interval <$> f i.start <*> f i.endsequence = traverse identity
import Aftok.Project (Project, Project'(..), ProjectId)import Aftok.Types (System)
instance decodeJsonInterval :: DecodeJson (Interval' String) wheredecodeJson json = doobj <- decodeJson jsoninterval <$> obj .: "start" <*> obj .: "end"interval :: forall i. i -> i -> Interval' iinterval s e = Interval { start: s, end: e }data TimeSpan' t= Before t| During (Interval' t)| After ttype TimeSpan = TimeSpan' DateTimederive instance timeSpanFunctor :: Functor TimeSpan'instance timeSpanFoldable :: Foldable TimeSpan' wherefoldr f b = case _ ofBefore a -> f a bDuring x -> foldr f b xAfter a -> f a bfoldl f b = case _ ofBefore a -> f b aDuring x -> foldl f b xAfter a -> f b afoldMap = foldMapDefaultRinstance timeSpanTraversable :: Traversable TimeSpan' wheretraverse f = case _ ofBefore a -> Before <$> f aDuring x -> During <$> traverse f xAfter a -> After <$> f asequence = traverse identity
data TimelineError= LogFailure (APIError)| Unexpected Stringinstance showTimelineError :: Show TimelineError whereshow = case _ ofLogFailure e -> show eUnexpected t -> t
apiLogStart :: ProjectId -> Aff (Either TimelineError Instant)apiLogStart (ProjectId pid) = dolet requestBody = Just <<< RB.Json <<< encodeJson $ { schemaVersion: "2.0" }response <- post RF.json ("/api/user/projects/" <> UUID.toString pid <> "/logStart") requestBodyliftEffect <<< runExceptT $ doevent <- withExceptT LogFailure $ parseDatedResponse responsecase event ofStartEvent t -> pure tStopEvent _ -> throwError <<< Unexpected $ "Expected start event, got stop."apiLogEnd :: ProjectId -> Aff (Either TimelineError Instant)apiLogEnd (ProjectId pid) = dolet requestBody = Just <<< RB.Json <<< encodeJson $ { schemaVersion: "2.0" }response <- post RF.json ("/api/user/projects/" <> UUID.toString pid <> "/logEnd") requestBodyliftEffect <<< runExceptT $ doevent <- withExceptT LogFailure $ parseDatedResponse responsecase event ofStartEvent _ -> throwError <<< Unexpected $ "Expected stop event, got start."StopEvent t -> pure tnewtype ListIntervalsResponse a = ListIntervalsResponse{ workIndex :: Array ({ intervals :: Array a })}derive instance listIntervalsResponseNewtype :: Newtype (ListIntervalsResponse a) _derive instance listIntervalsResponseFunctor :: Functor ListIntervalsResponseinstance listIntervalsResponseFoldable :: Foldable ListIntervalsResponse wherefoldr f b (ListIntervalsResponse r) = foldr f b (r.workIndex >>= _.intervals)foldl f b (ListIntervalsResponse r) = foldl f b (r.workIndex >>= _.intervals)foldMap = foldMapDefaultRinstance listIntervalsResponseTraversable :: Traversable ListIntervalsResponse wheretraverse f (ListIntervalsResponse r) =let traverseCreditRow r' = ({ intervals: _ }) <$> traverse f r'.intervalsin (ListIntervalsResponse <<< ({ workIndex: _ })) <$> traverse traverseCreditRow r.workIndexsequence = traverse identityinstance listIntervalsResponseDecodeJson :: DecodeJson a => DecodeJson (ListIntervalsResponse a) wheredecodeJson = map ListIntervalsResponse <<< decodeJson_ListIntervalsResponse :: Proxy (JsonCompose ListIntervalsResponse Interval' String)_ListIntervalsResponse = ProxyapiListIntervals :: ProjectId -> TimeSpan -> Aff (Either TimelineError (Array Interval))apiListIntervals pid ts = dots' <- liftEffect $ traverse (JD.toISOString <<< JD.fromDateTime) tslet queryElements = case ts' ofBefore t -> ["before=" <> t]During (Interval x) -> ["after=" <> x.start, "before=" <> x.end]After t -> ["after=" <> t]response <- get RF.json ("/api/user/projects/" <> pidStr pid <> "/workIndex?" <> intercalate "&" queryElements)liftEffect<<< runExceptT<<< map (\(ListIntervalsResponse r) -> r.workIndex >>= (_.intervals))<<< map decompose<<< withExceptT LogFailure$ parseDatedResponse response
credit_to_network, credit_to_address, credit_to_user_id, credit_to_project_id,event_type, event_time, event_metadataFROM work_eventsWHERE project_id = ? AND user_id = ? AND event_time >= ? |]
credit_to_network, credit_to_address, credit_to_user_id, credit_to_project_id,event_type, event_time, event_metadataFROM work_eventsWHERE project_id = ? AND user_id = ? AND event_time >= ? |]
pgEval (FindLatestEvents (ProjectId pid) (UserId uid) i) = domode <- askNetworkModepquery(logEntryParser mode)[sql| SELECT credit_to_type,credit_to_network, credit_to_address, credit_to_user_id, credit_to_project_id,event_type, event_time, event_metadataFROM work_eventsWHERE project_id = ?AND user_id = ?ORDER BY event_time DESCLIMIT ?|](pid, uid, i)
decimalParam :: (Integral i, MonadSnap m) => ByteString -> m (Maybe i)decimalParam k = runMaybeT $ dobs <- MaybeT $ getParam kMaybeT . pure . either (const Nothing) Just $ parseOnly decimal bs
projectPayoutsRoute = serveJSON (payoutsJSON nmode) $ method GET payoutsHandler
auctionRoute = serveJSON auctionJSON $ method GET auctionGetHandlerauctionBidRoute = serveJSON bidIdJSON $ method POST auctionBidHandler
auctionRoute =serveJSON auctionJSON $ method GET auctionGetHandlerauctionBidRoute =serveJSON bidIdJSON $ method POST auctionBidHandler