all repos — kōi @ 4a48ccfcb2820e792122c1a2d62d209c30239e47

Minimalist task manager

src/lib/store/tasksStore.ts (view raw)

  1import { get, writable } from "svelte/store";
  2import { debounce, WEEKDAYS } from "../utils";
  3import { taskToThing } from "../models/task";
  4import {
  5  getThingAll,
  6  saveSolidDatasetAt,
  7  setThing,
  8  removeThing,
  9} from "@inrupt/solid-client";
 10import { fetch } from "@inrupt/solid-client-authn-browser";
 11import podInfo from "./podInfoStore";
 12import { addToast } from "./toastStore";
 13import { DateTime } from "luxon";
 14
 15const DEBOUNCE_TIME_SYNC = 2000;
 16
 17const taskStore = writable<Task[]>([]);
 18const { update, set, subscribe } = taskStore;
 19
 20const addTask = (task: Omit<Task, "id">) => {
 21  const podUrl = get(podInfo).podUrl;
 22  update(tasks => [
 23    ...tasks,
 24    { ...task, id: `${podUrl}/tasks/default#${Date.now()}` },
 25  ]);
 26};
 27
 28const updateTask = (taskId: string, taskUpdate: Partial<Task>) => {
 29  update(tasks =>
 30    tasks.map(task => {
 31      if (task.id === taskId) return { ...task, ...taskUpdate };
 32      return task;
 33    })
 34  );
 35
 36  if (taskUpdate.done) {
 37    const task = get(taskStore).find(item => item.id === taskId);
 38    const now = DateTime.now();
 39    const datetime = task?.dueDate
 40      ? DateTime.fromJSDate(task.dueDate)
 41      : now
 42    let weekday = WEEKDAYS[task?.byDay as string];
 43    let dueDate: DateTime | null = null;
 44    if (task?.byDay && !task.byMonthWeek) {
 45      dueDate = datetime.set({ weekday });
 46      if (dueDate <= now) dueDate = dueDate.plus({ week: 1 })
 47    }
 48    else if (task?.byMonthDay) {
 49      dueDate = datetime.set({ day: task.byMonthDay })
 50      if (dueDate <= now) dueDate = dueDate.plus({ month: 1 })
 51    }
 52    else if (task?.byDay && task?.byMonthWeek) {
 53      dueDate = datetime.set({ weekday, weekNumber: task.byMonthWeek })
 54      if (dueDate <= now) dueDate = dueDate.plus({ month: 1 })
 55    }
 56
 57    if (dueDate) {
 58      console.log(`Tâche replanifiée pour le ${dueDate.toISODate()}`)
 59      addTask({ ...task, dueDate: dueDate.toJSDate(), done: false, endTime: undefined });
 60    }
 61  }
 62};
 63
 64const deleteTask = (taskId: string) => {
 65  update(tasks => tasks.filter(task => task.id !== taskId));
 66};
 67
 68// Sync tasks with pod data
 69let init = false;
 70subscribe(
 71  debounce(async (tasks: Task[]) => {
 72    if (!init) return (init = true);
 73
 74    let taskDataset = get(podInfo).tasksDataset;
 75    if (!taskDataset) throw new Error("No tasks dataset. Can't write to pod.");
 76
 77    const currentDatasetThings = getThingAll(taskDataset);
 78    const updatedDatasetThings = tasks.map(taskToThing);
 79
 80    // Add task things to dataset
 81    for (const taskThing of updatedDatasetThings) {
 82      taskDataset = setThing(taskDataset, taskThing);
 83    }
 84
 85    // Remove deleted tasks from dataset
 86    const removedThings = currentDatasetThings.filter(
 87      thing => !updatedDatasetThings.find(thg => thg.url === thing.url)
 88    );
 89    for (const removedThing of removedThings) {
 90      taskDataset = removeThing(taskDataset, removedThing);
 91    }
 92
 93    const podUrl = get(podInfo).podUrl;
 94    const savedSolidDataset = await saveSolidDatasetAt(
 95      `${podUrl}/tasks/default`,
 96      taskDataset,
 97      { fetch: fetch }
 98    );
 99    podInfo.update(store => ({ ...store, tasksDataset: savedSolidDataset }));
100    addToast("Tâches enregistrées vers le pod.");
101  }, DEBOUNCE_TIME_SYNC)
102);
103
104export default { set, update, subscribe, addTask, updateTask, deleteTask };