fix: commenting issues fixed

This commit is contained in:
sriramveeraghanta 2023-09-01 00:22:50 +05:30
parent 4fd7a78d70
commit 376da835ba
9 changed files with 97 additions and 82 deletions

View File

@ -56,15 +56,18 @@ export const IssueListBlock: FC<{ issue: IIssue }> = observer((props) => {
</div> </div>
<div className="inline-flex flex-shrink-0 items-center gap-2 text-xs"> <div className="inline-flex flex-shrink-0 items-center gap-2 text-xs">
{projectStore.deploySettings?.votes && (
<>
{/* upvotes */} {/* upvotes */}
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<IssueBlockUpVotes number={totalUpVotes.length} /> <IssueBlockUpVotes number={totalUpVotes.length} />
</div> </div>
{/* downotes */} {/* downotes */}
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<IssueBlockDownVotes number={totalDownVotes.length} /> <IssueBlockDownVotes number={totalDownVotes.length} />
</div> </div>
</>
)}
{/* priority */} {/* priority */}
{issue?.priority && ( {issue?.priority && (

View File

@ -1,16 +1,16 @@
import { useEffect } from "react";
import Image from "next/image"; import Image from "next/image";
import { observer } from "mobx-react-lite";
import { useRouter } from "next/router";
// components // components
import { NavbarSearch } from "./search"; import { NavbarSearch } from "./search";
import { NavbarIssueBoardView } from "./issue-board-view"; import { NavbarIssueBoardView } from "./issue-board-view";
import { NavbarIssueFilter } from "./issue-filter"; import { NavbarIssueFilter } from "./issue-filter";
import { NavbarTheme } from "./theme"; import { NavbarTheme } from "./theme";
// mobx react lite // lib
import { observer } from "mobx-react-lite";
// mobx
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// store
import { RootStore } from "store/root"; import { RootStore } from "store/root";
import { useEffect } from "react";
import { useRouter } from "next/router";
const renderEmoji = (emoji: string | { name: string; color: string }) => { const renderEmoji = (emoji: string | { name: string; color: string }) => {
if (!emoji) return; if (!emoji) return;
@ -39,7 +39,6 @@ const IssueNavbar = observer(() => {
useEffect(() => { useEffect(() => {
if (workspace_slug && projectStore) { if (workspace_slug && projectStore) {
if (board) { if (board) {
console.log("setting");
projectStore.setActiveBoard(board.toString()); projectStore.setActiveBoard(board.toString());
} else { } else {
router.push(`/${workspace_slug}/${project_slug}?board=list`); router.push(`/${workspace_slug}/${project_slug}?board=list`);

View File

@ -1,22 +1,16 @@
import React, { useEffect, useState, useRef } from "react"; import React, { useEffect, useState, useRef } from "react";
import { useForm, Controller } from "react-hook-form";
// react-hook-form
import { useForm } from "react-hook-form";
// mobx
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
// headless ui
import { Menu, Transition } from "@headlessui/react"; import { Menu, Transition } from "@headlessui/react";
// lib
import { useMobxStore } from "lib/mobx/store-provider";
// icons // icons
import { ChatBubbleLeftEllipsisIcon, CheckIcon, XMarkIcon, EllipsisVerticalIcon } from "@heroicons/react/24/outline"; import { ChatBubbleLeftEllipsisIcon, CheckIcon, XMarkIcon, EllipsisVerticalIcon } from "@heroicons/react/24/outline";
// helpers // helpers
import { timeAgo } from "helpers/date-time.helper"; import { timeAgo } from "helpers/date-time.helper";
// types // types
import { Comment } from "types"; import { Comment } from "types";
// components
import { TipTapEditor } from "components/tiptap"; import { TipTapEditor } from "components/tiptap";
type Props = { type Props = {
@ -26,51 +20,37 @@ type Props = {
export const CommentCard: React.FC<Props> = observer((props) => { export const CommentCard: React.FC<Props> = observer((props) => {
const { comment, workspaceSlug } = props; const { comment, workspaceSlug } = props;
// store
const { user: userStore, issue: issueStore } = useMobxStore(); const { user: userStore, issue: issueStore, issueDetails: issueDetailStore } = useMobxStore();
// states
const editorRef = useRef<any>(null);
const showEditorRef = useRef<any>(null);
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const { const {
formState: { isSubmitting }, formState: { isSubmitting },
handleSubmit, handleSubmit,
setFocus, setFocus,
watch, control,
setValue, } = useForm<any>({
} = useForm<Comment>({ defaultValues: { comment_html: comment.comment_html },
defaultValues: comment,
}); });
const handleDelete = async () => { const handleDelete = async () => {
if (!workspaceSlug || !issueStore.activePeekOverviewIssueId) return; if (!workspaceSlug || !issueDetailStore.peekId) return;
await issueStore.deleteIssueCommentAsync( await issueDetailStore.deleteIssueComment(workspaceSlug, comment.project, issueDetailStore.peekId, comment.id);
workspaceSlug,
comment.project,
issueStore.activePeekOverviewIssueId,
comment.id
);
}; };
const handleCommentUpdate = async (formData: Comment) => { const handleCommentUpdate = async (formData: Comment) => {
if (!workspaceSlug || !issueStore.activePeekOverviewIssueId) return; if (!workspaceSlug || !issueDetailStore.peekId) return;
const response = await issueStore.updateIssueCommentAsync( console.log("formData", formData);
const response = await issueDetailStore.updateIssueComment(
workspaceSlug, workspaceSlug,
comment.project, comment.project,
issueStore.activePeekOverviewIssueId, issueDetailStore.peekId,
comment.id, comment.id,
formData formData
); );
if (response) {
editorRef.current?.setEditorValue(response.comment_html);
showEditorRef.current?.setEditorValue(response.comment_html);
}
setIsEditing(false); setIsEditing(false);
}; };
@ -82,6 +62,7 @@ export const CommentCard: React.FC<Props> = observer((props) => {
<div className="relative flex items-start space-x-3"> <div className="relative flex items-start space-x-3">
<div className="relative px-1"> <div className="relative px-1">
{comment.actor_detail.avatar && comment.actor_detail.avatar !== "" ? ( {comment.actor_detail.avatar && comment.actor_detail.avatar !== "" ? (
// eslint-disable-next-line @next/next/no-img-element
<img <img
src={comment.actor_detail.avatar} src={comment.actor_detail.avatar}
alt={ alt={
@ -118,17 +99,21 @@ export const CommentCard: React.FC<Props> = observer((props) => {
className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`} className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`}
> >
<div> <div>
<Controller
control={control}
name="comment_html"
render={({ field: { onChange, value } }) => (
<TipTapEditor <TipTapEditor
workspaceSlug={workspaceSlug as string} workspaceSlug={workspaceSlug as string}
ref={editorRef} value={value}
value={watch("comment_html")}
debouncedUpdatesEnabled={false} debouncedUpdatesEnabled={false}
customClassName="min-h-[50px] p-3 shadow-sm" customClassName="min-h-[50px] p-3 shadow-sm"
onChange={(comment_json: Object, comment_html: string) => { onChange={(comment_json: Object, comment_html: string) => {
setValue("comment_json", comment_json); onChange(comment_html);
setValue("comment_html", comment_html);
}} }}
/> />
)}
/>
</div> </div>
<div className="flex gap-1 self-end"> <div className="flex gap-1 self-end">
<button <button
@ -149,8 +134,7 @@ export const CommentCard: React.FC<Props> = observer((props) => {
</form> </form>
<div className={`${isEditing ? "hidden" : ""}`}> <div className={`${isEditing ? "hidden" : ""}`}>
<TipTapEditor <TipTapEditor
workspaceSlug={workspaceSlug as string} workspaceSlug={workspaceSlug.toString()}
ref={showEditorRef}
value={comment.comment_html} value={comment.comment_html}
editable={false} editable={false}
customClassName="text-xs border border-custom-border-200 bg-custom-background-100" customClassName="text-xs border border-custom-border-200 bg-custom-background-100"

View File

@ -20,6 +20,8 @@ export const PeekOverviewIssueActivity: React.FC<Props> = observer((props) => {
const comments = issueDetailStore.details[issueDetailStore.peekId || ""]?.comments || []; const comments = issueDetailStore.details[issueDetailStore.peekId || ""]?.comments || [];
console.log("comments", comments);
return ( return (
<div> <div>
<h4 className="font-medium">Activity</h4> <h4 className="font-medium">Activity</h4>

View File

@ -19,7 +19,7 @@ export const IssuePeekOverview: React.FC<Props> = observer((props) => {
// router // router
const router = useRouter(); const router = useRouter();
const { workspace_slug, project_slug, peekId } = router.query; const { workspace_slug, project_slug, peekId, board } = router.query;
// store // store
const { issueDetails: issueDetailStore, issue: issueStore } = useMobxStore(); const { issueDetails: issueDetailStore, issue: issueStore } = useMobxStore();
@ -34,14 +34,13 @@ export const IssuePeekOverview: React.FC<Props> = observer((props) => {
}, [workspace_slug, project_slug, issueDetailStore, issueDetails, peekId, issueStore.issues]); }, [workspace_slug, project_slug, issueDetailStore, issueDetails, peekId, issueStore.issues]);
const handleClose = () => { const handleClose = () => {
const { query } = router;
delete query.peekId;
issueDetailStore.setPeekId(null); issueDetailStore.setPeekId(null);
router.replace( router.replace(
{ {
pathname: `/${workspace_slug?.toString()}/${project_slug}`, pathname: `/${workspace_slug?.toString()}/${project_slug}`,
query, query: {
board,
},
}, },
undefined, undefined,
{ shallow: true } { shallow: true }

View File

@ -30,7 +30,7 @@ export const SidePeekView: React.FC<Props> = observer((props) => {
<PeekOverviewIssueDetails issueDetails={issueDetails} /> <PeekOverviewIssueDetails issueDetails={issueDetails} />
</div> </div>
{/* issue properties */} {/* issue properties */}
<div className="w-full mt-10"> <div className="w-full mt-6">
<PeekOverviewIssueProperties issueDetails={issueDetails} /> <PeekOverviewIssueProperties issueDetails={issueDetails} />
</div> </div>
{/* divider */} {/* divider */}

View File

@ -38,7 +38,6 @@ const HomePage = () => {
router.push(`/onboarding?next_path=${next_path}`); router.push(`/onboarding?next_path=${next_path}`);
return; return;
} }
console.log("hello");
router.push(next_path.toString()); router.push(next_path.toString());
}; };

View File

@ -1,5 +1,6 @@
module.exports = { module.exports = {
plugins: { plugins: {
"tailwindcss/nesting": {},
tailwindcss: {}, tailwindcss: {},
autoprefixer: {}, autoprefixer: {},
}, },

View File

@ -23,7 +23,14 @@ export interface IIssueDetailStore {
fetchIssueDetails: (workspaceId: string, projectId: string, issueId: string) => void; fetchIssueDetails: (workspaceId: string, projectId: string, issueId: string) => void;
// issue comments // issue comments
addIssueComment: (workspaceId: string, projectId: string, issueId: string, data: any) => Promise<void>; addIssueComment: (workspaceId: string, projectId: string, issueId: string, data: any) => Promise<void>;
deleteIssueComment: (workspaceId: string, projectId: string, issueId: string) => void; updateIssueComment: (
workspaceId: string,
projectId: string,
issueId: string,
comment_id: string,
data: any
) => Promise<any>;
deleteIssueComment: (workspaceId: string, projectId: string, issueId: string, comment_id: string) => void;
// issue reactions // issue reactions
addIssueReaction: (workspaceId: string, projectId: string, issueId: string, data: any) => void; addIssueReaction: (workspaceId: string, projectId: string, issueId: string, data: any) => void;
removeIssueReaction: (workspaceId: string, projectId: string, issueId: string, data: any) => void; removeIssueReaction: (workspaceId: string, projectId: string, issueId: string, data: any) => void;
@ -40,7 +47,7 @@ class IssueDetailStore implements IssueDetailStore {
details: { details: {
[key: string]: IIssue; [key: string]: IIssue;
} = {}; } = {};
issueService: any; issueService;
rootStore: RootStore; rootStore: RootStore;
constructor(_rootStore: RootStore) { constructor(_rootStore: RootStore) {
@ -97,7 +104,6 @@ class IssueDetailStore implements IssueDetailStore {
try { try {
const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId); const issueDetails = this.rootStore.issue.issues?.find((i) => i.id === issueId);
const issueCommentResponse = await this.issueService.createIssueComment(workspaceSlug, projectId, issueId, data); const issueCommentResponse = await this.issueService.createIssueComment(workspaceSlug, projectId, issueId, data);
console.log("issueCommentResponse", issueCommentResponse);
if (issueDetails) { if (issueDetails) {
runInAction(() => { runInAction(() => {
this.details = { this.details = {
@ -116,36 +122,58 @@ class IssueDetailStore implements IssueDetailStore {
} }
}; };
updateIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, data: any) => { updateIssueComment = async (
workspaceSlug: string,
projectId: string,
issueId: string,
commentId: string,
data: any
) => {
try { try {
const issueVoteResponse = await this.issueService.updateIssueComment(workspaceSlug, projectId, issueId, data); const issueCommentUpdateResponse = await this.issueService.updateIssueComment(
if (issueVoteResponse) { workspaceSlug,
projectId,
issueId,
commentId,
data
);
// const issueComments = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
if (issueCommentUpdateResponse) {
runInAction(() => { runInAction(() => {
const remainingComments = this.details[issueId].comments.filter((com) => com.id === commentId);
this.details = { this.details = {
...this.details, ...this.details,
[issueId]: { [issueId]: {
...issueDetails, ...this.details[issueId],
comments: commentsResponse, comments: [...remainingComments, issueCommentUpdateResponse],
}, },
}; };
}); });
} }
return issueCommentUpdateResponse;
} catch (error) { } catch (error) {
console.log("Failed to add issue comment"); console.log("Failed to add issue comment");
} }
}; };
deleteIssueComment = async () => { deleteIssueComment = async (workspaceSlug: string, projectId: string, issueId: string, comment_id: string) => {
try { try {
const issueVoteResponse = await this.issueService.deleteIssueComment(workspaceSlug, projectId, issueId, data); const issueVoteResponse = await this.issueService.deleteIssueComment(
// const issueDetails = await this.issueService.fetchIssueDetails(workspaceSlug, projectId, issueId); workspaceSlug,
projectId,
issueId,
comment_id
);
const issueComments = await this.issueService.getIssueComments(workspaceSlug, projectId, issueId);
if (issueVoteResponse) { if (issueVoteResponse) {
runInAction(() => { runInAction(() => {
this.details = { this.details = {
...this.details, ...this.details,
[issueId]: { [issueId]: {
...issueDetails, ...this.details[issueId],
comments: issueComments,
}, },
}; };
}); });