2024-07-25 19:11:34 +02:00
|
|
|
// this file is responsible for managing boards within chats and tasks within boards.
|
2024-07-22 02:05:27 +02:00
|
|
|
|
2024-07-22 11:49:05 +02:00
|
|
|
import {
|
2026-04-01 08:29:39 +00:00
|
|
|
DATA_VERSION,
|
|
|
|
|
checkMatchesObjectStructure,
|
2024-07-22 11:49:05 +02:00
|
|
|
} from "../Utility/typeSafety";
|
2024-07-23 18:23:26 +02:00
|
|
|
import FileModel, { FileContent, FileModelSubPath } from "./fileModel";
|
2024-07-22 02:05:27 +02:00
|
|
|
|
2024-07-26 03:14:55 +02:00
|
|
|
import CalendarModel from "./calendarModel";
|
2024-07-22 02:16:58 +02:00
|
|
|
import ChatModel from "../Chat/chatModel";
|
2026-04-08 14:02:12 +00:00
|
|
|
import { Colors } from "../../colors";
|
2024-07-25 17:30:32 +02:00
|
|
|
import { HandlerManager } from "../Utility/utility";
|
2024-07-26 03:14:55 +02:00
|
|
|
import SettingsModel from "../Global/settingsModel";
|
2024-07-22 13:09:33 +02:00
|
|
|
import StorageModel from "../Global/storageModel";
|
2024-07-25 17:30:32 +02:00
|
|
|
import { v4 } from "uuid";
|
2024-07-22 02:16:58 +02:00
|
|
|
|
2024-07-24 17:28:49 +02:00
|
|
|
export default class BoardsAndTasksModel {
|
2026-04-13 10:58:21 +00:00
|
|
|
readonly storageModel: StorageModel;
|
|
|
|
|
readonly settingsModel: SettingsModel;
|
|
|
|
|
readonly chatModel: ChatModel;
|
|
|
|
|
readonly fileModel: FileModel;
|
2026-04-01 08:29:39 +00:00
|
|
|
|
2026-04-13 10:58:21 +00:00
|
|
|
readonly calendarModel: CalendarModel;
|
2026-04-01 08:29:39 +00:00
|
|
|
|
|
|
|
|
// data
|
2026-04-13 10:58:21 +00:00
|
|
|
readonly boardHandlerManager = new HandlerManager<BoardInfoFileContent>();
|
|
|
|
|
readonly taskHandlerManager = new HandlerManager<TaskFileContent>();
|
2026-04-01 08:29:39 +00:00
|
|
|
|
|
|
|
|
// paths
|
|
|
|
|
getBasePath = (): string[] => {
|
|
|
|
|
return this.fileModel.getModelContainerPath(FileModelSubPath.ModelTask);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getViewPath = (): string[] => {
|
|
|
|
|
return [...this.getBasePath(), FileModelSubPath.ModelView];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getBoardFilePath = (boardId: string): string[] => {
|
|
|
|
|
return [...this.fileModel.getFilePath(boardId)];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getTaskFilePath = (taskId: string): string[] => {
|
|
|
|
|
return [...this.fileModel.getFilePath(taskId)];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getBoardContainerPath = (): string[] => {
|
|
|
|
|
return [...this.getBasePath(), TaskModelSubPaths.Boards];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getBoardDirectoryPath = (boardId: string): string[] => {
|
|
|
|
|
return [...this.getBoardContainerPath(), boardId];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getTaskContainerPath = (boardId: string): string[] => {
|
|
|
|
|
return [
|
|
|
|
|
...this.getBoardDirectoryPath(boardId),
|
|
|
|
|
TaskModelSubPaths.BoardTasks,
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getTaskReferencePath = (boardId: string, fileId: string): string[] => {
|
|
|
|
|
return [...this.getTaskContainerPath(boardId), fileId];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// handlers
|
|
|
|
|
handleFileContent = (fileContent: FileContent<string>): void => {
|
|
|
|
|
if (
|
|
|
|
|
checkMatchesObjectStructure(
|
|
|
|
|
fileContent,
|
|
|
|
|
BoardInfoFileContentReference,
|
|
|
|
|
) == true
|
|
|
|
|
) {
|
|
|
|
|
this.handleBoard(fileContent as BoardInfoFileContent);
|
|
|
|
|
} else if (
|
|
|
|
|
checkMatchesObjectStructure(
|
|
|
|
|
fileContent,
|
|
|
|
|
TaskFileContentReference,
|
|
|
|
|
) == true
|
|
|
|
|
) {
|
|
|
|
|
this.handleTask(fileContent as TaskFileContent);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
handleBoard = (boardInfoFileContent: BoardInfoFileContent) => {
|
|
|
|
|
this.updateBoard(boardInfoFileContent);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
handleTask = (taskFileContent: TaskFileContent) => {
|
|
|
|
|
this.updateTask(taskFileContent);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// boards
|
|
|
|
|
createBoard = (name: string): BoardInfoFileContent => {
|
|
|
|
|
const boardInfoFileContent: BoardInfoFileContent =
|
|
|
|
|
BoardsAndTasksModel.createBoardInfoFileContent(
|
|
|
|
|
v4(),
|
|
|
|
|
name,
|
2026-04-08 14:02:12 +00:00
|
|
|
Colors.Standard,
|
2026-04-01 08:29:39 +00:00
|
|
|
);
|
|
|
|
|
return boardInfoFileContent;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
|
|
|
|
|
this.storeBoard(boardInfoFileContent);
|
|
|
|
|
this.boardHandlerManager.trigger(boardInfoFileContent);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateBoardAndSend = (boardInfoFileContent: BoardInfoFileContent): void => {
|
|
|
|
|
this.updateBoard(boardInfoFileContent);
|
2026-04-15 10:41:44 +00:00
|
|
|
this.chatModel.sendMessage("", undefined, boardInfoFileContent);
|
2026-04-01 08:29:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
storeBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
|
|
|
|
|
// store info
|
|
|
|
|
this.fileModel.storeFileContent(boardInfoFileContent);
|
|
|
|
|
|
|
|
|
|
// add to list
|
|
|
|
|
const boardDirectoryPath: string[] = this.getBoardDirectoryPath(
|
|
|
|
|
boardInfoFileContent.fileId,
|
|
|
|
|
);
|
|
|
|
|
this.storageModel.write(boardDirectoryPath, "");
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
deleteBoard = (boardId: string): void => {
|
|
|
|
|
const boardFilePath: string[] = this.getBoardFilePath(boardId);
|
|
|
|
|
const boardDirectoryPath: string[] =
|
|
|
|
|
this.getBoardDirectoryPath(boardId);
|
|
|
|
|
|
|
|
|
|
this.storageModel.removeRecursively(boardFilePath);
|
|
|
|
|
this.storageModel.removeRecursively(boardDirectoryPath);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
listBoardIds = (): string[] => {
|
|
|
|
|
const boardContainerPath: string[] = this.getBoardContainerPath();
|
|
|
|
|
const boardIds: string[] = this.storageModel.list(boardContainerPath);
|
|
|
|
|
return boardIds;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getBoardInfo = (fileId: string): BoardInfoFileContent | null => {
|
|
|
|
|
const boardInfoFileContentOrNull: BoardInfoFileContent | null =
|
|
|
|
|
this.fileModel.getLatestFileContent(
|
|
|
|
|
fileId,
|
|
|
|
|
BoardInfoFileContentReference,
|
|
|
|
|
);
|
|
|
|
|
return boardInfoFileContentOrNull;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getBoardName = (boardId: string): string => {
|
|
|
|
|
const boardInfo: BoardInfoFileContent | null =
|
|
|
|
|
this.getBoardInfo(boardId);
|
|
|
|
|
if (boardInfo == null) return "";
|
|
|
|
|
return boardInfo.name;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//tasks
|
|
|
|
|
createTask = (boardId: string): TaskFileContent => {
|
|
|
|
|
const taskFileContent: TaskFileContent =
|
|
|
|
|
BoardsAndTasksModel.createTaskFileContent(v4(), "", boardId);
|
|
|
|
|
return taskFileContent;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateTask = (taskFileContent: TaskFileContent): void => {
|
|
|
|
|
this.storeTask(taskFileContent);
|
|
|
|
|
this.taskHandlerManager.trigger(taskFileContent);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
updateTaskAndSend = (taskFileContent: TaskFileContent): void => {
|
|
|
|
|
this.updateTask(taskFileContent);
|
2026-04-15 10:41:44 +00:00
|
|
|
this.chatModel.sendMessage("", undefined, taskFileContent);
|
2026-04-01 08:29:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
storeTask = (taskFileContent: TaskFileContent): void => {
|
|
|
|
|
// store info
|
|
|
|
|
this.fileModel.storeFileContent(taskFileContent);
|
|
|
|
|
|
|
|
|
|
// add to board
|
|
|
|
|
const taskReferencePath: string[] = this.getTaskReferencePath(
|
|
|
|
|
taskFileContent.boardId,
|
|
|
|
|
taskFileContent.fileId,
|
|
|
|
|
);
|
|
|
|
|
this.storageModel.write(taskReferencePath, "");
|
|
|
|
|
|
|
|
|
|
// add to calendar
|
|
|
|
|
this.calendarModel.storeTaskReference(taskFileContent);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
listTaskIds = (boardId: string): string[] => {
|
|
|
|
|
const taskContainerPath: string[] = this.getTaskContainerPath(boardId);
|
|
|
|
|
const fileIds: string[] = this.storageModel.list(taskContainerPath);
|
|
|
|
|
return fileIds;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
listTaskVersionIds = (taskId: string): string[] => {
|
|
|
|
|
const versionIds: string[] = this.fileModel.listFileContentIds(taskId);
|
|
|
|
|
return versionIds;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getLatestTaskFileContent = (taskId: string): TaskFileContent | null => {
|
|
|
|
|
const taskFileContentOrNull: TaskFileContent | null =
|
|
|
|
|
this.fileModel.getLatestFileContent(
|
|
|
|
|
taskId,
|
|
|
|
|
TaskFileContentReference,
|
|
|
|
|
);
|
|
|
|
|
return taskFileContentOrNull;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
getSpecificTaskFileContent = (
|
|
|
|
|
taskId: string,
|
|
|
|
|
versionId: string,
|
|
|
|
|
): TaskFileContent | null => {
|
|
|
|
|
const taskFileContentOrNull: TaskFileContent | null =
|
|
|
|
|
this.fileModel.getFileContent(
|
|
|
|
|
taskId,
|
|
|
|
|
versionId,
|
|
|
|
|
TaskFileContentReference,
|
|
|
|
|
);
|
|
|
|
|
return taskFileContentOrNull;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
deleteTask = (boardId: string, taskId: string): void => {
|
|
|
|
|
const taskFilePath: string[] = this.getTaskFilePath(taskId);
|
|
|
|
|
this.storageModel.removeRecursively(taskFilePath);
|
|
|
|
|
|
|
|
|
|
this.deleteTaskReference(boardId, taskId);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
deleteTaskReference = (boardId: string, taskId: string): void => {
|
|
|
|
|
const taskReferencePath: string[] = this.getTaskReferencePath(
|
|
|
|
|
boardId,
|
|
|
|
|
taskId,
|
|
|
|
|
);
|
|
|
|
|
this.storageModel.removeRecursively(taskReferencePath);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// init
|
|
|
|
|
constructor(
|
|
|
|
|
storageModel: StorageModel,
|
|
|
|
|
settingsModel: SettingsModel,
|
|
|
|
|
chatModel: ChatModel,
|
|
|
|
|
fileModel: FileModel,
|
2024-07-22 14:36:03 +02:00
|
|
|
) {
|
2026-04-01 08:29:39 +00:00
|
|
|
this.storageModel = storageModel;
|
|
|
|
|
this.settingsModel = settingsModel;
|
|
|
|
|
this.chatModel = chatModel;
|
|
|
|
|
this.fileModel = fileModel;
|
|
|
|
|
|
|
|
|
|
this.calendarModel = new CalendarModel(
|
|
|
|
|
this.storageModel,
|
|
|
|
|
this.settingsModel,
|
|
|
|
|
this.fileModel,
|
|
|
|
|
);
|
2024-07-22 14:36:03 +02:00
|
|
|
}
|
2026-04-01 08:29:39 +00:00
|
|
|
|
|
|
|
|
// utility
|
|
|
|
|
static createBoardInfoFileContent = (
|
|
|
|
|
fileId: string,
|
|
|
|
|
name: string,
|
2026-04-08 14:02:12 +00:00
|
|
|
color: Colors,
|
2026-04-01 08:29:39 +00:00
|
|
|
): BoardInfoFileContent => {
|
|
|
|
|
const fileContent: FileContent<"board-info"> =
|
|
|
|
|
FileModel.createFileContent(fileId, "board-info");
|
|
|
|
|
return {
|
|
|
|
|
...fileContent,
|
|
|
|
|
|
|
|
|
|
name,
|
|
|
|
|
color,
|
|
|
|
|
};
|
2024-07-22 14:36:03 +02:00
|
|
|
};
|
2026-04-01 08:29:39 +00:00
|
|
|
|
|
|
|
|
static createTaskFileContent = (
|
|
|
|
|
fileId: string,
|
|
|
|
|
name: string,
|
|
|
|
|
boardId: string,
|
|
|
|
|
): TaskFileContent => {
|
|
|
|
|
const fileContent: FileContent<"task"> = FileModel.createFileContent(
|
|
|
|
|
fileId,
|
|
|
|
|
"task",
|
|
|
|
|
);
|
|
|
|
|
return {
|
|
|
|
|
...fileContent,
|
|
|
|
|
|
|
|
|
|
name,
|
|
|
|
|
boardId,
|
|
|
|
|
};
|
2024-07-22 11:49:05 +02:00
|
|
|
};
|
2024-07-22 02:16:58 +02:00
|
|
|
}
|
2024-07-22 02:05:27 +02:00
|
|
|
|
2024-07-23 18:23:26 +02:00
|
|
|
export enum TaskModelSubPaths {
|
2026-04-01 08:29:39 +00:00
|
|
|
Boards = "boards",
|
|
|
|
|
BoardTasks = "tasks",
|
2024-07-23 21:33:22 +02:00
|
|
|
}
|
2024-07-22 12:39:26 +02:00
|
|
|
|
2024-07-22 02:05:27 +02:00
|
|
|
// types
|
2024-07-22 19:28:39 +02:00
|
|
|
export interface BoardInfoFileContent extends FileContent<"board-info"> {
|
2026-04-01 08:29:39 +00:00
|
|
|
name: string;
|
2026-04-08 14:02:12 +00:00
|
|
|
color: Colors;
|
2024-07-22 14:36:03 +02:00
|
|
|
}
|
|
|
|
|
|
2024-07-22 18:11:18 +02:00
|
|
|
export interface TaskFileContent extends FileContent<"task"> {
|
2026-04-01 08:29:39 +00:00
|
|
|
name: string;
|
|
|
|
|
boardId: string;
|
2024-07-22 11:49:05 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
description?: string;
|
2024-07-22 02:16:58 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
category?: string;
|
|
|
|
|
status?: string;
|
|
|
|
|
priority?: string;
|
2024-07-24 03:36:21 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
date?: string;
|
|
|
|
|
time?: string;
|
2024-07-22 02:16:58 +02:00
|
|
|
}
|
2024-07-22 11:20:43 +02:00
|
|
|
|
2024-07-22 12:22:52 +02:00
|
|
|
// reference
|
2024-07-22 19:28:39 +02:00
|
|
|
export const BoardInfoFileContentReference: BoardInfoFileContent = {
|
2026-04-01 08:29:39 +00:00
|
|
|
dataVersion: DATA_VERSION,
|
2024-07-22 11:20:43 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
fileId: "string",
|
|
|
|
|
fileContentId: "",
|
|
|
|
|
creationDate: "",
|
2024-07-22 17:23:48 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
type: "board-info",
|
2024-07-22 11:49:05 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
name: "",
|
2026-04-08 14:02:12 +00:00
|
|
|
color: "" as Colors,
|
2024-07-22 11:20:43 +02:00
|
|
|
};
|
2024-07-22 12:22:52 +02:00
|
|
|
|
2024-07-22 18:11:18 +02:00
|
|
|
export const TaskFileContentReference: TaskFileContent = {
|
2026-04-01 08:29:39 +00:00
|
|
|
dataVersion: DATA_VERSION,
|
2024-07-22 12:22:52 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
fileId: "string",
|
|
|
|
|
fileContentId: "",
|
|
|
|
|
creationDate: "",
|
|
|
|
|
type: "task",
|
2024-07-22 14:36:03 +02:00
|
|
|
|
2026-04-01 08:29:39 +00:00
|
|
|
name: "",
|
|
|
|
|
boardId: "",
|
2024-07-22 15:07:31 +02:00
|
|
|
};
|