floq 0.2.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.ja.md +4 -0
  2. package/README.md +4 -0
  3. package/dist/i18n/en.d.ts +16 -0
  4. package/dist/i18n/en.js +9 -0
  5. package/dist/i18n/ja.js +9 -0
  6. package/dist/ui/App.js +116 -58
  7. package/dist/ui/SplashScreen.js +1 -1
  8. package/dist/ui/components/HelpModal.js +3 -2
  9. package/dist/ui/components/KanbanBoard.js +100 -40
  10. package/dist/ui/history/HistoryContext.d.ts +29 -0
  11. package/dist/ui/history/HistoryContext.js +44 -0
  12. package/dist/ui/history/HistoryManager.d.ts +56 -0
  13. package/dist/ui/history/HistoryManager.js +137 -0
  14. package/dist/ui/history/commands/ConvertToProjectCommand.d.ts +19 -0
  15. package/dist/ui/history/commands/ConvertToProjectCommand.js +37 -0
  16. package/dist/ui/history/commands/CreateCommentCommand.d.ts +18 -0
  17. package/dist/ui/history/commands/CreateCommentCommand.js +23 -0
  18. package/dist/ui/history/commands/CreateTaskCommand.d.ts +18 -0
  19. package/dist/ui/history/commands/CreateTaskCommand.js +24 -0
  20. package/dist/ui/history/commands/DeleteCommentCommand.d.ts +17 -0
  21. package/dist/ui/history/commands/DeleteCommentCommand.js +26 -0
  22. package/dist/ui/history/commands/DeleteTaskCommand.d.ts +18 -0
  23. package/dist/ui/history/commands/DeleteTaskCommand.js +51 -0
  24. package/dist/ui/history/commands/LinkTaskCommand.d.ts +20 -0
  25. package/dist/ui/history/commands/LinkTaskCommand.js +37 -0
  26. package/dist/ui/history/commands/MoveTaskCommand.d.ts +25 -0
  27. package/dist/ui/history/commands/MoveTaskCommand.js +43 -0
  28. package/dist/ui/history/commands/index.d.ts +7 -0
  29. package/dist/ui/history/commands/index.js +7 -0
  30. package/dist/ui/history/index.d.ts +6 -0
  31. package/dist/ui/history/index.js +8 -0
  32. package/dist/ui/history/types.d.ts +26 -0
  33. package/dist/ui/history/types.js +4 -0
  34. package/dist/ui/history/useHistory.d.ts +24 -0
  35. package/dist/ui/history/useHistory.js +31 -0
  36. package/package.json +3 -3
@@ -0,0 +1,18 @@
1
+ import type { UndoableCommand } from '../types.js';
2
+ import type { Task } from '../../../db/schema.js';
3
+ interface DeleteTaskParams {
4
+ task: Task;
5
+ description: string;
6
+ }
7
+ /**
8
+ * Command to delete a task (and its comments)
9
+ */
10
+ export declare class DeleteTaskCommand implements UndoableCommand {
11
+ readonly description: string;
12
+ private readonly task;
13
+ private savedComments;
14
+ constructor(params: DeleteTaskParams);
15
+ execute(): Promise<void>;
16
+ undo(): Promise<void>;
17
+ }
18
+ export {};
@@ -0,0 +1,51 @@
1
+ import { eq } from 'drizzle-orm';
2
+ import { getDb, schema } from '../../../db/index.js';
3
+ /**
4
+ * Command to delete a task (and its comments)
5
+ */
6
+ export class DeleteTaskCommand {
7
+ description;
8
+ task;
9
+ savedComments = [];
10
+ constructor(params) {
11
+ this.task = params.task;
12
+ this.description = params.description;
13
+ }
14
+ async execute() {
15
+ const db = getDb();
16
+ // Save comments before deleting
17
+ this.savedComments = await db
18
+ .select()
19
+ .from(schema.comments)
20
+ .where(eq(schema.comments.taskId, this.task.id));
21
+ // Delete comments first
22
+ await db.delete(schema.comments).where(eq(schema.comments.taskId, this.task.id));
23
+ // Delete the task
24
+ await db.delete(schema.tasks).where(eq(schema.tasks.id, this.task.id));
25
+ }
26
+ async undo() {
27
+ const db = getDb();
28
+ // Restore the task
29
+ await db.insert(schema.tasks).values({
30
+ id: this.task.id,
31
+ title: this.task.title,
32
+ description: this.task.description,
33
+ status: this.task.status,
34
+ isProject: this.task.isProject,
35
+ parentId: this.task.parentId,
36
+ waitingFor: this.task.waitingFor,
37
+ dueDate: this.task.dueDate,
38
+ createdAt: this.task.createdAt,
39
+ updatedAt: this.task.updatedAt,
40
+ });
41
+ // Restore comments
42
+ for (const comment of this.savedComments) {
43
+ await db.insert(schema.comments).values({
44
+ id: comment.id,
45
+ taskId: comment.taskId,
46
+ content: comment.content,
47
+ createdAt: comment.createdAt,
48
+ });
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,20 @@
1
+ import type { UndoableCommand } from '../types.js';
2
+ interface LinkTaskParams {
3
+ taskId: string;
4
+ fromParentId: string | null;
5
+ toParentId: string | null;
6
+ description: string;
7
+ }
8
+ /**
9
+ * Command to link/unlink a task to a project
10
+ */
11
+ export declare class LinkTaskCommand implements UndoableCommand {
12
+ readonly description: string;
13
+ private readonly taskId;
14
+ private readonly fromParentId;
15
+ private readonly toParentId;
16
+ constructor(params: LinkTaskParams);
17
+ execute(): Promise<void>;
18
+ undo(): Promise<void>;
19
+ }
20
+ export {};
@@ -0,0 +1,37 @@
1
+ import { eq } from 'drizzle-orm';
2
+ import { getDb, schema } from '../../../db/index.js';
3
+ /**
4
+ * Command to link/unlink a task to a project
5
+ */
6
+ export class LinkTaskCommand {
7
+ description;
8
+ taskId;
9
+ fromParentId;
10
+ toParentId;
11
+ constructor(params) {
12
+ this.taskId = params.taskId;
13
+ this.fromParentId = params.fromParentId;
14
+ this.toParentId = params.toParentId;
15
+ this.description = params.description;
16
+ }
17
+ async execute() {
18
+ const db = getDb();
19
+ await db
20
+ .update(schema.tasks)
21
+ .set({
22
+ parentId: this.toParentId,
23
+ updatedAt: new Date(),
24
+ })
25
+ .where(eq(schema.tasks.id, this.taskId));
26
+ }
27
+ async undo() {
28
+ const db = getDb();
29
+ await db
30
+ .update(schema.tasks)
31
+ .set({
32
+ parentId: this.fromParentId,
33
+ updatedAt: new Date(),
34
+ })
35
+ .where(eq(schema.tasks.id, this.taskId));
36
+ }
37
+ }
@@ -0,0 +1,25 @@
1
+ import type { UndoableCommand } from '../types.js';
2
+ import type { TaskStatus } from '../../../db/schema.js';
3
+ interface MoveTaskParams {
4
+ taskId: string;
5
+ fromStatus: TaskStatus;
6
+ toStatus: TaskStatus;
7
+ fromWaitingFor: string | null;
8
+ toWaitingFor: string | null;
9
+ description: string;
10
+ }
11
+ /**
12
+ * Command to move a task to a different status
13
+ */
14
+ export declare class MoveTaskCommand implements UndoableCommand {
15
+ readonly description: string;
16
+ private readonly taskId;
17
+ private readonly fromStatus;
18
+ private readonly toStatus;
19
+ private readonly fromWaitingFor;
20
+ private readonly toWaitingFor;
21
+ constructor(params: MoveTaskParams);
22
+ execute(): Promise<void>;
23
+ undo(): Promise<void>;
24
+ }
25
+ export {};
@@ -0,0 +1,43 @@
1
+ import { eq } from 'drizzle-orm';
2
+ import { getDb, schema } from '../../../db/index.js';
3
+ /**
4
+ * Command to move a task to a different status
5
+ */
6
+ export class MoveTaskCommand {
7
+ description;
8
+ taskId;
9
+ fromStatus;
10
+ toStatus;
11
+ fromWaitingFor;
12
+ toWaitingFor;
13
+ constructor(params) {
14
+ this.taskId = params.taskId;
15
+ this.fromStatus = params.fromStatus;
16
+ this.toStatus = params.toStatus;
17
+ this.fromWaitingFor = params.fromWaitingFor;
18
+ this.toWaitingFor = params.toWaitingFor;
19
+ this.description = params.description;
20
+ }
21
+ async execute() {
22
+ const db = getDb();
23
+ await db
24
+ .update(schema.tasks)
25
+ .set({
26
+ status: this.toStatus,
27
+ waitingFor: this.toWaitingFor,
28
+ updatedAt: new Date(),
29
+ })
30
+ .where(eq(schema.tasks.id, this.taskId));
31
+ }
32
+ async undo() {
33
+ const db = getDb();
34
+ await db
35
+ .update(schema.tasks)
36
+ .set({
37
+ status: this.fromStatus,
38
+ waitingFor: this.fromWaitingFor,
39
+ updatedAt: new Date(),
40
+ })
41
+ .where(eq(schema.tasks.id, this.taskId));
42
+ }
43
+ }
@@ -0,0 +1,7 @@
1
+ export { CreateTaskCommand } from './CreateTaskCommand.js';
2
+ export { DeleteTaskCommand } from './DeleteTaskCommand.js';
3
+ export { MoveTaskCommand } from './MoveTaskCommand.js';
4
+ export { LinkTaskCommand } from './LinkTaskCommand.js';
5
+ export { ConvertToProjectCommand } from './ConvertToProjectCommand.js';
6
+ export { CreateCommentCommand } from './CreateCommentCommand.js';
7
+ export { DeleteCommentCommand } from './DeleteCommentCommand.js';
@@ -0,0 +1,7 @@
1
+ export { CreateTaskCommand } from './CreateTaskCommand.js';
2
+ export { DeleteTaskCommand } from './DeleteTaskCommand.js';
3
+ export { MoveTaskCommand } from './MoveTaskCommand.js';
4
+ export { LinkTaskCommand } from './LinkTaskCommand.js';
5
+ export { ConvertToProjectCommand } from './ConvertToProjectCommand.js';
6
+ export { CreateCommentCommand } from './CreateCommentCommand.js';
7
+ export { DeleteCommentCommand } from './DeleteCommentCommand.js';
@@ -0,0 +1,6 @@
1
+ export type { UndoableCommand, HistoryState } from './types.js';
2
+ export { MAX_HISTORY_SIZE } from './types.js';
3
+ export { HistoryManager, getHistoryManager } from './HistoryManager.js';
4
+ export { HistoryProvider, useHistoryContext } from './HistoryContext.js';
5
+ export { useHistory } from './useHistory.js';
6
+ export { CreateTaskCommand, DeleteTaskCommand, MoveTaskCommand, LinkTaskCommand, ConvertToProjectCommand, CreateCommentCommand, DeleteCommentCommand, } from './commands/index.js';
@@ -0,0 +1,8 @@
1
+ export { MAX_HISTORY_SIZE } from './types.js';
2
+ // Manager
3
+ export { HistoryManager, getHistoryManager } from './HistoryManager.js';
4
+ // React integration
5
+ export { HistoryProvider, useHistoryContext } from './HistoryContext.js';
6
+ export { useHistory } from './useHistory.js';
7
+ // Commands
8
+ export { CreateTaskCommand, DeleteTaskCommand, MoveTaskCommand, LinkTaskCommand, ConvertToProjectCommand, CreateCommentCommand, DeleteCommentCommand, } from './commands/index.js';
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Interface for undoable commands (Command Pattern)
3
+ */
4
+ export interface UndoableCommand {
5
+ /** Human-readable description of the command for display */
6
+ readonly description: string;
7
+ /** Execute the command */
8
+ execute(): Promise<void>;
9
+ /** Undo the command (reverse the operation) */
10
+ undo(): Promise<void>;
11
+ }
12
+ /**
13
+ * State of the history manager
14
+ */
15
+ export interface HistoryState {
16
+ /** Number of commands that can be undone */
17
+ undoCount: number;
18
+ /** Number of commands that can be redone */
19
+ redoCount: number;
20
+ /** Description of the last executed command (if any) */
21
+ lastCommandDescription: string | null;
22
+ }
23
+ /**
24
+ * Maximum number of commands to keep in history
25
+ */
26
+ export declare const MAX_HISTORY_SIZE = 50;
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Maximum number of commands to keep in history
3
+ */
4
+ export const MAX_HISTORY_SIZE = 50;
@@ -0,0 +1,24 @@
1
+ import type { UndoableCommand } from './types.js';
2
+ /**
3
+ * Hook for undo/redo functionality
4
+ */
5
+ export declare function useHistory(): {
6
+ /** Execute a command and add to history */
7
+ execute: (command: UndoableCommand) => Promise<void>;
8
+ /** Undo the last command */
9
+ undo: () => Promise<boolean>;
10
+ /** Redo the last undone command */
11
+ redo: () => Promise<boolean>;
12
+ /** Whether undo is available */
13
+ canUndo: boolean;
14
+ /** Whether redo is available */
15
+ canRedo: boolean;
16
+ /** Number of commands that can be undone */
17
+ undoCount: number;
18
+ /** Number of commands that can be redone */
19
+ redoCount: number;
20
+ /** Description of what would be undone */
21
+ undoDescription: string | null;
22
+ /** Description of what would be redone */
23
+ redoDescription: string | null;
24
+ };
@@ -0,0 +1,31 @@
1
+ import { useCallback } from 'react';
2
+ import { useHistoryContext } from './HistoryContext.js';
3
+ /**
4
+ * Hook for undo/redo functionality
5
+ */
6
+ export function useHistory() {
7
+ const { execute, undo, redo, canUndo, canRedo, state, undoDescription, redoDescription } = useHistoryContext();
8
+ const executeCommand = useCallback(async (command) => {
9
+ await execute(command);
10
+ }, [execute]);
11
+ return {
12
+ /** Execute a command and add to history */
13
+ execute: executeCommand,
14
+ /** Undo the last command */
15
+ undo,
16
+ /** Redo the last undone command */
17
+ redo,
18
+ /** Whether undo is available */
19
+ canUndo,
20
+ /** Whether redo is available */
21
+ canRedo,
22
+ /** Number of commands that can be undone */
23
+ undoCount: state.undoCount,
24
+ /** Number of commands that can be redone */
25
+ redoCount: state.redoCount,
26
+ /** Description of what would be undone */
27
+ undoDescription,
28
+ /** Description of what would be redone */
29
+ redoDescription,
30
+ };
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floq",
3
- "version": "0.2.3",
3
+ "version": "0.3.1",
4
4
  "description": "Floq - Getting Things Done Task Manager with MS-DOS style themes",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -33,9 +33,9 @@
33
33
  "license": "MIT",
34
34
  "repository": {
35
35
  "type": "git",
36
- "url": "git+https://github.com/polidog/gtd-cli.git"
36
+ "url": "git+https://github.com/polidog/floq.git"
37
37
  },
38
- "homepage": "https://github.com/polidog/gtd-cli#readme",
38
+ "homepage": "https://github.com/polidog/floq#readme",
39
39
  "dependencies": {
40
40
  "@libsql/client": "^0.17.0",
41
41
  "better-sqlite3": "^11.7.0",