Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add repeat subtasks for repeating tasks #427 #2659

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

StartAGarden
Copy link

Description

The repeating tasks are updated so they include their sub-tasks.
Example Use Case: The user wants to add a task for a daily "Morning Routine" including several sub-tasks (steps of the routine), without having to re-add the sub-tasks every day.

There is no way to individually decide for certain sub tasks to be repeatable or not in this implementation. All sub tasks of a repeatable parent task are automatically repeatable, too.

Issues Resolved

#427

Check List

  • When a task is repeatable and a sub task is added, the sub task automatically gets repeatable, too
  • When a task with subtasks is made repeatable, all sub tasks are made repeatable, too
  • BUGFIX: fixed taskCfg not updating when repeatable task gets updated (tested my changing name of repeatable task and changing to next day -> was the old name)
  • only main repeatable tasks are shown in the "Scheduled" Tab, subs automatically get removed when the parent tasks repeatable gets removed

@StartAGarden StartAGarden changed the title Add repeat subtasks try2 feat: add repeat subtasks for repeating tasks #427 Jun 29, 2023
@StartAGarden
Copy link
Author

@johannesjo Looking forward to your review! I was struggling a lot with rxjs and observables, this project is probably perfect for getting better in using them... There are some questions in comments in there, maybe you can answer them? Also if there are structural things that are missing or that could be optimized please let me know, I would love to improve the code.

),
);

removeConfigIdFromTaskArchiveTasks$: any = createEffect(
() =>
this._actions$.pipe(
ofType(deleteTaskRepeatCfg),
tap(({ id }) => {
tap(async ({ id }) => {
const subTasks = await this._taskRepeatCfgService
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that this is necessary, since only parent tasks should have a repeat config linked to it, but not their sub tasks.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see comment below

return this._taskService.createNewTaskWithDefaults({
title: taskRepeatCfg.title,
additional: {
repeatCfgId: taskRepeatCfg.id,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just leave out the repeatCfgId part

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see comment below

this._actions$.pipe(
ofType(updateTask),
tap(async (aAction) => {
const allTasks = await this._taskService.allTasks$.pipe(first()).toPromise();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to directly use taskService.getByIdOnce$ here.

/**
* Updates the repeatCfg of a task, if the task was updated.
*/
updateRepeatCfgWhenTaskUpdates: any = createEffect(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this (honestly I am unsure :D)? Are there potential edge cases and problems that this might cause?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about edge cases, but without this you have no way of changing contents of a repeatable task as far as I was able to see.
What I did: I tried to change the title of a repeatable task, but since each day the new tasks are generated based on the repeatCfg (where the title was not updated), the old title would appear. So if I wanted to actually change the title, I would have to remove the repeat-cfg first, then change the title and then add the repeat-config back.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently you can change existing repeatable task instances by editing the repeatable config. If you edit the title there, the app asks you if you want to update all existing tasks. The idea behind it is, that you might want to have different notes and even tags for different instances. But I can see how it might be more intuitive to ditch this behavior and do it like this. Let's try it out!

* When adding a sub task, this function checks if the parent is a repeatable task and therefore the sub-task also has to be.
* If that is the case, a repeat-cfg gets added for each subtask, too.
*/
addTaskRepeatCfgForSubTask: any = createEffect(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imho subtasks should not be repeatable tasks, but just subtasks of a task with a repeatable config.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since finished tasks get deleted (at least that's what it seemed like when I tried to observe how the app works?) and I am not confident enough at this point to try and change things on such a fundamental level, I based this approach on the fact that repeatCfgs are persisted and can be used to store the information of the sub tasks. I basically mirrored that structure with the repeatCfs:

All Tasks (sub + parent) are stored as tasks (all together) in the store (only difference is if they have subtask-ids or a parent-Id or not)
All repeatCfgs (sub + parent) are stored as repeatCfs (all together) in the store (only difference is that they have a parent id or not)

Since all information of a repeatable task gets generated from a repeatable config, I only see 2 ways of storing the information for the sub tasks:

  • storing all information about all subtasks in the parent repeat config (which would go against the structure that is currently implemented for normal tasks and therefore would feel like bad practise to me, but that might just be my view)
  • storing the information about sub tasks as a subtask-repeatable-config

Definitely let me know if I missed something.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Afaics subtasks don't need to "know" that they are a child task of a repeatable task and I also think different parent repeatable tasks should be allowed to have different sub tasks. To solve this I would not reference "real" sub tasks but rather provide a simple input that allows to create a list of sub tasks with no more information than maybe the title.

Using real "subtasks" as reference point creates all sorts of messy problems, when moving them around or deleting them or their parent.

@johannesjo
Copy link
Owner

Thank you very much! The code looks very clean! Much appreciated!

I am a bit pressed for time, so I wasn't able to provide a complete feedback yet. Sending the incomplete feedback anyway since I am not sure I will find more time before next Friday.

@StartAGarden
Copy link
Author

StartAGarden commented Jul 1, 2023

Thank you very much! The code looks very clean! Much appreciated!

I am a bit pressed for time, so I wasn't able to provide a complete feedback yet. Sending the incomplete feedback anyway since I am not sure I will find more time before next Friday.

No problem, just take your time! I added my thoughts to your comments already so you can have a better insight into my thought progress for the review.

@johannesjo
Copy link
Owner

johannesjo commented Jul 7, 2023

I think I understand now my main misunderstanding :D

The current approach for repeatable tasks is to take the repeatCfg as template to create new instances. Existing instances are not touched unless the the repeatCfg is updated by using the dedicated dialog for it. This allows an instance to be used relatively independent from others, e.g. I could create different sub tasks or notes every time.

The changes you are providing take a different approach by making changes to a task directly change the repeatCfg and by making changes to sub tasks also reflect on new instances. This might be more intuitive to new users (and thus ultimately desirable, but
I am not a 100% sure yet), but possibly confusing to existing ones. I am also a bit afraid that it might lead to non trivial problems further down the road, e.g. when moving sub tasks to other parent tasks, deleting them and also when dealing with archive tasks.

So I think I might have to test this a bit more to understand all the implications of this changes. Or alternatively we can go with the "simpler" change that I proposed in the comment above and stick with the current approach of doing things. What do you think?

@GadiZimerman
Copy link

@CodiumAI-Agent /review

@CodiumAI-Agent
Copy link

PR Analysis

  • 🎯 Main theme: Adding repeat subtasks for repeating tasks
  • 📌 Type of PR: Enhancement
  • 🧪 Relevant tests added: No
  • Focused PR: Yes, the PR is focused on adding repeat subtasks for repeating tasks. All changes are related to this functionality.
  • 🔒 Security concerns: No, the PR does not introduce possible security concerns or issues like SQL injection, XSS, CSRF, and others.

PR Feedback

  • 💡 General PR suggestions: The PR introduces a new feature of repeating subtasks for repeating tasks which is a valuable addition. However, it lacks tests to ensure the new functionality works as expected. It's recommended to add relevant unit tests. Also, there are several 'TODO' comments in the code which should be addressed or removed to avoid confusion in the future.

How to use

Tag me in a comment '@CodiumAI-Agent' and add one of the following commands:
/review - Request a review of the latest update to the PR.
/describe - Modify the PR title and description based on the contents of the PR.
/improve - Suggest improvements to the code in the PR. These will be provided as pull request comments, ready to commit.
/ask - Pose a question about the PR.


// we only want to continue if the task doesn't already have a repeatCfgId
if (task.repeatCfgId === null) {
console.log('A TASKKK', task);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing the console.log statements as they are generally not recommended for production code. They can expose sensitive information and clutter the console output. [important]

}
}),
),
{ dispatch: false }, // Question: What exactly does this do?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'dispatch: false' in the createEffect function means that the effect will not dispatch any new actions. If you want to dispatch new actions from within the effect, you should remove this option or set it to true. [medium]

() =>
this._actions$.pipe(
ofType(updateTask),
tap(async (aAction) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'await' inside the 'tap' operator may lead to unexpected behavior. It's better to use 'mergeMap' or 'concatMap' to handle asynchronous operations in an Observable chain. [important]

@StartAGarden
Copy link
Author

I think I understand now my main misunderstanding :D

The current approach for repeatable tasks is to take the repeatCfg as template to create new instances. Existing instances are not touched unless the the repeatCfg is updated by using the dedicated dialog for it. This allows an instance to be used relatively independent from others, e.g. I could create different sub tasks or notes every time.

The changes you are providing take a different approach by making changes to a task directly change the repeatCfg and by making changes to sub tasks also reflect on new instances. This might be more intuitive to new users (and thus ultimately desirable, but I am not a 100% sure yet), but possibly confusing to existing ones. I am also a bit afraid that it might lead to non trivial problems further down the road, e.g. when moving sub tasks to other parent tasks, deleting them and also when dealing with archive tasks.

So I think I might have to test this a bit more to understand all the implications of this changes. Or alternatively we can go with the "simpler" change that I proposed in the comment above and stick with the current approach of doing things. What do you think?

First of all: Sorry for the late answer! Once I have a quiet minute I will definitely look into your suggested simpler version, as I generally agree with trying to avoid possible problems or confusion. I am just really pressed for time these days so I am not quite sure when I will be able to pick it up again, but I hope to find time soon and I will contact you again, if I have further questions :)

@Olmo-Gutierrez
Copy link

How is this doing?

@StartAGarden
Copy link
Author

How is this doing?

Since there has been a lot of things happening for me, I don't have time at all to work on this. If anyone wants to pick this up, feel free. If not I hope to maybe get to it at the end of the year, but currently I don't have any capacity to work on it.... :(

@johannesjo
Copy link
Owner

@StartAGarden no worries! Thank you very much for your effort!

Any volunteers to pick this up?

@Jagdfalke
Copy link
Collaborator

Hi @StartAGarden, how are you doing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants