Skip to content

Commit

Permalink
Split back out all project layer types
Browse files Browse the repository at this point in the history
  • Loading branch information
Erudition committed Aug 15, 2023
1 parent 993c578 commit e3bd3e6
Show file tree
Hide file tree
Showing 32 changed files with 1,575 additions and 1,337 deletions.
4 changes: 3 additions & 1 deletion LESSONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ But this is "making guesses about the future", and can lead to overengineering:
- You don't always want that metadata derived in exactly the same way in every situation, I've learned.
- When you change one little bit of a huge collection, the old meta collection needs to be replaced, forcing all of those meta fields to be calculated again. By leaving derived data out until the last possible moment, you can let the compiler see that same input -> same output for all of the unchanged items that are being used elsewhere, and only recalculate the items affected by the change.

Instead, I'm going to try to push all derivations to "the edge" - the place where it's actually needed. Despite the extra arguments to accessor functions, it's equivalent or better performance and it avoids issues with making assumptions about how I'll use it later.
Instead, I'm going to try to push all derivations to "the edge" - the place where it's actually needed. Despite the extra arguments to accessor functions, it's equivalent or better performance and it avoids issues with making assumptions about how I'll use it later.

Update: actually, I think it's good enough for now to have the meta objects simply contain pointers to their parent objects - not adding any derived data, so no copying, each type's library functions can reach into the parents if needed. We'll see if this is a bottleneck in the future, but I really need to guarantee that the parents are reachable rather than having to deal with maybes everywhere. Since imports only go one way, the contained children will have to be the skeletons, but the child type's libraries can be used for accessing those.
5 changes: 4 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@

# Timeflow
- Take widget out of dictionary, we'll probably only need a pre-known amount
- Responsive screen sizing
- Responsive screen sizing

# Task data structures
- move Assignment et. al. back into their own modules?
3 changes: 1 addition & 2 deletions elm/Activity/HistorySession.elm
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import SmartTime.Human.Moment as HumanMoment exposing (Zone)
import SmartTime.Moment as Moment exposing (..)
import SmartTime.Period as Period exposing (Period(..))
import Task.Assignment exposing (AssignmentID)
import Task.Meta exposing (ProjectLayers)
import Task.Project exposing (ProjectSkel)
import Task.Layers exposing (ProjectLayers)
import TimeTrackable exposing (TimeTrackable)


Expand Down
20 changes: 10 additions & 10 deletions elm/Integrations/Marvin.elm
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import SmartTime.Human.Duration as HumanDuration
import SmartTime.Human.Moment as HumanMoment
import SmartTime.Moment as Moment exposing (Moment)
import SmartTime.Period as Period exposing (Period)
import Task.Assignable
import Task.Assignment
import Task.Project
import Task.AssignableSkel
import Task.AssignmentSkel
import Task.ProjectSkel
import TimeBlock.TimeBlock exposing (TimeBlock)
import Url.Builder

Expand Down Expand Up @@ -464,7 +464,7 @@ handle classCounter profile ( time, timeZone ) response =
Maybe.andThen (Profile.getAssignmentByID profile ( time, timeZone )) activeInstanceIDMaybe

activeMarvinIDMaybe =
Maybe.andThen (Task.Assignment.getExtra "marvinID") activeInstanceMaybe
Maybe.andThen (Task.AssignmentSkel.getExtra "marvinID") activeInstanceMaybe
in
-- also Ok, Marvin returns empty string
( Change.none
Expand Down Expand Up @@ -779,7 +779,7 @@ marvinUpdateCurrentlyTracking : Profile -> ( Moment, HumanMoment.Zone ) -> Maybe
marvinUpdateCurrentlyTracking profile ( time, timeZone ) instanceIDMaybe starting =
case Maybe.andThen (Profile.getAssignmentByID profile ( time, timeZone )) instanceIDMaybe of
Just instanceNowTracking ->
case Task.Assignment.getExtra "marvinID" instanceNowTracking of
case Task.AssignmentSkel.getExtra "marvinID" instanceNowTracking of
Nothing ->
( [], Cmd.none )

Expand All @@ -789,9 +789,9 @@ marvinUpdateCurrentlyTracking profile ( time, timeZone ) instanceIDMaybe startin
timeTrack partialAccessToken marvinIDAssociatedWithInstance starting

updateInstance =
Task.Assignment.setExtra
Task.AssignmentSkel.setExtra
"marvinTimes"
(timesUpdater profile (Task.Assignment.getID instanceNowTracking))
(timesUpdater profile (Task.AssignmentSkel.getID instanceNowTracking))
instanceNowTracking

updateTimesCmd =
Expand Down Expand Up @@ -852,7 +852,7 @@ trackTruthToTimelineSessions : Profile -> ( Moment, HumanMoment.Zone ) -> TrackT
trackTruthToTimelineSessions profile ( time, timeZone ) truthItem =
let
isCorrectInstance instance =
Just truthItem.task == Task.Assignment.getExtra "marvinID" instance
Just truthItem.task == Task.AssignmentSkel.getExtra "marvinID" instance

matchingInstance =
List.find isCorrectInstance (Profile.assignments profile ( time, timeZone ))
Expand Down Expand Up @@ -887,14 +887,14 @@ trackTruthToTimelineSessions profile ( time, timeZone ) truthItem =
Log.logMessageOnly "no matching instance when constructing timeline sessions from marvin data!" []

Just instance ->
case Task.Assignment.getActivityID instance of
case Task.AssignmentSkel.getActivityID instance of
Nothing ->
[]

Just activity ->
let
toSession moment1 moment2 =
( activity, Just <| Task.Assignment.getID instance, Period.fromPair ( moment1, moment2 ) )
( activity, Just <| Task.AssignmentSkel.getID instance, Period.fromPair ( moment1, moment2 ) )
in
List.map2 toSession startsList stopsList

Expand Down
96 changes: 48 additions & 48 deletions elm/Integrations/Marvin/MarvinItem.elm
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ import SmartTime.Human.Clock exposing (TimeOfDay)
import SmartTime.Human.Moment
import SmartTime.Moment as Moment exposing (Moment(..))
import SmartTime.Period as Period exposing (Period(..))
import Task.Assignable
import Task.Assignment
import Task.Meta exposing (..)
import Task.AssignableSkel
import Task.AssignmentSkel
import Task.Progress
import Task.Project
import Task.Project exposing (..)
import Task.ProjectSkel
import Task.SessionSkel exposing (UserPlannedSession)
import TimeBlock.TimeBlock as TimeBlock exposing (TimeBlock)
import ZoneHistory exposing (ZoneHistory)
Expand Down Expand Up @@ -392,16 +392,16 @@ toDocketTask profile marvinItem =
let
-- TODO we shouldn't calculate the whole assignable/assignment list on every item import. Figure it out above, then pass to this function
existingAssignables =
(Task.Meta.projectToAssignableLayers profile.projects).assignables
(Task.Project.projectToAssignableLayers profile.projects).assignables
|> AnyDict.values

existingAssignablesWithMarvinLink =
Dict.fromList <| List.filterMap pairAssignableWithMarvinIDMaybe existingAssignables

pairAssignableWithMarvinIDMaybe ass =
case Task.Meta.assignableGetExtra "marvinGeneratorID" ass of
case Task.Project.assignableGetExtra "marvinGeneratorID" ass of
Just marvinID ->
Just ( marvinID, Task.Meta.assignableID ass )
Just ( marvinID, Task.Project.assignableID ass )

Nothing ->
Nothing
Expand Down Expand Up @@ -575,19 +575,19 @@ toDocketTask profile marvinItem =
Nothing ->
let
newEntry c =
Task.Project.initProjectWithAssignable (createAssignable (Change.reuseContext "action" c)) c
Task.ProjectSkel.initProjectWithAssignable (createAssignable (Change.reuseContext "action" c)) c

createAssignable : Change.Creator (Reg Task.Assignable.AssignableSkel)
createAssignable c =
let
newAssignableChanger : Reg Task.Assignable.AssignableSkel -> List Change
newAssignableChanger newAssignable =
RepDb.addNew
(\c2 -> Task.Assignment.newWithChanges assignmentChanges (Change.reuseContext marvinItem.id c2))
(\c2 -> Task.AssignmentSkel.newWithChanges assignmentChanges (Change.reuseContext marvinItem.id c2))
(Reg.latest newAssignable).manualAssignments
:: assignableChanges (Reg.latest newAssignable)
in
Task.Assignable.new (Change.reuseContext marvinItem.id c) marvinItem.title newAssignableChanger
Task.AssignableSkel.new (Change.reuseContext marvinItem.id c) marvinItem.title newAssignableChanger
in
[ RepDb.addNew newEntry profile.projects
]
Expand All @@ -599,10 +599,10 @@ fromDocket : Task.Meta.Assignment -> Maybe MarvinItem
fromDocket instance =
let
idMaybe =
Task.Meta.assignmentGetExtra "marvinID" instance
Task.Project.assignmentGetExtra "marvinID" instance

revMaybe =
Task.Meta.assignmentGetExtra "marvinCouchdbRev" instance
Task.Project.assignmentGetExtra "marvinCouchdbRev" instance

toDate =
Maybe.andThen (SmartTime.Human.Calendar.fromNumberString >> Result.toMaybe)
Expand All @@ -618,44 +618,44 @@ fromDocket instance =
Just
{ id = id
, rev = rev
, done = Task.Meta.assignmentCompleted instance
, day = toDate <| Task.Meta.assignmentGetExtra "marvinDay" instance
, title = Task.Meta.assignmentTitle instance
, parentId = Task.Meta.assignmentGetExtra "marvinParentID" instance
, labelIds = Maybe.withDefault [] <| Maybe.map String.words <| Task.Meta.assignmentGetExtra "marvinLabels" instance
, firstScheduled = toDate <| Task.Meta.assignmentGetExtra "marvinFirstScheduled" instance
, rank = Maybe.withDefault 0 <| Maybe.andThen String.toInt <| Task.Meta.assignmentGetExtra "marvinRank" instance
, dailySection = Task.Meta.assignmentGetExtra "marvinDailySection" instance
, bonusSection = Maybe.withDefault Essential <| Maybe.andThen (useDecoder essentialOrBonusDecoder) (Task.Meta.assignmentGetExtra "marvinEssentialOrBonus" instance)
, customSection = Task.Meta.assignmentGetExtra "marvinCustomSection" instance
, timeBlockSection = Task.Meta.assignmentGetExtra "marvinTimeBlockSection" instance
, note = Task.Meta.assignmentGetExtra "marvinNote" instance
, dueDate = toDate <| Task.Meta.assignmentGetExtra "marvinDueDate" instance
, timeEstimate = Just <| Task.Meta.assignmentEstimatedEffort instance
, isReward = Maybe.withDefault False <| Maybe.map toBool <| Task.Meta.assignmentGetExtra "marvinIsReward" instance
, isStarred = Maybe.withDefault 0 <| Maybe.andThen String.toInt <| Task.Meta.assignmentGetExtra "marvinIsStarred" instance
, isFrogged = Maybe.withDefault 0 <| Maybe.andThen String.toInt <| Task.Meta.assignmentGetExtra "marvinIsFrogged" instance
, plannedWeek = toDate <| Task.Meta.assignmentGetExtra "marvinPlannedWeek" instance
, done = Task.Project.assignmentCompleted instance
, day = toDate <| Task.Project.assignmentGetExtra "marvinDay" instance
, title = Task.Project.assignmentTitle instance
, parentId = Task.Project.assignmentGetExtra "marvinParentID" instance
, labelIds = Maybe.withDefault [] <| Maybe.map String.words <| Task.Project.assignmentGetExtra "marvinLabels" instance
, firstScheduled = toDate <| Task.Project.assignmentGetExtra "marvinFirstScheduled" instance
, rank = Maybe.withDefault 0 <| Maybe.andThen String.toInt <| Task.Project.assignmentGetExtra "marvinRank" instance
, dailySection = Task.Project.assignmentGetExtra "marvinDailySection" instance
, bonusSection = Maybe.withDefault Essential <| Maybe.andThen (useDecoder essentialOrBonusDecoder) (Task.Project.assignmentGetExtra "marvinEssentialOrBonus" instance)
, customSection = Task.Project.assignmentGetExtra "marvinCustomSection" instance
, timeBlockSection = Task.Project.assignmentGetExtra "marvinTimeBlockSection" instance
, note = Task.Project.assignmentGetExtra "marvinNote" instance
, dueDate = toDate <| Task.Project.assignmentGetExtra "marvinDueDate" instance
, timeEstimate = Just <| Task.Project.assignmentEstimatedEffort instance
, isReward = Maybe.withDefault False <| Maybe.map toBool <| Task.Project.assignmentGetExtra "marvinIsReward" instance
, isStarred = Maybe.withDefault 0 <| Maybe.andThen String.toInt <| Task.Project.assignmentGetExtra "marvinIsStarred" instance
, isFrogged = Maybe.withDefault 0 <| Maybe.andThen String.toInt <| Task.Project.assignmentGetExtra "marvinIsFrogged" instance
, plannedWeek = toDate <| Task.Project.assignmentGetExtra "marvinPlannedWeek" instance
, plannedMonth = Nothing -- TODO Maybe (Year, Month)
, rewardPoints = 0 -- TODO Float
, rewardId = Task.Meta.assignmentGetExtra "marvinRewardID" instance
, backburner = Maybe.withDefault False <| Maybe.map toBool <| Task.Meta.assignmentGetExtra "marvinBackburner" instance
, reviewDate = toDate <| Task.Meta.assignmentGetExtra "marvinReviewDate" instance
, itemSnoozeTime = Maybe.andThen (SmartTime.Human.Moment.fromStandardStringLoose >> Result.toMaybe) <| Task.Meta.assignmentGetExtra "marvinItemSnoozeTime" instance
, permaSnoozeTime = Maybe.andThen (SmartTime.Human.Clock.fromStandardString >> Result.toMaybe) <| Task.Meta.assignmentGetExtra "marvinPermaSnoozeTime" instance
, timeZoneOffset = Maybe.andThen String.toInt <| Task.Meta.assignmentGetExtra "marvinTimeZoneOffset" instance
, startDate = toDate <| Task.Meta.assignmentGetExtra "marvinStartDate" instance
, endDate = toDate <| Task.Meta.assignmentGetExtra "marvinEndDate" instance
, db = Maybe.withDefault "tasks" <| Task.Meta.assignmentGetExtra "marvinDb" instance
, times = parseTimesList <| Maybe.withDefault "[]" <| Task.Meta.assignmentGetExtra "marvinTimes" instance
, taskTime = Maybe.andThen (SmartTime.Human.Clock.fromStandardString >> Result.toMaybe) <| Task.Meta.assignmentGetExtra "marvinTaskTime" instance
, pinId = Task.Meta.assignmentGetExtra "marvinPinID" instance
, recurringTaskId = Task.Meta.assignmentGetExtra "recurringTaskID" instance
, masterRank = Maybe.withDefault 0 <| Maybe.andThen String.toFloat <| Task.Meta.assignmentGetExtra "marvinMasterRank" instance
, createdAt = Maybe.withDefault Moment.zero <| Maybe.andThen (SmartTime.Human.Moment.fromStandardStringLoose >> Result.toMaybe) <| Task.Meta.assignmentGetExtra "marvinCreatedAt" instance
, doneAt = Maybe.andThen (SmartTime.Human.Moment.fromStandardStringLoose >> Result.toMaybe) <| Task.Meta.assignmentGetExtra "marvinDoneAt" instance
, updatedAt = Maybe.andThen (SmartTime.Human.Moment.fromStandardStringLoose >> Result.toMaybe) <| Task.Meta.assignmentGetExtra "marvinUpdatedAt" instance
, fieldUpdates = Maybe.withDefault Dict.empty <| Maybe.andThen (useDecoder (Decode.dict decodeUnixTimestamp)) <| Task.Meta.assignmentGetExtra "marvinFieldUpdates" instance
, rewardId = Task.Project.assignmentGetExtra "marvinRewardID" instance
, backburner = Maybe.withDefault False <| Maybe.map toBool <| Task.Project.assignmentGetExtra "marvinBackburner" instance
, reviewDate = toDate <| Task.Project.assignmentGetExtra "marvinReviewDate" instance
, itemSnoozeTime = Maybe.andThen (SmartTime.Human.Moment.fromStandardStringLoose >> Result.toMaybe) <| Task.Project.assignmentGetExtra "marvinItemSnoozeTime" instance
, permaSnoozeTime = Maybe.andThen (SmartTime.Human.Clock.fromStandardString >> Result.toMaybe) <| Task.Project.assignmentGetExtra "marvinPermaSnoozeTime" instance
, timeZoneOffset = Maybe.andThen String.toInt <| Task.Project.assignmentGetExtra "marvinTimeZoneOffset" instance
, startDate = toDate <| Task.Project.assignmentGetExtra "marvinStartDate" instance
, endDate = toDate <| Task.Project.assignmentGetExtra "marvinEndDate" instance
, db = Maybe.withDefault "tasks" <| Task.Project.assignmentGetExtra "marvinDb" instance
, times = parseTimesList <| Maybe.withDefault "[]" <| Task.Project.assignmentGetExtra "marvinTimes" instance
, taskTime = Maybe.andThen (SmartTime.Human.Clock.fromStandardString >> Result.toMaybe) <| Task.Project.assignmentGetExtra "marvinTaskTime" instance
, pinId = Task.Project.assignmentGetExtra "marvinPinID" instance
, recurringTaskId = Task.Project.assignmentGetExtra "recurringTaskID" instance
, masterRank = Maybe.withDefault 0 <| Maybe.andThen String.toFloat <| Task.Project.assignmentGetExtra "marvinMasterRank" instance
, createdAt = Maybe.withDefault Moment.zero <| Maybe.andThen (SmartTime.Human.Moment.fromStandardStringLoose >> Result.toMaybe) <| Task.Project.assignmentGetExtra "marvinCreatedAt" instance
, doneAt = Maybe.andThen (SmartTime.Human.Moment.fromStandardStringLoose >> Result.toMaybe) <| Task.Project.assignmentGetExtra "marvinDoneAt" instance
, updatedAt = Maybe.andThen (SmartTime.Human.Moment.fromStandardStringLoose >> Result.toMaybe) <| Task.Project.assignmentGetExtra "marvinUpdatedAt" instance
, fieldUpdates = Maybe.withDefault Dict.empty <| Maybe.andThen (useDecoder (Decode.dict decodeUnixTimestamp)) <| Task.Project.assignmentGetExtra "marvinFieldUpdates" instance
}

_ ->
Expand Down
4 changes: 2 additions & 2 deletions elm/Integrations/Todoist.elm
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import SmartTime.Duration as Duration exposing (Duration)
import SmartTime.Human.Calendar as Calendar exposing (CalendarDate)
import SmartTime.Human.Duration as HumanDuration exposing (HumanDuration)
import SmartTime.Human.Moment as HumanMoment exposing (FuzzyMoment)
import Task.Assignable as Task exposing (AssignableSkel)
import Task.Assignment as Task exposing (AssignmentSkel)
import Task.AssignableSkel as Task exposing (AssignableSkel)
import Task.AssignmentSkel as Task exposing (AssignmentSkel)
import Task.Progress
import Url
import Url.Builder
Expand Down
2 changes: 1 addition & 1 deletion elm/Main.elm
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ import SmartTime.Human.Moment
import SmartTime.Moment as Moment
import SmartTime.Period as Period exposing (Period)
import Task as Job
import Task.Assignment as Assignment exposing (Assignment)
import Task.AssignmentSkel as Assignment exposing (Assignment)
import TaskList
import TaskPort
import TimeTracker
Expand Down
6 changes: 3 additions & 3 deletions elm/Plan/Plan.elm
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import List.Extra as List
import SmartTime.Duration exposing (Duration)
import SmartTime.Human.Duration exposing (HumanDuration(..), dur)
import SmartTime.Period exposing (Period)
import Task.Assignable as Class
import Task.Assignment as Instance exposing (Assignment)
import Task.Project as Entry
import Task.AssignableSkel as Class
import Task.AssignmentSkel as Instance exposing (Assignment)
import Task.ProjectSkel as Entry


{-| Current Idea: Go through list of To-Be-Planned in this order
Expand Down
Loading

0 comments on commit e3bd3e6

Please sign in to comment.