Skip to content

Commit

Permalink
Merge pull request #251 from cabcookie:add-todo-button
Browse files Browse the repository at this point in the history
Schnelles Hinzufügen von Aufgaben ermöglichen
  • Loading branch information
cabcookie authored Nov 22, 2024
2 parents 106998a + 9980e56 commit 8785117
Show file tree
Hide file tree
Showing 23 changed files with 426 additions and 63 deletions.
22 changes: 6 additions & 16 deletions api/ContextProjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { toast } from "@/components/ui/use-toast";
import { Context } from "@/contexts/ContextContext";
import {
addDaysToDate,
newDateTimeString,
toISODateString,
uniqArraySorted,
} from "@/helpers/functional";
Expand All @@ -25,6 +24,10 @@ import {
import { FC, ReactNode, createContext, useContext } from "react";
import useSWR, { KeyedMutator } from "swr";
import { handleApiErrors } from "./globals";
import {
createActivityApi,
createProjectActivityApi,
} from "./helpers/activity";
import { CrmProject, mapCrmProject } from "./useCrmProjects";
const client = generateClient<Schema>();

Expand Down Expand Up @@ -323,16 +326,7 @@ export const ProjectsContextProvider: FC<ProjectsContextProviderProps> = ({
projects?.find((project) => project.id === projectId);

const createProjectActivity = async (projectId: string) => {
const { data: activity, errors: errorsActivity } =
await client.models.Activity.create({
formatVersion: 3,
noteBlockIds: [],
finishedOn: newDateTimeString(),
});
if (errorsActivity) {
handleApiErrors(errorsActivity, "Error creating activity");
return;
}
const activity = await createActivityApi();
if (!activity) return;
const updated: Project[] =
projects?.map((project) =>
Expand All @@ -341,11 +335,7 @@ export const ProjectsContextProvider: FC<ProjectsContextProviderProps> = ({
: { ...project, activityIds: [activity.id, ...project.activityIds] }
) || [];
mutateProjects(updated, false);
const { data, errors } = await client.models.ProjectActivity.create({
activityId: activity.id,
projectsId: projectId,
});
if (errors) handleApiErrors(errors, "Error linking activity with project");
const data = await createProjectActivityApi(projectId, activity.id);
mutateProjects(updated);
return data?.activityId;
};
Expand Down
45 changes: 45 additions & 0 deletions api/helpers/activity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { type Schema } from "@/amplify/data/resource";
import { newDateTimeString } from "@/helpers/functional";
import { generateClient } from "aws-amplify/data";
import { handleApiErrors } from "../globals";
const client = generateClient<Schema>();

export const createActivityApi = async () => {
const { data, errors } = await client.models.Activity.create({
formatVersion: 3,
noteBlockIds: [],
finishedOn: newDateTimeString(),
notes: null,
notesJson: null,
});
if (errors) {
handleApiErrors(errors, "Error creating activity");
return;
}
return data;
};

export const updateActivityBlockIds = async (
activityId: string,
blockIds: string[]
) => {
const { data, errors } = await client.models.Activity.update({
id: activityId,
noteBlockIds: blockIds,
});
if (errors)
handleApiErrors(errors, "Error updating linked blocks on activity");
return data;
};

export const createProjectActivityApi = async (
projectsId: string,
activityId: string
) => {
const { data, errors } = await client.models.ProjectActivity.create({
activityId,
projectsId,
});
if (errors) handleApiErrors(errors, "Error linking activity with project");
return data;
};
12 changes: 12 additions & 0 deletions api/helpers/people.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { type Schema } from "@/amplify/data/resource";
import { generateClient } from "aws-amplify/api";
const client = generateClient<Schema>();

export const createMentionedPersonApi = (
noteBlockId: string,
personId: string
) =>
client.models.NoteBlockPerson.create({
noteBlockId,
personId,
});
25 changes: 25 additions & 0 deletions api/helpers/todo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { type Schema } from "@/amplify/data/resource";
import { newDateString } from "@/helpers/functional";
import { generateClient } from "aws-amplify/data";
const client = generateClient<Schema>();

export const createTodoApi = (content: string, done: boolean) =>
client.models.Todo.create({
todo: content,
status: done ? "DONE" : "OPEN",
doneOn: done ? newDateString() : null,
});

export const createBlockApi = (
activityId: string,
content: string | null,
todoId: string | undefined,
type: string
) =>
client.models.NoteBlock.create({
activityId,
formatVersion: 3,
type,
content,
todoId,
});
7 changes: 2 additions & 5 deletions api/useActivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { generateClient, SelectionSet } from "aws-amplify/data";
import { useState } from "react";
import useSWR from "swr";
import { handleApiErrors } from "./globals";
import { createProjectActivityApi } from "./helpers/activity";
const client = generateClient<Schema>();

export type TempIdMapping = {
Expand Down Expand Up @@ -145,11 +146,7 @@ const useActivity = (activityId?: string) => {
projectIds: [...activity.projectIds, projectId],
};
mutateActivity(updated, false);
const { data, errors } = await client.models.ProjectActivity.create({
activityId: activity.id,
projectsId: projectId,
});
if (errors) handleApiErrors(errors, "Error adding project to current note");
const data = await createProjectActivityApi(projectId, activity.id);
if (data) toast({ title: "Added note to another project" });
mutateActivity(updated);
return data?.id;
Expand Down
1 change: 0 additions & 1 deletion api/useDailyPlans.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ const useDailyPlans = (status?: DailyPlanStatus) => {
const dayPlanProject = flow(
identity<DailyPlan[] | undefined>,
find(["id", dayPlanId]),
(test) => test,
get("projects"),
find(["projectId", projectId])
)(dailyPlans) as DailyPlanProject | undefined;
Expand Down
4 changes: 2 additions & 2 deletions api/useInboxWorkflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ const useInboxWorkflow = (mutate: HandleMutationFn) => {
type: !block.type
? "paragraph"
: parentType === "orderedList"
? "listItemOrdered"
: block.type,
? "listItemOrdered"
: block.type,
content: !todoId ? stringifyBlock(block) : null,
...(!todoId ? {} : { todoId }),
});
Expand Down
92 changes: 91 additions & 1 deletion api/useProjectTodos.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { type Schema } from "@/amplify/data/resource";
import { stringifyBlock } from "@/components/ui-elements/editors/helpers/blocks";
import { getPeopleMentioned } from "@/components/ui-elements/editors/helpers/mentioned-people-cud";
import { isNotNil, newDateString } from "@/helpers/functional";
import {
getTodoDoneOn,
Expand All @@ -22,6 +24,13 @@ import {
} from "lodash/fp";
import useSWR from "swr";
import { handleApiErrors } from "./globals";
import {
createActivityApi,
createProjectActivityApi,
updateActivityBlockIds,
} from "./helpers/activity";
import { createMentionedPersonApi } from "./helpers/people";
import { createBlockApi, createTodoApi } from "./helpers/todo";
const client = generateClient<Schema>();

export type Todo = {
Expand Down Expand Up @@ -154,7 +163,88 @@ const useProjectTodos = (projectId: string | undefined) => {
return data?.id;
};

return { projectTodos, isLoading, error, finishTodo };
const createTodoRecord = async (todo: JSONContent) => {
const { data, errors } = await createTodoApi(stringifyBlock(todo), false);
if (errors) handleApiErrors(errors, "Creating todo failed");
return data;
};

const createNoteBlockRecord = async (activityId: string, todoId: string) => {
const { data, errors } = await createBlockApi(
activityId,
null,
todoId,
"taskItem"
);
if (errors) handleApiErrors(errors, "Creating note block failed");
return data?.id;
};

const createMentionedPerson =
(blockId: string) =>
async (personId: string): Promise<string | undefined> => {
const { data, errors } = await createMentionedPersonApi(
blockId,
personId
);
if (errors) handleApiErrors(errors, "Creating mentioned person failed");
return data?.id;
};

const createMentionedPeople = async (blockId: string, todo: JSONContent) => {
const peopleIds = await Promise.all(
flow(
getPeopleMentioned,
map("attrs.id"),
map(createMentionedPerson(blockId))
)(todo)
);
return peopleIds;
};

const createTodo = async (todo: JSONContent) => {
if (!projectId) return;
const activity = await createActivityApi();
if (!activity) return;
const projectActivity = await createProjectActivityApi(
projectId,
activity.id
);
if (!projectActivity) return;
const todoBlock = {
type: "taskItem",
attrs: {
checked: false,
},
content: todo.content,
} as JSONContent;
const todoData = await createTodoRecord(todoBlock);
if (!todoData) return;
const blockId = await createNoteBlockRecord(activity.id, todoData.id);
if (!blockId) return;
const updatedActivity = await updateActivityBlockIds(activity.id, [
blockId,
]);
if (!updatedActivity) return;
await createMentionedPeople(blockId, todo);
mutate([
...(projectTodos ?? []),
{
todoId: todoData.id,
todo: todoBlock,
done: false,
doneOn: null,
activityId: activity.id,
blockId,
isOrphan: false,
updatedAt: new Date(),
projectActivityId: projectActivity.id,
},
]);
return todoData.id;
};

return { projectTodos, isLoading, error, finishTodo, createTodo };
};

export default useProjectTodos;
4 changes: 2 additions & 2 deletions components/meetings/meeting-next-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Todo } from "@/api/useProjectTodos";
import { FC } from "react";
import DefaultAccordionItem from "../ui-elements/accordion/DefaultAccordionItem";
import { getTodoText } from "../ui-elements/editors/helpers/text-generation";
import TodoEditor from "../ui-elements/editors/todo-editor/TodoEditor";
import TodoViewer from "../ui-elements/editors/todo-viewer/TodoViewer";

type MeetingNextActionsProps = {
todos: Todo[] | undefined;
Expand All @@ -16,7 +16,7 @@ const MeetingNextActions: FC<MeetingNextActionsProps> = ({ todos }) =>
triggerTitle="Agreed Next Actions"
triggerSubTitle={getTodoText(todos)}
>
<TodoEditor todos={todos} />
<TodoViewer todos={todos} />
</DefaultAccordionItem>
);

Expand Down
5 changes: 4 additions & 1 deletion components/planning/day/DailyPlanProject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useDailyPlans, {
DailyPlanProject,
} from "@/api/useDailyPlans";
import useProjectTodos, { ProjectTodo } from "@/api/useProjectTodos";
import AddTodoSection from "@/components/ui-elements/editors/todo-editor/AddTodoSection";
import ShowHideSwitch from "@/components/ui-elements/ShowHideSwitch";
import { setPostponedTodoList, setTodoList } from "@/helpers/today";
import { flow, get, identity } from "lodash/fp";
Expand All @@ -25,7 +26,7 @@ const DailyPlanProjectComponent: FC<DailyPlanProjectProps> = ({
const { addProjectToDayPlan, postponeTodo } = useDailyPlans("OPEN");
const { getProjectById } = useProjectsContext();
const [project, setProject] = useState<Project | undefined>();
const { projectTodos, finishTodo } = useProjectTodos(project?.id);
const { projectTodos, finishTodo, createTodo } = useProjectTodos(project?.id);
const [openTodos, setOpenTodos] = useState<ProjectTodo[] | undefined>();
const [closedTodos, setClosedTodos] = useState<ProjectTodo[] | undefined>();
const [postponedTodos, setPostponedTodos] = useState<
Expand Down Expand Up @@ -74,6 +75,8 @@ const DailyPlanProjectComponent: FC<DailyPlanProjectProps> = ({

{showTodos && (
<>
<AddTodoSection onSave={createTodo} />

<DailyPlanProjectTodos
status="OPEN"
todos={openTodos}
Expand Down
6 changes: 3 additions & 3 deletions components/planning/day/ShowProjectTodos.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import useProjectTodos, { ProjectTodo } from "@/api/useProjectTodos";
import TodoEditor from "@/components/ui-elements/editors/todo-editor/TodoEditor";
import TodoViewer from "@/components/ui-elements/editors/todo-viewer/TodoViewer";
import ShowHideSwitch from "@/components/ui-elements/ShowHideSwitch";
import { filter, flow, identity } from "lodash/fp";
import { FC, useEffect, useState } from "react";
Expand Down Expand Up @@ -29,7 +29,7 @@ const ShowProjectTodos: FC<ShowProjectTodosProps> = ({ projectId }) => {

return (
<div>
{!!openTodos?.length && <TodoEditor todos={openTodos} />}
{!!openTodos?.length && <TodoViewer todos={openTodos} />}

<ShowHideSwitch
value={showClosed}
Expand All @@ -38,7 +38,7 @@ const ShowProjectTodos: FC<ShowProjectTodosProps> = ({ projectId }) => {
className="ml-1 md:ml-2"
/>

{showClosed && closedTodos?.length && <TodoEditor todos={closedTodos} />}
{showClosed && closedTodos?.length && <TodoViewer todos={closedTodos} />}
</div>
);
};
Expand Down
8 changes: 4 additions & 4 deletions components/ui-elements/editors/helpers/blocks-cud.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* Create, update, delete operations on blocks (i.e., NoteBlock) */

import { type Schema } from "@/amplify/data/resource";
import { createBlockApi } from "@/api/helpers/todo";
import { Activity, TempIdMapping } from "@/api/useActivity";
import { not } from "@/helpers/functional";
import { Editor, JSONContent } from "@tiptap/core";
Expand Down Expand Up @@ -89,13 +90,12 @@ export const createBlock = async ({
todoId,
type,
}: TBlockCreationSet): Promise<TempIdMapping> => {
const { data, errors } = await client.models.NoteBlock.create({
const { data, errors } = await createBlockApi(
activityId,
formatVersion: 3,
type,
content,
todoId,
});
type
);
if (errors)
throw new TransactionError(
"Creating note block failed",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* Create, update, delete operations on mentioned people (i.e., NoteMentionedPersonPerson) */

import { type Schema } from "@/amplify/data/resource";
import { createMentionedPersonApi } from "@/api/helpers/people";
import { Activity, TempIdMapping } from "@/api/useActivity";
import { not } from "@/helpers/functional";
import { Editor, JSONContent } from "@tiptap/core";
Expand Down Expand Up @@ -51,10 +52,7 @@ const createMentionedPerson = async ({
personId,
tempId,
}: TMentionedPersonCreationSet): Promise<MentionedPersonTempIdMapping> => {
const { data, errors } = await client.models.NoteBlockPerson.create({
noteBlockId: blockId,
personId,
});
const { data, errors } = await createMentionedPersonApi(blockId, personId);
if (errors)
throw new TransactionError(
"Creating mentioned person failed",
Expand Down
Loading

0 comments on commit 8785117

Please sign in to comment.