Skip to content

Commit

Permalink
Merge pull request #2058 from makeplane/dev-deploy-fixes
Browse files Browse the repository at this point in the history
fix: speeding up reactions and votes 🚀
  • Loading branch information
sriramveeraghanta authored Sep 1, 2023
2 parents 71c8f79 + 2155a33 commit a6cd080
Show file tree
Hide file tree
Showing 12 changed files with 189 additions and 665 deletions.
6 changes: 2 additions & 4 deletions apps/space/components/issues/board-views/block-state.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
"use client";

// constants
import { issueGroupFilter } from "constants/data";

Expand All @@ -8,8 +6,8 @@ export const IssueBlockState = ({ state }: any) => {

if (stateGroup === null) return <></>;
return (
<div className="flex items-center justify-between gap-1 w-full rounded shadow-sm border-[0.5px] border-custom-border-300 duration-300 focus:outline-none px-2.5 py-1 text-xs cursor-pointer hover:bg-custom-background-80">
<div className="flex items-center cursor-pointer w-full gap-1.5 text-custom-text-200">
<div className="flex items-center justify-between gap-1 w-full rounded shadow-sm border-[0.5px] border-custom-border-300 duration-300 focus:outline-none px-2.5 py-1 text-xs">
<div className="flex items-center w-full gap-1.5 text-custom-text-200">
<stateGroup.icon />
<div className="text-xs">{state?.name}</div>
</div>
Expand Down
14 changes: 1 addition & 13 deletions apps/space/components/issues/board-views/list/block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { IIssue } from "types/issue";
// store
import { RootStore } from "store/root";
import { IssueVotes } from "components/issues/peek-overview";

export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => {
const { issue } = props;
Expand Down Expand Up @@ -56,19 +57,6 @@ export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => {
</div>

<div className="inline-flex flex-shrink-0 items-center gap-2 text-xs">
{projectStore.deploySettings?.votes && (
<>
{/* upvotes */}
<div className="flex-shrink-0">
<IssueBlockUpVotes number={totalUpVotes.length} />
</div>
{/* downotes */}
<div className="flex-shrink-0">
<IssueBlockDownVotes number={totalDownVotes.length} />
</div>
</>
)}

{/* priority */}
{issue?.priority && (
<div className="flex-shrink-0">
Expand Down
13 changes: 10 additions & 3 deletions apps/space/components/issues/navbar/theme.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
"use client";

// next theme
import { useTheme } from "next-themes";

// mobx react lite
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";

export const NavbarTheme = observer(() => {
const [appTheme, setAppTheme] = useState("light");

const { setTheme, theme } = useTheme();

const handleTheme = () => {
setTheme(theme === "light" ? "dark" : "light");
};

useEffect(() => {
if (!theme) return;

setAppTheme(theme);
}, [theme]);

return (
<button
type="button"
onClick={handleTheme}
className="relative w-7 h-7 grid place-items-center bg-custom-background-100 hover:bg-custom-background-80 text-custom-text-100 rounded"
>
<span className="material-symbols-rounded text-sm">{theme === "light" ? "dark_mode" : "light_mode"}</span>
<span className="material-symbols-rounded text-sm">{appTheme === "light" ? "dark_mode" : "light_mode"}</span>
</button>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ export const CommentCard: React.FC<Props> = observer((props) => {
) : (
<div className={`grid h-7 w-7 place-items-center rounded-full border-2 border-white bg-gray-500 text-white`}>
{comment.actor_detail.is_bot
? comment.actor_detail.first_name.charAt(0)
: comment.actor_detail.display_name.charAt(0)}
? comment?.actor_detail?.first_name?.charAt(0)
: comment?.actor_detail?.display_name?.charAt(0)}
</div>
)}

Expand Down
4 changes: 2 additions & 2 deletions apps/space/components/issues/peek-overview/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const PeekOverviewHeader: React.FC<Props> = (props) => {
<div className="flex justify-between items-center">
<div className="flex items-center gap-4">
{issueDetailStore.peekMode === "side" && (
<button type="button" onClick={handleClose} autoFocus={false}>
<button type="button" onClick={handleClose}>
<East
sx={{
fontSize: "14px",
Expand Down Expand Up @@ -134,7 +134,7 @@ export const PeekOverviewHeader: React.FC<Props> = (props) => {
</div>
{(issueDetailStore.peekMode === "side" || issueDetailStore.peekMode === "modal") && (
<div className="flex items-center gap-2 flex-shrink-0">
<button type="button" onClick={handleCopyLink} className="-rotate-45">
<button type="button" onClick={handleCopyLink} className="-rotate-45 focus:outline-none" tabIndex={1}>
<Icon iconName="link" />
</button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const PeekOverviewIssueActivity: React.FC<Props> = observer((props) => {
)}
</>
) : (
<div className="bg-custom-background-80 px-2 py-2.5 flex items-center justify-between gap-2 border border-custom-border-300 rounded">
<div className="bg-custom-background-80 px-2 py-2.5 flex items-center justify-between gap-2 border border-custom-border-300 rounded mt-4">
<p className="flex gap-2 text-sm text-custom-text-200 break-words overflow-hidden">
<Icon iconName="lock" className="!text-sm" />
Sign in to add your comment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ export const IssueEmojiReactions: React.FC = observer(() => {
if (!workspace_slug || !project_slug || !issueId) return;
const userReaction = reactions?.find((r) => r.actor_detail.id === user?.id && r.reaction === reactionHex);
if (userReaction) return;
issueDetailsStore.addIssueReaction(workspace_slug.toString(), project_slug.toString(), issueId, {
reaction: reactionHex,
});
issueDetailsStore.addIssueReaction(workspace_slug.toString(), project_slug.toString(), issueId, reactionHex);
};

const handleReactionClick = (reactionHex: string) => {
Expand Down Expand Up @@ -57,6 +55,7 @@ export const IssueEmojiReactions: React.FC = observer(() => {
if (reactions.length > 0)
return (
<Tooltip
key={reaction}
tooltipContent={
<div>
{reactions
Expand All @@ -74,7 +73,6 @@ export const IssueEmojiReactions: React.FC = observer(() => {
handleReactionClick(reaction);
});
}}
key={reaction}
className={`flex items-center gap-1 text-custom-text-100 text-sm h-full px-2 py-1 rounded-md ${
reactions?.some((r) => r.actor_detail.id === user?.id && r.reaction === reaction)
? "bg-custom-primary-100/10"
Expand Down
171 changes: 116 additions & 55 deletions apps/space/store/issue_details.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { makeObservable, observable, action, runInAction } from "mobx";
import { v4 as uuidv4 } from "uuid";
// store
import { RootStore } from "./root";
// services
import IssueService from "services/issue.service";
import { IIssue } from "types/issue";
import { IIssue, IVote } from "types/issue";

export type IPeekMode = "side" | "modal" | "full";

Expand Down Expand Up @@ -32,8 +33,8 @@ export interface IIssueDetailStore {
) => Promise<any>;
deleteIssueComment: (workspaceId: string, projectId: string, issueId: string, comment_id: string) => void;
// issue reactions
addIssueReaction: (workspaceId: string, projectId: string, issueId: string, data: any) => void;
removeIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionId: string) => void;
addIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionHex: string) => void;
removeIssueReaction: (workspaceId: string, projectId: string, issueId: string, reactionHex: string) => void;
// issue votes
addIssueVote: (workspaceId: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => Promise<void>;
removeIssueVote: (workspaceId: string, projectId: string, issueId: string) => Promise<void>;
Expand Down Expand Up @@ -88,7 +89,7 @@ class IssueDetailStore implements IssueDetailStore {
this.details = {
...this.details,
[issueId]: {
...issueDetails,
...(this.details[issueId] ?? issueDetails),
comments: commentsResponse,
},
};
Expand Down Expand Up @@ -174,84 +175,144 @@ class IssueDetailStore implements IssueDetailStore {
}
};

addIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => {
addIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
try {
const issueVoteResponse = await this.issueService.createIssueReaction(workspaceSlug, projectId, issueId, data);
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
reactions: [
...this.details[issueId].reactions,
{
id: uuidv4(),
issue: issueId,
reaction: reactionHex,
actor_detail: this.rootStore.user.currentActor,
},
],
},
};
});

if (issueVoteResponse) {
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
reactions: [...this.details[issueId].reactions, issueVoteResponse],
},
};
});
}
await this.issueService.createIssueReaction(workspaceSlug, projectId, issueId, {
reaction: reactionHex,
});
} catch (error) {
console.log("Failed to add issue vote");
const issueReactions = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
reactions: issueReactions,
},
};
});
}
};

removeIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionId: string) => {
removeIssueReaction = async (workspaceSlug: string, projectId: string, issueId: string, reactionHex: string) => {
try {
await this.issueService.deleteIssueReaction(workspaceSlug, projectId, issueId, reactionId);
const reactions = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
const newReactions = this.details[issueId].reactions.filter(
(_r) => !(_r.reaction === reactionHex && _r.actor_detail.id === this.rootStore.user.currentUser?.id)
);

if (reactions) {
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
reactions: reactions,
},
};
});
}
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
reactions: newReactions,
},
};
});

await this.issueService.deleteIssueReaction(workspaceSlug, projectId, issueId, reactionHex);
} catch (error) {
console.log("Failed to remove issue reaction");
const reactions = await this.issueService.getIssueReactions(workspaceSlug, projectId, issueId);
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
reactions: reactions,
},
};
});
}
};

addIssueVote = async (workspaceSlug: string, projectId: string, issueId: string, data: { vote: 1 | -1 }) => {
const newVote: IVote = {
actor: this.rootStore.user.currentUser?.id ?? "",
actor_detail: this.rootStore.user.currentActor,
issue: issueId,
project: projectId,
workspace: workspaceSlug,
vote: data.vote,
};

const filteredVotes = this.details[issueId].votes.filter((v) => v.actor !== this.rootStore.user.currentUser?.id);

try {
const issueVoteResponse = await this.issueService.createIssueVote(workspaceSlug, projectId, issueId, data);
const issueDetails = await this.issueService.getIssueById(workspaceSlug, projectId, issueId);
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
votes: [...filteredVotes, newVote],
},
};
});

if (issueVoteResponse) {
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...issueDetails,
},
};
});
}
await this.issueService.createIssueVote(workspaceSlug, projectId, issueId, data);
} catch (error) {
console.log("Failed to add issue vote");
const issueVotes = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);

runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
votes: issueVotes,
},
};
});
}
};

removeIssueVote = async (workspaceSlug: string, projectId: string, issueId: string) => {
const newVotes = this.details[issueId].votes.filter((v) => v.actor !== this.rootStore.user.currentUser?.id);

try {
await this.issueService.deleteIssueVote(workspaceSlug, projectId, issueId);
const issueDetails = await this.issueService.getIssueById(workspaceSlug, projectId, issueId);
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
votes: newVotes,
},
};
});

if (issueDetails) {
runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...issueDetails,
},
};
});
}
await this.issueService.deleteIssueVote(workspaceSlug, projectId, issueId);
} catch (error) {
console.log("Failed to remove issue vote");
const issueVotes = await this.issueService.getIssueVotes(workspaceSlug, projectId, issueId);

runInAction(() => {
this.details = {
...this.details,
[issueId]: {
...this.details[issueId],
votes: issueVotes,
},
};
});
}
};
}
Expand Down
Loading

1 comment on commit a6cd080

@vercel
Copy link

@vercel vercel bot commented on a6cd080 Sep 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

plane-sh-dev – ./apps/space

plane-sh-dev-plane.vercel.app
plane-sh-dev-git-develop-plane.vercel.app
plane-space-dev.vercel.app

Please sign in to comment.