thombruce / toodles

✅ A super simple todo app
https://toodles.thombruce.com/
GNU General Public License v3.0
0 stars 0 forks source link

Schedule #124

Closed thombruce closed 1 month ago

thombruce commented 1 month ago

Moves schedule logic out of Todo scope and into own module.

If applicable, we may migrate this code to TNT Core.

By submitting this pull request, you agree to follow our Code of Conduct: https://github.com/thombruce/.github/blob/main/CODE_OF_CONDUCT.md


Internal use. Do not delete.

netlify[bot] commented 1 month ago

Deploy Preview for toodles canceled.

Name Link
Latest commit d0d07f514f418ec9bcf6ddcf5d39da668a2da7ad
Latest deploy log https://app.netlify.com/sites/toodles/deploys/66bc1feaa5b001000895cab9
github-actions[bot] commented 1 month ago

Coverage Summary for `./packages/web`

Status Category Percentage Covered / Total
🟢 Lines 69.71% / 60% 435 / 624
🟢 Statements 69.71% / 60% 435 / 624
🟢 Functions 65.85% / 60% 27 / 41
🟢 Branches 72.05% / 60% 49 / 68
File Coverage
File Stmts % Branch % Funcs % Lines Uncovered Lines
packages/web/src/components/ContextTag.vue 20% 100% 0% 20% 4-15
packages/web/src/components/HashTag.vue 20% 100% 0% 20% 4-15
packages/web/src/components/ProgressBar.vue 70.17% 66.66% 100% 70.17% 16-23, 26-34
packages/web/src/components/ProjectTag.vue 20% 100% 0% 20% 4-15
packages/web/src/components/TagTag.vue 71.42% 100% 0% 71.42% 6-7
packages/web/src/components/TodoItem.vue 80.7% 40% 28.57% 80.7% 21, 26-27, 33-40
packages/web/src/components/TodoList.vue 73.68% 100% 100% 73.68% 11-15
packages/web/src/components/TodoPriority.vue 20% 100% 0% 20% 4-15
packages/web/src/components/TodoText.vue 68.08% 60% 85.71% 68.08% 15-18, 21-25, 34-36, 40-42
packages/web/src/models/Todo.ts 89.65% 76.92% 100% 89.65% 35-41, 55-56
packages/web/src/plugins/dexie.ts 62.82% 80% 66.66% 62.82% 46-54, 59-78
packages/web/src/plugins/lunr.ts 100% 100% 100% 100%
packages/web/src/plugins/timepiece.ts 71.42% 60% 50% 71.42% 14-19
packages/web/src/stores/todos.ts 73.44% 100% 83.33% 73.44% 23, 27, 31-33, 37-39, 43-45, 49-51, 55-57, 61-63, 67-69, 73-75, 79-81, 85-87, 91-93, 97-99, 109-117
thombruce commented 1 month ago

The code has been heavily refactored on the fly as part of the transition. I've tested some of the behaviours and have some confidence it's all working, but I haven't fully reviewed my efforts yet.

Notably, all if else weekday testers have been replaces with a single line:

else if (days = str.match(/((?:mon|tues|wednes|thurs|fri|satur|sun)day)/gi)) return Schedule.days(days.map(d => dayToWeekday(d)))

I wasn't completely happy that that regex had to abandon start and end of string anchors (^$) but I was struggling to get the expected behaviour out of it while they were present. This will now match any weekday, if one is present, anywhere in the every string. That... should be fine, honestly. There is currently no other reason to include weekdays by name except for this case.

dayToWeekday() is a custom function that matches the weekday string to its equivalent RRule designation:

function dayToWeekday(day) {
  if (/^monday$/i.test(day)) return RRule.MO
  else if (/^tuesday$/i.test(day)) return RRule.TU
  else if (/^wednesday$/i.test(day)) return RRule.WE
  else if (/^thursday$/i.test(day)) return RRule.TH
  else if (/^friday$/i.test(day)) return RRule.FR
  else if (/^saturday$/i.test(day)) return RRule.SA
  else if (/^sunday$/i.test(day)) return RRule.SU
}

One obvious revision might be to permit partial day strings to reflect common weekday abbreviations:

An example regex for Thursdays: /thu?r?s?(?:day)?/ <- _Though, that would also matchthrdayandthsday. Any chance we can be more robust? Ensure that each previous character does actually exist? Maybe like..._ ->/(?:th|thu|thur|thurs|thursday)/` This becomes very verbose when we add all the other weekdays. Something to work on, not urgently.

thombruce commented 1 month ago

If we do start matching abbreviations in our weekday match, then when it comes to pairing that with its RRule counterpart we can actually discard most of the string. We only need the first two characters:

function dayToWeekday(day) {
  if (/^mo/i.test(day)) return RRule.MO
  else if (/^tu/i.test(day)) return RRule.TU
  else if (/^we/i.test(day)) return RRule.WE
  else if (/^th/i.test(day)) return RRule.TH
  else if (/^fr/i.test(day)) return RRule.FR
  else if (/^sa/i.test(day)) return RRule.SA
  else if (/^su/i.test(day)) return RRule.SU
}

We should probably still use regexes so that we can maintain case insensitivity. There is another way where we cast the string to a lowercase string and check whether it startsWith but my focus is on keeping this code as lean as possible. I don't actually know what method would perform best, but performance can be a later concern.

thombruce commented 1 month ago

So how's this?

else if (days = str.match(/((?:mon?|tue?s?|wed?(?:nes)?|thu?r?s?|fri?|sat(?:ur)?|sun?)(?:day)?)/gi)) return Schedule.days(days.map(d => dayToWeekday(d)))

It's gonna have some false positives, for sure. Malformed weekday strings, like thrday, are going to be matched... but that's actually not a huge problem, right? Our main concern are those first two characters - so long as those are correct, it doesn't matter!

Ah, no! There is a genuine issue with this...

Since I've made a lot of parts optional and we don't have anchors in this regex, it's going to match partial values anywhere in the string like... "mo"... which will match "monthly" <- That's a false positive we do care about!