diff --git a/apps/dashboard/public/login-preview.png b/apps/dashboard/public/login-preview.png new file mode 100644 index 0000000..ffe5342 Binary files /dev/null and b/apps/dashboard/public/login-preview.png differ diff --git a/apps/dashboard/src/components/details/detail-sidebar.tsx b/apps/dashboard/src/components/details/detail-sidebar.tsx index f56e19f..a14e44f 100644 --- a/apps/dashboard/src/components/details/detail-sidebar.tsx +++ b/apps/dashboard/src/components/details/detail-sidebar.tsx @@ -64,7 +64,7 @@ export function DetailParticipantAvatars({ }>; }) { return ( -
+
{actors.map((actor, index) => ( diff --git a/apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx b/apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx index 127a6d7..e7b88ed 100644 --- a/apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx +++ b/apps/dashboard/src/components/pulls/detail/pull-detail-activity.tsx @@ -3,6 +3,7 @@ import { ChevronDownIcon, ChevronUpIcon, CircleIcon, + Delete01Icon, EditIcon, GitCommitIcon, GitMergeIcon, @@ -40,6 +41,7 @@ import { import { LabelPill } from "#/components/details/label-pill"; import { formatRelativeTime } from "#/lib/format-relative-time"; import { + deleteBranch, dismissPullReview, getCommentPage, getTimelineEventPage, @@ -160,6 +162,16 @@ export function PullDetailActivitySection({
)} + {pr.isMerged && ( +
+ +
+ )} +
@@ -199,6 +211,85 @@ function MergeStatusSection({ ); } +function MergedBranchBanner({ + owner, + repo, + branchName, +}: { + owner: string; + repo: string; + branchName: string; +}) { + const [isDeleting, setIsDeleting] = useState(false); + const [isDeleted, setIsDeleted] = useState(false); + + const handleDelete = async () => { + setIsDeleting(true); + try { + const result = await deleteBranch({ + data: { owner, repo, branch: branchName }, + }); + if (result.ok) { + setIsDeleted(true); + } else { + toast.error(result.error); + checkPermissionWarning(result, `${owner}/${repo}`); + setIsDeleting(false); + } + } catch { + toast.error("Failed to delete branch"); + setIsDeleting(false); + } + }; + + return ( +
+
+ +
+

+ {isDeleted ? ( + <> + Branch{" "} + + {branchName} + {" "} + has been deleted. + + ) : ( + <> + Branch{" "} + + {branchName} + {" "} + has been merged. + + )} +

+ {!isDeleted && ( + + )} +
+ ); +} + function MergeStatusCard({ status, owner, diff --git a/apps/dashboard/src/components/pulls/review/review-file-diff-block.tsx b/apps/dashboard/src/components/pulls/review/review-file-diff-block.tsx index d0bdc33..444b518 100644 --- a/apps/dashboard/src/components/pulls/review/review-file-diff-block.tsx +++ b/apps/dashboard/src/components/pulls/review/review-file-diff-block.tsx @@ -157,6 +157,7 @@ export const ReviewFileDiffBlock = memo(function ReviewFileDiffBlock({ `[data-utility-button] { background-color: ${mutedFg}; }`, `[data-line-annotation] { font-family: 'Inter Variable', 'Inter', 'Avenir Next', ui-sans-serif, system-ui, sans-serif; }`, `[data-line-annotation] code { font-family: var(--diffs-font-family, var(--diffs-font-fallback)); }`, + `[data-diff] { border: 1px solid var(--border); border-top: 0; border-radius: 4px; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; overflow: hidden; }`, isDark ? `:host { --diffs-bg-addition-override: color-mix(in lab, var(--diffs-bg) 92%, var(--diffs-addition-base)); --diffs-bg-addition-number-override: color-mix(in lab, var(--diffs-bg) 88%, var(--diffs-addition-base)); --diffs-bg-addition-emphasis-override: color-mix(in lab, var(--diffs-bg) 75%, var(--diffs-addition-base)); --diffs-bg-deletion-override: color-mix(in lab, var(--diffs-bg) 92%, var(--diffs-deletion-base)); --diffs-bg-deletion-number-override: color-mix(in lab, var(--diffs-bg) 88%, var(--diffs-deletion-base)); --diffs-bg-deletion-emphasis-override: color-mix(in lab, var(--diffs-bg) 75%, var(--diffs-deletion-base)); }` : `:host { --diffs-bg-addition-override: color-mix(in lab, var(--diffs-bg) 82%, var(--diffs-addition-base)); --diffs-bg-addition-number-override: color-mix(in lab, var(--diffs-bg) 78%, var(--diffs-addition-base)); --diffs-bg-deletion-override: color-mix(in lab, var(--diffs-bg) 82%, var(--diffs-deletion-base)); --diffs-bg-deletion-number-override: color-mix(in lab, var(--diffs-bg) 78%, var(--diffs-deletion-base)); }`, diff --git a/apps/dashboard/src/lib/github.functions.ts b/apps/dashboard/src/lib/github.functions.ts index 91ad1ce..f2fd2f7 100644 --- a/apps/dashboard/src/lib/github.functions.ts +++ b/apps/dashboard/src/lib/github.functions.ts @@ -2325,6 +2325,28 @@ export const mergePullRequest = createServerFn({ method: "POST" }) } }); +export const deleteBranch = createServerFn({ method: "POST" }) + .inputValidator( + identityValidator<{ owner: string; repo: string; branch: string }>, + ) + .handler(async ({ data }): Promise => { + const context = await getGitHubContext(); + if (!context) { + return { ok: false, error: "Not authenticated" }; + } + + try { + await context.octokit.rest.git.deleteRef({ + owner: data.owner, + repo: data.repo, + ref: `heads/${data.branch}`, + }); + return { ok: true }; + } catch (error) { + return toMutationError("delete branch", error); + } + }); + async function getPullFilesResult( context: GitHubContext, data: PullFilesPageInput, diff --git a/apps/dashboard/src/routes/login.tsx b/apps/dashboard/src/routes/login.tsx index bcd2746..97690d1 100644 --- a/apps/dashboard/src/routes/login.tsx +++ b/apps/dashboard/src/routes/login.tsx @@ -64,7 +64,7 @@ function LoginPage() { DiffKit

- Review workspace + Beta version

@@ -74,11 +74,6 @@ function LoginPage() {

Review your GitHub work in one place

-

- DiffKit pulls together open pull requests, assigned issues, - and pending code reviews into one fast workspace so you can - move through GitHub work without tab sprawl. -

- -
-

- What DiffKit helps you do -

- -
@@ -122,54 +99,21 @@ function LoginPage() { aria-hidden="true" className="size-1.5 rounded-full bg-border" /> -

Simple now, room to layer more later.

+

Your GitHub activity, one dashboard away.

-
-
-

- Developer workflow -

-

- A calmer way to triage PRs, issues, and review requests. -

-

- Use one dashboard for GitHub queues, detailed pull request - views, issue threads, and code review context. -

-
- -
- - - -
-
+ DiffKit dashboard preview
); } - -function FeaturePanel({ label, value }: { label: string; value: string }) { - return ( -
-

{label}

-

{value}

-
- ); -} diff --git a/packages/icons/src/index.ts b/packages/icons/src/index.ts index 25da882..5f5b001 100644 --- a/packages/icons/src/index.ts +++ b/packages/icons/src/index.ts @@ -22,6 +22,7 @@ export { ComputerIcon as SystemIcon, Copy01Icon as CopyIcon, DashboardSquare01Icon as DashboardIcon, + Delete01Icon, DragDropVerticalIcon as GripVerticalIcon, File02Icon as FileIcon, Folder01Icon as FolderIcon, diff --git a/packages/ui/package.json b/packages/ui/package.json index 3e73e45..7b21c88 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -19,6 +19,7 @@ "@diffkit/icons": "workspace:*", "@fontsource-variable/geist-mono": "^5.2.7", "@fontsource-variable/inter": "^5.2.8", + "@m2d/react-markdown": "^1.0.0", "@radix-ui/react-alert-dialog": "^1.1.6", "@radix-ui/react-avatar": "^1.1.3", "@radix-ui/react-checkbox": "^1.1.4", @@ -43,7 +44,6 @@ "next-themes": "^0.4.4", "react-day-picker": "8.10.1", "react-hook-form": "^7.54.2", - "react-markdown": "^10.1.0", "react-resizable-panels": "^3.0.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", diff --git a/packages/ui/src/components/markdown.tsx b/packages/ui/src/components/markdown.tsx index 1e7b54f..8e85839 100644 --- a/packages/ui/src/components/markdown.tsx +++ b/packages/ui/src/components/markdown.tsx @@ -1,6 +1,5 @@ +import { Md } from "@m2d/react-markdown/client"; import { Suspense, use, useCallback, useRef, useState } from "react"; -import type { Components } from "react-markdown"; -import ReactMarkdown from "react-markdown"; import rehypeRaw from "rehype-raw"; import remarkGfm from "remark-gfm"; import type { BundledLanguage, Highlighter } from "shiki"; @@ -152,8 +151,9 @@ function ShikiCode({ code, lang }: { code: string; lang: string }) { ); } -const components: Components = { - h1: ({ children, ...props }) => ( +// eslint-disable-next-line @typescript-eslint/no-explicit-any -- component overrides receive union props from @m2d/react-markdown +const components: Record> = { + h1: ({ node: _, children, ...props }) => (

), - h2: ({ children, ...props }) => ( + h2: ({ node: _, children, ...props }) => (

), - h3: ({ children, ...props }) => ( + h3: ({ node: _, children, ...props }) => (

), - h4: ({ children, ...props }) => ( + h4: ({ node: _, children, ...props }) => (

{children}

), - p: ({ children, ...props }) => ( + p: ({ node: _, children, ...props }) => (

{children}

), - a: ({ children, href, ...props }) => ( + a: ({ node: _, children, href, ...props }) => ( ), - ul: ({ children, ...props }) => ( + ul: ({ node: _, children, ...props }) => (