mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 00:46:45 +00:00
233 lines
6 KiB
TypeScript
233 lines
6 KiB
TypeScript
import { IssueProviderKey } from '../issue/issue.model';
|
|
import { EntityState } from '@ngrx/entity';
|
|
import { TaskAttachment } from './task-attachment/task-attachment.model';
|
|
// Import the unified Task type from plugin-api
|
|
import { Task as PluginTask } from '@super-productivity/plugin-api';
|
|
|
|
export enum HideSubTasksMode {
|
|
// Show is undefined
|
|
HideDone = 1,
|
|
HideAll = 2,
|
|
}
|
|
|
|
export enum TaskDetailTargetPanel {
|
|
Default = 'Default',
|
|
Attachments = 'Attachments',
|
|
Notes = 'Notes',
|
|
DONT_OPEN_PANEL = 'DONT_OPEN_PANEL',
|
|
}
|
|
|
|
export type DropListModelSource =
|
|
| 'UNDONE'
|
|
| 'DONE'
|
|
| 'BACKLOG'
|
|
| 'ADD_TASK_PANEL'
|
|
| 'OVERDUE'
|
|
| 'LATER_TODAY';
|
|
|
|
// NOTE: do not change these, as they are used inside task repeat model directly
|
|
// (new can be added though)
|
|
export enum TaskReminderOptionId {
|
|
DoNotRemind = 'DoNotRemind',
|
|
AtStart = 'AtStart',
|
|
m5 = 'm5',
|
|
m10 = 'm10',
|
|
m15 = 'm15',
|
|
m30 = 'm30',
|
|
h1 = 'h1',
|
|
}
|
|
|
|
export interface TaskReminderOption {
|
|
value: TaskReminderOptionId;
|
|
label: string;
|
|
}
|
|
|
|
export interface TimeSpentOnDayCopy {
|
|
[key: string]: number;
|
|
}
|
|
|
|
export interface TaskArchive extends EntityState<ArchiveTask> {
|
|
ids: string[];
|
|
}
|
|
|
|
export type TimeSpentOnDay = Readonly<TimeSpentOnDayCopy>;
|
|
|
|
export interface IssueTaskTimeTracked {
|
|
[key: string]: number;
|
|
}
|
|
|
|
export interface IssueFieldsForTask {
|
|
// NOTE: keep in mind that the issueId is not unique (especially for github)
|
|
issueId?: string;
|
|
issueProviderId?: string;
|
|
issueType?: IssueProviderKey;
|
|
issueWasUpdated?: boolean;
|
|
// TODO remove null again
|
|
issueLastUpdated?: number | null;
|
|
issueAttachmentNr?: number;
|
|
issueTimeTracked?: IssueTaskTimeTracked;
|
|
issuePoints?: number;
|
|
issueLastSyncedValues?: Record<string, unknown>;
|
|
}
|
|
|
|
// Extend the plugin Task type with app-specific fields
|
|
// Omit issue fields from PluginTask to avoid conflict with IssueFieldsForTask
|
|
export interface TaskCopy
|
|
extends
|
|
Omit<
|
|
PluginTask,
|
|
| 'issueId'
|
|
| 'issueProviderId'
|
|
| 'issueType'
|
|
| 'issueWasUpdated'
|
|
| 'issueLastUpdated'
|
|
| 'issueAttachmentNr'
|
|
| 'issuePoints'
|
|
>,
|
|
IssueFieldsForTask {
|
|
// Override required fields that are optional in plugin type
|
|
projectId: string;
|
|
timeSpentOnDay: TimeSpentOnDay;
|
|
|
|
// Additional app-specific fields
|
|
|
|
/**
|
|
* Scheduled time as Unix timestamp (ms). For tasks scheduled with a specific time.
|
|
*
|
|
* IMPORTANT: dueWithTime and dueDay follow a mutual exclusivity pattern:
|
|
* - When dueWithTime is set, dueDay MUST be undefined/null (not both set)
|
|
* - When reading, check dueWithTime FIRST (it takes priority over dueDay)
|
|
*
|
|
* @see docs/ai/dueDay-dueWithTime-mutual-exclusivity.md
|
|
*/
|
|
dueWithTime?: number | null;
|
|
|
|
/**
|
|
* Scheduled date as ISO date string (YYYY-MM-DD). For tasks scheduled for all-day (no specific time).
|
|
*
|
|
* IMPORTANT: dueDay and dueWithTime follow a mutual exclusivity pattern:
|
|
* - When dueDay is set, dueWithTime should be undefined/null (for new data)
|
|
* - When dueWithTime is set, dueDay MUST be undefined/null (not both set)
|
|
* - When reading, check dueWithTime FIRST (it takes priority over dueDay)
|
|
* - Legacy data may have both fields set; handle via priority pattern
|
|
*
|
|
* @see docs/ai/dueDay-dueWithTime-mutual-exclusivity.md
|
|
*/
|
|
dueDay?: string | null;
|
|
hasPlannedTime?: boolean;
|
|
|
|
/**
|
|
* Deadline date as ISO string (YYYY-MM-DD). For deadlines without a specific time.
|
|
* Follows mutual exclusivity with deadlineWithTime (same pattern as dueDay/dueWithTime).
|
|
*/
|
|
deadlineDay?: string | null;
|
|
|
|
/**
|
|
* Deadline as Unix timestamp (ms). For deadlines with a specific time.
|
|
* When set, deadlineDay MUST be cleared.
|
|
*/
|
|
deadlineWithTime?: number | null;
|
|
|
|
/** Reminder timestamp for the deadline. */
|
|
deadlineRemindAt?: number | null;
|
|
attachments: TaskAttachment[];
|
|
reminderId?: string | null;
|
|
|
|
// Ensure type compatibility for internal fields
|
|
modified?: number;
|
|
doneOn?: number;
|
|
parentId?: string;
|
|
remindAt?: number;
|
|
repeatCfgId?: string;
|
|
_hideSubTasksMode?: HideSubTasksMode;
|
|
}
|
|
|
|
/**
|
|
* standard task but with:
|
|
* * reminder removed, if any
|
|
* * sub tasks not included (but copied)
|
|
*/
|
|
// attachment data saved to it
|
|
export type ArchiveTask = Readonly<TaskCopy>;
|
|
|
|
export type Task = Readonly<TaskCopy>;
|
|
|
|
export interface TaskWithReminderData extends Task {
|
|
readonly reminderData: { remindAt: number };
|
|
readonly parentData?: Task;
|
|
readonly isDeadlineReminder?: boolean;
|
|
}
|
|
|
|
export interface TaskWithReminder extends Task {
|
|
remindAt: number;
|
|
}
|
|
|
|
export interface TaskWithDueTime extends Task {
|
|
dueWithTime: number;
|
|
}
|
|
|
|
export interface TaskWithDueDay extends Task {
|
|
dueDay: string;
|
|
}
|
|
|
|
export type TaskPlannedWithDayOrTime = TaskWithDueTime | TaskWithDueDay;
|
|
|
|
export interface TaskWithDeadlineDay extends Task {
|
|
deadlineDay: string;
|
|
}
|
|
|
|
export interface TaskWithDeadlineTime extends Task {
|
|
deadlineWithTime: number;
|
|
}
|
|
|
|
export type TaskWithDeadline = TaskWithDeadlineDay | TaskWithDeadlineTime;
|
|
|
|
export interface TaskWithoutReminder extends Task {
|
|
remindAt: undefined;
|
|
}
|
|
|
|
export interface TaskWithPlannedForDayIndication extends TaskWithoutReminder {
|
|
plannedForDay: string;
|
|
}
|
|
|
|
export interface TaskWithSubTasks extends Task {
|
|
readonly subTasks: Task[];
|
|
}
|
|
|
|
// make title required and add optional property for possible related (parent) task
|
|
export type IssueTask = Partial<Task> & {
|
|
title: string;
|
|
related_to?: string;
|
|
};
|
|
|
|
export const DEFAULT_TASK: Omit<TaskCopy, 'projectId'> = {
|
|
id: '',
|
|
subTaskIds: [],
|
|
timeSpentOnDay: {},
|
|
timeSpent: 0,
|
|
timeEstimate: 0,
|
|
isDone: false,
|
|
title: '',
|
|
tagIds: [],
|
|
created: Date.now(),
|
|
|
|
attachments: [],
|
|
};
|
|
|
|
export interface TaskState extends EntityState<Task> {
|
|
// overwrite entity model to avoid problems with typing
|
|
ids: string[];
|
|
|
|
// additional entities state properties
|
|
currentTaskId: string | null;
|
|
selectedTaskId: string | null;
|
|
taskDetailTargetPanel?: TaskDetailTargetPanel | null;
|
|
lastCurrentTaskId: string | null;
|
|
isDataLoaded: boolean;
|
|
}
|
|
|
|
export interface WorklogTask extends Task {
|
|
dateStr: string;
|
|
}
|
|
|
|
export type SubmitTrigger = 'blur' | 'escape' | 'enter' | 'modEnter';
|