mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-22 15:37:02 +00:00
feat(dueDate): make day changes work as expected
This commit is contained in:
parent
a1c4d527d2
commit
fa93e83a91
10 changed files with 143 additions and 18 deletions
|
|
@ -13,12 +13,12 @@ import { TODAY_TAG } from '../../tag/tag.const';
|
|||
import { IssueProvider } from '../../issue/issue.model';
|
||||
import { Project } from '../../project/project.model';
|
||||
import { selectAllProjects } from '../../project/store/project.selectors';
|
||||
import { getWorklogStr } from '../../../util/get-work-log-str';
|
||||
import {
|
||||
selectTagFeatureState,
|
||||
selectTodayTagTaskIds,
|
||||
} from '../../tag/store/tag.reducer';
|
||||
import { isToday } from '../../../util/is-today.util';
|
||||
import { selectTodayStr } from '../../../root-store/app-state/app-state.selectors';
|
||||
|
||||
const mapSubTasksToTasks = (tasksIN: any[]): TaskWithSubTasks[] => {
|
||||
return tasksIN
|
||||
|
|
@ -117,18 +117,22 @@ export const selectStartableTasks = createSelector(
|
|||
},
|
||||
);
|
||||
|
||||
export const selectOverdueTasks = createSelector(selectTaskFeatureState, (s): Task[] => {
|
||||
const today = new Date(getWorklogStr());
|
||||
const todayStart = new Date(today);
|
||||
todayStart.setHours(0, 0, 0, 0);
|
||||
return s.ids
|
||||
.map((id) => s.entities[id] as Task)
|
||||
.filter(
|
||||
(task) =>
|
||||
(task.dueDay && new Date(task.dueDay) < today) ||
|
||||
(task.dueWithTime && task.dueWithTime < todayStart.getTime()),
|
||||
);
|
||||
});
|
||||
export const selectOverdueTasks = createSelector(
|
||||
selectTaskFeatureState,
|
||||
selectTodayStr,
|
||||
(s, todayStr): Task[] => {
|
||||
const today = new Date(todayStr);
|
||||
const todayStart = new Date(today);
|
||||
todayStart.setHours(0, 0, 0, 0);
|
||||
return s.ids
|
||||
.map((id) => s.entities[id] as Task)
|
||||
.filter(
|
||||
(task) =>
|
||||
(task.dueDay && new Date(task.dueDay) < today) ||
|
||||
(task.dueWithTime && task.dueWithTime < todayStart.getTime()),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export const selectOverdueTasksOnToday = createSelector(
|
||||
selectOverdueTasks,
|
||||
|
|
@ -180,8 +184,9 @@ export const selectOverdueTasksWithSubTasks = createSelector(
|
|||
export const selectAllTasksDueAndOverdue = createSelector(
|
||||
selectTaskFeatureState,
|
||||
selectTagFeatureState,
|
||||
(s, tagState): Task[] => {
|
||||
const today = new Date(getWorklogStr());
|
||||
selectTodayStr,
|
||||
(s, tagState, todayStr): Task[] => {
|
||||
const today = new Date(todayStr);
|
||||
return s.ids
|
||||
.map((id) => s.entities[id] as Task)
|
||||
.filter(
|
||||
|
|
@ -462,9 +467,8 @@ export const selectAllTasksWithDueDay = createSelector(
|
|||
|
||||
export const selectAllTasksDueToday = createSelector(
|
||||
selectTaskFeatureState,
|
||||
(taskState): (TaskWithDueTime | TaskWithDueDay)[] => {
|
||||
const todayStr = getWorklogStr();
|
||||
|
||||
selectTodayStr,
|
||||
(taskState, todayStr): (TaskWithDueTime | TaskWithDueDay)[] => {
|
||||
const allDueDayTasks = Object.values(taskState.entities).filter(
|
||||
(task) => !!task && !!(task as TaskWithDueTime).dueDay && todayStr === task.dueDay,
|
||||
) as TaskWithDueDay[];
|
||||
|
|
|
|||
9
src/app/root-store/app-state/app-state.actions.ts
Normal file
9
src/app/root-store/app-state/app-state.actions.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { createActionGroup, props } from '@ngrx/store';
|
||||
|
||||
export const AppStateActions = createActionGroup({
|
||||
source: 'AppState',
|
||||
events: {
|
||||
'Set Today String': props<{ todayStr: string }>(),
|
||||
},
|
||||
});
|
||||
25
src/app/root-store/app-state/app-state.effects.spec.ts
Normal file
25
src/app/root-store/app-state/app-state.effects.spec.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// import { TestBed } from '@angular/core/testing';
|
||||
// import { provideMockActions } from '@ngrx/effects/testing';
|
||||
// import { Observable } from 'rxjs';
|
||||
//
|
||||
// import { AppStateEffects } from './app-state.effects';
|
||||
//
|
||||
// describe('AppStateEffects', () => {
|
||||
// let actions$: Observable<any>;
|
||||
// let effects: AppStateEffects;
|
||||
//
|
||||
// beforeEach(() => {
|
||||
// TestBed.configureTestingModule({
|
||||
// providers: [
|
||||
// AppStateEffects,
|
||||
// provideMockActions(() => actions$)
|
||||
// ]
|
||||
// });
|
||||
//
|
||||
// effects = TestBed.inject(AppStateEffects);
|
||||
// });
|
||||
//
|
||||
// it('should be created', () => {
|
||||
// expect(effects).toBeTruthy();
|
||||
// });
|
||||
// });
|
||||
18
src/app/root-store/app-state/app-state.effects.ts
Normal file
18
src/app/root-store/app-state/app-state.effects.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { inject, Injectable } from '@angular/core';
|
||||
import { createEffect } from '@ngrx/effects';
|
||||
|
||||
import { map, skip } from 'rxjs/operators';
|
||||
import { AppStateActions } from './app-state.actions';
|
||||
import { GlobalTrackingIntervalService } from '../../core/global-tracking-interval/global-tracking-interval.service';
|
||||
|
||||
@Injectable()
|
||||
export class AppStateEffects {
|
||||
private _globalTimeTrackingIntervalService = inject(GlobalTrackingIntervalService);
|
||||
|
||||
setTodayStr$ = createEffect(() => {
|
||||
return this._globalTimeTrackingIntervalService.todayDateStr$.pipe(
|
||||
skip(1), // skip first since it should be already the default value
|
||||
map((todayStr) => AppStateActions.setTodayString({ todayStr })),
|
||||
);
|
||||
});
|
||||
}
|
||||
13
src/app/root-store/app-state/app-state.reducer.spec.ts
Normal file
13
src/app/root-store/app-state/app-state.reducer.spec.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// import { reducer, initialState } from './app-state.reducer';
|
||||
//
|
||||
// describe('AppState Reducer', () => {
|
||||
// describe('an unknown action', () => {
|
||||
// it('should return the previous state', () => {
|
||||
// const action = {} as any;
|
||||
//
|
||||
// const result = reducer(initialState, action);
|
||||
//
|
||||
// expect(result).toBe(initialState);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
26
src/app/root-store/app-state/app-state.reducer.ts
Normal file
26
src/app/root-store/app-state/app-state.reducer.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { createFeature, createReducer, on } from '@ngrx/store';
|
||||
import { AppStateActions } from './app-state.actions';
|
||||
import { getWorklogStr } from '../../util/get-work-log-str';
|
||||
|
||||
export const appStateFeatureKey = 'appState';
|
||||
|
||||
export interface AppState {
|
||||
todayStr: string;
|
||||
}
|
||||
|
||||
export const appStateInitialState: AppState = {
|
||||
todayStr: getWorklogStr(),
|
||||
};
|
||||
|
||||
export const appStateReducer = createReducer(
|
||||
appStateInitialState,
|
||||
on(AppStateActions.setTodayString, (state, { todayStr }) => ({
|
||||
...state,
|
||||
todayStr,
|
||||
})),
|
||||
);
|
||||
|
||||
export const appStateFeature = createFeature({
|
||||
name: appStateFeatureKey,
|
||||
reducer: appStateReducer,
|
||||
});
|
||||
12
src/app/root-store/app-state/app-state.selectors.spec.ts
Normal file
12
src/app/root-store/app-state/app-state.selectors.spec.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// import * as fromAppState from './app-state.reducer';
|
||||
// import { selectAppStateState } from './app-state.selectors';
|
||||
//
|
||||
// describe('AppState Selectors', () => {
|
||||
// it('should select the feature state', () => {
|
||||
// const result = selectAppStateState({
|
||||
// [fromAppState.appStateFeatureKey]: {}
|
||||
// });
|
||||
//
|
||||
// expect(result).toEqual({});
|
||||
// });
|
||||
// });
|
||||
11
src/app/root-store/app-state/app-state.selectors.ts
Normal file
11
src/app/root-store/app-state/app-state.selectors.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { createFeatureSelector, createSelector } from '@ngrx/store';
|
||||
import * as fromAppState from './app-state.reducer';
|
||||
|
||||
export const selectAppStateState = createFeatureSelector<fromAppState.AppState>(
|
||||
fromAppState.appStateFeatureKey,
|
||||
);
|
||||
|
||||
export const selectTodayStr = createSelector(
|
||||
selectAppStateState,
|
||||
(state: fromAppState.AppState) => state.todayStr,
|
||||
);
|
||||
|
|
@ -94,10 +94,15 @@ import { timeTrackingFeature } from '../features/time-tracking/store/time-tracki
|
|||
import { TimeTrackingEffects } from '../features/time-tracking/store/time-tracking.effects';
|
||||
import { plannerFeature } from '../features/planner/store/planner.reducer';
|
||||
import { PlannerEffects } from '../features/planner/store/planner.effects';
|
||||
import { AppStateEffects } from './app-state/app-state.effects';
|
||||
import { appStateFeature } from './app-state/app-state.reducer';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
StoreModule.forFeature(appStateFeature),
|
||||
EffectsModule.forFeature([AppStateEffects]),
|
||||
|
||||
StoreModule.forFeature(LAYOUT_FEATURE_NAME, layoutReducer),
|
||||
EffectsModule.forFeature([LayoutEffects]),
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
} from '../features/boards/store/boards.reducer';
|
||||
import * as fromPlanner from '../features/planner/store/planner.reducer';
|
||||
import { PlannerState } from '../features/planner/store/planner.reducer';
|
||||
import { AppState, appStateFeatureKey } from './app-state/app-state.reducer';
|
||||
|
||||
export interface RootState {
|
||||
[TASK_FEATURE_NAME]: TaskState;
|
||||
|
|
@ -28,4 +29,5 @@ export interface RootState {
|
|||
[CONFIG_FEATURE_NAME]: GlobalConfigState;
|
||||
[BOARDS_FEATURE_NAME]: BoardsState;
|
||||
[fromPlanner.plannerFeatureKey]: PlannerState;
|
||||
[appStateFeatureKey]: AppState;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue