Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move goal feat (wip) #2067

Draft
wants to merge 27 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6833fd7
add timestamp field in goalItem
vinaybadgujar102 Oct 10, 2024
2190635
feat: add and integrate LWW based conflict resolution
vinaybadgujar102 Oct 10, 2024
3756ad8
add: basic move goal functionality
vinaybadgujar102 Oct 11, 2024
583df9d
Merge remote-tracking branch 'origin/main' into vin/1918/move-goal
vinaybadgujar102 Oct 15, 2024
1df4ea4
fix: location state problem while coming out of move state
vinaybadgujar102 Oct 15, 2024
46c1ba2
feat(collaboration): Implement goal creation suggestion in reciever s…
vinaybadgujar102 Oct 24, 2024
21d4a07
feat(collaboration): Add handling of shared child goal which is moved…
vinaybadgujar102 Oct 24, 2024
7518be3
fix: move goal out of shared goal issue
vinaybadgujar102 Oct 24, 2024
86c5264
add newGoalMoved action
vinaybadgujar102 Oct 24, 2024
6209ebe
feat(move): handle goal move in collaborated goal
vinaybadgujar102 Oct 25, 2024
7aa85b4
style: improve ui of move goal suggestio
vinaybadgujar102 Oct 25, 2024
3eba505
chore: remove logs
vinaybadgujar102 Oct 25, 2024
6005a8a
patch: dont pass old parent id in move change payload
vinaybadgujar102 Oct 25, 2024
36b2660
feat(move): handle share updates for move goal out of shared goal wit…
vinaybadgujar102 Oct 26, 2024
d94db61
feat(move): skip processing move update if root goal is moved
vinaybadgujar102 Oct 26, 2024
b64433e
feat(sharing): push participant in child goals also
vinaybadgujar102 Oct 27, 2024
d5c090b
refactor: pluck the code for addition of new shared goal in function …
vinaybadgujar102 Oct 27, 2024
c347441
chore: add type to changes
vinaybadgujar102 Oct 27, 2024
8494239
fix: new goal add broken
vinaybadgujar102 Oct 28, 2024
4e87593
feat(collaboration): add support of having participants when a subgoa…
vinaybadgujar102 Oct 28, 2024
43efc3c
remove: newgoalmoved check
vinaybadgujar102 Oct 30, 2024
7ec0e15
show new changes to root goal of shared goal
vinaybadgujar102 Nov 4, 2024
b68440a
Merge remote-tracking branch 'origin/main' into vin/1918/move-goal
vinaybadgujar102 Nov 4, 2024
cde09d6
fix: archived action not processed correctly
vinaybadgujar102 Nov 4, 2024
951b8bc
patch: if a descendant is moved from shared goal to non shared goal, …
vinaybadgujar102 Nov 4, 2024
4f34812
feat(collaboration): integrate new shared goal creation function
vinaybadgujar102 Nov 4, 2024
5e297d0
fix: particpant not being correctly passed to partner goals while new…
vinaybadgujar102 Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/Interfaces/IContactMessages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { GoalItem } from "@src/models/GoalItem";

export interface SharedGoalMessage {
relId: string;
goalWithChildrens: GoalItem[];
lastProcessedTimestamp: string;
type: "shareMessage";
installId: string;
TTL: number;
}

export interface SharedGoalMessageResponse {
success: boolean;
response: SharedGoalMessage[];
}
16 changes: 8 additions & 8 deletions src/api/GoalsAPI/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,22 +157,22 @@ export const unarchiveUserGoal = async (goal: GoalItem) => {
await unarchiveGoal(goal);
};

export const removeGoal = async (goal: GoalItem) => {
export const removeGoal = async (goal: GoalItem, permanently = false) => {
await deleteHintItem(goal.id);
await Promise.allSettled([
db.goalsCollection.delete(goal.id).catch((err) => console.log("failed to delete", err)),
addDeletedGoal(goal),
permanently ? null : addDeletedGoal(goal),
]);
};

export const removeChildrenGoals = async (parentGoalId: string) => {
export const removeChildrenGoals = async (parentGoalId: string, permanently = false) => {
const childrenGoals = await getChildrenGoals(parentGoalId);
if (childrenGoals.length === 0) {
return;
}
childrenGoals.forEach((goal) => {
removeChildrenGoals(goal.id);
removeGoal(goal);
removeChildrenGoals(goal.id, permanently);
removeGoal(goal, permanently);
});
};

Expand Down Expand Up @@ -312,9 +312,9 @@ export const notifyNewColabRequest = async (id: string, relId: string) => {
// });
// };

export const removeGoalWithChildrens = async (goal: GoalItem) => {
await removeChildrenGoals(goal.id);
await removeGoal(goal);
export const removeGoalWithChildrens = async (goal: GoalItem, permanently = false) => {
await removeChildrenGoals(goal.id, permanently);
await removeGoal(goal, permanently);
if (goal.parentGoalId !== "root") {
getGoal(goal.parentGoalId).then(async (parentGoal: GoalItem) => {
const parentGoalSublist = parentGoal.sublist;
Expand Down
39 changes: 32 additions & 7 deletions src/api/SharedWMAPI/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import { db } from "@models";
import { GoalItem } from "@src/models/GoalItem";
import { createGoalObjectFromTags } from "@src/helpers/GoalProcessor";
import { addDeletedGoal, addGoal } from "../GoalsAPI";
import { addGoal } from "../GoalsAPI";
import { getContactByRelId } from "../ContactsAPI";

export const addSharedWMSublist = async (parentGoalId: string, goalIds: string[]) => {
db.transaction("rw", db.sharedWMCollection, async () => {
Expand All @@ -17,29 +18,53 @@ export const addSharedWMSublist = async (parentGoalId: string, goalIds: string[]
});
};

export const addSharedWMGoal = async (goalDetails: object) => {
export const addSharedWMGoal = async (goalDetails: GoalItem, relId = "") => {
console.log("[addSharedWMGoal] Input goal details:", goalDetails);
console.log("[addSharedWMGoal] Input relId:", relId);

const { participants } = goalDetails;
const newGoal = createGoalObjectFromTags({ ...goalDetails, typeOfGoal: "shared" });
if (participants) newGoal.participants = participants;
let updatedParticipants = participants || [];

if (relId) {
const contact = await getContactByRelId(relId);
if (contact) {
const contactExists = updatedParticipants.some((p) => p.relId === relId);
if (!contactExists) {
updatedParticipants = [...updatedParticipants, { ...contact, following: true, type: "sharer" }];
}
}
}

console.log("[addSharedWMGoal] Updated participants:", updatedParticipants);
const newGoal = createGoalObjectFromTags({
...goalDetails,
typeOfGoal: "shared",
participants: updatedParticipants,
});

await db
.transaction("rw", db.sharedWMCollection, async () => {
await db.sharedWMCollection.add(newGoal);
console.log("[addSharedWMGoal] Goal added to sharedWMCollection");
})
.then(async () => {
const { parentGoalId } = newGoal;
if (parentGoalId !== "root") {
console.log("[addSharedWMGoal] Adding goal to parent sublist. ParentId:", parentGoalId);
await addSharedWMSublist(parentGoalId, [newGoal.id]);
}
})
.catch((e) => {
console.log(e.stack || e);
console.error("[addSharedWMGoal] Error:", e.stack || e);
});

console.log("[addSharedWMGoal] Successfully created goal with ID:", newGoal.id);
return newGoal.id;
};

export const addGoalsInSharedWM = async (goals: GoalItem[]) => {
export const addGoalsInSharedWM = async (goals: GoalItem[], relId: string) => {
goals.forEach((ele) => {
addSharedWMGoal(ele).then((res) => console.log(res, "added"));
addSharedWMGoal(ele, relId).then((res) => console.log(res, "added"));
});
};

Expand Down
17 changes: 17 additions & 0 deletions src/common/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,23 @@ const Icon: React.FC<IconProps> = ({ title, active }) => {
</svg>
);

case "Move":
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="200"
height="200"
fill={color2}
version="1.1"
viewBox="0 0 232.439 232.439"
xmlSpace="preserve"
>
<g>
<path d="M55.416 64.245a7.499 7.499 0 00-8.174 1.625L2.197 110.915a7.502 7.502 0 000 10.608l45.045 45.045a7.501 7.501 0 0012.804-5.304v-90.09a7.499 7.499 0 00-4.63-6.929zm-10.37 78.912l-26.938-26.938L45.046 89.28v53.877zM121.523 2.196a7.502 7.502 0 00-10.607 0L65.871 47.241a7.5 7.5 0 005.304 12.804h90.09a7.499 7.499 0 005.304-12.804L121.523 2.196zM89.281 45.045l26.938-26.938 26.939 26.938H89.281zM230.242 110.915L185.197 65.87a7.499 7.499 0 00-12.804 5.304v90.09a7.499 7.499 0 0012.804 5.304l45.045-45.045a7.502 7.502 0 000-10.608zm-42.849 32.242V89.28l26.939 26.938-26.939 26.939zM161.263 172.393H71.175a7.499 7.499 0 00-5.304 12.804l45.045 45.046a7.502 7.502 0 0010.608-.001l45.043-45.046a7.499 7.499 0 00-5.304-12.803zm-45.043 41.94l-26.938-26.939h53.876l-26.938 26.939z" />
</g>
</svg>
);

default:
return <div />;
}
Expand Down
24 changes: 24 additions & 0 deletions src/common/ZButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { darkModeState } from "@src/store";
import React from "react";
import { useRecoilValue } from "recoil";

interface ZButtonProps {
children: React.ReactNode;
onClick?: () => void;
className?: string;
}

const ZButton: React.FC<ZButtonProps> = ({ children, onClick, className }) => {
const darkModeStatus = useRecoilValue(darkModeState);

const defaultClassName = `default-btn${darkModeStatus ? "-dark" : ""}`;
const combinedClassName = className ? `${defaultClassName} ${className}` : defaultClassName;

return (
<button type="button" className={combinedClassName} onClick={onClick}>
{children}
</button>
);
};

export default ZButton;
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ const AcceptBtn = ({ typeAtPriority, acceptChanges }: AcceptBtnProps) => {
{typeAtPriority === "restored" && "Restore for me too"}
{typeAtPriority === "deleted" && "Delete for me too"}
{typeAtPriority === "subgoals" && "Add all checked"}
{typeAtPriority === "newGoalMoved" && "Move for me too"}
{typeAtPriority === "modifiedGoals" && "Make all checked changes"}
{typeAtPriority === "moved" && "Move for me too"}
</button>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ import SubHeader from "@src/common/SubHeader";
import ContactItem from "@src/models/ContactItem";
import ZModal from "@src/common/ZModal";

import { addGoalToNewParentSublist, getAllDescendants, removeGoalFromParentSublist } from "@src/helpers/GoalController";
import Header from "./Header";
import AcceptBtn from "./AcceptBtn";
import IgnoreBtn from "./IgnoreBtn";
import "./DisplayChangesModal.scss";
import { getMovedSubgoalsList } from "./ShowChanges";

const DisplayChangesModal = ({ currentMainGoal }: { currentMainGoal: GoalItem }) => {
const darkModeStatus = useRecoilValue(darkModeState);
Expand All @@ -34,6 +36,33 @@ const DisplayChangesModal = ({ currentMainGoal }: { currentMainGoal: GoalItem })
const [goalUnderReview, setGoalUnderReview] = useState<GoalItem>();
const [participants, setParticipants] = useState<ContactItem[]>([]);
const [currentDisplay, setCurrentDisplay] = useState<typeOfChange | "none">("none");
const [oldParentTitle, setOldParentTitle] = useState<string>("");
const [newParentTitle, setNewParentTitle] = useState<string>("");

useEffect(() => {
const fetchParentTitles = async () => {
if (!goalUnderReview) return;

try {
const currentGoalInDB = await getGoal(goalUnderReview.id);
const oldParentId = currentGoalInDB?.parentGoalId;

const [oldParent, newParent] = await Promise.all([
oldParentId ? getGoal(oldParentId) : null,
getGoal(goalUnderReview.parentGoalId),
]);

setOldParentTitle(oldParent?.title || "root");
setNewParentTitle(newParent?.title || "Non-shared goal");
} catch (error) {
console.error("Error fetching parent titles:", error);
setOldParentTitle("root");
setNewParentTitle("Non-shared goal");
}
};

fetchParentTitles();
}, [goalUnderReview]);

const [showSuggestions, setShowSuggestions] = useState(false);
const [unselectedChanges, setUnselectedChanges] = useState<string[]>([]);
Expand Down Expand Up @@ -125,21 +154,52 @@ const DisplayChangesModal = ({ currentMainGoal }: { currentMainGoal: GoalItem })
if (!goalUnderReview || !currentMainGoal) {
return;
}
const removeChanges = currentDisplay === "subgoals" ? newGoals.map(({ goal }) => goal.id) : [goalUnderReview.id];
const removeChanges =
currentDisplay === "subgoals" || currentDisplay === "newGoalMoved"
? newGoals.map(({ goal }) => goal.id)
: currentDisplay === "moved"
? [goalUnderReview.id, ...(await getAllDescendants(goalUnderReview.id)).map((goal: GoalItem) => goal.id)]
: [goalUnderReview.id];

if (currentDisplay !== "none") {
await deleteGoalChangesInID(currentMainGoal.id, participants[activePPT].relId, currentDisplay, removeChanges);
}
setCurrentDisplay("none");
};

const handleMoveChanges = async () => {
if (!goalUnderReview) {
console.log("No goal under review.");
return;
}
const parentGoal = await getGoal(goalUnderReview.parentGoalId);

await Promise.all([
updateGoal(goalUnderReview.id, { parentGoalId: parentGoal?.id ?? "root" }),
removeGoalFromParentSublist(goalUnderReview.id, parentGoal?.title ?? "root"),
addGoalToNewParentSublist(goalUnderReview.id, parentGoal?.id ?? "root"),
]);

// TODO: handle this later
// await sendUpdatedGoal(
// goalUnderReview.id,
// [],
// true,
// updatesIntent === "suggestion" ? [] : [participants[activePPT].relId],
// );
};

const acceptChanges = async () => {
if (!goalUnderReview) {
return;
}
if (currentDisplay !== "none") {
await deleteChanges();
}
if (currentDisplay === "subgoals") {
if (currentDisplay === "moved") {
await handleMoveChanges();
}
if (currentDisplay === "subgoals" || currentDisplay === "newGoalMoved") {
const goalsToBeSelected = newGoals
.filter(({ goal }) => !unselectedChanges.includes(goal.id))
.map(({ goal }) => goal);
Expand Down Expand Up @@ -205,12 +265,16 @@ const DisplayChangesModal = ({ currentMainGoal }: { currentMainGoal: GoalItem })
console.log("🚀 ~ getChanges ~ changedGoal:", changedGoal);
if (changedGoal) {
setGoalUnderReview({ ...changedGoal });
if (typeAtPriority === "subgoals") {
// TODO: remove the newGoalsMoved and try handle in subgoal only
if (typeAtPriority === "subgoals" || typeAtPriority === "newGoalMoved") {
setNewGoals(goals || []);
} else if (typeAtPriority === "modifiedGoals") {
setUpdatesIntent(goals[0].intent);
const incGoal: GoalItem = { ...goals[0].goal };
setUpdateList({ ...findGoalTagChanges(changedGoal, incGoal) });
} else if (typeAtPriority === "moved") {
setUpdatesIntent(goals[0].intent);
setGoalUnderReview({ ...goals[0].goal });
}
}
}
Expand All @@ -237,6 +301,23 @@ const DisplayChangesModal = ({ currentMainGoal }: { currentMainGoal: GoalItem })
init();
}, [currentMainGoal]);

const getChangedGoalFromRoot = async (rootGoal: GoalItem, relId: string) => {
const { typeAtPriority, goals, parentId } = await jumpToLowestChanges(rootGoal.id, relId);

if (typeAtPriority === "none") return { typeAtPriority, goals, parentId };

const changedGoal = await getGoal(parentId);
if (!changedGoal) return { typeAtPriority, goals, parentId };

return {
typeAtPriority,
goals,
parentId,
changedGoal,
rootGoal,
};
};

return (
<ZModal type="popupModal" open>
{currentMainGoal && (
Expand Down Expand Up @@ -289,7 +370,8 @@ const DisplayChangesModal = ({ currentMainGoal }: { currentMainGoal: GoalItem })
)}
{["deleted", "archived", "restored"].includes(currentDisplay) && <div />}
{currentDisplay === "modifiedGoals" && getEditChangesList()}
{currentDisplay === "subgoals" && getSubgoalsList()}
{(currentDisplay === "subgoals" || currentDisplay === "newGoalMoved") && getSubgoalsList()}
{currentDisplay === "moved" && getMovedSubgoalsList(goalUnderReview, oldParentTitle, newParentTitle)}

<div className="d-flex justify-fe gap-20">
{goalUnderReview && (
Expand Down
12 changes: 12 additions & 0 deletions src/components/GoalsComponents/DisplayChangesModal/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ const Header = ({
{contactName} added to {title}.&nbsp; &nbsp; Add as well ?
</>
);
case "newGoalMoved":
return (
<>
{contactName} moved {title} to {title}.&nbsp; &nbsp; Move as well ?
</>
);
case "modifiedGoals":
return (
<>
Expand All @@ -42,6 +48,12 @@ const Header = ({
{contactName} restored {title}.
</>
);
case "moved":
return (
<>
{contactName} moved {title}.
</>
);
default:
return <>&nbsp;</>;
}
Expand Down
Loading
Loading