diff --git a/src/app/features/tasks/store/task-db.effects.ts b/src/app/features/tasks/store/task-db.effects.ts deleted file mode 100644 index 81eae5666e..0000000000 --- a/src/app/features/tasks/store/task-db.effects.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { inject, Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { - __updateMultipleTaskSimple, - addReminderIdToTask, - addSubTask, - addTask, - convertToMainTask, - deleteTask, - deleteTasks, - moveSubTask, - moveSubTaskDown, - moveSubTaskToBottom, - moveSubTaskToTop, - moveSubTaskUp, - moveToArchive_, - moveToOtherProject, - removeReminderFromTask, - removeTagsForAllTasks, - removeTimeSpent, - reScheduleTaskWithTime, - restoreTask, - roundTimeSpentForDay, - scheduleTaskWithTime, - toggleTaskHideSubTasks, - undoDeleteTask, - unScheduleTask, - updateTask, - updateTaskTags, - updateTaskUi, -} from './task.actions'; -import { select, Store } from '@ngrx/store'; -import { auditTime, first, switchMap, tap, withLatestFrom } from 'rxjs/operators'; -import { selectTaskFeatureState } from './task.selectors'; -import { TaskState } from '../task.model'; -import { environment } from '../../../../environments/environment'; -import { addTaskRepeatCfgToTask } from '../../task-repeat-cfg/store/task-repeat-cfg.actions'; -import { - addTaskAttachment, - deleteTaskAttachment, - updateTaskAttachment, -} from '../task-attachment/task-attachment.actions'; -import { PlannerActions } from '../../planner/store/planner.actions'; -import { deleteProject } from '../../project/store/project.actions'; -import { PfapiService } from '../../../pfapi/pfapi.service'; -import { TimeTrackingActions } from '../../time-tracking/store/time-tracking.actions'; -import { TIME_TRACKING_TO_DB_INTERVAL } from '../../../app.constants'; -import { planTasksForToday } from '../../tag/store/tag.actions'; - -@Injectable() -export class TaskDbEffects { - private _actions$ = inject(Actions); - private _store$ = inject>(Store); - private _pfapiService = inject(PfapiService); - - updateTaskAuditTime$: any = createEffect( - () => - this._actions$.pipe( - ofType( - // TIME TRACKING - TimeTrackingActions.addTimeSpent, - ), - auditTime(TIME_TRACKING_TO_DB_INTERVAL), - switchMap(() => this._store$.pipe(select(selectTaskFeatureState), first())), - tap((taskState) => this._saveToLs(taskState, true)), - ), - { dispatch: false }, - ); - - updateTask$: any = createEffect( - () => - this._actions$.pipe( - ofType( - addTask, - restoreTask, - deleteTask, - deleteTasks, - undoDeleteTask, - addSubTask, - convertToMainTask, - removeTimeSpent, - // setCurrentTask, - // unsetCurrentTask, - // toggleStart, - - updateTask, - __updateMultipleTaskSimple, - updateTaskTags, - removeTagsForAllTasks, - moveSubTask, - moveSubTaskUp, - moveSubTaskDown, - moveSubTaskToTop, - moveSubTaskToBottom, - moveToArchive_, - moveToOtherProject, - roundTimeSpentForDay, - - // REMINDER - addReminderIdToTask, - scheduleTaskWithTime, - reScheduleTaskWithTime, - unScheduleTask, - removeReminderFromTask, - - // ATTACHMENT ACTIONS - addTaskAttachment, - deleteTaskAttachment, - updateTaskAttachment, - - // RELATED ACTIONS - addTaskRepeatCfgToTask, - - // PLANNER - PlannerActions.transferTask, - PlannerActions.moveBeforeTask, - PlannerActions.planTaskForDay, - planTasksForToday, - - // PROJECT - deleteProject, - ), - withLatestFrom(this._store$.pipe(select(selectTaskFeatureState))), - tap(([, taskState]) => this._saveToLs(taskState, true)), - ), - { dispatch: false }, - ); - - updateTaskUi$: any = createEffect( - () => - this._actions$.pipe( - ofType(updateTaskUi, toggleTaskHideSubTasks), - withLatestFrom(this._store$.pipe(select(selectTaskFeatureState))), - tap(([, taskState]) => this._saveToLs(taskState)), - ), - { dispatch: false }, - ); - - // @debounce(50) - private _saveToLs( - taskState: TaskState, - isUpdateRevAndLastUpdate: boolean = false, - ): void { - this._pfapiService.m.task.save( - { - ...taskState, - - // make sure those are never set to something - selectedTaskId: environment.production ? null : taskState.selectedTaskId, - currentTaskId: null, - }, - { isUpdateRevAndLastUpdate }, - ); - } -} diff --git a/src/app/features/time-tracking/store/time-tracking.reducer.ts b/src/app/features/time-tracking/store/time-tracking.reducer.ts index 454af886c5..5a2bde749d 100644 --- a/src/app/features/time-tracking/store/time-tracking.reducer.ts +++ b/src/app/features/time-tracking/store/time-tracking.reducer.ts @@ -27,20 +27,6 @@ export const timeTrackingReducer = createReducer( on(TimeTrackingActions.addTimeSpent, (state, { task, date }) => { const isUpdateProject = !!task.projectId; - console.log({ - ...state.tag, - ...([TODAY_TAG.id, ...task.tagIds] as string[]).reduce((acc, tagId) => { - acc[tagId] = { - ...state.tag[tagId], - [date]: { - ...state.tag[tagId]?.[date], - e: roundTsToMinutes(Date.now()), - s: roundTsToMinutes(state.tag[tagId]?.[date]?.s || Date.now()), - }, - }; - return acc; - }, {}), - }); return { ...state, diff --git a/src/app/root-store/feature-stores.module.ts b/src/app/root-store/feature-stores.module.ts index ce0f0a4f91..adf5fe4951 100644 --- a/src/app/root-store/feature-stores.module.ts +++ b/src/app/root-store/feature-stores.module.ts @@ -62,7 +62,6 @@ import { import { TaskRepeatCfgEffects } from '../features/task-repeat-cfg/store/task-repeat-cfg.effects'; import { TaskDueEffects } from '../features/tasks/store/task-due.effects'; import { TASK_FEATURE_NAME, taskReducer } from '../features/tasks/store/task.reducer'; -import { TaskDbEffects } from '../features/tasks/store/task-db.effects'; import { TaskInternalEffects } from '../features/tasks/store/task-internal.effects'; import { TaskRelatedModelEffects } from '../features/tasks/store/task-related-model.effects'; import { TaskReminderEffects } from '../features/tasks/store/task-reminder.effects'; @@ -150,7 +149,6 @@ import { SaveToDbEffects } from './shared/save-to-db.effects'; StoreModule.forFeature(TASK_FEATURE_NAME, taskReducer), EffectsModule.forFeature([ - TaskDbEffects, TaskInternalEffects, TaskRelatedModelEffects, TaskReminderEffects, diff --git a/src/app/root-store/shared/save-to-db.effects.ts b/src/app/root-store/shared/save-to-db.effects.ts index 1f17ff96b3..8e3c12b98f 100644 --- a/src/app/root-store/shared/save-to-db.effects.ts +++ b/src/app/root-store/shared/save-to-db.effects.ts @@ -1,7 +1,7 @@ import { inject, Injectable } from '@angular/core'; -import { Actions, createEffect } from '@ngrx/effects'; -import { skip, switchMap } from 'rxjs/operators'; -import { MemoizedSelector, Store } from '@ngrx/store'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { auditTime, filter, first, map, skip, switchMap, tap } from 'rxjs/operators'; +import { MemoizedSelector, select, Store } from '@ngrx/store'; import { PfapiService } from '../../pfapi/pfapi.service'; import { selectBoardsState } from '../../features/boards/store/boards.selectors'; import { selectConfigFeatureState } from '../../features/config/store/global-config.reducer'; @@ -17,10 +17,17 @@ import { selectTaskRepeatCfgFeatureState } from '../../features/task-repeat-cfg/ import { selectMetricFeatureState } from '../../features/metric/store/metric.selectors'; import { DataInitStateService } from '../../core/data-init/data-init-state.service'; import { RootState } from '../root-state'; - -// NOTE task state is a bit special, since we have ui only actions and we throttle addTimeSpent -// NOTE TimeTrackingState is also a bit special, since we throttle addTimeSpent -// NOTE: reminders are saved in reminderService +import { selectTaskFeatureState } from '../../features/tasks/store/task.selectors'; +import { TimeTrackingActions } from '../../features/time-tracking/store/time-tracking.actions'; +import { + setCurrentTask, + toggleStart, + toggleTaskHideSubTasks, + unsetCurrentTask, + updateTaskUi, +} from '../../features/tasks/store/task.actions'; +import { TIME_TRACKING_TO_DB_INTERVAL } from '../../app.constants'; +import { environment } from '../../../environments/environment'; @Injectable() export class SaveToDbEffects { @@ -29,7 +36,64 @@ export class SaveToDbEffects { private _pfapiService = inject(PfapiService); private _dataInitStateService = inject(DataInitStateService); - // Infer the correct type for each modelKey from PfapiService['m'] + // -------------------------------------------------- + // NOTE TimeTrackingState is also a bit special, since we throttle addTimeSpent => TimeTrackingEffects + // NOTE: reminders are saved in reminderService => ReminderService + // -------------------------------------------------- + + tag$ = this.createSaveEffect(selectTagFeatureState, 'tag'); + project$ = this.createSaveEffect(selectProjectFeatureState, 'project'); + globalCfg$ = this.createSaveEffect(selectConfigFeatureState, 'globalConfig'); + planner$ = this.createSaveEffect(selectPlannerState, 'planner'); + boards$ = this.createSaveEffect(selectBoardsState, 'boards'); + issueProvider$ = this.createSaveEffect(selectIssueProviderState, 'issueProvider'); + note$ = this.createSaveEffect(selectNoteFeatureState, 'note'); + metric$ = this.createSaveEffect(selectMetricFeatureState, 'metric'); + improvement$ = this.createSaveEffect(selectImprovementFeatureState, 'improvement'); + obstruction$ = this.createSaveEffect(selectObstructionFeatureState, 'obstruction'); + simpleCounter$ = this.createSaveEffect( + selectSimpleCounterFeatureState, + 'simpleCounter', + ); + taskRepeatCfg$ = this.createSaveEffect( + selectTaskRepeatCfgFeatureState, + 'taskRepeatCfg', + ); + + task$ = this.createSaveEffectWithFilter(selectTaskFeatureState, 'task', [ + TimeTrackingActions.addTimeSpent.type, + setCurrentTask.type, + updateTaskUi.type, + toggleTaskHideSubTasks.type, + unsetCurrentTask.type, + toggleStart.type, + ]); + + updateTaskAuditTime$ = createEffect( + () => + this._actions.pipe( + ofType( + // TIME TRACKING + TimeTrackingActions.addTimeSpent, + ), + auditTime(TIME_TRACKING_TO_DB_INTERVAL), + switchMap(() => this._store.pipe(select(selectTaskFeatureState), first())), + tap((taskState) => { + this._pfapiService.m.task.save( + { + ...taskState, + + // make sure those are never set to something + selectedTaskId: environment.production ? null : taskState.selectedTaskId, + currentTaskId: null, + }, + { isUpdateRevAndLastUpdate: true }, + ); + }), + ), + { dispatch: false }, + ); + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type private createSaveEffect( selector: MemoizedSelector< @@ -53,22 +117,37 @@ export class SaveToDbEffects { ); } - tag$ = this.createSaveEffect(selectTagFeatureState, 'tag'); - project$ = this.createSaveEffect(selectProjectFeatureState, 'project'); - globalCfg$ = this.createSaveEffect(selectConfigFeatureState, 'globalConfig'); - planner$ = this.createSaveEffect(selectPlannerState, 'planner'); - boards$ = this.createSaveEffect(selectBoardsState, 'boards'); - issueProvider$ = this.createSaveEffect(selectIssueProviderState, 'issueProvider'); - note$ = this.createSaveEffect(selectNoteFeatureState, 'note'); - metric$ = this.createSaveEffect(selectMetricFeatureState, 'metric'); - improvement$ = this.createSaveEffect(selectImprovementFeatureState, 'improvement'); - obstruction$ = this.createSaveEffect(selectObstructionFeatureState, 'obstruction'); - simpleCounter$ = this.createSaveEffect( - selectSimpleCounterFeatureState, - 'simpleCounter', - ); - taskRepeatCfg$ = this.createSaveEffect( - selectTaskRepeatCfgFeatureState, - 'taskRepeatCfg', - ); + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + private createSaveEffectWithFilter( + selector: MemoizedSelector< + RootState, + Parameters<(typeof this._pfapiService.m)[K]['save']>[0] + >, + modelKey: K, + ignoredActionsTypes: string[], + ) { + return createEffect( + () => + this._dataInitStateService.isAllDataLoadedInitially$.pipe( + switchMap(() => this._store.select(selector)), + skip(1), + switchMap((state) => + // thankfully the next action after is the action that triggered the change + this._actions.pipe( + first(), + map((a) => [state, a]), + ), + ), + tap(([state, action]) => console.log('1', action.type)), + filter(([state, action]) => !ignoredActionsTypes.includes(action.type)), + tap(([state, action]) => console.log('22', action.type)), + switchMap(([state]) => + this._pfapiService.m[modelKey].save(state, { + isUpdateRevAndLastUpdate: true, + }), + ), + ), + { dispatch: false }, + ); + } }