7TQPQW3NPNUK6CMTOT5ZE4MDENJ5SUOJ2VF2M4JGKHLZHXVX4F3QC GLQSD33YYNRDK23R7W2LEIXODI4N5JD3RHX5VMRR5WPMSVMS333QC NAFJ6RB3KYDBSTSNB3WQSVUQEPUGG2RZCBWRF4XNT2UKSOXDNMDQC Z5KNL332YCRMHKU3NG7YWNLUCNHKSLXBZ3O22FSS47MNVXU2FDLAC PPW6ROC5U7FZCJCH2RX7UJ3PJYNPUMNEZ6KKO3375VFRUM4VT3VQC QAC2QJ32ZLAK25KJ7SWT27WOZKD2MMDE7OZPHIRRFP2W2QZW7PBAC QH4UB73NUR2XPHZQ2RGJBKKUBN43RKC7ZJBCFPP4ESUIIEDDR5XQC B4MTB6UOH5VPZQ7KDQ23TZSR3CIFGVGVBEFL26LMFAQ5RL7CXPRQC WRPIYG3EUHZR6N6T74ZXZDXATRMIRLXAQ24UNUNSVTVYGMT2VDSQC QU5FW67RGCWOWT2YFM4NYMJFFHWIRPQANQBBAHBKZUY7UYMCSIMQC JXG3FCXYBDKMUD77DOM7RCIJYKB7BILC43OHHDZBE7YQRGAMUCCAC QMEYU4MWLTSWPWEEOFRLK2IKE64BY3V5X73323WPLCGPP3TPDYGAC J6S23MDGHVSCVVIRB6XRNSY3EGTDNWFJHV7RYLIEHBUK5KU63CFQC OUR4PAOTXXKXQPMAR5TIYX7MBRRJS2WVTZS7SN4SOGML7SPJIJGQC O2BZOX7MS4JCDS3C6EJQXAWUEQV6HVDCIF2FIN2BCJNRLIU6ZVKAC RB2ETNIFLQUA6OA66DAEOXZ25ENMQGNKX5CZRSKEYHTD6BQ6NTFQC SAESJLLYCQJUIHKFYFV53AWHFOSGI5SKLVS7DPTQO6BKGITPYPUQC other -> throwError $ Error { status: Just other, message: r.statusText }parseDatedResponseMay ::forall t.Traversable t =>DecodeJson (t String) =>Either AJAX.Error (Response Json) ->ExceptT APIError Effect (Maybe (t Instant))parseDatedResponseMay = case _ ofLeft err -> throwError $ Error { status: Nothing, message: printError err }Right r -> case r.status ofStatusCode 403 -> throwError $ ForbiddenStatusCode 404 -> pure NothingStatusCode 200 -> withExceptT (ParseFailure r.body) $ Just <<< map fromDateTime <$> decodeDatedJson r.body
import Control.Monad.Except.Trans (ExceptT, runExceptT, except, withExceptT)import Control.Monad.Error.Class (throwError)import Data.Argonaut.Core (Json)
import Control.Monad.Except.Trans (runExceptT)-- import Control.Monad.Except.Trans (ExceptT, runExceptT, except, withExceptT)-- import Control.Monad.Error.Class (throwError)-- import Data.Argonaut.Core (Json)
import Data.Rational (Rational)import Data.Time.Duration (Hours, Days)import Data.Traversable (traverse)import Data.UUID (parseUUID)import Effect (Effect)
import Data.Rational (Rational, (%))import Data.Time.Duration (Hours(..), Days(..))import Data.Traversable (class Traversable, traverse)-- import Effect (Effect)
( APIError(..) )import Aftok.Api.Json (parseDate)
( APIError )import Aftok.Api.Json( decompose, parseDatedResponse)data DepreciationFn= LinearDepreciation { undep :: Days, dep :: Days }instance decodeDepreciationFn :: DecodeJson DepreciationFn wheredecodeJson json = dox <- decodeJson jsondtype <- x .: "type"args <- x .: "arguments"case dtype of"LinearDepreciation" -> doundep <- Days <$> args .: "undep"dep <- Days <$> args .: "dep"pure $ LinearDepreciation { undep, dep }other -> Left $ "Unrecognized depreciation function: " <> other
derive instance newtypeProject :: Newtype (Project' a) _
derive instance projectNewtype :: Newtype (Project' a) _derive instance projectFunctor :: Functor Project'instance projectFoldable :: Foldable Project' wherefoldr f b (Project' p) = f (p.inceptionDate) bfoldl f b (Project' p) = f b (p.inceptionDate)foldMap = foldMapDefaultRinstance projectTraversable :: Traversable Project' wheretraverse f (Project' p) = Project' <<< (\b -> p { inceptionDate = b }) <$> f (p.inceptionDate)sequence = traverse identity
data DepreciationFn= LinearDepreciation { undep :: Days, dep :: Days }
instance decodeJsonProject :: DecodeJson (Project' String) wheredecodeJson json = dox <- decodeJson jsonproject <- x .: "project"projectId <- x .: "projectId"projectName <- project .: "projectName"inceptionDate <- project .: "inceptionDate"initiator <- project .: "initiator"depFn <- project .: "depreciationFn"pure $ Project' { projectId, projectName, inceptionDate, initiator, depFn }
type ProjectUserData = ProjectUserData' DateTime
instance decodeJsonContributor :: DecodeJson (Contributor' String) wheredecodeJson json = dox <- decodeJson jsonuserId <- x .: "userId"handle <- x .: "username"joinedOn <- x .: "joinedOn"timeDevoted <- Hours <$> x .: "timeDevoted"revShareObj <- x .: "revenueShare"num <- revShareObj .: "numerator"den <- revShareObj .: "denominator"let revShare = num % denpure $ Contributor' { userId, handle, joinedOn, timeDevoted, revShare }
projectIdStr <- x .: "projectId"projectId <- ProjectId <$> (note "Failed to decode project UUID" $ parseUUID projectIdStr)projectName <- project .: "projectName"inceptionDate <- project .: "inceptionDate"initiatorStr <- project .: "initiator"initiator <- UserId <$> (note "Failed to decode initiator UUID" $ parseUUID initiatorStr)pure $ Project' { projectId, projectName, inceptionDate, initiator }
contributors <- x .: "contributors"pure $ ProjectDetail' { project, contributors }
result <- get RF.json "/api/projects"EC.liftEffect <<< runExceptT$ case result ofLeft err -> throwError $ Error { status: Nothing, message: printError err }Right r -> case r.status ofStatusCode 403 -> throwError ForbiddenStatusCode 200 -> dorecords <- except $ lmap (ParseFailure r.body) (decodeJson r.body)traverse parseProject recordsother -> throwError $ Error { status: Just other, message: r.statusText }
response <- get RF.json "/api/projects"EC.liftEffect<<< runExceptT<<< map decompose<<< map (map toDateTime)$ parseDatedResponse response
parseProject :: Json -> ExceptT APIError Effect ProjectparseProject json = doProject' p <- except <<< lmap (ParseFailure json) $ decodeJson jsonpdate <- withExceptT (ParseFailure json) $ parseDate p.inceptionDatepure $ Project' (p { inceptionDate = pdate })
-- getProjectDetail :: ProjectId -> Aff (Maybe ProjectDetail)-- getProjectDetail pid = do-- response <- get RF.json ("/api/user/projects/" <> pidStr pid)-- EC.liftEffect-- <<< map (\dt -> ProjectDetail' {-- project: dt.project,-- contributors: M.fromFoldable $ map (\c -> (Tuple c.userId c)) dt.contributors-- })-- $ parsed
[ HH.slot _projectList unit (ProjectList.component system pcaps) st.selectedProject (Just <<< ProjectSelected) ]
[ HH.slot_projectListunit(ProjectList.component system pcaps)st.selectedProject(Just <<< (\(ProjectList.ProjectChange p) -> ProjectSelected p))]
depreciationCols detail.depreciation <>[ colmd2 ((\(ProjectUserData' p) -> p.userName) <$> M.lookup project.initiator detail.contributors)
depreciationCols project.depFn <>[ colmd2 ((\(Contributor' p) -> p.handle) <$> M.lookup project.initiator detail.contributors)
contributorCols :: ProjectUserData -> H.ComponentHTML OverviewAction Slots mcontributorCols (ProjectUserData' pud) =let pct = maybe "N/A" (\f -> F.toString (f * F.fromInt 100)) (F.fromNumber (R.toNumber pud.currentPayoutRatio) :: Maybe (F.Fixed F.P10000))
contributorCols :: Contributor' DateTime -> H.ComponentHTML OverviewAction Slots mcontributorCols (Contributor' pud) =let pct = maybe "N/A" (\f -> F.toString (f * F.fromInt 100)) (F.fromNumber (R.toNumber pud.revShare) :: Maybe (F.Fixed F.P10000))
[ HH.slot _projectList unit (ProjectList.component system pcaps) st.selectedProject (Just <<< ProjectSelected) ]
[ HH.slot_projectListunit(ProjectList.component system pcaps)st.selectedProject(Just <<< (\(ProjectList.ProjectChange p) -> ProjectSelected p))]
derive instance projectIdNewtype :: Newtype ProjectId _
instance projectIdDecodeJson :: DecodeJson ProjectId wheredecodeJson json = douuidStr <- decodeJson jsonProjectId <$> (note "Failed to decode project UUID" $ parseUUID uuidStr)