fix: merge conflicts from preview

This commit is contained in:
sriram veeraghanta 2024-08-16 17:55:08 +05:30
commit 3729011cb0
283 changed files with 4895 additions and 5157 deletions

View file

@ -8,7 +8,7 @@ import { AlertModalCore, TOAST_TYPE, setToast } from "@plane/ui";
// constants
import { PROJECT_ERROR_MESSAGES } from "@/constants/project";
// hooks
import { useIssues, useProject } from "@/hooks/store";
import { useIssues, useProject, useUser } from "@/hooks/store";
type Props = {
isOpen: boolean;
@ -26,6 +26,7 @@ export const DeleteIssueModal: React.FC<Props> = (props) => {
// store hooks
const { issueMap } = useIssues();
const { getProjectById } = useProject();
const { data: currentUser, canPerformProjectAdminActions } = useUser();
useEffect(() => {
setIsDeleting(false);
@ -36,6 +37,8 @@ export const DeleteIssueModal: React.FC<Props> = (props) => {
// derived values
const issue = data ? data : issueMap[dataId!];
const projectDetails = getProjectById(issue?.project_id);
const isIssueCreator = issue?.created_by === currentUser?.id;
const authorized = isIssueCreator || canPerformProjectAdminActions;
const onClose = () => {
setIsDeleting(false);
@ -44,6 +47,16 @@ export const DeleteIssueModal: React.FC<Props> = (props) => {
const handleIssueDelete = async () => {
setIsDeleting(true);
if (!authorized) {
setToast({
title: PROJECT_ERROR_MESSAGES.permissionError.title,
type: TOAST_TYPE.ERROR,
message: PROJECT_ERROR_MESSAGES.permissionError.message,
});
onClose();
return;
}
if (onSubmit)
await onSubmit()
.then(() => {

View file

@ -70,11 +70,12 @@ export const useRelationOperations = (): TRelationIssueOperations => {
},
remove: async (workspaceSlug: string, projectId: string, issueId: string) => {
try {
await removeIssue(workspaceSlug, projectId, issueId);
captureIssueEvent({
eventName: ISSUE_DELETED,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
path: pathname,
return removeIssue(workspaceSlug, projectId, issueId).then(() => {
captureIssueEvent({
eventName: ISSUE_DELETED,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
path: pathname,
});
});
} catch (error) {
captureIssueEvent({

View file

@ -150,13 +150,14 @@ export const useSubIssueOperations = (): TSubIssueOperations => {
deleteSubIssue: async (workspaceSlug: string, projectId: string, parentIssueId: string, issueId: string) => {
try {
setSubIssueHelpers(parentIssueId, "issue_loader", issueId);
await deleteSubIssue(workspaceSlug, projectId, parentIssueId, issueId);
captureIssueEvent({
eventName: "Sub-issue deleted",
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
path: pathname,
return deleteSubIssue(workspaceSlug, projectId, parentIssueId, issueId).then(() => {
captureIssueEvent({
eventName: "Sub-issue deleted",
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
path: pathname,
});
setSubIssueHelpers(parentIssueId, "issue_loader", issueId);
});
setSubIssueHelpers(parentIssueId, "issue_loader", issueId);
} catch (error) {
captureIssueEvent({
eventName: "Sub-issue removed",

View file

@ -137,7 +137,11 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
>
<>
<form className={`flex-col gap-2 ${isEditing ? "flex" : "hidden"}`}>
<div>
<div
onKeyDown={(e) => {
if (e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !isEmpty) handleSubmit(onEnter)(e);
}}
>
<LiteTextEditor
workspaceId={workspaceId}
projectId={projectId}
@ -147,13 +151,9 @@ export const IssueCommentCard: FC<TIssueCommentCard> = observer((props) => {
initialValue={watch("comment_html") ?? ""}
value={null}
onChange={(comment_json, comment_html) => setValue("comment_html", comment_html)}
onEnterKeyPress={(commentHTML) => {
const isCommentEmpty =
commentHTML?.trim() === "" ||
commentHTML === "<p></p>" ||
(isEmptyHtmlString(commentHTML ?? "") && !commentHTML?.includes("mention-component"));
if (!isCommentEmpty && !isSubmitting) {
handleSubmit(onEnter)();
onEnterKeyPress={(e) => {
if (!isEmpty && !isSubmitting) {
handleSubmit(onEnter)(e);
}
}}
showSubmitButton={false}

View file

@ -33,6 +33,7 @@ export const IssueCommentCreate: FC<TIssueCommentCreate> = (props) => {
const {
handleSubmit,
control,
watch,
formState: { isSubmitting },
reset,
} = useForm<Partial<TIssueComment>>({
@ -49,8 +50,19 @@ export const IssueCommentCreate: FC<TIssueCommentCreate> = (props) => {
editorRef.current?.clearEditor();
});
const commentHTML = watch("comment_html");
const isEmpty =
commentHTML?.trim() === "" ||
commentHTML === "<p></p>" ||
(isEmptyHtmlString(commentHTML ?? "") && !commentHTML?.includes("mention-component"));
return (
<div>
<div
onKeyDown={(e) => {
if (e.key === "Enter" && !e.shiftKey && !e.ctrlKey && !e.metaKey && !isEmpty && !isSubmitting)
handleSubmit(onSubmit)(e);
}}
>
<Controller
name="access"
control={control}
@ -65,13 +77,9 @@ export const IssueCommentCreate: FC<TIssueCommentCreate> = (props) => {
value={"<p></p>"}
projectId={projectId}
workspaceSlug={workspaceSlug}
onEnterKeyPress={(commentHTML) => {
const isEmpty =
commentHTML?.trim() === "" ||
commentHTML === "<p></p>" ||
(isEmptyHtmlString(commentHTML ?? "") && !commentHTML?.includes("mention-component"));
onEnterKeyPress={(e) => {
if (!isEmpty && !isSubmitting) {
handleSubmit(onSubmit)();
handleSubmit(onSubmit)(e);
}
}}
ref={editorRef}

View file

@ -21,6 +21,7 @@ type TIssueActivity = {
projectId: string;
issueId: string;
disabled?: boolean;
isIntakeIssue?: boolean;
};
export type TActivityOperations = {
@ -30,7 +31,7 @@ export type TActivityOperations = {
};
export const IssueActivity: FC<TIssueActivity> = observer((props) => {
const { workspaceSlug, projectId, issueId, disabled = false } = props;
const { workspaceSlug, projectId, issueId, disabled = false, isIntakeIssue = false } = props;
// hooks
const { createComment, updateComment, removeComment } = useIssueDetail();
const { getProjectById } = useProject();
@ -114,12 +115,14 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
<div className="flex items-center justify-between">
<div className="text-lg text-custom-text-100">Activity</div>
<div className="flex items-center gap-2">
<IssueActivityWorklogCreateButton
workspaceSlug={workspaceSlug}
projectId={projectId}
issueId={issueId}
disabled={disabled}
/>
{!isIntakeIssue && (
<IssueActivityWorklogCreateButton
workspaceSlug={workspaceSlug}
projectId={projectId}
issueId={issueId}
disabled={disabled}
/>
)}
<ActivityFilterRoot selectedFilters={selectedFilters} toggleFilter={toggleFilter} />
</div>
</div>

View file

@ -78,14 +78,18 @@ export const IssueDetailQuickActions: FC<Props> = observer((props) => {
const handleDeleteIssue = async () => {
try {
if (issue?.archived_at) await removeArchivedIssue(workspaceSlug, projectId, issueId);
else await removeIssue(workspaceSlug, projectId, issueId);
router.push(`/${workspaceSlug}/projects/${projectId}/issues`);
captureIssueEvent({
eventName: ISSUE_DELETED,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
path: pathname,
});
if (issue?.archived_at) {
return removeArchivedIssue(workspaceSlug, projectId, issueId).then(() => {
router.push(`/${workspaceSlug}/projects/${projectId}/issues`);
captureIssueEvent({
eventName: ISSUE_DELETED,
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
path: pathname,
});
});
} else {
return removeIssue(workspaceSlug, projectId, issueId);
}
} catch (error) {
setToast({
title: "Error!",

View file

@ -132,7 +132,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
<UserCircle2 className="h-4 w-4 flex-shrink-0" />
<span>Created by</span>
</div>
<div className="h-full flex items-center gap-1.5 rounded px-2 py-0.5 text-sm justify-between cursor-default">
<div className="w-full h-full flex items-center gap-1.5 rounded px-2 py-0.5 text-sm justify-between cursor-not-allowed">
<ButtonAvatars showTooltip userIds={createdByDetails.id} />
<span className="flex-grow truncate text-xs leading-5">{createdByDetails?.display_name}</span>
</div>

View file

@ -134,7 +134,7 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
<UserCircle2 className="h-4 w-4 flex-shrink-0" />
<span>Created by</span>
</div>
<div className="h-full flex items-center gap-1.5 rounded px-2 py-0.5 text-sm justify-between cursor-default">
<div className="w-full h-full flex items-center gap-1.5 rounded px-2 py-0.5 text-sm justify-between cursor-not-allowed">
<ButtonAvatars showTooltip userIds={createdByDetails?.id} />
<span className="flex-grow truncate text-xs leading-5">{createdByDetails?.display_name}</span>
</div>

View file

@ -34,6 +34,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
} = useIssues(EIssuesStoreType.ARCHIVED);
const {
peekIssue,
setPeekIssue,
issue: { fetchIssue },
fetchActivities,
} = useIssueDetail();
@ -44,6 +45,11 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
const [loader, setLoader] = useState(true);
const [error, setError] = useState(false);
const removeRoutePeekId = () => {
setPeekIssue(undefined);
if (embedIssue) embedRemoveCurrentNotification && embedRemoveCurrentNotification();
};
const issueOperations: TIssueOperations = useMemo(
() => ({
fetch: async (workspaceSlug: string, projectId: string, issueId: string, loader = true) => {
@ -95,16 +101,13 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
},
remove: async (workspaceSlug: string, projectId: string, issueId: string) => {
try {
issues?.removeIssue(workspaceSlug, projectId, issueId);
setToast({
title: "Success!",
type: TOAST_TYPE.SUCCESS,
message: "Issue deleted successfully",
});
captureIssueEvent({
eventName: ISSUE_DELETED,
payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" },
path: pathname,
return issues?.removeIssue(workspaceSlug, projectId, issueId).then(() => {
captureIssueEvent({
eventName: ISSUE_DELETED,
payload: { id: issueId, state: "SUCCESS", element: "Issue peek-overview" },
path: pathname,
});
removeRoutePeekId();
});
} catch (error) {
setToast({

View file

@ -131,7 +131,7 @@ export const IssueView: FC<IIssueView> = observer((props) => {
toggleDeleteIssueModal(null);
}}
data={issue}
onSubmit={() => issueOperations.remove(workspaceSlug, projectId, issueId).then(() => removeRoutePeekId())}
onSubmit={async () => issueOperations.remove(workspaceSlug, projectId, issueId)}
/>
)}