-
Notifications
You must be signed in to change notification settings - Fork 4.1k
fix: show work item ID in created confirmation toast #8727
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: preview
Are you sure you want to change the base?
Changes from 1 commit
9e8ed6e
ffdd877
3782ff6
9f14bbd
648341d
8612c54
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,70 +21,101 @@ type TCreateIssueToastActionItems = { | |
| isEpic?: boolean; | ||
| }; | ||
|
|
||
| export const CreateIssueToastActionItems = observer(function CreateIssueToastActionItems( | ||
| props: TCreateIssueToastActionItems | ||
| ) { | ||
| const { workspaceSlug, projectId, issueId, isEpic = false } = props; | ||
| // state | ||
| const [copied, setCopied] = useState(false); | ||
| // store hooks | ||
| const { | ||
| issue: { getIssueById }, | ||
| } = useIssueDetail(); | ||
| const { getProjectIdentifierById } = useProject(); | ||
| export const CreateIssueToastActionItems = observer( | ||
| function CreateIssueToastActionItems(props: TCreateIssueToastActionItems) { | ||
| const { workspaceSlug, projectId, issueId, isEpic = false } = props; | ||
| // state | ||
| const [copied, setCopied] = useState(false); | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| // store hooks | ||
| const { | ||
| issue: { getIssueById }, | ||
| } = useIssueDetail(); | ||
| const { getProjectIdentifierById } = useProject(); | ||
|
|
||
| // derived values | ||
| const issue = getIssueById(issueId); | ||
| const projectIdentifier = getProjectIdentifierById(issue?.project_id); | ||
| // derived values | ||
| const issue = getIssueById(issueId); | ||
| const projectIdentifier = getProjectIdentifierById(issue?.project_id); | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard the visible work item ID until the project identifier exists.
Also applies to: 64-65, 82-88 🤖 Prompt for AI Agents |
||
| if (!issue) return null; | ||
| if (!issue) return null; | ||
|
|
||
| const workItemLink = generateWorkItemLink({ | ||
| workspaceSlug, | ||
| projectId: issue?.project_id, | ||
| issueId, | ||
| projectIdentifier, | ||
| sequenceId: issue?.sequence_id, | ||
| isEpic, | ||
| }); | ||
| const workItemLink = generateWorkItemLink({ | ||
| workspaceSlug, | ||
| projectId: issue?.project_id, | ||
| issueId, | ||
| projectIdentifier, | ||
| sequenceId: issue?.sequence_id, | ||
| isEpic, | ||
| }); | ||
|
|
||
| const copyToClipboard = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => { | ||
| try { | ||
| await copyUrlToClipboard(workItemLink); | ||
| setCopied(true); | ||
| setTimeout(() => setCopied(false), 3000); | ||
| } catch (error) { | ||
| setCopied(false); | ||
| } | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| }; | ||
| const copyToClipboard = async ( | ||
| e: React.MouseEvent<HTMLButtonElement, MouseEvent>, | ||
| ) => { | ||
| try { | ||
| await copyUrlToClipboard(workItemLink); | ||
| setCopied(true); | ||
| setTimeout(() => setCopied(false), 3000); | ||
| } catch (error) { | ||
| setCopied(false); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clipboard failures are swallowed silently. Both handlers catch the write error, clear local state, and then do nothing else. A denied clipboard permission will look like a no-op to the user and leave no diagnostic trail. Please log/report the error and surface a failure state. As per coding guidelines, "Use try-catch with proper error types and log errors appropriately for error handling." Also applies to: 69-75 🤖 Prompt for AI Agents |
||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="-ml-2 flex items-center gap-1 text-11 text-secondary"> | ||
| <a | ||
| href={workItemLink} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="rounded-sm px-2 py-1 font-medium text-accent-primary hover:bg-surface-2" | ||
| > | ||
| {`View ${isEpic ? "epic" : "work item"}`} | ||
| </a> | ||
| const workItemId = `${projectIdentifier}-${issue?.sequence_id}`; | ||
|
|
||
| {copied ? ( | ||
| <> | ||
| <span className="cursor-default px-2 py-1 text-secondary">Copied!</span> | ||
| </> | ||
| ) : ( | ||
| <> | ||
| <button | ||
| className="hidden cursor-pointer rounded-sm px-2 py-1 text-tertiary group-hover:flex hover:bg-surface-2 hover:text-secondary" | ||
| onClick={copyToClipboard} | ||
| > | ||
| Copy link | ||
| </button> | ||
| </> | ||
| )} | ||
| </div> | ||
| ); | ||
| }); | ||
| const copyWorkItemId = async ( | ||
| e: React.MouseEvent<HTMLButtonElement, MouseEvent>, | ||
| ) => { | ||
| try { | ||
| await copyUrlToClipboard(workItemId); | ||
| setCopied(true); | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| setTimeout(() => setCopied(false), 3000); | ||
| } catch (error) { | ||
| setCopied(false); | ||
| } | ||
| e.preventDefault(); | ||
| e.stopPropagation(); | ||
| }; | ||
|
|
||
| return ( | ||
| <div className="-ml-2 flex items-center gap-1 text-11 text-secondary"> | ||
| <span className="rounded-sm px-2 py-1 font-medium text-secondary"> | ||
| {workItemId} | ||
| </span> | ||
|
|
||
| <button | ||
| className="cursor-pointer rounded-sm px-2 py-1 text-tertiary hover:bg-surface-2 hover:text-secondary" | ||
| onClick={copyWorkItemId} | ||
| > | ||
| {copied ? "Copied!" : "Copy ID"} | ||
| </button> | ||
|
|
||
| <a | ||
| href={workItemLink} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="rounded-sm px-2 py-1 font-medium text-accent-primary hover:bg-surface-2" | ||
| > | ||
| {`View ${isEpic ? "epic" : "work item"}`} | ||
| </a> | ||
|
|
||
| {copied ? ( | ||
| <> | ||
| <span className="cursor-default px-2 py-1 text-secondary"> | ||
| Link Copied! | ||
| </span> | ||
| </> | ||
| ) : ( | ||
| <> | ||
| <button | ||
| className="hidden cursor-pointer rounded-sm px-2 py-1 text-tertiary group-hover:flex hover:bg-surface-2 hover:text-secondary" | ||
| onClick={copyToClipboard} | ||
| > | ||
| Copy link | ||
| </button> | ||
| </> | ||
| )} | ||
| </div> | ||
| ); | ||
| }, | ||
| ); | ||
Uh oh!
There was an error while loading. Please reload this page.