[WEB-468] fix: issue detail endpoints (#3722)
* dev: add is_subscriber to issue details endpoint * dev: remove is_subscribed annotation from detail serializers * dev: update issue details endpoint * dev: inbox issue create * dev: issue detail serializer * dev: optimize and add extra fields for issue details * dev: remove data from issue updates * dev: add fields for issue link and attachment * remove expecting a issue response while updating and deleting an issue * change link, attachment and reaction types and modify store to recieve their data from within the issue detail API call * make changes for subscription store to recieve data from issue detail API call * dev: add issue reaction id * add query prarms for archived issue --------- Co-authored-by: rahulramesha <rahulramesham@gmail.com>
This commit is contained in:
parent
7927b7678d
commit
03e5f4a5bd
31 changed files with 490 additions and 324 deletions
|
|
@ -196,9 +196,9 @@ export const CreateUpdateDraftIssueModal: React.FC<IssuesModalProps> = observer(
|
|||
const updateDraftIssue = async (payload: Partial<TIssue>) => {
|
||||
await draftIssues
|
||||
.updateIssue(workspaceSlug as string, activeProject ?? "", data?.id ?? "", payload)
|
||||
.then((res) => {
|
||||
.then(() => {
|
||||
if (isUpdatingSingleIssue) {
|
||||
mutate<TIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...res }), false);
|
||||
mutate<TIssue>(PROJECT_ISSUES_DETAILS, (prevData) => ({ ...prevData, ...payload } as TIssue), false);
|
||||
} else {
|
||||
if (payload.parent_id) mutate(SUB_ISSUES(payload.parent_id.toString()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { FC, useState } from "react";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
import { useIssueDetail } from "hooks/store";
|
||||
import { useIssueDetail, useMember } from "hooks/store";
|
||||
// ui
|
||||
import { ExternalLinkIcon, Tooltip } from "@plane/ui";
|
||||
// icons
|
||||
|
|
@ -26,6 +26,7 @@ export const IssueLinkDetail: FC<TIssueLinkDetail> = (props) => {
|
|||
toggleIssueLinkModal: toggleIssueLinkModalStore,
|
||||
link: { getLinkById },
|
||||
} = useIssueDetail();
|
||||
const { getUserDetails } = useMember();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
// state
|
||||
|
|
@ -38,6 +39,8 @@ export const IssueLinkDetail: FC<TIssueLinkDetail> = (props) => {
|
|||
const linkDetail = getLinkById(linkId);
|
||||
if (!linkDetail) return <></>;
|
||||
|
||||
const createdByDetails = getUserDetails(linkDetail.created_by_id);
|
||||
|
||||
return (
|
||||
<div key={linkId}>
|
||||
<IssueLinkCreateUpdateModal
|
||||
|
|
@ -110,10 +113,11 @@ export const IssueLinkDetail: FC<TIssueLinkDetail> = (props) => {
|
|||
<p className="mt-0.5 stroke-[1.5] text-xs text-custom-text-300">
|
||||
Added {calculateTimeAgo(linkDetail.created_at)}
|
||||
<br />
|
||||
by{" "}
|
||||
{linkDetail.created_by_detail.is_bot
|
||||
? linkDetail.created_by_detail.first_name + " Bot"
|
||||
: linkDetail.created_by_detail.display_name}
|
||||
{createdByDetails && (
|
||||
<>
|
||||
by {createdByDetails?.is_bot ? createdByDetails?.first_name + " Bot" : createdByDetails?.display_name}
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||
showToast: boolean = true
|
||||
) => {
|
||||
try {
|
||||
const response = await updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
await updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
if (showToast) {
|
||||
setToastAlert({
|
||||
title: "Issue updated successfully",
|
||||
|
|
@ -106,7 +106,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
|||
}
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...response, state: "SUCCESS", element: "Issue detail page" },
|
||||
payload: { ...data, issueId, state: "SUCCESS", element: "Issue detail page" },
|
||||
updates: {
|
||||
changed_property: Object.keys(data).join(","),
|
||||
change_details: Object.values(data).join(","),
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import { FC, useState } from "react";
|
||||
import { Bell, BellOff } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { FC, useState } from "react";
|
||||
// UI
|
||||
import { Button, Loader } from "@plane/ui";
|
||||
// hooks
|
||||
import { useIssueDetail } from "hooks/store";
|
||||
import useToast from "hooks/use-toast";
|
||||
import isNil from "lodash/isNil";
|
||||
|
||||
export type TIssueSubscription = {
|
||||
workspaceSlug: string;
|
||||
|
|
@ -25,17 +26,17 @@ export const IssueSubscription: FC<TIssueSubscription> = observer((props) => {
|
|||
// state
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const subscription = getSubscriptionByIssueId(issueId);
|
||||
const isSubscribed = getSubscriptionByIssueId(issueId);
|
||||
|
||||
const handleSubscription = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
if (subscription?.subscribed) await removeSubscription(workspaceSlug, projectId, issueId);
|
||||
if (isSubscribed) await removeSubscription(workspaceSlug, projectId, issueId);
|
||||
else await createSubscription(workspaceSlug, projectId, issueId);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: `Issue ${subscription?.subscribed ? `unsubscribed` : `subscribed`} successfully.!`,
|
||||
message: `Issue ${subscription?.subscribed ? `unsubscribed` : `subscribed`} successfully.!`,
|
||||
title: `Issue ${isSubscribed ? `unsubscribed` : `subscribed`} successfully.!`,
|
||||
message: `Issue ${isSubscribed ? `unsubscribed` : `subscribed`} successfully.!`,
|
||||
});
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
|
|
@ -48,42 +49,32 @@ export const IssueSubscription: FC<TIssueSubscription> = observer((props) => {
|
|||
}
|
||||
};
|
||||
|
||||
if (!subscription)
|
||||
if (isNil(isSubscribed))
|
||||
return (
|
||||
<Loader>
|
||||
<Loader.Item width="92px" height="27px" />
|
||||
<Loader.Item width="106px" height="28px" />
|
||||
</Loader>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
{subscription ? (
|
||||
<div>
|
||||
<Button
|
||||
size="sm"
|
||||
prependIcon={subscription?.subscribed ? <BellOff /> : <Bell className="h-3 w-3" />}
|
||||
variant="outline-primary"
|
||||
className="hover:!bg-custom-primary-100/20"
|
||||
onClick={handleSubscription}
|
||||
>
|
||||
{loading ? (
|
||||
<span>
|
||||
<span className="hidden sm:block">Loading...</span>
|
||||
</span>
|
||||
) : subscription?.subscribed ? (
|
||||
<div className="hidden sm:block">Unsubscribe</div>
|
||||
) : (
|
||||
<div className="hidden sm:block">Subscribe</div>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Loader>
|
||||
<Loader.Item height="28px" width="106px" />
|
||||
</Loader>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
<div>
|
||||
<Button
|
||||
size="sm"
|
||||
prependIcon={isSubscribed ? <BellOff /> : <Bell className="h-3 w-3" />}
|
||||
variant="outline-primary"
|
||||
className="hover:!bg-custom-primary-100/20"
|
||||
onClick={handleSubscription}
|
||||
>
|
||||
{loading ? (
|
||||
<span>
|
||||
<span className="hidden sm:block">Loading</span>...
|
||||
</span>
|
||||
) : isSubscribed ? (
|
||||
<div className="hidden sm:block">Unsubscribe</div>
|
||||
) : (
|
||||
<div className="hidden sm:block">Subscribe</div>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
|||
if (!workspaceSlug || !payload.project_id || !data?.id) return;
|
||||
|
||||
try {
|
||||
const response = await currentIssueStore.updateIssue(workspaceSlug, payload.project_id, data.id, payload, viewId);
|
||||
await currentIssueStore.updateIssue(workspaceSlug, payload.project_id, data.id, payload, viewId);
|
||||
setToastAlert({
|
||||
type: "success",
|
||||
title: "Success!",
|
||||
|
|
@ -191,11 +191,10 @@ export const CreateUpdateIssueModal: React.FC<IssuesModalProps> = observer((prop
|
|||
});
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...response, state: "SUCCESS" },
|
||||
payload: { ...payload, issueId: data.id, state: "SUCCESS" },
|
||||
path: router.asPath,
|
||||
});
|
||||
handleClose();
|
||||
return response;
|
||||
} catch (error) {
|
||||
setToastAlert({
|
||||
type: "error",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import { ISSUE_UPDATED, ISSUE_DELETED } from "constants/event-tracker";
|
|||
|
||||
interface IIssuePeekOverview {
|
||||
is_archived?: boolean;
|
||||
onIssueUpdate?: (issue: Partial<TIssue>) => Promise<void>;
|
||||
}
|
||||
|
||||
export type TIssuePeekOperations = {
|
||||
|
|
@ -46,7 +45,7 @@ export type TIssuePeekOperations = {
|
|||
};
|
||||
|
||||
export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
||||
const { is_archived = false, onIssueUpdate } = props;
|
||||
const { is_archived = false } = props;
|
||||
// hooks
|
||||
const { setToastAlert } = useToast();
|
||||
// router
|
||||
|
|
@ -87,7 +86,6 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||
) => {
|
||||
try {
|
||||
const response = await updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
if (onIssueUpdate) await onIssueUpdate(response);
|
||||
if (showToast)
|
||||
setToastAlert({
|
||||
title: "Issue updated successfully",
|
||||
|
|
@ -96,7 +94,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||
});
|
||||
captureIssueEvent({
|
||||
eventName: ISSUE_UPDATED,
|
||||
payload: { ...response, state: "SUCCESS", element: "Issue peek-overview" },
|
||||
payload: { ...data, issueId, state: "SUCCESS", element: "Issue peek-overview" },
|
||||
updates: {
|
||||
changed_property: Object.keys(data).join(","),
|
||||
change_details: Object.values(data).join(","),
|
||||
|
|
@ -314,7 +312,6 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
|
|||
removeIssueFromModule,
|
||||
removeModulesFromIssue,
|
||||
setToastAlert,
|
||||
onIssueUpdate,
|
||||
captureIssueEvent,
|
||||
router.asPath,
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue