mirror of
https://github.com/makeplane/plane.git
synced 2026-06-14 03:30:00 +00:00
[WEB-6534] feat: update work item creation toast with clickable identifier (#6766)
* chore: work item create toast ux enhancements * chore: code refactoring
This commit is contained in:
committed by
GitHub
parent
8b6b659053
commit
15dbd4fe6f
@@ -145,7 +145,6 @@ export const CreateUpdateEpicModalBase = observer(function CreateUpdateEpicModal
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: "Success!",
|
||||
message: "Epic created successfully.",
|
||||
actionItems: response?.project_id && (
|
||||
<CreateIssueToastActionItems
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
|
||||
@@ -47,20 +47,23 @@ export const CreateIssueToastActionItems = observer(function CreateIssueToastAct
|
||||
// derived values
|
||||
const issue = getIssueById(issueId);
|
||||
const projectIdentifier = getProjectIdentifierById(issue?.project_id);
|
||||
const hasIdentifier = !!(projectIdentifier && issue?.sequence_id);
|
||||
const identifier = hasIdentifier ? `${projectIdentifier}-${issue.sequence_id}` : null;
|
||||
|
||||
const workItemLink = generateWorkItemLink({
|
||||
workspaceSlug,
|
||||
projectId: issue?.project_id,
|
||||
issueId,
|
||||
projectIdentifier,
|
||||
sequenceId: issue?.sequence_id,
|
||||
isEpic,
|
||||
});
|
||||
|
||||
const workItemIdentifier = projectIdentifier && issue?.sequence_id ? `${projectIdentifier}-${issue.sequence_id}` : "";
|
||||
const workItemLink = hasIdentifier
|
||||
? generateWorkItemLink({
|
||||
workspaceSlug,
|
||||
projectId: issue?.project_id,
|
||||
issueId,
|
||||
projectIdentifier,
|
||||
sequenceId: issue?.sequence_id,
|
||||
isEpic,
|
||||
})
|
||||
: null;
|
||||
|
||||
const handleCopyLink = useCallback(
|
||||
async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
if (!workItemLink) return;
|
||||
try {
|
||||
await copyUrlToClipboard(workItemLink);
|
||||
setLinkCopied(true);
|
||||
@@ -77,8 +80,9 @@ export const CreateIssueToastActionItems = observer(function CreateIssueToastAct
|
||||
|
||||
const handleCopyId = useCallback(
|
||||
async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
if (!identifier) return;
|
||||
try {
|
||||
await copyTextToClipboard(workItemIdentifier);
|
||||
await copyTextToClipboard(identifier);
|
||||
setIdCopied(true);
|
||||
if (idTimerRef.current) clearTimeout(idTimerRef.current);
|
||||
idTimerRef.current = setTimeout(() => setIdCopied(false), 3000);
|
||||
@@ -88,33 +92,45 @@ export const CreateIssueToastActionItems = observer(function CreateIssueToastAct
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
},
|
||||
[workItemIdentifier]
|
||||
[identifier]
|
||||
);
|
||||
|
||||
if (!issue) return null;
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between text-11 text-secondary w-full">
|
||||
<div className="flex items-center gap-1">
|
||||
<a
|
||||
href={workItemLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={cn(getButtonStyling("ghost", "sm"), "text-accent-primary no-underline")}
|
||||
>
|
||||
{t("common.view")}
|
||||
</a>
|
||||
<div className="flex flex-col gap-1 w-full">
|
||||
<p className="text-body-xs-regular text-tertiary">
|
||||
{identifier ? (
|
||||
<button onClick={handleCopyId} className="cursor-pointer hover:underline">
|
||||
{identifier}
|
||||
</button>
|
||||
) : (
|
||||
<span>{isEpic ? "Epic" : "Work item"}</span>
|
||||
)}
|
||||
{" created successfully"}
|
||||
</p>
|
||||
<div className="flex items-center justify-between text-11 text-secondary -ml-2">
|
||||
<div className="flex items-center gap-1">
|
||||
{workItemLink && (
|
||||
<>
|
||||
<a
|
||||
href={workItemLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={cn(getButtonStyling("ghost", "sm"), "text-accent-primary no-underline")}
|
||||
>
|
||||
{t("common.view")}
|
||||
</a>
|
||||
|
||||
<Button variant="ghost" size="sm" onClick={handleCopyLink} disabled={linkCopied}>
|
||||
{linkCopied ? t("common.copied") : t("common.actions.copy_link")}
|
||||
</Button>
|
||||
<Button variant="ghost" size="sm" onClick={handleCopyLink} disabled={linkCopied}>
|
||||
{linkCopied ? t("common.copied") : t("common.actions.copy_link")}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{idCopied && <span className="cursor-default px-2 py-1 text-secondary">{t("common.actions.id_copied")}</span>}
|
||||
</div>
|
||||
|
||||
{workItemIdentifier && (
|
||||
<Button variant="ghost" size="sm" onClick={handleCopyId} disabled={idCopied}>
|
||||
{idCopied ? t("common.actions.id_copied") : workItemIdentifier}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -178,7 +178,7 @@ export const QuickAddIssueRoot = observer(function QuickAddIssueRoot(props: TQui
|
||||
loading: isEpic ? t("epic.adding") : t("issue.adding"),
|
||||
success: {
|
||||
title: t("common.success"),
|
||||
message: () => `${isEpic ? t("epic.create.success") : t("issue.create.success")}`,
|
||||
message: () => undefined,
|
||||
actionItems: (data) => (
|
||||
<CreateIssueToastActionItems
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
|
||||
@@ -257,7 +257,7 @@ export const CreateUpdateIssueModalBase = observer(function CreateUpdateIssueMod
|
||||
setToast({
|
||||
type: TOAST_TYPE.SUCCESS,
|
||||
title: t("success"),
|
||||
message: `${is_draft_issue ? t("draft_created") : t("issue_created_successfully")} `,
|
||||
message: is_draft_issue ? `${t("draft_created")}` : undefined,
|
||||
actionItems: !is_draft_issue && response?.project_id && (
|
||||
<CreateIssueToastActionItems
|
||||
workspaceSlug={workspaceSlug.toString()}
|
||||
|
||||
@@ -41,7 +41,7 @@ type SetToastProps =
|
||||
actionItems?: React.ReactNode;
|
||||
};
|
||||
|
||||
type PromiseToastCallback<ToastData> = (data: ToastData) => string;
|
||||
type PromiseToastCallback<ToastData> = (data: ToastData) => string | undefined;
|
||||
type ActionItemsPromiseToastCallback<ToastData> = (data: ToastData) => React.ReactNode;
|
||||
|
||||
type PromiseToastData<ToastData> = {
|
||||
|
||||
Reference in New Issue
Block a user