implement auto reconnect
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import BoardsAndTasksModel, {
|
||||
BoardInfoFileContent,
|
||||
TaskFileContent,
|
||||
BoardInfoFileContent,
|
||||
TaskFileContent,
|
||||
} from "../../Model/Files/boardsAndTasksModel";
|
||||
|
||||
import ChatViewModel from "../Chat/chatViewModel";
|
||||
@@ -15,293 +15,299 @@ import TaskPageViewModel from "./taskPageViewModel";
|
||||
import TaskViewModel from "./taskViewModel";
|
||||
|
||||
export default class BoardViewModel extends TaskContainingPageViewModel {
|
||||
storageModel: StorageModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
storageModel: StorageModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
|
||||
taskPageViewModel: TaskPageViewModel;
|
||||
taskPageViewModel: TaskPageViewModel;
|
||||
|
||||
// data
|
||||
boardInfo: BoardInfoFileContent;
|
||||
// data
|
||||
boardInfo: BoardInfoFileContent;
|
||||
|
||||
// state
|
||||
name: React.State<string> = new React.State("");
|
||||
color: React.State<Color> = new React.State<any>(Color.Standard);
|
||||
// state
|
||||
name: React.State<string> = new React.State("");
|
||||
color: React.State<Color> = new React.State<any>(Color.Standard);
|
||||
|
||||
index: React.State<number> = new React.State(0);
|
||||
index: React.State<number> = new React.State(0);
|
||||
|
||||
selectedPage: React.State<BoardPageType> = new React.State<any>(
|
||||
BoardPageType.List
|
||||
);
|
||||
|
||||
isSelected: React.State<boolean>;
|
||||
isPresentingSettingsModal: React.State<boolean> = new React.State(false);
|
||||
isPresentingFilterModal: React.State<boolean> = new React.State(false);
|
||||
|
||||
searchViewModel: SearchViewModel<TaskViewModel>;
|
||||
filteredTaskViewModels: React.ListState<TaskViewModel> =
|
||||
new React.ListState();
|
||||
|
||||
// paths
|
||||
getBasePath = (): string[] => {
|
||||
return [...this.taskPageViewModel.getBoardViewPath(this.boardInfo.fileId)];
|
||||
};
|
||||
|
||||
getLastUsedBoardPath = (): string[] => {
|
||||
return [...this.getBasePath(), BoardViewModelSubPath.LastUsedView];
|
||||
};
|
||||
|
||||
getPreviousSearchesPath = (): string[] => {
|
||||
return [...this.getBasePath(), BoardViewModelSubPath.PreviousSearches];
|
||||
};
|
||||
|
||||
getLastSearchPath = (): string[] => {
|
||||
return [...this.getBasePath(), BoardViewModelSubPath.LastSearch];
|
||||
};
|
||||
|
||||
// settings
|
||||
saveSettings = (): void => {
|
||||
const newBoardInfoFileContent: BoardInfoFileContent =
|
||||
BoardsAndTasksModel.createBoardInfoFileContent(
|
||||
this.boardInfo.fileId,
|
||||
this.name.value,
|
||||
this.color.value
|
||||
);
|
||||
this.taskPageViewModel.updateBoard(newBoardInfoFileContent);
|
||||
};
|
||||
|
||||
applyColor = (): void => {
|
||||
this.taskPageViewModel.chatViewModel.setDisplayedColor(this.color.value);
|
||||
};
|
||||
|
||||
deleteBoard = (): void => {
|
||||
this.taskPageViewModel.deleteBoard(this.boardInfo);
|
||||
this.chatViewModel.taskBoardSuggestions.remove(this.boardInfo.fileId);
|
||||
this.close();
|
||||
};
|
||||
|
||||
// methods
|
||||
createTask = (): void => {
|
||||
this.createTaskFromBoardId(this.boardInfo.fileId);
|
||||
};
|
||||
|
||||
handleDropWithinBoard = (category?: string, status?: string): void => {
|
||||
const draggedObject: any = this.coreViewModel.draggedObject.value;
|
||||
if (draggedObject instanceof TaskViewModel == false) return;
|
||||
draggedObject.setCategoryAndStatus(category, status);
|
||||
};
|
||||
|
||||
handleDropBetweenBoards = (): void => {
|
||||
const draggedObject: any = this.coreViewModel.draggedObject.value;
|
||||
if (draggedObject instanceof TaskViewModel == false) return;
|
||||
draggedObject.setBoardId(this.boardInfo.fileId);
|
||||
};
|
||||
|
||||
// storage
|
||||
storeLastUsedView = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedView: string = this.selectedPage.value;
|
||||
this.storageModel.write(path, lastUsedView);
|
||||
};
|
||||
|
||||
restoreLastUsedView = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedView: string | null = this.storageModel.read(path);
|
||||
if (lastUsedView == null) return;
|
||||
|
||||
this.selectedPage.value = lastUsedView as BoardPageType;
|
||||
};
|
||||
|
||||
handleNewSearch = (searchTerm: string): void => {
|
||||
const suggestionPath: string[] = [
|
||||
...this.getPreviousSearchesPath(),
|
||||
searchTerm,
|
||||
];
|
||||
this.storageModel.write(suggestionPath, "");
|
||||
if (!this.coreViewModel.boardSearchSuggestions.value.has(searchTerm)) {
|
||||
this.coreViewModel.boardSearchSuggestions.add(searchTerm);
|
||||
}
|
||||
|
||||
const lastSearchPath: string[] = this.getLastSearchPath();
|
||||
this.storageModel.write(lastSearchPath, searchTerm);
|
||||
};
|
||||
|
||||
// view
|
||||
showTask = (taskFileContent: TaskFileContent): void => {
|
||||
if (taskFileContent.boardId != this.boardInfo.fileId) {
|
||||
// remove task that was moved to different board
|
||||
this.boardsAndTasksModel.deleteTaskReference(
|
||||
this.boardInfo.fileId,
|
||||
taskFileContent.fileId
|
||||
);
|
||||
this.removeTaskFromView(taskFileContent);
|
||||
return;
|
||||
}
|
||||
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent
|
||||
selectedPage: React.State<BoardPageType> = new React.State<any>(
|
||||
BoardPageType.List,
|
||||
);
|
||||
this.taskViewModels.set(taskFileContent.fileId, taskViewModel);
|
||||
};
|
||||
|
||||
removeTaskFromView = (taskFileContent: TaskFileContent): void => {
|
||||
this.taskViewModels.remove(taskFileContent.fileId);
|
||||
this.updateIndex();
|
||||
};
|
||||
isSelected: React.State<boolean>;
|
||||
isPresentingSettingsModal: React.State<boolean> = new React.State(false);
|
||||
isPresentingFilterModal: React.State<boolean> = new React.State(false);
|
||||
|
||||
select = (): void => {
|
||||
this.taskPageViewModel.selectBoard(this);
|
||||
};
|
||||
searchViewModel: SearchViewModel<TaskViewModel>;
|
||||
filteredTaskViewModels: React.ListState<TaskViewModel> =
|
||||
new React.ListState();
|
||||
|
||||
close = (): void => {
|
||||
this.taskPageViewModel.closeBoard();
|
||||
this.taskViewModels.clear();
|
||||
};
|
||||
// paths
|
||||
getBasePath = (): string[] => {
|
||||
return [
|
||||
...this.taskPageViewModel.getBoardViewPath(this.boardInfo.fileId),
|
||||
];
|
||||
};
|
||||
|
||||
showSettings = (): void => {
|
||||
this.isPresentingSettingsModal.value = true;
|
||||
};
|
||||
getLastUsedBoardPath = (): string[] => {
|
||||
return [...this.getBasePath(), BoardViewModelSubPath.LastUsedView];
|
||||
};
|
||||
|
||||
hideSettings = (): void => {
|
||||
this.saveSettings();
|
||||
this.isPresentingSettingsModal.value = false;
|
||||
};
|
||||
getPreviousSearchesPath = (): string[] => {
|
||||
return [...this.getBasePath(), BoardViewModelSubPath.PreviousSearches];
|
||||
};
|
||||
|
||||
showFilterModal = (): void => {
|
||||
this.isPresentingFilterModal.value = true;
|
||||
};
|
||||
getLastSearchPath = (): string[] => {
|
||||
return [...this.getBasePath(), BoardViewModelSubPath.LastSearch];
|
||||
};
|
||||
|
||||
hideFilterModal = (): void => {
|
||||
this.isPresentingFilterModal.value = false;
|
||||
};
|
||||
// settings
|
||||
saveSettings = (): void => {
|
||||
const newBoardInfoFileContent: BoardInfoFileContent =
|
||||
BoardsAndTasksModel.createBoardInfoFileContent(
|
||||
this.boardInfo.fileId,
|
||||
this.name.value,
|
||||
this.color.value,
|
||||
);
|
||||
this.taskPageViewModel.updateBoard(newBoardInfoFileContent);
|
||||
};
|
||||
|
||||
updateIndex = (): void => {
|
||||
const index: number =
|
||||
this.taskPageViewModel.boardIndexManager.getIndex(this);
|
||||
this.index.value = index;
|
||||
};
|
||||
applyColor = (): void => {
|
||||
this.taskPageViewModel.chatViewModel.setDisplayedColor(
|
||||
this.color.value,
|
||||
);
|
||||
};
|
||||
|
||||
// load
|
||||
loadListRelevantData = (): void => {
|
||||
this.name.value = this.boardInfo.name;
|
||||
this.color.value = this.boardInfo.color;
|
||||
};
|
||||
deleteBoard = (): void => {
|
||||
this.taskPageViewModel.deleteBoard(this.boardInfo);
|
||||
this.chatViewModel.taskBoardSuggestions.remove(this.boardInfo.fileId);
|
||||
this.close();
|
||||
};
|
||||
|
||||
loadTasks = (): void => {
|
||||
const taskIds: string[] = this.boardsAndTasksModel.listTaskIds(
|
||||
this.boardInfo.fileId
|
||||
);
|
||||
for (const taskId of taskIds) {
|
||||
if (this.taskViewModels.value.has(taskId)) return;
|
||||
// methods
|
||||
createTask = (): void => {
|
||||
this.createTaskFromBoardId(this.boardInfo.fileId);
|
||||
};
|
||||
|
||||
const taskFileContent: TaskFileContent | null =
|
||||
this.boardsAndTasksModel.getLatestTaskFileContent(taskId);
|
||||
if (taskFileContent == null) continue;
|
||||
handleDropWithinBoard = (category?: string, status?: string): void => {
|
||||
const draggedObject: any = this.coreViewModel.draggedObject.value;
|
||||
if (draggedObject instanceof TaskViewModel == false) return;
|
||||
draggedObject.setCategoryAndStatus(category, status);
|
||||
};
|
||||
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent
|
||||
);
|
||||
this.taskViewModels.set(taskFileContent.fileId, taskViewModel);
|
||||
}
|
||||
handleDropBetweenBoards = (): void => {
|
||||
const draggedObject: any = this.coreViewModel.draggedObject.value;
|
||||
if (draggedObject instanceof TaskViewModel == false) return;
|
||||
draggedObject.setBoardId(this.boardInfo.fileId);
|
||||
};
|
||||
|
||||
this.updateTaskIndices();
|
||||
};
|
||||
// storage
|
||||
storeLastUsedView = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedView: string = this.selectedPage.value;
|
||||
this.storageModel.write(path, lastUsedView);
|
||||
};
|
||||
|
||||
loadSearchSuggestions = (): void => {
|
||||
const dirPath: string[] = this.getPreviousSearchesPath();
|
||||
const searches: string[] = this.storageModel.list(dirPath);
|
||||
this.coreViewModel.boardSearchSuggestions.add(...searches);
|
||||
};
|
||||
restoreLastUsedView = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedView: string | null = this.storageModel.read(path);
|
||||
if (lastUsedView == null) return;
|
||||
|
||||
restoreSearch = (): void => {
|
||||
const lastSearchPath: string[] = this.getLastSearchPath();
|
||||
const lastSearch: string | null = this.storageModel.read(lastSearchPath);
|
||||
if (lastSearch != null) {
|
||||
this.searchViewModel.search(lastSearch);
|
||||
}
|
||||
};
|
||||
this.selectedPage.value = lastUsedView as BoardPageType;
|
||||
};
|
||||
|
||||
loadData = (): void => {
|
||||
this.restoreLastUsedView();
|
||||
this.loadTasks();
|
||||
this.loadSearchSuggestions();
|
||||
};
|
||||
handleNewSearch = (searchTerm: string): void => {
|
||||
const suggestionPath: string[] = [
|
||||
...this.getPreviousSearchesPath(),
|
||||
searchTerm,
|
||||
];
|
||||
this.storageModel.write(suggestionPath, "");
|
||||
if (!this.coreViewModel.boardSearchSuggestions.value.has(searchTerm)) {
|
||||
this.coreViewModel.boardSearchSuggestions.add(searchTerm);
|
||||
}
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel,
|
||||
taskPageViewModel: TaskPageViewModel,
|
||||
boardInfo: BoardInfoFileContent
|
||||
) {
|
||||
super(coreViewModel, chatViewModel, boardsAndTasksModel);
|
||||
const lastSearchPath: string[] = this.getLastSearchPath();
|
||||
this.storageModel.write(lastSearchPath, searchTerm);
|
||||
};
|
||||
|
||||
// set
|
||||
this.storageModel = storageModel;
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
this.taskPageViewModel = taskPageViewModel;
|
||||
this.boardInfo = boardInfo;
|
||||
// view
|
||||
showTask = (taskFileContent: TaskFileContent): void => {
|
||||
if (taskFileContent.boardId != this.boardInfo.fileId) {
|
||||
// remove task that was moved to different board
|
||||
this.boardsAndTasksModel.deleteTaskReference(
|
||||
this.boardInfo.fileId,
|
||||
taskFileContent.fileId,
|
||||
);
|
||||
this.removeTaskFromView(taskFileContent);
|
||||
return;
|
||||
}
|
||||
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent,
|
||||
);
|
||||
this.taskViewModels.set(taskFileContent.fileId, taskViewModel);
|
||||
};
|
||||
|
||||
removeTaskFromView = (taskFileContent: TaskFileContent): void => {
|
||||
this.taskViewModels.remove(taskFileContent.fileId);
|
||||
this.updateIndex();
|
||||
};
|
||||
|
||||
select = (): void => {
|
||||
this.taskPageViewModel.selectBoard(this);
|
||||
};
|
||||
|
||||
close = (): void => {
|
||||
this.taskPageViewModel.closeBoard();
|
||||
this.taskViewModels.clear();
|
||||
};
|
||||
|
||||
showSettings = (): void => {
|
||||
this.isPresentingSettingsModal.value = true;
|
||||
};
|
||||
|
||||
hideSettings = (): void => {
|
||||
this.saveSettings();
|
||||
this.isPresentingSettingsModal.value = false;
|
||||
};
|
||||
|
||||
showFilterModal = (): void => {
|
||||
this.isPresentingFilterModal.value = true;
|
||||
};
|
||||
|
||||
hideFilterModal = (): void => {
|
||||
this.isPresentingFilterModal.value = false;
|
||||
};
|
||||
|
||||
updateIndex = (): void => {
|
||||
const index: number =
|
||||
this.taskPageViewModel.boardIndexManager.getIndex(this);
|
||||
this.index.value = index;
|
||||
};
|
||||
|
||||
// load
|
||||
this.loadListRelevantData();
|
||||
loadListRelevantData = (): void => {
|
||||
this.name.value = this.boardInfo.name;
|
||||
this.color.value = this.boardInfo.color;
|
||||
};
|
||||
|
||||
// subscriptions
|
||||
this.isSelected = React.createProxyState(
|
||||
[this.taskPageViewModel.selectedBoardId],
|
||||
() =>
|
||||
this.taskPageViewModel.selectedBoardId.value == this.boardInfo.fileId
|
||||
);
|
||||
loadTasks = (): void => {
|
||||
const taskIds: string[] = this.boardsAndTasksModel.listTaskIds(
|
||||
this.boardInfo.fileId,
|
||||
);
|
||||
for (const taskId of taskIds) {
|
||||
if (this.taskViewModels.value.has(taskId)) return;
|
||||
|
||||
this.color.subscribe(() => {
|
||||
if (this.isSelected.value == false) return;
|
||||
this.applyColor();
|
||||
});
|
||||
const taskFileContent: TaskFileContent | null =
|
||||
this.boardsAndTasksModel.getLatestTaskFileContent(taskId);
|
||||
if (taskFileContent == null) continue;
|
||||
|
||||
this.selectedPage.subscribeSilent(() => {
|
||||
this.storeLastUsedView();
|
||||
});
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent,
|
||||
);
|
||||
this.taskViewModels.set(taskFileContent.fileId, taskViewModel);
|
||||
}
|
||||
|
||||
// handlers
|
||||
boardsAndTasksModel.taskHandlerManager.addHandler(
|
||||
(taskFileContent: TaskFileContent) => {
|
||||
if (taskFileContent.boardId != this.boardInfo.fileId) return;
|
||||
this.showTask(taskFileContent);
|
||||
this.updateTaskIndices();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// search
|
||||
this.searchViewModel = new SearchViewModel(
|
||||
this.taskViewModels,
|
||||
this.filteredTaskViewModels,
|
||||
TaskViewModel.getStringsForFilter,
|
||||
this.coreViewModel.boardSearchSuggestions
|
||||
);
|
||||
this.searchViewModel.appliedQuery.subscribeSilent((newQuery) => {
|
||||
this.handleNewSearch(newQuery);
|
||||
});
|
||||
this.restoreSearch();
|
||||
}
|
||||
loadSearchSuggestions = (): void => {
|
||||
const dirPath: string[] = this.getPreviousSearchesPath();
|
||||
const searches: string[] = this.storageModel.list(dirPath);
|
||||
this.coreViewModel.boardSearchSuggestions.add(...searches);
|
||||
};
|
||||
|
||||
restoreSearch = (): void => {
|
||||
const lastSearchPath: string[] = this.getLastSearchPath();
|
||||
const lastSearch: string | null =
|
||||
this.storageModel.read(lastSearchPath);
|
||||
if (lastSearch != null) {
|
||||
this.searchViewModel.search(lastSearch);
|
||||
}
|
||||
};
|
||||
|
||||
loadData = (): void => {
|
||||
this.restoreLastUsedView();
|
||||
this.loadTasks();
|
||||
this.loadSearchSuggestions();
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel,
|
||||
taskPageViewModel: TaskPageViewModel,
|
||||
boardInfo: BoardInfoFileContent,
|
||||
) {
|
||||
super(coreViewModel, chatViewModel, boardsAndTasksModel);
|
||||
|
||||
// set
|
||||
this.storageModel = storageModel;
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
this.taskPageViewModel = taskPageViewModel;
|
||||
this.boardInfo = boardInfo;
|
||||
|
||||
// load
|
||||
this.loadListRelevantData();
|
||||
|
||||
// subscriptions
|
||||
this.isSelected = React.createProxyState(
|
||||
[this.taskPageViewModel.selectedBoardId],
|
||||
() =>
|
||||
this.taskPageViewModel.selectedBoardId.value ==
|
||||
this.boardInfo.fileId,
|
||||
);
|
||||
|
||||
this.color.subscribe(() => {
|
||||
if (this.isSelected.value == false) return;
|
||||
this.applyColor();
|
||||
});
|
||||
|
||||
this.selectedPage.subscribeSilent(() => {
|
||||
this.storeLastUsedView();
|
||||
});
|
||||
|
||||
// handlers
|
||||
boardsAndTasksModel.taskHandlerManager.addHandler(
|
||||
(taskFileContent: TaskFileContent) => {
|
||||
if (taskFileContent.boardId != this.boardInfo.fileId) return;
|
||||
this.showTask(taskFileContent);
|
||||
this.updateTaskIndices();
|
||||
},
|
||||
);
|
||||
|
||||
// search
|
||||
this.searchViewModel = new SearchViewModel(
|
||||
this.taskViewModels,
|
||||
this.filteredTaskViewModels,
|
||||
TaskViewModel.getStringsForFilter,
|
||||
this.coreViewModel.boardSearchSuggestions,
|
||||
);
|
||||
this.searchViewModel.appliedQuery.subscribeSilent((newQuery) => {
|
||||
this.handleNewSearch(newQuery);
|
||||
});
|
||||
this.restoreSearch();
|
||||
}
|
||||
}
|
||||
|
||||
export enum BoardViewModelSubPath {
|
||||
LastUsedView = "last-used-view",
|
||||
PreviousSearches = "previous-searches",
|
||||
LastSearch = "last-search",
|
||||
LastUsedView = "last-used-view",
|
||||
PreviousSearches = "previous-searches",
|
||||
LastSearch = "last-search",
|
||||
}
|
||||
|
||||
// types
|
||||
export enum BoardPageType {
|
||||
List = "list",
|
||||
Kanban = "kanban",
|
||||
StatusGrid = "status-grid",
|
||||
List = "list",
|
||||
Kanban = "kanban",
|
||||
StatusGrid = "status-grid",
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import BoardsAndTasksModel, {
|
||||
TaskFileContent,
|
||||
TaskFileContent,
|
||||
} from "../../Model/Files/boardsAndTasksModel";
|
||||
import CalendarModel, { MonthGrid } from "../../Model/Files/calendarModel";
|
||||
|
||||
@@ -14,201 +14,208 @@ import TaskViewModel from "./taskViewModel";
|
||||
export const CALENDAR_EVENT_BOARD_ID = "events";
|
||||
|
||||
export default class CalendarPageViewModel extends TaskContainingPageViewModel {
|
||||
storageModel: StorageModel;
|
||||
calendarModel: CalendarModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
storageModel: StorageModel;
|
||||
calendarModel: CalendarModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
|
||||
// data
|
||||
get monthString(): string {
|
||||
return CalendarModel.getMonthString(
|
||||
this.selectedYear.value.toString(),
|
||||
this.selectedMonth.value.toString()
|
||||
);
|
||||
}
|
||||
|
||||
// paths
|
||||
getBasePath = (): string[] => {
|
||||
return [...this.calendarModel.getViewPath()];
|
||||
};
|
||||
|
||||
// state
|
||||
selectedYear: React.State<number> = new React.State(0);
|
||||
selectedMonth: React.State<number> = new React.State(0);
|
||||
selectedDate: React.State<number> = new React.State(0);
|
||||
|
||||
monthGrid: React.State<MonthGrid<React.MapState<TaskViewModel>> | undefined> =
|
||||
new React.State<any>(undefined);
|
||||
|
||||
// methods
|
||||
createEvent = (): void => {
|
||||
const taskFileContent: TaskFileContent =
|
||||
this.boardsAndTasksModel.createTask(CALENDAR_EVENT_BOARD_ID);
|
||||
taskFileContent.date = CalendarModel.getISODateString(
|
||||
this.selectedYear.value.toString(),
|
||||
this.selectedMonth.value.toString(),
|
||||
this.selectedDate.value.toString()
|
||||
);
|
||||
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent
|
||||
);
|
||||
|
||||
this.selectTask(taskViewModel);
|
||||
this.updateTaskIndices();
|
||||
};
|
||||
|
||||
getEventsForDate = (): React.MapState<TaskViewModel> | undefined => {
|
||||
const paddedDate: string = CalendarModel.padDateOrMonth(
|
||||
this.selectedDate.toString()
|
||||
);
|
||||
|
||||
if (this.monthGrid.value == undefined) {
|
||||
return undefined;
|
||||
// data
|
||||
get monthString(): string {
|
||||
return CalendarModel.getMonthString(
|
||||
this.selectedYear.value.toString(),
|
||||
this.selectedMonth.value.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
return this.monthGrid.value.days[paddedDate];
|
||||
};
|
||||
// paths
|
||||
getBasePath = (): string[] => {
|
||||
return [...this.calendarModel.getViewPath()];
|
||||
};
|
||||
|
||||
// view
|
||||
getTaskMapState = (
|
||||
taskFileContent: TaskFileContent
|
||||
): React.MapState<TaskViewModel> | null => {
|
||||
if (this.monthGrid.value == null) return null;
|
||||
// state
|
||||
selectedYear: React.State<number> = new React.State(0);
|
||||
selectedMonth: React.State<number> = new React.State(0);
|
||||
selectedDate: React.State<number> = new React.State(0);
|
||||
|
||||
const date: string = CalendarModel.isoToDateString(
|
||||
taskFileContent.date ?? ""
|
||||
);
|
||||
return this.monthGrid.value.days[date];
|
||||
};
|
||||
monthGrid: React.State<
|
||||
MonthGrid<React.MapState<TaskViewModel>> | undefined
|
||||
> = new React.State<any>(undefined);
|
||||
|
||||
showTask = (taskFileContent: TaskFileContent): void => {
|
||||
const monthString: string | undefined = CalendarModel.isoToMonthString(
|
||||
taskFileContent.date ?? ""
|
||||
);
|
||||
if (monthString == undefined || monthString != this.monthString) {
|
||||
this.removeTaskFromView(taskFileContent);
|
||||
this.calendarModel.deleteTaskReference(
|
||||
this.monthString,
|
||||
taskFileContent.fileId
|
||||
);
|
||||
return;
|
||||
// methods
|
||||
createEvent = (): void => {
|
||||
const taskFileContent: TaskFileContent =
|
||||
this.boardsAndTasksModel.createTask(CALENDAR_EVENT_BOARD_ID);
|
||||
taskFileContent.date = CalendarModel.getISODateString(
|
||||
this.selectedYear.value.toString(),
|
||||
this.selectedMonth.value.toString(),
|
||||
this.selectedDate.value.toString(),
|
||||
);
|
||||
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent,
|
||||
);
|
||||
|
||||
this.selectTask(taskViewModel);
|
||||
this.updateTaskIndices();
|
||||
};
|
||||
|
||||
getEventsForDate = (): React.MapState<TaskViewModel> | undefined => {
|
||||
const paddedDate: string = CalendarModel.padDateOrMonth(
|
||||
this.selectedDate.toString(),
|
||||
);
|
||||
|
||||
if (this.monthGrid.value == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.monthGrid.value.days[paddedDate];
|
||||
};
|
||||
|
||||
// view
|
||||
getTaskMapState = (
|
||||
taskFileContent: TaskFileContent,
|
||||
): React.MapState<TaskViewModel> | null => {
|
||||
if (this.monthGrid.value == null) return null;
|
||||
|
||||
const date: string = CalendarModel.isoToDateString(
|
||||
taskFileContent.date ?? "",
|
||||
);
|
||||
return this.monthGrid.value.days[date];
|
||||
};
|
||||
|
||||
showTask = (taskFileContent: TaskFileContent): void => {
|
||||
const monthString: string | undefined = CalendarModel.isoToMonthString(
|
||||
taskFileContent.date ?? "",
|
||||
);
|
||||
if (monthString == undefined || monthString != this.monthString) {
|
||||
this.removeTaskFromView(taskFileContent);
|
||||
this.calendarModel.deleteTaskReference(
|
||||
this.monthString,
|
||||
taskFileContent.fileId,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent,
|
||||
);
|
||||
const mapState: React.MapState<TaskViewModel> | null =
|
||||
this.getTaskMapState(taskFileContent);
|
||||
|
||||
this.taskViewModels.handleRemoval(taskViewModel, () => {
|
||||
mapState?.remove(taskFileContent.fileId);
|
||||
});
|
||||
|
||||
this.taskViewModels.remove(taskFileContent.fileId);
|
||||
this.taskViewModels.set(taskFileContent.fileId, taskViewModel);
|
||||
|
||||
mapState?.set(taskFileContent.fileId, taskViewModel);
|
||||
};
|
||||
|
||||
removeTaskFromView = (taskFileContent: TaskFileContent): void => {
|
||||
this.taskViewModels.remove(taskFileContent.fileId);
|
||||
};
|
||||
|
||||
showToday = (): void => {
|
||||
const today: Date = new Date();
|
||||
this.selectedYear.value = today.getFullYear();
|
||||
this.selectedMonth.value = today.getMonth() + 1;
|
||||
this.selectedDate.value = today.getDate();
|
||||
};
|
||||
|
||||
showPreviousMonth = (): void => {
|
||||
this.selectedMonth.value -= 1;
|
||||
|
||||
if (this.selectedMonth.value <= 0) {
|
||||
this.selectedYear.value -= 1;
|
||||
this.selectedMonth.value = 12;
|
||||
}
|
||||
};
|
||||
|
||||
showNextMonth = (): void => {
|
||||
this.selectedMonth.value += 1;
|
||||
|
||||
if (this.selectedMonth.value >= 13) {
|
||||
this.selectedYear.value += 1;
|
||||
this.selectedMonth.value = 1;
|
||||
}
|
||||
};
|
||||
|
||||
handleDrop = (year: string, month: string, date: string): void => {
|
||||
const ISOString: string = CalendarModel.getISODateString(
|
||||
year,
|
||||
month,
|
||||
date,
|
||||
);
|
||||
|
||||
const draggedObject: any = this.coreViewModel.draggedObject.value;
|
||||
if (draggedObject instanceof TaskViewModel == false) return;
|
||||
|
||||
draggedObject.setDate(ISOString);
|
||||
};
|
||||
|
||||
// load
|
||||
loadMonthTasks = (): void => {
|
||||
this.monthGrid.value = this.calendarModel.generateMonthGrid(
|
||||
this.selectedYear.value,
|
||||
this.selectedMonth.value,
|
||||
() => new React.MapState(),
|
||||
);
|
||||
const taskIds: string[] = this.calendarModel.listTaskIds(
|
||||
this.monthString,
|
||||
);
|
||||
|
||||
for (const taskId of taskIds) {
|
||||
const taskFileContent: TaskFileContent | null =
|
||||
this.boardsAndTasksModel.getLatestTaskFileContent(taskId);
|
||||
if (taskFileContent == null) continue;
|
||||
this.showTask(taskFileContent);
|
||||
}
|
||||
|
||||
this.updateTaskIndices();
|
||||
};
|
||||
|
||||
loadData = (): void => {
|
||||
this.loadMonthTasks();
|
||||
this.showToday();
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
calendarModel: CalendarModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel,
|
||||
) {
|
||||
super(coreViewModel, chatViewModel, boardsAndTasksModel);
|
||||
|
||||
this.storageModel = storageModel;
|
||||
this.calendarModel = calendarModel;
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
|
||||
this.chatViewModel = chatViewModel;
|
||||
|
||||
React.bulkSubscribe([this.selectedYear, this.selectedMonth], () => {
|
||||
this.loadMonthTasks();
|
||||
});
|
||||
|
||||
// handlers
|
||||
boardsAndTasksModel.taskHandlerManager.addHandler(
|
||||
(taskFileContent: TaskFileContent) => {
|
||||
this.showTask(taskFileContent);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent
|
||||
);
|
||||
const mapState: React.MapState<TaskViewModel> | null =
|
||||
this.getTaskMapState(taskFileContent);
|
||||
|
||||
this.taskViewModels.handleRemoval(taskViewModel, () => {
|
||||
mapState?.remove(taskFileContent.fileId);
|
||||
});
|
||||
|
||||
this.taskViewModels.remove(taskFileContent.fileId);
|
||||
this.taskViewModels.set(taskFileContent.fileId, taskViewModel);
|
||||
|
||||
mapState?.set(taskFileContent.fileId, taskViewModel);
|
||||
};
|
||||
|
||||
removeTaskFromView = (taskFileContent: TaskFileContent): void => {
|
||||
this.taskViewModels.remove(taskFileContent.fileId);
|
||||
};
|
||||
|
||||
showToday = (): void => {
|
||||
const today: Date = new Date();
|
||||
this.selectedYear.value = today.getFullYear();
|
||||
this.selectedMonth.value = today.getMonth() + 1;
|
||||
this.selectedDate.value = today.getDate();
|
||||
};
|
||||
|
||||
showPreviousMonth = (): void => {
|
||||
this.selectedMonth.value -= 1;
|
||||
|
||||
if (this.selectedMonth.value <= 0) {
|
||||
this.selectedYear.value -= 1;
|
||||
this.selectedMonth.value = 12;
|
||||
}
|
||||
};
|
||||
|
||||
showNextMonth = (): void => {
|
||||
this.selectedMonth.value += 1;
|
||||
|
||||
if (this.selectedMonth.value >= 13) {
|
||||
this.selectedYear.value += 1;
|
||||
this.selectedMonth.value = 1;
|
||||
}
|
||||
};
|
||||
|
||||
handleDrop = (year: string, month: string, date: string): void => {
|
||||
const ISOString: string = CalendarModel.getISODateString(year, month, date);
|
||||
|
||||
const draggedObject: any = this.coreViewModel.draggedObject.value;
|
||||
if (draggedObject instanceof TaskViewModel == false) return;
|
||||
|
||||
draggedObject.setDate(ISOString);
|
||||
};
|
||||
|
||||
// load
|
||||
loadMonthTasks = (): void => {
|
||||
this.monthGrid.value = this.calendarModel.generateMonthGrid(
|
||||
this.selectedYear.value,
|
||||
this.selectedMonth.value,
|
||||
() => new React.MapState()
|
||||
);
|
||||
const taskIds: string[] = this.calendarModel.listTaskIds(this.monthString);
|
||||
|
||||
for (const taskId of taskIds) {
|
||||
const taskFileContent: TaskFileContent | null =
|
||||
this.boardsAndTasksModel.getLatestTaskFileContent(taskId);
|
||||
if (taskFileContent == null) continue;
|
||||
this.showTask(taskFileContent);
|
||||
}
|
||||
|
||||
this.updateTaskIndices();
|
||||
};
|
||||
|
||||
loadData = (): void => {
|
||||
this.loadMonthTasks();
|
||||
this.showToday();
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
calendarModel: CalendarModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel
|
||||
) {
|
||||
super(coreViewModel, chatViewModel, boardsAndTasksModel);
|
||||
|
||||
this.storageModel = storageModel;
|
||||
this.calendarModel = calendarModel;
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
|
||||
this.chatViewModel = chatViewModel;
|
||||
|
||||
React.bulkSubscribe([this.selectedYear, this.selectedMonth], () => {
|
||||
this.loadMonthTasks();
|
||||
});
|
||||
|
||||
// handlers
|
||||
boardsAndTasksModel.taskHandlerManager.addHandler(
|
||||
(taskFileContent: TaskFileContent) => {
|
||||
this.showTask(taskFileContent);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export enum TaskPageViewModelSubPath {
|
||||
LastUsedBoard = "last-used-board",
|
||||
LastUsedBoard = "last-used-board",
|
||||
}
|
||||
|
||||
@@ -6,76 +6,83 @@ import ChatViewModel from "../Chat/chatViewModel";
|
||||
import CoreViewModel from "../Global/coreViewModel";
|
||||
|
||||
export default class MessagePageViewModel {
|
||||
chatViewModel: ChatViewModel;
|
||||
chatViewModel: ChatViewModel;
|
||||
|
||||
// state
|
||||
chatMessageViewModels: React.MapState<ChatMessageViewModel> =
|
||||
new React.MapState();
|
||||
composingMessage: React.State<string> = new React.State("");
|
||||
// state
|
||||
chatMessageViewModels: React.MapState<ChatMessageViewModel> =
|
||||
new React.MapState();
|
||||
composingMessage: React.State<string> = new React.State("");
|
||||
|
||||
// guards
|
||||
cannotSendMessage: React.State<boolean>;
|
||||
// guards
|
||||
cannotSendMessage: React.State<boolean>;
|
||||
|
||||
// methods
|
||||
sendMessage = (): void => {
|
||||
if (this.cannotSendMessage.value == true) return;
|
||||
// methods
|
||||
sendMessage = (): void => {
|
||||
if (this.cannotSendMessage.value == true) return;
|
||||
|
||||
this.sendMessageFromBody(this.composingMessage.value);
|
||||
this.composingMessage.value = "";
|
||||
};
|
||||
this.sendMessageFromBody(this.composingMessage.value);
|
||||
this.composingMessage.value = "";
|
||||
};
|
||||
|
||||
sendMessageFromBody = (body: string): void => {
|
||||
this.chatViewModel.chatModel.sendMessage(body);
|
||||
};
|
||||
sendMessageFromBody = (body: string): void => {
|
||||
this.chatViewModel.chatModel.sendMessage(body);
|
||||
};
|
||||
|
||||
decryptMessage = async (
|
||||
messageViewModel: ChatMessageViewModel
|
||||
): Promise<void> => {
|
||||
const chatMessage: ChatMessage = messageViewModel.chatMessage;
|
||||
await this.chatViewModel.chatModel.decryptMessage(chatMessage);
|
||||
this.chatViewModel.chatModel.addMessage(chatMessage);
|
||||
messageViewModel.loadData();
|
||||
};
|
||||
decryptMessage = async (
|
||||
messageViewModel: ChatMessageViewModel,
|
||||
): Promise<void> => {
|
||||
const chatMessage: ChatMessage = messageViewModel.chatMessage;
|
||||
await this.chatViewModel.chatModel.decryptMessage(chatMessage);
|
||||
this.chatViewModel.chatModel.addMessage(chatMessage);
|
||||
messageViewModel.loadData();
|
||||
};
|
||||
|
||||
// view
|
||||
showChatMessage = (chatMessage: ChatMessage): void => {
|
||||
const chatMessageViewModel = new ChatMessageViewModel(
|
||||
this.coreViewModel,
|
||||
this,
|
||||
chatMessage,
|
||||
chatMessage.sender == this.chatViewModel.settingsViewModel.username.value
|
||||
);
|
||||
// view
|
||||
showChatMessage = (chatMessage: ChatMessage): void => {
|
||||
const chatMessageViewModel = new ChatMessageViewModel(
|
||||
this.coreViewModel,
|
||||
this,
|
||||
chatMessage,
|
||||
chatMessage.sender ==
|
||||
this.chatViewModel.settingsViewModel.username.value,
|
||||
);
|
||||
|
||||
const existingChatMessageViewModel: ChatMessageViewModel | undefined =
|
||||
this.chatMessageViewModels.value.get(chatMessage.id);
|
||||
if (existingChatMessageViewModel != undefined) {
|
||||
existingChatMessageViewModel.body.value = chatMessage.body;
|
||||
existingChatMessageViewModel.status.value = chatMessage.status;
|
||||
} else {
|
||||
this.chatMessageViewModels.set(chatMessage.id, chatMessageViewModel);
|
||||
const existingChatMessageViewModel: ChatMessageViewModel | undefined =
|
||||
this.chatMessageViewModels.value.get(chatMessage.id);
|
||||
if (existingChatMessageViewModel != undefined) {
|
||||
existingChatMessageViewModel.body.value = chatMessage.body;
|
||||
existingChatMessageViewModel.status.value = chatMessage.status;
|
||||
} else {
|
||||
this.chatMessageViewModels.set(
|
||||
chatMessage.id,
|
||||
chatMessageViewModel,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// load
|
||||
loadData = (): void => {
|
||||
this.chatMessageViewModels.clear();
|
||||
for (const chatMessage of this.chatViewModel.chatModel.messages) {
|
||||
this.showChatMessage(chatMessage);
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
chatViewModel: ChatViewModel,
|
||||
) {
|
||||
this.chatViewModel = chatViewModel;
|
||||
|
||||
this.cannotSendMessage = React.createProxyState(
|
||||
[
|
||||
this.chatViewModel.settingsViewModel.username,
|
||||
this.composingMessage,
|
||||
],
|
||||
() =>
|
||||
this.chatViewModel.settingsViewModel.username.value == "" ||
|
||||
this.composingMessage.value == "",
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// load
|
||||
loadData = (): void => {
|
||||
this.chatMessageViewModels.clear();
|
||||
for (const chatMessage of this.chatViewModel.chatModel.messages) {
|
||||
this.showChatMessage(chatMessage);
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
chatViewModel: ChatViewModel
|
||||
) {
|
||||
this.chatViewModel = chatViewModel;
|
||||
|
||||
this.cannotSendMessage = React.createProxyState(
|
||||
[this.chatViewModel.settingsViewModel.username, this.composingMessage],
|
||||
() =>
|
||||
this.chatViewModel.settingsViewModel.username.value == "" ||
|
||||
this.composingMessage.value == ""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,128 +5,128 @@ import { Color } from "../../colors";
|
||||
import CoreViewModel from "../Global/coreViewModel";
|
||||
|
||||
export default class SettingsPageViewModel {
|
||||
chatViewModel: ChatViewModel;
|
||||
chatViewModel: ChatViewModel;
|
||||
|
||||
// state
|
||||
primaryChannel: React.State<string> = new React.State("");
|
||||
primaryChannelInput: React.State<string> = new React.State("");
|
||||
// state
|
||||
primaryChannel: React.State<string> = new React.State("");
|
||||
primaryChannelInput: React.State<string> = new React.State("");
|
||||
|
||||
secondaryChannels: React.ListState<string> = new React.ListState();
|
||||
newSecondaryChannelInput: React.State<string> = new React.State("");
|
||||
secondaryChannels: React.ListState<string> = new React.ListState();
|
||||
newSecondaryChannelInput: React.State<string> = new React.State("");
|
||||
|
||||
encryptionKeyInput: React.State<string> = new React.State("");
|
||||
shouldShowEncryptionKey: React.State<boolean> = new React.State(false);
|
||||
encryptionKeyInputType: React.State<"text" | "password"> =
|
||||
React.createProxyState([this.shouldShowEncryptionKey], () =>
|
||||
this.shouldShowEncryptionKey.value == true ? "text" : "password"
|
||||
encryptionKeyInput: React.State<string> = new React.State("");
|
||||
shouldShowEncryptionKey: React.State<boolean> = new React.State(false);
|
||||
encryptionKeyInputType: React.State<"text" | "password"> =
|
||||
React.createProxyState([this.shouldShowEncryptionKey], () =>
|
||||
this.shouldShowEncryptionKey.value == true ? "text" : "password",
|
||||
);
|
||||
|
||||
color: React.State<Color> = new React.State<any>(Color.Standard);
|
||||
|
||||
// guards
|
||||
cannotSetPrimaryChannel: React.State<boolean> = React.createProxyState(
|
||||
[this.primaryChannel, this.primaryChannelInput],
|
||||
() =>
|
||||
this.primaryChannelInput.value == "" ||
|
||||
this.primaryChannelInput.value == this.primaryChannel.value,
|
||||
);
|
||||
|
||||
color: React.State<Color> = new React.State<any>(Color.Standard);
|
||||
|
||||
// guards
|
||||
cannotSetPrimaryChannel: React.State<boolean> = React.createProxyState(
|
||||
[this.primaryChannel, this.primaryChannelInput],
|
||||
() =>
|
||||
this.primaryChannelInput.value == "" ||
|
||||
this.primaryChannelInput.value == this.primaryChannel.value
|
||||
);
|
||||
cannotAddSecondaryChannel: React.State<boolean> = React.createProxyState(
|
||||
[this.newSecondaryChannelInput],
|
||||
() => this.newSecondaryChannelInput.value == ""
|
||||
);
|
||||
cannotSetEncryptionKey: React.State<boolean>;
|
||||
|
||||
// methods
|
||||
setPrimaryChannel = (): void => {
|
||||
this.chatViewModel.chatModel.setPrimaryChannel(
|
||||
this.primaryChannelInput.value
|
||||
cannotAddSecondaryChannel: React.State<boolean> = React.createProxyState(
|
||||
[this.newSecondaryChannelInput],
|
||||
() => this.newSecondaryChannelInput.value == "",
|
||||
);
|
||||
this.primaryChannel.value =
|
||||
this.chatViewModel.chatModel.info.primaryChannel;
|
||||
cannotSetEncryptionKey: React.State<boolean>;
|
||||
|
||||
this.chatViewModel.chatListViewModel.updateIndices();
|
||||
};
|
||||
// methods
|
||||
setPrimaryChannel = (): void => {
|
||||
this.chatViewModel.chatModel.setPrimaryChannel(
|
||||
this.primaryChannelInput.value,
|
||||
);
|
||||
this.primaryChannel.value =
|
||||
this.chatViewModel.chatModel.info.primaryChannel;
|
||||
|
||||
addSecondaryChannel = (): void => {
|
||||
this.secondaryChannels.add(this.newSecondaryChannelInput.value);
|
||||
this.newSecondaryChannelInput.value = "";
|
||||
this.storeSecondaryChannels();
|
||||
this.loadSecondaryChannels();
|
||||
};
|
||||
this.chatViewModel.chatListViewModel.updateIndices();
|
||||
};
|
||||
|
||||
removeSecondaryChannel = (secondaryChannel: string): void => {
|
||||
this.secondaryChannels.remove(secondaryChannel);
|
||||
this.storeSecondaryChannels();
|
||||
};
|
||||
addSecondaryChannel = (): void => {
|
||||
this.secondaryChannels.add(this.newSecondaryChannelInput.value);
|
||||
this.newSecondaryChannelInput.value = "";
|
||||
this.storeSecondaryChannels();
|
||||
this.loadSecondaryChannels();
|
||||
};
|
||||
|
||||
storeSecondaryChannels = (): void => {
|
||||
this.chatViewModel.chatModel.setSecondaryChannels([
|
||||
...this.secondaryChannels.value.values(),
|
||||
]);
|
||||
};
|
||||
removeSecondaryChannel = (secondaryChannel: string): void => {
|
||||
this.secondaryChannels.remove(secondaryChannel);
|
||||
this.storeSecondaryChannels();
|
||||
};
|
||||
|
||||
setEncryptionKey = (): void => {
|
||||
this.chatViewModel.chatModel.setEncryptionKey(
|
||||
this.encryptionKeyInput.value
|
||||
);
|
||||
storeSecondaryChannels = (): void => {
|
||||
this.chatViewModel.chatModel.setSecondaryChannels([
|
||||
...this.secondaryChannels.value.values(),
|
||||
]);
|
||||
};
|
||||
|
||||
// disable button
|
||||
this.encryptionKeyInput.callSubscriptions();
|
||||
};
|
||||
setEncryptionKey = (): void => {
|
||||
this.chatViewModel.chatModel.setEncryptionKey(
|
||||
this.encryptionKeyInput.value,
|
||||
);
|
||||
|
||||
applyColor = (newColor: Color): void => {
|
||||
this.chatViewModel.setColor(newColor);
|
||||
};
|
||||
// disable button
|
||||
this.encryptionKeyInput.callSubscriptions();
|
||||
};
|
||||
|
||||
remove = (): void => {
|
||||
this.chatViewModel.close();
|
||||
this.chatViewModel.chatModel.delete();
|
||||
this.chatViewModel.chatListViewModel.untrackChat(this.chatViewModel);
|
||||
};
|
||||
applyColor = (newColor: Color): void => {
|
||||
this.chatViewModel.setColor(newColor);
|
||||
};
|
||||
|
||||
// load
|
||||
loadListRelevantData = (): void => {
|
||||
this.primaryChannel.value =
|
||||
this.chatViewModel.chatModel.info.primaryChannel;
|
||||
remove = (): void => {
|
||||
this.chatViewModel.close();
|
||||
this.chatViewModel.chatModel.delete();
|
||||
this.chatViewModel.chatListViewModel.untrackChat(this.chatViewModel);
|
||||
};
|
||||
|
||||
this.color.value = this.chatViewModel.chatModel.color;
|
||||
};
|
||||
// load
|
||||
loadListRelevantData = (): void => {
|
||||
this.primaryChannel.value =
|
||||
this.chatViewModel.chatModel.info.primaryChannel;
|
||||
|
||||
loadData = (): void => {
|
||||
this.primaryChannelInput.value =
|
||||
this.chatViewModel.chatModel.info.primaryChannel;
|
||||
this.color.value = this.chatViewModel.chatModel.color;
|
||||
};
|
||||
|
||||
this.loadSecondaryChannels();
|
||||
loadData = (): void => {
|
||||
this.primaryChannelInput.value =
|
||||
this.chatViewModel.chatModel.info.primaryChannel;
|
||||
|
||||
this.encryptionKeyInput.value =
|
||||
this.chatViewModel.chatModel.info.encryptionKey;
|
||||
};
|
||||
this.loadSecondaryChannels();
|
||||
|
||||
loadSecondaryChannels = (): void => {
|
||||
this.secondaryChannels.clear();
|
||||
for (const secondaryChannel of this.chatViewModel.chatModel
|
||||
.secondaryChannels) {
|
||||
this.secondaryChannels.add(secondaryChannel);
|
||||
this.encryptionKeyInput.value =
|
||||
this.chatViewModel.chatModel.info.encryptionKey;
|
||||
};
|
||||
|
||||
loadSecondaryChannels = (): void => {
|
||||
this.secondaryChannels.clear();
|
||||
for (const secondaryChannel of this.chatViewModel.chatModel
|
||||
.secondaryChannels) {
|
||||
this.secondaryChannels.add(secondaryChannel);
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
chatViewModel: ChatViewModel,
|
||||
) {
|
||||
this.chatViewModel = chatViewModel;
|
||||
this.loadListRelevantData();
|
||||
|
||||
this.cannotSetEncryptionKey = React.createProxyState(
|
||||
[this.encryptionKeyInput],
|
||||
() =>
|
||||
this.encryptionKeyInput.value ==
|
||||
this.chatViewModel.chatModel.info.encryptionKey,
|
||||
);
|
||||
|
||||
this.color.subscribe((newColor) => {
|
||||
this.applyColor(newColor);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
chatViewModel: ChatViewModel
|
||||
) {
|
||||
this.chatViewModel = chatViewModel;
|
||||
this.loadListRelevantData();
|
||||
|
||||
this.cannotSetEncryptionKey = React.createProxyState(
|
||||
[this.encryptionKeyInput],
|
||||
() =>
|
||||
this.encryptionKeyInput.value ==
|
||||
this.chatViewModel.chatModel.info.encryptionKey
|
||||
);
|
||||
|
||||
this.color.subscribe((newColor) => {
|
||||
this.applyColor(newColor);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import BoardsAndTasksModel, {
|
||||
TaskFileContent,
|
||||
TaskFileContent,
|
||||
} from "../../Model/Files/boardsAndTasksModel";
|
||||
|
||||
import ChatViewModel from "../Chat/chatViewModel";
|
||||
@@ -10,58 +10,58 @@ import { IndexManager } from "../../Model/Utility/utility";
|
||||
import TaskViewModel from "./taskViewModel";
|
||||
|
||||
export default class TaskContainingPageViewModel {
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
|
||||
// state
|
||||
taskIndexManager: IndexManager<TaskViewModel> = new IndexManager(
|
||||
(taskViewModel: TaskViewModel) => taskViewModel.sortingString
|
||||
);
|
||||
|
||||
selectedTaskViewModel: React.State<TaskViewModel | undefined> =
|
||||
new React.State<any>(undefined);
|
||||
|
||||
taskViewModels: React.MapState<TaskViewModel> = new React.MapState();
|
||||
|
||||
// methods
|
||||
createTaskFromBoardId = (boardId: string): void => {
|
||||
const taskFileContent: TaskFileContent =
|
||||
this.boardsAndTasksModel.createTask(boardId);
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent
|
||||
// state
|
||||
taskIndexManager: IndexManager<TaskViewModel> = new IndexManager(
|
||||
(taskViewModel: TaskViewModel) => taskViewModel.sortingString,
|
||||
);
|
||||
this.selectTask(taskViewModel);
|
||||
this.updateTaskIndices();
|
||||
};
|
||||
|
||||
// view
|
||||
showTask = (taskFileContent: TaskFileContent): void => {};
|
||||
removeTaskFromView = (taskFileContent: TaskFileContent): void => {};
|
||||
selectedTaskViewModel: React.State<TaskViewModel | undefined> =
|
||||
new React.State<any>(undefined);
|
||||
|
||||
selectTask = (selectedTask: TaskViewModel): void => {
|
||||
this.selectedTaskViewModel.value = selectedTask;
|
||||
};
|
||||
taskViewModels: React.MapState<TaskViewModel> = new React.MapState();
|
||||
|
||||
closeTask = () => {
|
||||
this.selectedTaskViewModel.value = undefined;
|
||||
};
|
||||
// methods
|
||||
createTaskFromBoardId = (boardId: string): void => {
|
||||
const taskFileContent: TaskFileContent =
|
||||
this.boardsAndTasksModel.createTask(boardId);
|
||||
const taskViewModel: TaskViewModel = new TaskViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
taskFileContent,
|
||||
);
|
||||
this.selectTask(taskViewModel);
|
||||
this.updateTaskIndices();
|
||||
};
|
||||
|
||||
updateTaskIndices = (): void => {
|
||||
this.taskIndexManager.update([...this.taskViewModels.value.values()]);
|
||||
for (const boardViewModel of this.taskViewModels.value.values()) {
|
||||
boardViewModel.updateIndex();
|
||||
// view
|
||||
showTask = (taskFileContent: TaskFileContent): void => {};
|
||||
removeTaskFromView = (taskFileContent: TaskFileContent): void => {};
|
||||
|
||||
selectTask = (selectedTask: TaskViewModel): void => {
|
||||
this.selectedTaskViewModel.value = selectedTask;
|
||||
};
|
||||
|
||||
closeTask = () => {
|
||||
this.selectedTaskViewModel.value = undefined;
|
||||
};
|
||||
|
||||
updateTaskIndices = (): void => {
|
||||
this.taskIndexManager.update([...this.taskViewModels.value.values()]);
|
||||
for (const boardViewModel of this.taskViewModels.value.values()) {
|
||||
boardViewModel.updateIndex();
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel,
|
||||
) {
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
}
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel
|
||||
) {
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import BoardsAndTasksModel, {
|
||||
BoardInfoFileContent,
|
||||
BoardInfoFileContent,
|
||||
} from "../../Model/Files/boardsAndTasksModel";
|
||||
|
||||
import BoardViewModel from "./boardViewModel";
|
||||
@@ -11,169 +11,169 @@ import { IndexManager } from "../../Model/Utility/utility";
|
||||
import StorageModel from "../../Model/Global/storageModel";
|
||||
|
||||
export default class TaskPageViewModel {
|
||||
storageModel: StorageModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
storageModel: StorageModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
|
||||
// data
|
||||
boardIndexManager: IndexManager<BoardViewModel> = new IndexManager(
|
||||
(boardViewModel: BoardViewModel) => boardViewModel.name.value
|
||||
);
|
||||
|
||||
// paths
|
||||
getBasePath = (): string[] => {
|
||||
return [...this.boardsAndTasksModel.getViewPath()];
|
||||
};
|
||||
|
||||
getBoardViewPath = (boardId): string[] => {
|
||||
return [...this.getBasePath(), boardId];
|
||||
};
|
||||
|
||||
getLastUsedBoardPath = (): string[] => {
|
||||
return [...this.getBasePath(), TaskPageViewModelSubPath.LastUsedBoard];
|
||||
};
|
||||
|
||||
// state
|
||||
newBoardNameInput: React.State<string> = new React.State("");
|
||||
|
||||
boardViewModels: React.MapState<BoardViewModel> = new React.MapState();
|
||||
|
||||
isShowingBoadList: React.State<boolean> = new React.State(true);
|
||||
|
||||
selectedBoardId: React.State<string | undefined> = new React.State<any>(
|
||||
undefined
|
||||
);
|
||||
|
||||
// guards
|
||||
cannotCreateBoard: React.State<boolean> = React.createProxyState(
|
||||
[this.newBoardNameInput],
|
||||
() => this.newBoardNameInput.value == ""
|
||||
);
|
||||
|
||||
// methods
|
||||
createBoard = (): void => {
|
||||
if (this.cannotCreateBoard.value == true) return;
|
||||
|
||||
const boardInfoFileContent: BoardInfoFileContent =
|
||||
this.boardsAndTasksModel.createBoard(this.newBoardNameInput.value);
|
||||
this.newBoardNameInput.value = "";
|
||||
|
||||
this.showBoardInList(boardInfoFileContent);
|
||||
this.boardsAndTasksModel.updateBoardAndSend(boardInfoFileContent);
|
||||
this.updateBoardIndices();
|
||||
};
|
||||
|
||||
updateBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
|
||||
this.boardsAndTasksModel.updateBoardAndSend(boardInfoFileContent);
|
||||
this.updateBoardIndices();
|
||||
};
|
||||
|
||||
deleteBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
|
||||
this.boardsAndTasksModel.deleteBoard(boardInfoFileContent.fileId);
|
||||
this.boardViewModels.remove(boardInfoFileContent.fileId);
|
||||
this.updateBoardIndices();
|
||||
};
|
||||
|
||||
// view
|
||||
toggleBoardList = (): void => {
|
||||
this.isShowingBoadList.value = !this.isShowingBoadList.value;
|
||||
};
|
||||
|
||||
showBoardInList = (boardInfo: BoardInfoFileContent): void => {
|
||||
const boardViewModel: BoardViewModel = new BoardViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.storageModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
boardInfo
|
||||
// data
|
||||
boardIndexManager: IndexManager<BoardViewModel> = new IndexManager(
|
||||
(boardViewModel: BoardViewModel) => boardViewModel.name.value,
|
||||
);
|
||||
this.boardViewModels.set(boardInfo.fileId, boardViewModel);
|
||||
|
||||
this.chatViewModel.taskBoardSuggestions.set(boardInfo.fileId, [
|
||||
boardInfo.fileId,
|
||||
this.boardsAndTasksModel.getBoardName(boardInfo.fileId),
|
||||
]);
|
||||
};
|
||||
// paths
|
||||
getBasePath = (): string[] => {
|
||||
return [...this.boardsAndTasksModel.getViewPath()];
|
||||
};
|
||||
|
||||
selectBoard = (boardViewModel: BoardViewModel): void => {
|
||||
this.selectedBoardId.value = boardViewModel.boardInfo.fileId;
|
||||
this.chatViewModel.displayedColor.value = boardViewModel.color.value;
|
||||
getBoardViewPath = (boardId): string[] => {
|
||||
return [...this.getBasePath(), boardId];
|
||||
};
|
||||
|
||||
this.storeLastUsedBoard();
|
||||
};
|
||||
getLastUsedBoardPath = (): string[] => {
|
||||
return [...this.getBasePath(), TaskPageViewModelSubPath.LastUsedBoard];
|
||||
};
|
||||
|
||||
closeBoard = (): void => {
|
||||
this.selectedBoardId.value = undefined;
|
||||
this.chatViewModel.resetColor();
|
||||
// state
|
||||
newBoardNameInput: React.State<string> = new React.State("");
|
||||
|
||||
this.storeLastUsedBoard();
|
||||
};
|
||||
boardViewModels: React.MapState<BoardViewModel> = new React.MapState();
|
||||
|
||||
updateBoardIndices = (): void => {
|
||||
this.boardIndexManager.update([...this.boardViewModels.value.values()]);
|
||||
for (const boardViewModel of this.boardViewModels.value.values()) {
|
||||
boardViewModel.updateIndex();
|
||||
}
|
||||
};
|
||||
isShowingBoadList: React.State<boolean> = new React.State(true);
|
||||
|
||||
// storage
|
||||
storeLastUsedBoard = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedBoardId: string = this.selectedBoardId.value ?? "";
|
||||
this.storageModel.write(path, lastUsedBoardId);
|
||||
};
|
||||
selectedBoardId: React.State<string | undefined> = new React.State<any>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
openLastUsedBoard = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedBoardId: string | null = this.storageModel.read(path);
|
||||
if (lastUsedBoardId == null) return;
|
||||
// guards
|
||||
cannotCreateBoard: React.State<boolean> = React.createProxyState(
|
||||
[this.newBoardNameInput],
|
||||
() => this.newBoardNameInput.value == "",
|
||||
);
|
||||
|
||||
const boardViewModel: BoardViewModel | undefined =
|
||||
this.boardViewModels.value.get(lastUsedBoardId);
|
||||
if (boardViewModel == undefined) return;
|
||||
// methods
|
||||
createBoard = (): void => {
|
||||
if (this.cannotCreateBoard.value == true) return;
|
||||
|
||||
this.selectBoard(boardViewModel);
|
||||
};
|
||||
const boardInfoFileContent: BoardInfoFileContent =
|
||||
this.boardsAndTasksModel.createBoard(this.newBoardNameInput.value);
|
||||
this.newBoardNameInput.value = "";
|
||||
|
||||
// load
|
||||
loadData = (): void => {
|
||||
this.boardViewModels.clear();
|
||||
|
||||
const boardIds: string[] = this.boardsAndTasksModel.listBoardIds();
|
||||
for (const boardId of boardIds) {
|
||||
const boardInfo: BoardInfoFileContent | null =
|
||||
this.boardsAndTasksModel.getBoardInfo(boardId);
|
||||
if (boardInfo == null) continue;
|
||||
|
||||
this.showBoardInList(boardInfo);
|
||||
}
|
||||
|
||||
this.updateBoardIndices();
|
||||
this.openLastUsedBoard();
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
boardModel: BoardsAndTasksModel
|
||||
) {
|
||||
this.storageModel = storageModel;
|
||||
this.boardsAndTasksModel = boardModel;
|
||||
|
||||
this.chatViewModel = chatViewModel;
|
||||
|
||||
// handlers
|
||||
boardModel.boardHandlerManager.addHandler(
|
||||
(boardInfoFileContent: BoardInfoFileContent) => {
|
||||
this.showBoardInList(boardInfoFileContent);
|
||||
this.boardsAndTasksModel.updateBoardAndSend(boardInfoFileContent);
|
||||
this.updateBoardIndices();
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
updateBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
|
||||
this.boardsAndTasksModel.updateBoardAndSend(boardInfoFileContent);
|
||||
this.updateBoardIndices();
|
||||
};
|
||||
|
||||
deleteBoard = (boardInfoFileContent: BoardInfoFileContent): void => {
|
||||
this.boardsAndTasksModel.deleteBoard(boardInfoFileContent.fileId);
|
||||
this.boardViewModels.remove(boardInfoFileContent.fileId);
|
||||
this.updateBoardIndices();
|
||||
};
|
||||
|
||||
// view
|
||||
toggleBoardList = (): void => {
|
||||
this.isShowingBoadList.value = !this.isShowingBoadList.value;
|
||||
};
|
||||
|
||||
showBoardInList = (boardInfo: BoardInfoFileContent): void => {
|
||||
const boardViewModel: BoardViewModel = new BoardViewModel(
|
||||
this.coreViewModel,
|
||||
this.chatViewModel,
|
||||
this.storageModel,
|
||||
this.boardsAndTasksModel,
|
||||
this,
|
||||
boardInfo,
|
||||
);
|
||||
this.boardViewModels.set(boardInfo.fileId, boardViewModel);
|
||||
|
||||
this.chatViewModel.taskBoardSuggestions.set(boardInfo.fileId, [
|
||||
boardInfo.fileId,
|
||||
this.boardsAndTasksModel.getBoardName(boardInfo.fileId),
|
||||
]);
|
||||
};
|
||||
|
||||
selectBoard = (boardViewModel: BoardViewModel): void => {
|
||||
this.selectedBoardId.value = boardViewModel.boardInfo.fileId;
|
||||
this.chatViewModel.displayedColor.value = boardViewModel.color.value;
|
||||
|
||||
this.storeLastUsedBoard();
|
||||
};
|
||||
|
||||
closeBoard = (): void => {
|
||||
this.selectedBoardId.value = undefined;
|
||||
this.chatViewModel.resetColor();
|
||||
|
||||
this.storeLastUsedBoard();
|
||||
};
|
||||
|
||||
updateBoardIndices = (): void => {
|
||||
this.boardIndexManager.update([...this.boardViewModels.value.values()]);
|
||||
for (const boardViewModel of this.boardViewModels.value.values()) {
|
||||
boardViewModel.updateIndex();
|
||||
}
|
||||
};
|
||||
|
||||
// storage
|
||||
storeLastUsedBoard = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedBoardId: string = this.selectedBoardId.value ?? "";
|
||||
this.storageModel.write(path, lastUsedBoardId);
|
||||
};
|
||||
|
||||
openLastUsedBoard = (): void => {
|
||||
const path: string[] = this.getLastUsedBoardPath();
|
||||
const lastUsedBoardId: string | null = this.storageModel.read(path);
|
||||
if (lastUsedBoardId == null) return;
|
||||
|
||||
const boardViewModel: BoardViewModel | undefined =
|
||||
this.boardViewModels.value.get(lastUsedBoardId);
|
||||
if (boardViewModel == undefined) return;
|
||||
|
||||
this.selectBoard(boardViewModel);
|
||||
};
|
||||
|
||||
// load
|
||||
loadData = (): void => {
|
||||
this.boardViewModels.clear();
|
||||
|
||||
const boardIds: string[] = this.boardsAndTasksModel.listBoardIds();
|
||||
for (const boardId of boardIds) {
|
||||
const boardInfo: BoardInfoFileContent | null =
|
||||
this.boardsAndTasksModel.getBoardInfo(boardId);
|
||||
if (boardInfo == null) continue;
|
||||
|
||||
this.showBoardInList(boardInfo);
|
||||
}
|
||||
|
||||
this.updateBoardIndices();
|
||||
this.openLastUsedBoard();
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
storageModel: StorageModel,
|
||||
boardModel: BoardsAndTasksModel,
|
||||
) {
|
||||
this.storageModel = storageModel;
|
||||
this.boardsAndTasksModel = boardModel;
|
||||
|
||||
this.chatViewModel = chatViewModel;
|
||||
|
||||
// handlers
|
||||
boardModel.boardHandlerManager.addHandler(
|
||||
(boardInfoFileContent: BoardInfoFileContent) => {
|
||||
this.showBoardInList(boardInfoFileContent);
|
||||
this.updateBoardIndices();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export enum TaskPageViewModelSubPath {
|
||||
LastUsedBoard = "last-used-board",
|
||||
LastUsedBoard = "last-used-board",
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "bloatless-react";
|
||||
|
||||
import BoardsAndTasksModel, {
|
||||
TaskFileContent,
|
||||
TaskFileContent,
|
||||
} from "../../Model/Files/boardsAndTasksModel";
|
||||
import { localeCompare, padZero } from "../../Model/Utility/utility";
|
||||
|
||||
@@ -11,225 +11,235 @@ import TaskContainingPageViewModel from "./taskContainingPageViewModel";
|
||||
import { allowDrag } from "../../View/utility";
|
||||
|
||||
export default class TaskViewModel {
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
boardsAndTasksModel: BoardsAndTasksModel;
|
||||
|
||||
containingModel: TaskContainingPageViewModel;
|
||||
containingModel: TaskContainingPageViewModel;
|
||||
|
||||
// data
|
||||
task: TaskFileContent;
|
||||
// data
|
||||
task: TaskFileContent;
|
||||
|
||||
get sortingString(): string {
|
||||
const splitDate: string[] = this.date.value.split("-");
|
||||
const year = padZero(splitDate[0], 4);
|
||||
const month = padZero(splitDate[1], 2);
|
||||
const date = padZero(splitDate[2], 2);
|
||||
get sortingString(): string {
|
||||
const splitDate: string[] = this.date.value.split("-");
|
||||
const year = padZero(splitDate[0], 4);
|
||||
const month = padZero(splitDate[1], 2);
|
||||
const date = padZero(splitDate[2], 2);
|
||||
|
||||
const splitTime: string[] = this.time.value.split(":");
|
||||
const hour = padZero(splitTime[0], 2);
|
||||
const minute = padZero(splitTime[1], 2);
|
||||
const splitTime: string[] = this.time.value.split(":");
|
||||
const hour = padZero(splitTime[0], 2);
|
||||
const minute = padZero(splitTime[1], 2);
|
||||
|
||||
const priorityNumber = parseInt(this.priority.value);
|
||||
const invertedPriority = 100 - priorityNumber;
|
||||
const priorityNumber = parseInt(this.priority.value);
|
||||
const invertedPriority = 100 - priorityNumber;
|
||||
|
||||
return (
|
||||
year + month + date + hour + minute + invertedPriority + this.name.value
|
||||
);
|
||||
}
|
||||
|
||||
// paths
|
||||
getFilePath = (): string[] => {
|
||||
return this.boardsAndTasksModel.getTaskFilePath(this.task.fileId);
|
||||
};
|
||||
|
||||
// state
|
||||
index: React.State<number> = new React.State(0);
|
||||
|
||||
boardId: React.State<string> = new React.State("");
|
||||
|
||||
name: React.State<string> = new React.State("");
|
||||
description: React.State<string> = new React.State("");
|
||||
|
||||
category: React.State<string> = new React.State("");
|
||||
status: React.State<string> = new React.State("");
|
||||
priority: React.State<string> = new React.State("");
|
||||
|
||||
date: React.State<string> = new React.State("");
|
||||
time: React.State<string> = new React.State("");
|
||||
|
||||
selectedVersionId: React.State<string> = new React.State("");
|
||||
versionIds: React.ListState<string> = new React.ListState();
|
||||
|
||||
// methods
|
||||
dragStart = (event: DragEvent): void => {
|
||||
allowDrag(event);
|
||||
this.coreViewModel.draggedObject.value = this;
|
||||
};
|
||||
|
||||
setCategoryAndStatus = (category?: string, status?: string): void => {
|
||||
if (category != undefined) this.category.value = category;
|
||||
if (status != undefined) this.status.value = status;
|
||||
this.save();
|
||||
};
|
||||
|
||||
setBoardId = (boardId: string): void => {
|
||||
this.boardId.value = boardId;
|
||||
this.save();
|
||||
};
|
||||
|
||||
setDate = (dateISOString: string): void => {
|
||||
this.date.value = dateISOString;
|
||||
this.save();
|
||||
};
|
||||
|
||||
// view
|
||||
open = (): void => {
|
||||
this.containingModel.selectTask(this);
|
||||
};
|
||||
|
||||
close = (): void => {
|
||||
this.containingModel.closeTask();
|
||||
};
|
||||
|
||||
closeAndDiscard = (): void => {
|
||||
this.close();
|
||||
this.loadTaskData();
|
||||
}
|
||||
|
||||
closeAndSave = (): void => {
|
||||
this.close();
|
||||
this.save();
|
||||
};
|
||||
|
||||
updateIndex = (): void => {
|
||||
const index: number = this.containingModel.taskIndexManager.getIndex(this);
|
||||
this.index.value = index;
|
||||
};
|
||||
|
||||
updateSuggestions = (): void => {
|
||||
if (
|
||||
this.coreViewModel.taskCategorySuggestions.value.has(
|
||||
this.category.value
|
||||
) == false
|
||||
) {
|
||||
this.coreViewModel.taskCategorySuggestions.add(this.category.value);
|
||||
return (
|
||||
year +
|
||||
month +
|
||||
date +
|
||||
hour +
|
||||
minute +
|
||||
invertedPriority +
|
||||
this.name.value
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
this.coreViewModel.taskStatusSuggestions.value.has(this.status.value) ==
|
||||
false
|
||||
) {
|
||||
this.coreViewModel.taskStatusSuggestions.add(this.status.value);
|
||||
}
|
||||
};
|
||||
// paths
|
||||
getFilePath = (): string[] => {
|
||||
return this.boardsAndTasksModel.getTaskFilePath(this.task.fileId);
|
||||
};
|
||||
|
||||
// settings
|
||||
save = (): void => {
|
||||
const newTaskFileContent: TaskFileContent =
|
||||
BoardsAndTasksModel.createTaskFileContent(
|
||||
this.task.fileId,
|
||||
this.name.value,
|
||||
this.task.boardId
|
||||
);
|
||||
// state
|
||||
index: React.State<number> = new React.State(0);
|
||||
|
||||
newTaskFileContent.boardId = this.boardId.value;
|
||||
newTaskFileContent.description = this.description.value;
|
||||
newTaskFileContent.status = this.status.value;
|
||||
newTaskFileContent.category = this.category.value;
|
||||
newTaskFileContent.priority = this.priority.value;
|
||||
newTaskFileContent.date = this.date.value;
|
||||
newTaskFileContent.time = this.time.value;
|
||||
boardId: React.State<string> = new React.State("");
|
||||
|
||||
this.boardsAndTasksModel.updateTaskAndSend(newTaskFileContent);
|
||||
name: React.State<string> = new React.State("");
|
||||
description: React.State<string> = new React.State("");
|
||||
|
||||
this.containingModel.showTask(newTaskFileContent);
|
||||
this.containingModel.updateTaskIndices();
|
||||
category: React.State<string> = new React.State("");
|
||||
status: React.State<string> = new React.State("");
|
||||
priority: React.State<string> = new React.State("");
|
||||
|
||||
this.updateSuggestions();
|
||||
};
|
||||
date: React.State<string> = new React.State("");
|
||||
time: React.State<string> = new React.State("");
|
||||
|
||||
deleteTask = (): void => {
|
||||
this.close();
|
||||
this.boardsAndTasksModel.deleteTask(this.task.boardId, this.task.fileId);
|
||||
this.containingModel.removeTaskFromView(this.task);
|
||||
};
|
||||
selectedVersionId: React.State<string> = new React.State("");
|
||||
versionIds: React.ListState<string> = new React.ListState();
|
||||
|
||||
// load
|
||||
loadVersionIds = (): void => {
|
||||
const versionIds: string[] = this.boardsAndTasksModel.listTaskVersionIds(
|
||||
this.task.fileId
|
||||
);
|
||||
const sortedVersionIds = versionIds.sort(localeCompare).reverse();
|
||||
this.versionIds.clear();
|
||||
this.versionIds.add(...sortedVersionIds);
|
||||
};
|
||||
// methods
|
||||
dragStart = (event: DragEvent): void => {
|
||||
allowDrag(event);
|
||||
this.coreViewModel.draggedObject.value = this;
|
||||
};
|
||||
|
||||
switchVersion = (versionId: string): void => {
|
||||
const taskFileContent: TaskFileContent | null =
|
||||
this.boardsAndTasksModel.getSpecificTaskFileContent(
|
||||
this.task.fileId,
|
||||
versionId
|
||||
);
|
||||
if (taskFileContent == null) return;
|
||||
setCategoryAndStatus = (category?: string, status?: string): void => {
|
||||
if (category != undefined) this.category.value = category;
|
||||
if (status != undefined) this.status.value = status;
|
||||
this.save();
|
||||
};
|
||||
|
||||
this.task = taskFileContent;
|
||||
this.loadTaskData();
|
||||
};
|
||||
setBoardId = (boardId: string): void => {
|
||||
this.boardId.value = boardId;
|
||||
this.save();
|
||||
};
|
||||
|
||||
loadAllData = (): void => {
|
||||
this.loadTaskData();
|
||||
this.loadVersionIds();
|
||||
};
|
||||
setDate = (dateISOString: string): void => {
|
||||
this.date.value = dateISOString;
|
||||
this.save();
|
||||
};
|
||||
|
||||
loadTaskData = (): void => {
|
||||
this.boardId.value = this.task.boardId;
|
||||
// view
|
||||
open = (): void => {
|
||||
this.containingModel.selectTask(this);
|
||||
};
|
||||
|
||||
this.name.value = this.task.name;
|
||||
this.description.value = this.task.description ?? "";
|
||||
close = (): void => {
|
||||
this.containingModel.closeTask();
|
||||
};
|
||||
|
||||
this.category.value = this.task.category ?? "";
|
||||
this.status.value = this.task.status ?? "";
|
||||
this.priority.value = this.task.priority ?? "";
|
||||
closeAndDiscard = (): void => {
|
||||
this.close();
|
||||
this.loadTaskData();
|
||||
};
|
||||
|
||||
this.date.value = this.task.date ?? "";
|
||||
this.time.value = this.task.time ?? "";
|
||||
closeAndSave = (): void => {
|
||||
this.close();
|
||||
this.save();
|
||||
};
|
||||
|
||||
this.selectedVersionId.value = this.task.fileContentId;
|
||||
updateIndex = (): void => {
|
||||
const index: number =
|
||||
this.containingModel.taskIndexManager.getIndex(this);
|
||||
this.index.value = index;
|
||||
};
|
||||
|
||||
this.updateSuggestions();
|
||||
};
|
||||
updateSuggestions = (): void => {
|
||||
if (
|
||||
this.coreViewModel.taskCategorySuggestions.value.has(
|
||||
this.category.value,
|
||||
) == false
|
||||
) {
|
||||
this.coreViewModel.taskCategorySuggestions.add(this.category.value);
|
||||
}
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel,
|
||||
containingModel: TaskContainingPageViewModel,
|
||||
taskFileContent: TaskFileContent
|
||||
) {
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
this.containingModel = containingModel;
|
||||
if (
|
||||
this.coreViewModel.taskStatusSuggestions.value.has(
|
||||
this.status.value,
|
||||
) == false
|
||||
) {
|
||||
this.coreViewModel.taskStatusSuggestions.add(this.status.value);
|
||||
}
|
||||
};
|
||||
|
||||
this.task = taskFileContent;
|
||||
// settings
|
||||
save = (): void => {
|
||||
const newTaskFileContent: TaskFileContent =
|
||||
BoardsAndTasksModel.createTaskFileContent(
|
||||
this.task.fileId,
|
||||
this.name.value,
|
||||
this.task.boardId,
|
||||
);
|
||||
|
||||
newTaskFileContent.boardId = this.boardId.value;
|
||||
newTaskFileContent.description = this.description.value;
|
||||
newTaskFileContent.status = this.status.value;
|
||||
newTaskFileContent.category = this.category.value;
|
||||
newTaskFileContent.priority = this.priority.value;
|
||||
newTaskFileContent.date = this.date.value;
|
||||
newTaskFileContent.time = this.time.value;
|
||||
|
||||
this.boardsAndTasksModel.updateTaskAndSend(newTaskFileContent);
|
||||
|
||||
this.containingModel.showTask(newTaskFileContent);
|
||||
this.containingModel.updateTaskIndices();
|
||||
|
||||
this.updateSuggestions();
|
||||
};
|
||||
|
||||
deleteTask = (): void => {
|
||||
this.close();
|
||||
this.boardsAndTasksModel.deleteTask(
|
||||
this.task.boardId,
|
||||
this.task.fileId,
|
||||
);
|
||||
this.containingModel.removeTaskFromView(this.task);
|
||||
};
|
||||
|
||||
// load
|
||||
this.loadAllData();
|
||||
loadVersionIds = (): void => {
|
||||
const versionIds: string[] =
|
||||
this.boardsAndTasksModel.listTaskVersionIds(this.task.fileId);
|
||||
const sortedVersionIds = versionIds.sort(localeCompare).reverse();
|
||||
this.versionIds.clear();
|
||||
this.versionIds.add(...sortedVersionIds);
|
||||
};
|
||||
|
||||
// subscriptions
|
||||
this.selectedVersionId.subscribeSilent((selectedVersionId) => {
|
||||
this.switchVersion(selectedVersionId);
|
||||
});
|
||||
}
|
||||
switchVersion = (versionId: string): void => {
|
||||
const taskFileContent: TaskFileContent | null =
|
||||
this.boardsAndTasksModel.getSpecificTaskFileContent(
|
||||
this.task.fileId,
|
||||
versionId,
|
||||
);
|
||||
if (taskFileContent == null) return;
|
||||
|
||||
// utility
|
||||
static getStringsForFilter = (taskViewModel: TaskViewModel): string[] => {
|
||||
return [
|
||||
taskViewModel.task.name,
|
||||
taskViewModel.task.description ?? "",
|
||||
taskViewModel.task.category ?? "",
|
||||
taskViewModel.task.status ?? "",
|
||||
taskViewModel.task.priority ?? "",
|
||||
taskViewModel.task.date ?? "",
|
||||
taskViewModel.task.time ?? "",
|
||||
];
|
||||
};
|
||||
this.task = taskFileContent;
|
||||
this.loadTaskData();
|
||||
};
|
||||
|
||||
loadAllData = (): void => {
|
||||
this.loadTaskData();
|
||||
this.loadVersionIds();
|
||||
};
|
||||
|
||||
loadTaskData = (): void => {
|
||||
this.boardId.value = this.task.boardId;
|
||||
|
||||
this.name.value = this.task.name;
|
||||
this.description.value = this.task.description ?? "";
|
||||
|
||||
this.category.value = this.task.category ?? "";
|
||||
this.status.value = this.task.status ?? "";
|
||||
this.priority.value = this.task.priority ?? "";
|
||||
|
||||
this.date.value = this.task.date ?? "";
|
||||
this.time.value = this.task.time ?? "";
|
||||
|
||||
this.selectedVersionId.value = this.task.fileContentId;
|
||||
|
||||
this.updateSuggestions();
|
||||
};
|
||||
|
||||
// init
|
||||
constructor(
|
||||
public coreViewModel: CoreViewModel,
|
||||
public chatViewModel: ChatViewModel,
|
||||
boardsAndTasksModel: BoardsAndTasksModel,
|
||||
containingModel: TaskContainingPageViewModel,
|
||||
taskFileContent: TaskFileContent,
|
||||
) {
|
||||
this.boardsAndTasksModel = boardsAndTasksModel;
|
||||
this.containingModel = containingModel;
|
||||
|
||||
this.task = taskFileContent;
|
||||
|
||||
// load
|
||||
this.loadAllData();
|
||||
|
||||
// subscriptions
|
||||
this.selectedVersionId.subscribeSilent((selectedVersionId) => {
|
||||
this.switchVersion(selectedVersionId);
|
||||
});
|
||||
}
|
||||
|
||||
// utility
|
||||
static getStringsForFilter = (taskViewModel: TaskViewModel): string[] => {
|
||||
return [
|
||||
taskViewModel.task.name,
|
||||
taskViewModel.task.description ?? "",
|
||||
taskViewModel.task.category ?? "",
|
||||
taskViewModel.task.status ?? "",
|
||||
taskViewModel.task.priority ?? "",
|
||||
taskViewModel.task.date ?? "",
|
||||
taskViewModel.task.time ?? "",
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user