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 #2067

Open
wants to merge 57 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 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
406a183
remove: dead code and ts-ignore comment
vinaybadgujar102 Nov 5, 2024
c419332
fix: tslint issues
vinaybadgujar102 Nov 5, 2024
156ec4d
remove: dead code
vinaybadgujar102 Nov 5, 2024
4400271
remove: dead code
vinaybadgujar102 Nov 5, 2024
280269a
handle move in partner goals
vinaybadgujar102 Nov 5, 2024
d45934f
move the move hear button in global add button
vinaybadgujar102 Nov 6, 2024
3425d13
uncomment code
vinaybadgujar102 Nov 6, 2024
b2cbdc8
edit: bottom navbar to support move goal mode
vinaybadgujar102 Nov 6, 2024
30ba34c
add participants to child when goal shared to new contacts when shari…
vinaybadgujar102 Nov 7, 2024
6baa127
show the move guide and move the move here button in global add butto…
vinaybadgujar102 Nov 9, 2024
06465a5
restrict render of move here button
vinaybadgujar102 Nov 9, 2024
669bd46
increase width of add pill and show toast when goal is moved
vinaybadgujar102 Nov 9, 2024
9f3fd12
fix: sharedwm goal disappear when moved to non shared goal
vinaybadgujar102 Nov 9, 2024
46e2dc0
add move goal action confirmation
vinaybadgujar102 Nov 10, 2024
db860a4
when in move state single tap on global add btn show options
vinaybadgujar102 Nov 10, 2024
983c6ef
edit move goal confirmation modal wording
vinaybadgujar102 Nov 11, 2024
988f2b7
Merge remote-tracking branch 'origin' into vin/1918/move-goal
vinaybadgujar102 Nov 11, 2024
96c1b8d
fix eslint issues
vinaybadgujar102 Nov 11, 2024
0558d2a
fix: partner goal disappears when use modified by sharer
vinaybadgujar102 Nov 12, 2024
d8d9ced
add types
vinaybadgujar102 Nov 13, 2024
b8108bd
integrate lww merge conflict resolution for the collaborated goals (e…
vinaybadgujar102 Nov 13, 2024
2baf26c
refactor: use styles from short css file
vinaybadgujar102 Nov 16, 2024
c78b4a1
fix: duplicate move request sent
vinaybadgujar102 Nov 23, 2024
fb22e87
fix: backticks not being removed for code snippet
vinaybadgujar102 Nov 23, 2024
3b31127
fix: sublist array not updating correctly while moving goals
vinaybadgujar102 Nov 24, 2024
5614dc2
fix: typo
vinaybadgujar102 Nov 24, 2024
f942c2c
improve changes modal heading title for new goal moved action
vinaybadgujar102 Nov 24, 2024
80a6fea
revert: bug causing code
vinaybadgujar102 Nov 24, 2024
88b9cce
disable move button when processing move operation
vinaybadgujar102 Nov 24, 2024
60b5536
fix: duplicate new add subgoal request sent to collaborator
vinaybadgujar102 Nov 24, 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[];
}
3 changes: 2 additions & 1 deletion src/Interfaces/IPopupModals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface TConfirmActionState {
addHint: boolean;
deleteHint: boolean;
reportHint: boolean;
move: boolean;
};
collaboration: {
colabRequest: boolean;
Expand All @@ -20,7 +21,7 @@ export interface TConfirmActionState {

export interface TConfirmGoalAction {
actionCategory: "goal";
actionName: "archive" | "delete" | "shareAnonymously" | "shareWithOne" | "restore";
actionName: "archive" | "delete" | "shareAnonymously" | "shareWithOne" | "restore" | "move";
}

export interface TConfirmColabGoalAction {
Expand Down
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
57 changes: 49 additions & 8 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 Expand Up @@ -83,7 +108,7 @@ export const getRootGoalsOfPartner = async (relId: string) => {
).reverse();
};

export const updateSharedWMGoal = async (id: string, changes: object) => {
export const updateSharedWMGoal = async (id: string, changes: Partial<GoalItem>) => {
db.transaction("rw", db.sharedWMCollection, async () => {
await db.sharedWMCollection.update(id, changes).then((updated) => updated);
}).catch((e) => {
Expand Down Expand Up @@ -157,3 +182,19 @@ export const convertSharedWMGoalToColab = async (goal: GoalItem) => {
})
.catch((err) => console.log(err));
};

export const updateSharedWMParentSublist = async (oldParentId: string, newParentId: string, goalId: string) => {
// Remove from old parent
const oldParentGoal = await getSharedWMGoal(oldParentId);
if (oldParentGoal?.sublist) {
const updatedOldSublist = oldParentGoal.sublist.filter((id) => id !== goalId);
await updateSharedWMGoal(oldParentId, { sublist: updatedOldSublist });
}

// Add to new parent
const newParentGoal = await getSharedWMGoal(newParentId);
if (newParentGoal) {
const updatedNewSublist = [...(newParentGoal.sublist || []), goalId];
await updateSharedWMGoal(newParentId, { sublist: updatedNewSublist });
}
};
4 changes: 2 additions & 2 deletions src/common/ConfirmationModal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Checkbox } from "antd";
import React, { useState } from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { useTranslation } from "react-i18next";
import { Trans, useTranslation } from "react-i18next";

import { darkModeState, displayConfirmation } from "@src/store";
import { ConfirmationModalProps } from "@src/Interfaces/IPopupModals";
Expand Down Expand Up @@ -51,7 +51,7 @@ const ConfirmationModal: React.FC<ConfirmationModalProps> = ({ action, handleCli
{t(headerKey)}
</p>
<p>
{t("note")}: {t(noteKey)}
{t("note")}: <Trans i18nKey={noteKey} components={{ br: <br />, ul: <ul />, li: <li /> }} />
</p>
<div style={{ display: "flex", gap: "5px" }}>
<Checkbox
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;
1 change: 1 addition & 0 deletions src/components/BottomNavbar/BottomNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const BottomNavbar = ({ title }: { title: string }) => {
}
}
};

const { activeGoalId } = location.state || {};
const isAddBtnVisible = title !== "Focus" && (isPartnerModeActive ? !!activeGoalId : true);
return (
Expand Down
97 changes: 78 additions & 19 deletions src/components/GlobalAddBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { ReactNode, useEffect } from "react";
import { useRecoilValue } from "recoil";
import React, { ReactNode, useEffect, useState } from "react";
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import { useTranslation } from "react-i18next";
import { useLocation, useNavigate, useParams, useSearchParams } from "react-router-dom";

Expand All @@ -17,6 +17,10 @@ import { TGoalCategory } from "@src/models/GoalItem";
import { allowAddingBudgetGoal } from "@src/store/GoalsState";
import useLongPress from "@src/hooks/useLongPress";
import { useKeyPress } from "@src/hooks/useKeyPress";
import { moveGoalState } from "@src/store/moveGoalState";
import { moveGoalHierarchy } from "@src/helpers/GoalController";
import { displayToast, lastAction } from "@src/store";
import { useParentGoalContext } from "@src/contexts/parentGoal-context";

interface AddGoalOptionProps {
children: ReactNode;
Expand Down Expand Up @@ -52,10 +56,20 @@ const GlobalAddBtn = ({ add }: { add: string }) => {
const { handleAddFeeling } = useFeelingStore();
const isPartnerModeActive = !!partnerId;

const setToastMessage = useSetRecoilState(displayToast);

const setLastAction = useSetRecoilState(lastAction);

const {
parentData: { parentGoal = { id: "root" } },
} = useParentGoalContext();

const navigate = useNavigate();
const [searchParams] = useSearchParams();
const themeSelection = useRecoilValue(themeSelectionMode);
const isAddingBudgetGoalAllowed = useRecoilValue(allowAddingBudgetGoal);
const [goalToMove, setGoalToMove] = useRecoilState(moveGoalState);
const [isDisabled, setIsDisabled] = useState(false);

const enterPressed = useKeyPress("Enter");
const plusPressed = useKeyPress("+");
Expand All @@ -77,6 +91,13 @@ const GlobalAddBtn = ({ add }: { add: string }) => {
};
const handleGlobalAddClick = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.stopPropagation();
if (goalToMove) {
if (add === "myGoals" || isPartnerModeActive) {
navigate(`/goals/${parentId}?addOptions=true`, { state });
}
return;
}

if (themeSelection) {
window.history.back();
} else if (add === "myTime" || add === "myGoals" || isPartnerModeActive) {
Expand All @@ -102,13 +123,28 @@ const GlobalAddBtn = ({ add }: { add: string }) => {

const { onClick, onMouseDown, onMouseUp, onTouchStart, onTouchEnd } = handlers;

const handleMoveGoalHere = async () => {
if (!goalToMove) return;
setIsDisabled(true);
await moveGoalHierarchy(goalToMove.id, parentId).then(() => {
setToastMessage({ open: true, message: "Goal moved successfully", extra: "" });
});
setLastAction("goalMoved");
setGoalToMove(null);
setIsDisabled(false);
window.history.back();
};

useEffect(() => {
if ((plusPressed || enterPressed) && !state.goalType) {
// @ts-ignore
handleGlobalAddClick(new MouseEvent("click"));
}
}, [plusPressed, enterPressed]);

const shouldRenderMoveButton =
goalToMove && goalToMove.id !== parentGoal?.id && goalToMove.parentGoalId !== parentGoal?.id;

if (searchParams?.get("addOptions")) {
return (
<>
Expand All @@ -119,23 +155,46 @@ const GlobalAddBtn = ({ add }: { add: string }) => {
window.history.back();
}}
/>
<AddGoalOption
handleClick={() => {
handleAddGoal("Budget");
}}
disabled={!isAddingBudgetGoalAllowed}
bottom={144}
>
{t("addBtnBudget")}
</AddGoalOption>
<AddGoalOption
handleClick={() => {
handleAddGoal("Standard");
}}
bottom={74}
>
{t("addBtnGoal")}
</AddGoalOption>
{goalToMove ? (
<>
<AddGoalOption
handleClick={handleMoveGoalHere}
bottom={144}
disabled={!shouldRenderMoveButton || isDisabled}
>
{t("Move here")}
</AddGoalOption>
<AddGoalOption
handleClick={() => {
setGoalToMove(null);
window.history.back();
}}
bottom={74}
>
{t("Cancel")}
</AddGoalOption>
</>
) : (
<>
<AddGoalOption
handleClick={() => {
handleAddGoal("Budget");
}}
disabled={!isAddingBudgetGoalAllowed}
bottom={144}
>
{t("addBtnBudget")}
</AddGoalOption>
<AddGoalOption
handleClick={() => {
handleAddGoal("Standard");
}}
bottom={74}
>
{t("addBtnGoal")}
</AddGoalOption>
</>
)}
</>
);
}
Expand Down
Loading
Loading