Add project creation modal.
[?]
Feb 14, 2021, 5:04 AM
YHSVVVYW2RVHLFF3I4DUFSHPSQ2AIJUBSIZ343R3ZATUQKX5DR6QCDependencies
- [2]
XGMFJUERFix the broken modals. - [3]
V54JCKJXPayment request creation. - [4]
U7YAT2ZKAdd error reporting to signup form. - [5]
ARX7SHY5Begin work on login UI. - [6]
SAESJLLYInitial experiments in hash routing. - [7]
ZIG57EE6Fix project selection, end log end on project switch. - [8]
OUR4PAOTUse local dates for display of intervals. - [9]
3HTCTHHUAdd halogen-portal dependency and update argonaut. - [10]
PT4276XCAdd logout functionality. - [11]
JXG3FCXYUpgrade ps + halogen versions. - [12]
O2BZOX7MAdd signup form, captcha check. - [13]
GLQSD33YUse mock capability for overview init. - [14]
QU5FW67RAdd project selection to time tracker. - [15]
7TQPQW3NBegin adding parsing for project detail. - [16]
RV7ZIULZUpdate overview to have access to the real project detail capability. - [17]
KKJSBWO6Add createPaymentRequestHandler - [18]
B4MTB6UOPersist project across pages. - [19]
AKM2VYBLFix errors with project ID persistence. - [20]
PPW6ROC5Render project data - [21]
T2DN23M7Factor out billing create component. - [22]
Z5KNL332Add skeleton of project overview HTML. - [23]
RSF6UAJKBreak out api module for timeline. - [24]
ANDJ6GEYAdd billing component skeleton. - [25]
KET5QGQPAdd billable list (in-progress) - [26]
ZHV75AENbasic cleanup - [27]
QMEYU4MWAdd display for prior intervals. - [28]
NJNMO72SAdd zcash.com submodule and update client to modern halogen. - [29]
4GOBY5NQWIP on modals. - [30]
WRPIYG3EUse project listing functionality to check for whether we have a cookie. - [31]
BPIQKEXEgussify - [32]
J6S23MDGUse server timestamps for interval start and end. - [33]
46PUXHTYImplement project invitations. - [34]
NAFJ6RB3Minor module reorg. - [35]
QH4UB73NFormat with purty. - [36]
APOATM4XAdd getProjectDetail call to project API - [37]
YBLHJFCNImplement billing modal. - [38]
QAC2QJ32Add project overview page to client. - [39]
AAALU5A2Fix client routing - [40]
VTZT2ILUWire up billing navigation. - [*]
RB2ETNIFAdd skeletal PureScript client project.
Change contents
- replacement in client/src/Aftok/Api/Project.purs at line 7
import Data.Argonaut.Core (Json, fromString)import Data.Argonaut.Core (Json, fromString, jsonEmptyObject) - replacement in client/src/Aftok/Api/Project.purs at line 9
import Data.Argonaut.Encode (encodeJson)import Data.Argonaut.Encode (encodeJson, (:=), (~>)) - edit in client/src/Aftok/Api/Project.purs at line 224[3.1138]
type ProjectCreateRequest ={ projectName :: String, depf :: DepreciationFn}encodeProjectCreateRequest :: ProjectCreateRequest -> JsonencodeProjectCreateRequest pc ="projectName" := pc.projectName~> "depf" := (case pc.depf ofLinearDepreciation vs ->encodeJson {"type": "LinearDepreciation","arguments": { "undep": unwrap vs.undep, dep: unwrap vs.dep }})~> jsonEmptyObjectdecodeProjectId :: Json -> Either JsonDecodeError ProjectIddecodeProjectId json = (_ .: "projectId") =<< decodeJson jsoncreateProject :: ProjectCreateRequest -> Aff (Either APIError ProjectId)createProject pc = dolet body = RB.json $ encodeProjectCreateRequest pcresponse <- post RF.json "/api/projects/" (Just body)parseResponse decodeProjectId response - edit in client/src/Aftok/Billing.purs at line 5
-- import Data.DateTime (DateTime, date) - edit in client/src/Aftok/Billing.purs at line 9
import Data.Newtype (unwrap) - edit in client/src/Aftok/Billing.purs at line 10
-- import Data.Time.Duration (Hours(..)) - edit in client/src/Aftok/Billing.purs at line 14
-- import Effect.Class (liftEffect)-- import Effect.Now (nowDateTime) - edit in client/src/Aftok/Billing.purs at line 24
import Aftok.Api.Project (Project) - replacement in client/src/Aftok/Billing.purs at line 37
= Maybe Project= Maybe ProjectId - replacement in client/src/Aftok/Billing.purs at line 40
= { selectedProject :: Maybe Project= { selectedProject :: Maybe ProjectId - replacement in client/src/Aftok/Billing.purs at line 47
| ProjectSelected Project| ProjectSelected ProjectId - replacement in client/src/Aftok/Billing.purs at line 53
= forall query. H.Slot query ProjectList.Event id= forall query. H.Slot query ProjectList.Output id - replacement in client/src/Aftok/Billing.purs at line 78
H.Component HH.HTML query BillingInput ProjectList.Event mH.Component HH.HTML query BillingInput ProjectList.Output m - replacement in client/src/Aftok/Billing.purs at line 121
Just p ->[ renderBillableList (unwrap p).projectId st.billablesJust pid ->[ renderBillableList pid st.billables - replacement in client/src/Aftok/Billing.purs at line 128
, E.onClick (\_ -> Just (OpenBillableModal (unwrap p).projectId)), E.onClick (\_ -> Just (OpenBillableModal pid)) - replacement in client/src/Aftok/Billing.purs at line 195
eval :: BillingAction -> H.HalogenM BillingState BillingAction Slots ProjectList.Event m Uniteval :: BillingAction -> H.HalogenM BillingState BillingAction Slots ProjectList.Output m Unit - replacement in client/src/Aftok/Billing.purs at line 199
currentProject <- H.gets (_.selectedProject)traverse_ refreshBillables currentProjectcurrentPid <- H.gets (_.selectedProject)traverse_ refreshBillables currentPid - replacement in client/src/Aftok/Billing.purs at line 202[3.6797]→[3.6797:6880](∅→∅),[3.6880]→[3.15466:15493](∅→∅),[3.4048]→[3.6880:7093](∅→∅),[3.15493]→[3.6880:7093](∅→∅),[3.6880]→[3.6880:7093](∅→∅)
ProjectSelected p -> docurrentProject <- H.gets (_.selectedProject)refreshBillables pwhen (all (\p' -> (unwrap p').projectId /= (unwrap p).projectId) currentProject)$ doH.raise (ProjectList.ProjectChange p)H.modify_ (_ { selectedProject = Just p })ProjectSelected pid -> docurrentPid <- H.gets (_.selectedProject)refreshBillables pidwhen (all (_ /= pid) currentPid) $ doH.raise (ProjectList.ProjectChange pid)H.modify_ (_ { selectedProject = Just pid }) - replacement in client/src/Aftok/Billing.purs at line 213
currentProject <- H.gets (_.selectedProject)traverse_ refreshBillables currentProjectcurrentPid <- H.gets (_.selectedProject)traverse_ refreshBillables currentPid - replacement in client/src/Aftok/Billing.purs at line 220
refreshBillables currentProject = dobillables <- lift $ caps.listProjectBillables (unwrap currentProject).projectIdrefreshBillables pid = dobillables <- lift $ caps.listProjectBillables pid - edit in client/src/Aftok/Overview.purs at line 5
import Data.Array (reverse, sortWith) - edit in client/src/Aftok/Overview.purs at line 32
import Aftok.Projects.Create as Create - replacement in client/src/Aftok/Overview.purs at line 36
( Project, Project'(..)( Project'(..) - replacement in client/src/Aftok/Overview.purs at line 45
= Maybe Project= Maybe ProjectId - replacement in client/src/Aftok/Overview.purs at line 48
= { selectedProject :: Maybe Project= { selectedProject :: Maybe ProjectId - edit in client/src/Aftok/Overview.purs at line 52
data Invitation= InviteByEmail String| InviteByZaddr String - replacement in client/src/Aftok/Overview.purs at line 54
| ProjectSelected Project| Invite ProjectId| ProjectSelected ProjectId| OpenCreateModal| OpenInviteModal ProjectId - replacement in client/src/Aftok/Overview.purs at line 59
= forall query. H.Slot query ProjectList.Event id= forall query. H.Slot query ProjectList.Output id - edit in client/src/Aftok/Overview.purs at line 63
, projectCreateModal :: Create.Slot Unit - edit in client/src/Aftok/Overview.purs at line 68
_projectCreateModal = SProxy :: SProxy "projectCreateModal" - edit in client/src/Aftok/Overview.purs at line 74
, createCaps :: Create.Capability m - replacement in client/src/Aftok/Overview.purs at line 83
H.Component HH.HTML query OverviewInput ProjectList.Event mH.Component HH.HTML query OverviewInput ProjectList.Output m - replacement in client/src/Aftok/Overview.purs at line 112
[ P.classes (ClassName <$> [ "col-md-5", "text-muted", "text-center", "mx-auto" ]) ][ P.classes (ClassName <$> [ "text-muted", "text-center", "mx-auto" ]) ] - edit in client/src/Aftok/Overview.purs at line 121
, system.portal_projectCreateModalunit(Create.component system caps.createCaps)unitNothing(Just <<< (\(Create.ProjectCreated p) -> ProjectSelected p)) - edit in client/src/Aftok/Overview.purs at line 132
, HH.div[ P.classes (ClassName <$> [ "pt-6", "mx-auto" ]) ][ HH.button[ P.classes [ C.btn, C.btnPrimary ], P.type_ ButtonButton, E.onClick (\_ -> Just OpenCreateModal)][ HH.text "Create a new project" ]] - replacement in client/src/Aftok/Overview.purs at line 181
<> (contributorCols <$> (L.toUnfoldable $ M.values detail.contributors))<><> (contributorCols <$> (reverse<<< sortWith ((_.revShare) <<< unwrap)<<< L.toUnfoldable$ M.values detail.contributors))<> - replacement in client/src/Aftok/Overview.purs at line 195
, E.onClick (\_ -> Just (Invite project.projectId)), E.onClick (\_ -> Just (OpenInviteModal project.projectId)) - replacement in client/src/Aftok/Overview.purs at line 240
eval :: OverviewAction -> H.HalogenM OverviewState OverviewAction Slots ProjectList.Event m Uniteval :: OverviewAction -> H.HalogenM OverviewState OverviewAction Slots ProjectList.Output m Unit - replacement in client/src/Aftok/Overview.purs at line 245
traverse_ (setProjectDetail <<< (\p -> (unwrap p).projectId)) currentProjectInvite pid -> dotraverse_ setProjectDetail currentProjectOpenCreateModal -> dovoid <<< H.query _projectCreateModal unit $ H.tell (Create.OpenModal)OpenInviteModal pid -> do - replacement in client/src/Aftok/Overview.purs at line 250
ProjectSelected p -> doProjectSelected pid -> do - replacement in client/src/Aftok/Overview.purs at line 252
when (all (\p' -> (unwrap p').projectId /= (unwrap p).projectId) currentProject)when (all (_ /= pid) currentProject) - replacement in client/src/Aftok/Overview.purs at line 254[3.11730]→[3.5276:5328](∅→∅),[3.5328]→[3.11770:11827](∅→∅),[3.11770]→[3.11770:11827](∅→∅),[3.11827]→[3.628:680](∅→∅)
H.raise (ProjectList.ProjectChange p)H.modify_ (_ { selectedProject = Just p })setProjectDetail (unwrap p).projectIdH.raise (ProjectList.ProjectChange pid)H.modify_ (_ { selectedProject = Just pid })setProjectDetail pid - replacement in client/src/Aftok/Overview.purs at line 258
setProjectDetail :: ProjectId -> H.HalogenM OverviewState OverviewAction Slots ProjectList.Event m UnitsetProjectDetail :: ProjectId -> H.HalogenM OverviewState OverviewAction Slots ProjectList.Output m Unit - edit in client/src/Aftok/Overview.purs at line 269
, createCaps: Create.apiCapability - edit in client/src/Aftok/Overview.purs at line 299
, createCaps: Create.apiCapability - edit in client/src/Aftok/ProjectList.purs at line 6
-- import Data.Bifunctor (lmap) - edit in client/src/Aftok/ProjectList.purs at line 9
import Data.Newtype (unwrap) - edit in client/src/Aftok/ProjectList.purs at line 14
, ProjectId - replacement in client/src/Aftok/ProjectList.purs at line 32
= Maybe Project= Maybe ProjectIddata Query a= ProjectCreated ProjectId a - replacement in client/src/Aftok/ProjectList.purs at line 37
data Event= ProjectChange Projectdata Output= ProjectChange ProjectId - replacement in client/src/Aftok/ProjectList.purs at line 41
= forall query. H.Slot query Event id= H.Slot Query Output id - replacement in client/src/Aftok/ProjectList.purs at line 44
= { selectedProject :: Maybe Project= { selectedPid :: Maybe ProjectId - replacement in client/src/Aftok/ProjectList.purs at line 49
= Initialize= Initialize (Maybe ProjectId) - replacement in client/src/Aftok/ProjectList.purs at line 57
forall query m.forall m. - replacement in client/src/Aftok/ProjectList.purs at line 61
H.Component HH.HTML query Input Event mH.Component HH.HTML Query Input Output m - replacement in client/src/Aftok/ProjectList.purs at line 69
{ handleAction = eval, initialize = Just Initialize{ handleAction = handleAction, handleQuery = handleQuery, initialize = Just (Initialize Nothing) - replacement in client/src/Aftok/ProjectList.purs at line 76
initialState input = { selectedProject: input, projects: [] }initialState input = { selectedPid: input, projects: [] } - replacement in client/src/Aftok/ProjectList.purs at line 92
( [ HH.option [ P.selected (isNothing st.selectedProject), P.disabled true ] [ HH.text "Select a project" ] ]( [ HH.option [ P.selected (isNothing st.selectedPid), P.disabled true ] [ HH.text "Select a project" ] ] - replacement in client/src/Aftok/ProjectList.purs at line 99
[ P.selected (any (\(Project' p') -> p'.projectId == p.projectId) st.selectedProject)[ P.selected (any (p.projectId == _) st.selectedPid) - replacement in client/src/Aftok/ProjectList.purs at line 104[3.1519]→[3.5814:5875](∅→∅),[3.5875]→[3.13580:13620](∅→∅),[3.7638]→[3.13580:13620](∅→∅),[3.13580]→[3.13580:13620](∅→∅)
eval :: Action -> H.HalogenM CState Action () Event m Uniteval = case _ ofInitialize -> dohandleQuery :: forall slots a. Query a -> H.HalogenM CState Action slots Output m (Maybe a)handleQuery = case _ ofProjectCreated pid a -> dohandleAction (Initialize (Just pid))pure (Just a)handleAction :: forall slots. Action -> H.HalogenM CState Action slots Output m UnithandleAction = case _ ofInitialize pidMay -> do - replacement in client/src/Aftok/ProjectList.purs at line 116
Right projects -> H.modify_ (_ { projects = projects })Right projects -> H.modify_ (_ { projects = projects, selectedPid = pidMay }) - replacement in client/src/Aftok/ProjectList.purs at line 120
traverse_ (H.raise <<< ProjectChange) (index projects (i - 1))traverse_ (\p -> H.raise $ ProjectChange (unwrap p).projectId) (index projects (i - 1)) - file addition: Create.purs[3.7504]
module Aftok.Projects.Create whereimport Preludeimport Control.Monad.Trans.Class (lift)import Data.Either (Either(..), note)import Data.Foldable (any)import Data.Maybe (Maybe(..))import Data.Number (fromString) as Numberimport Data.Time.Duration (Days(..))import Data.Validation.Semigroup (V(..), toEither)import Effect.Aff (Aff)import DOM.HTML.Indexed.ButtonType (ButtonType(..))import Halogen as Himport Halogen.HTML as HHimport Halogen.HTML.Core (ClassName(..))import Halogen.HTML.Events as Eimport Halogen.HTML.Properties as Pimport Halogen.HTML.Properties.ARIA as ARIAimport Aftok.Api.Project (ProjectCreateRequest, DepreciationFn(..), createProject)import Aftok.Api.Types (APIError(..))import Aftok.HTML.Classes as Cimport Aftok.Modals.ModalFFI as ModalFFIimport Aftok.Types (System, ProjectId)data Field= NameField| UndepField| DepFieldderive instance fieldEq :: Eq Fieldderive instance fieldOrd :: Ord Fieldtype CState ={ projectName :: Maybe String, undep :: Maybe Days, dep :: Maybe Days, fieldErrors :: Array Field}data Query a= OpenModal adata Output= ProjectCreated ProjectIddata Action= SetName String| SetUndepDays String| SetDepDays String| Save| Closetype Slot id= H.Slot Query Output idtype Capability (m :: Type -> Type)= { createProject :: ProjectCreateRequest -> m (Either APIError ProjectId)}modalId :: StringmodalId = "createProject"component ::forall input m.Monad m =>System m ->Capability m ->H.Component HH.HTML Query input Output mcomponent system caps =H.mkComponent{ initialState: const initialState, render, eval: H.mkEval$ H.defaultEval{ handleAction = handleAction, handleQuery = handleQuery}}whereinitialState :: CStateinitialState ={ projectName : Nothing, undep : Nothing, dep : Nothing, fieldErrors : []}render :: forall slots. CState -> H.ComponentHTML Action slots mrender st =HH.div[ P.classes [ C.modal ], P.id_ modalId, P.tabIndex (negate 1), ARIA.role "dialog", ARIA.labelledBy (modalId <> "Title"), ARIA.hidden "true"][ HH.div[ P.classes [C.modalDialog], ARIA.role "document" ][ HH.div[ P.classes [C.modalContent] ][ HH.div[ P.classes [C.modalHeader] ][ HH.h5 [P.classes [C.modalTitle], P.id_ (modalId <>"Title") ] [HH.text "Create a new project"], HH.button[ P.classes [ C.close ], ARIA.label "Close", P.type_ ButtonButton, E.onClick (\_ -> Just Close)][ HH.span [ARIA.hidden "true"] [HH.text "×"]]], HH.div[ P.classes [C.modalBody] ][ HH.form_[ formGroup st[ NameField ][ HH.label[ P.for "projectName"][ HH.text "Project Name" ], HH.input[ P.type_ P.InputText, P.classes [ C.formControl, C.formControlSm ], P.id_ "projectName", P.placeholder "My awesome new project!!!", E.onValueInput (Just <<< SetName)]], formGroup st[ UndepField ][ HH.label[ P.for "undepDays"][ HH.text "Number of days before a share begins to depreciate" ], HH.input[ P.type_ P.InputNumber, P.classes [ C.formControl, C.formControlXs, C.formControlFlush, C.marginX2 ], P.id_ "undepDays", P.placeholder "180", E.onValueInput (Just <<< SetUndepDays)]], formGroup st[ DepField ][ HH.label[ P.for "undepDays"][ HH.text "Number of days over which a share depreciates" ], HH.input[ P.type_ P.InputNumber, P.classes [ C.formControl, C.formControlXs, C.formControlFlush, C.marginX2 ], P.id_ "undepDays", P.placeholder "1800", E.onValueInput (Just <<< SetDepDays)]]]], HH.div[ P.classes [C.modalFooter] ][ HH.button[ P.type_ ButtonButton, P.classes [ C.btn, C.btnSecondary], E.onClick (\_ -> Just Close)][ HH.text "Close" ], HH.button[ P.type_ ButtonButton, P.classes [ C.btn, C.btnPrimary ], E.onClick (\_ -> Just Save)][ HH.text "Create project"]]]]]formGroup :: forall i a. CState -> Array Field -> Array (HH.HTML i a) -> HH.HTML i aformGroup st fields body =HH.div[ P.classes [C.formGroup] ](body <> (fieldError st =<< fields))fieldError :: forall i a. CState -> Field -> Array (HH.HTML i a)fieldError st field =if any (_ == field) st.fieldErrorsthen case field ofNameField -> err "The name field is required"UndepField -> err "A number of days before depreciation starts is required"DepField -> err "The number of days over which a share depreciates is required"else []whereerr str =[ HH.div_[ HH.span[ P.classes (ClassName <$> [ "badge", "badge-danger-soft" ]) ] [ HH.text str ] ]]-- we use a query to initialize, since this is a modal that doesn't actually get unloaded.handleQuery :: forall slots a. Query a -> H.HalogenM CState Action slots Output m (Maybe a)handleQuery = case _ ofOpenModal a -> doH.modify_ (const initialState)lift $ system.toggleModal modalId ModalFFI.ShowModalpure (Just a)handleAction :: forall slots. Action -> H.HalogenM CState Action slots Output m UnithandleAction = case _ ofSetName name ->H.modify_ (_ { projectName = Just name })SetUndepDays days ->case Number.fromString days of(Just n) -> H.modify_ (_ { undep = Just $ Days n })(Nothing) -> pure unitSetDepDays days ->case Number.fromString days of(Just n) -> H.modify_ (_ { dep = Just $ Days n })(Nothing) -> pure unitSave -> donameV <- V <<< note [NameField] <$> H.gets (_.projectName)undepV <- V <<< note [UndepField] <$> H.gets (_.undep)depV <- V <<< note [DepField] <$> H.gets (_.dep)let req = { projectName: _, depf : _}reqV =req <$> nameV<*> (LinearDepreciation <$> ({ undep: _, dep: _ } <$> undepV <*> depV))case toEither reqV ofRight req' -> dores <- lift $ caps.createProject req'case res ofRight pid -> doH.raise (ProjectCreated pid)handleAction CloseLeft errs -> dolift $ system.error (show errs)Left errors -> doH.modify_ (_ { fieldErrors = errors })Close -> doH.modify_ (const initialState) -- wipe the state for safetylift $ system.toggleModal modalId ModalFFI.HideModalapiCapability :: Capability AffapiCapability ={ createProject: createProject}mockCapability :: Capability AffmockCapability ={ createProject: \_ -> pure $ Left Forbidden } - edit in client/src/Aftok/Timeline.purs at line 18
import Data.Newtype (unwrap) - edit in client/src/Aftok/Timeline.purs at line 62
import Aftok.Api.Project( Project, Project'(..)) - replacement in client/src/Aftok/Timeline.purs at line 91
= Maybe Project= Maybe ProjectId - replacement in client/src/Aftok/Timeline.purs at line 94
= { selectedProject :: Maybe Project= { selectedProject :: Maybe ProjectId - replacement in client/src/Aftok/Timeline.purs at line 102
| ProjectSelected Project| ProjectSelected ProjectId - replacement in client/src/Aftok/Timeline.purs at line 108
= forall query. H.Slot query ProjectList.Event id= forall query. H.Slot query ProjectList.Output id - replacement in client/src/Aftok/Timeline.purs at line 130
H.Component HH.HTML query Input ProjectList.Event mH.Component HH.HTML query Input ProjectList.Output m - replacement in client/src/Aftok/Timeline.purs at line 169
(Just <<< (\(ProjectList.ProjectChange p) -> ProjectSelected p))(Just <<< (\(ProjectList.ProjectChange pid) -> ProjectSelected pid)) - replacement in client/src/Aftok/Timeline.purs at line 193
eval :: TimelineAction -> H.HalogenM TimelineState TimelineAction Slots ProjectList.Event m Uniteval :: TimelineAction -> H.HalogenM TimelineState TimelineAction Slots ProjectList.Output m Unit - replacement in client/src/Aftok/Timeline.purs at line 200
ProjectSelected p -> doProjectSelected pid -> do - replacement in client/src/Aftok/Timeline.purs at line 204[3.29602]→[3.29602:29767](∅→∅),[3.29767]→[3.6431:6477](∅→∅),[3.6477]→[3.29801:29830](∅→∅),[3.29801]→[3.29801:29830](∅→∅)
when (oldActive && any (\p' -> (unwrap p').projectId /= (unwrap p).projectId) currentProject)$ do(traverse_ logEnd currentProject)H.raise (ProjectList.ProjectChange p)setStateForProject pwhen (oldActive && any (_ /= pid) currentProject)$ (traverse_ logEnd currentProject)H.raise (ProjectList.ProjectChange pid)setStateForProject pid - replacement in client/src/Aftok/Timeline.purs at line 222
logStart :: Project -> H.HalogenM TimelineState TimelineAction Slots ProjectList.Event m UnitlogStart (Project' p) = dologged <- lift $ caps.logStart p.projectIdlogStart :: ProjectId -> H.HalogenM TimelineState TimelineAction Slots ProjectList.Output m UnitlogStart pid = dologged <- lift $ caps.logStart pid - replacement in client/src/Aftok/Timeline.purs at line 229
logEnd :: Project -> H.HalogenM TimelineState TimelineAction Slots ProjectList.Event m UnitlogEnd (Project' p) = dologged <- lift $ caps.logEnd p.projectIdlogEnd :: ProjectId -> H.HalogenM TimelineState TimelineAction Slots ProjectList.Output m UnitlogEnd pid = dologged <- lift $ caps.logEnd pid - replacement in client/src/Aftok/Timeline.purs at line 239
setStateForProject :: Project -> H.HalogenM TimelineState TimelineAction Slots ProjectList.Event m UnitsetStateForProject p = dosetStateForProject :: ProjectId -> H.HalogenM TimelineState TimelineAction Slots ProjectList.Output m UnitsetStateForProject pid = do - replacement in client/src/Aftok/Timeline.purs at line 242
intervals' <- lift $ caps.listIntervals (unwrap p).projectId timeSpanintervals' <- lift $ caps.listIntervals pid timeSpan - replacement in client/src/Aftok/Timeline.purs at line 254
latestEventResponse <- lift $ caps.getLatestEvent (unwrap p).projectIdlatestEventResponse <- lift $ caps.getLatestEvent pid - replacement in client/src/Aftok/Timeline.purs at line 271
H.modify_ (_ { selectedProject = Just p, history = hist, active = active })H.modify_ (_ { selectedProject = Just pid, history = hist, active = active }) - replacement in client/src/Main.purs at line 22
import Aftok.Types (System, liveSystem)import Aftok.Types (System, ProjectId, liveSystem) - edit in client/src/Main.purs at line 25
import Aftok.Api.Project (Project) - replacement in client/src/Main.purs at line 93
, selectedProject :: Maybe Project, selectedProject :: Maybe ProjectId - replacement in client/src/Main.purs at line 100
| ProjectAction ProjectList.Event| ProjectAction ProjectList.Output