mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-22 15:37:02 +00:00
feat: move task stuff to save to db effects
This commit is contained in:
parent
d0f3bbbd56
commit
085d7eeff6
4 changed files with 105 additions and 197 deletions
|
|
@ -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<any>>(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 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<K extends keyof typeof this._pfapiService.m>(
|
||||
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<K extends keyof typeof this._pfapiService.m>(
|
||||
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 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue