GitFOSS
William Nemenchaimprove code
c048dc5 (parent 3e8b201)4/7/2024, 3:04:16 AM
improve code
+ 429
- 339
app/components/PageHeader.tsx
@@ -72,7 +72,7 @@ export const PageHeader: VFC<PageHeaderProps & WithThemeSchemeProp> = ({
           aria-label={"Explore Repositories"}
           href={buildRouteLink(AppRoute.REPOSITORY_EXPLORE, null)}
         >
-          Explore Repositories
+          Explore
         </a>
       </StyledPageHeaderNav>
       <StyledActionsArea>

app/components/TextInput.styled.ts
@@ -4,11 +4,10 @@ import styled, { css } from "styled-components";
 import type { WithThemeSchemeProp } from "../types";
 import { NamedColors } from "../utils/style";
 
-export const TextInput = styled.input<WithThemeSchemeProp>`
+const inputBase = css<WithThemeSchemeProp>`
   width: 100%;
-  height: 40px;
 
-  padding: 0 12px;
+  padding: 12px;
 
   appearance: none;
   border-radius: 8px;

...
@@ -28,3 +27,19 @@ export const TextInput = styled.input<WithThemeSchemeProp>`
     `};
   }
 `;
+
+export const TextInput = styled.input<WithThemeSchemeProp>`
+  height: 40px;
+  ${inputBase};
+`;
+
+export const TextArea = styled.textarea<WithThemeSchemeProp>`
+  ${inputBase};
+`;
+
+export const Select = styled.select<WithThemeSchemeProp>`
+  height: 40px;
+  ${inputBase};
+
+  padding: 0 12px;
+`;

app/components/index.ts
@@ -9,4 +9,4 @@ export { MarkdownToJsx } from "./MarkdownToJsx";
 export { PageHeader } from "./PageHeader";
 export { PageWrapper } from "./PageWrapper";
 export { TextEllipsis } from "./TextEllipsis.styled";
-export { TextInput } from "./TextInput.styled";
+export { TextInput, TextArea, Select } from "./TextInput.styled";

app/controllers/ssh-auth.ts
@@ -14,18 +14,11 @@ const onSSHAuth: ReqHandler<AppRouteParams, AppRoute.SSH_AUTH> = async (
     cryptoService: request.cryptoService,
   });
 
-  // console.log("request:", request);
-
   request.body =
     typeof request.body === "string" ? JSON.parse(request.body) : request.body;
 
   const { command, repoSlug, username, publicKey } = request.body;
 
-  console.log("command:", command);
-  console.log("repoSlug:", repoSlug);
-  console.log("username:", username);
-  console.log("publicKey:", publicKey);
-
   const result = await gitService.repositoryResolver(
     repoSlug.replace(/\.git$/, "")
   );

...
@@ -35,18 +28,11 @@ const onSSHAuth: ReqHandler<AppRouteParams, AppRoute.SSH_AUTH> = async (
     ? gitRepositoryDir
     : `${gitRepositoryDir}.git`;
 
-  console.log("authMode:", authMode);
-  console.log("gitRepositoryDir:", gitRepositoryDir);
-
   if (
     authMode === GitServer.AuthMode.NEVER ||
     (authMode === GitServer.AuthMode.PUSH_ONLY &&
       command !== "git-receive-pack") // push
   ) {
-    console.log(
-      "no need for auth, repo is public/push_only and command is not push"
-    );
-
     reply.status(200).send({
       success: true,
       authMode,

...
@@ -64,17 +50,12 @@ const onSSHAuth: ReqHandler<AppRouteParams, AppRoute.SSH_AUTH> = async (
     }
   );
 
-  console.log(
-    "authorization result:",
-    isAuthorizationValid ? "valid" : "invalid"
-  );
-
   // const gitSideBandMessage = require("git-side-band-message");
   // const msg = gitSideBandMessage("Failure has occured!", Buffer.from("\u0003"));
 
-  const { frame } = require("git-pkt-line");
-  const msg = frame("error", "Forbidden access.");
-  console.log("message:", msg.toString("ascii"));
+  // const { frame } = require("git-pkt-line");
+  // const msg = frame("error", "Forbidden access.");
+  // console.log("message:", msg.toString("ascii"));
 
   reply.status(isAuthorizationValid ? 200 : 400).send({
     success: isAuthorizationValid,

app/islands/RepositoryForkForm.tsx
@@ -5,9 +5,9 @@ import React, { useCallback, useEffect, useState } from "react";
 // generated via script[generate:prisma]
 import type { Organization, ResourceVisibility } from "@prisma/client";
 // app
-import { Button } from "../components/Button.styled";
-import { Grid } from "../components/Grid";
+import type { WithThemeSchemeProp } from "../types";
 import { slugify } from "../utils/shared";
+import { Button, Grid, Select, TextInput } from "../components";
 
 export interface RepositoryForkFormProps {
   disabled?: boolean;

...
@@ -21,8 +21,11 @@ export interface RepositoryForkFormProps {
   };
 }
 
-const RepositoryForkForm: ReactIsland<RepositoryForkFormProps> = ({
+const RepositoryForkForm: ReactIsland<
+  RepositoryForkFormProps & WithThemeSchemeProp
+> = ({
   availableParentOrgs,
+  themeScheme,
   disabled = false,
   editMode = false,
   initialValues = undefined,

...
@@ -82,88 +85,98 @@ const RepositoryForkForm: ReactIsland<RepositoryForkFormProps> = ({
     <div>
       <fieldset>
         <legend>Fork details</legend>
-        {/* Repository Name */}
-        <Grid.Col fluid nowrap>
-          <label htmlFor={"target_repo_display_name"}>
-            Repository Name <span>(*)</span>:
-          </label>
-          <input
-            disabled={disabled}
-            name={"target_repo_display_name"}
-            onChange={onDisplayNameInputChange}
-            placeholder={"i.e. My Super Project"}
-            required
-            style={styles.inputMaxWidth}
-            type={"text"}
-            value={displayName}
-          />
-        </Grid.Col>
-        <Grid.Row fluid nowrap alignItems={"center"}>
-          {/* Parent Organization Select */}
-          <Grid.Col fluid nowrap>
-            <label htmlFor={"target_org_slug"}>
-              Owner Organization <span>(*)</span>:
+        <Grid.Col fluid nowrap gap={8}>
+          {/* Repository Name */}
+          <Grid.Col fluid nowrap gap={4}>
+            <label htmlFor={"target_repo_display_name"}>
+              Repository Name <span>(*)</span>:
             </label>
-            <select
+            <TextInput
+              themeScheme={themeScheme}
+              name={"target_repo_display_name"}
               disabled={disabled}
-              defaultValue={
-                availableParentOrgs.length >= 1
-                  ? availableParentOrgs[0].slug
-                  : initialValues?.target_org_slug
-              }
-              name={"target_org_slug"}
+              onChange={onDisplayNameInputChange}
+              placeholder={"i.e. My Super Project"}
               required
               style={styles.inputMaxWidth}
-            >
-              {availableParentOrgs.map((org) => (
-                <option key={org.id} value={org.slug}>
-                  {org.displayName || org.slug}
-                </option>
-              ))}
-            </select>
+              type={"text"}
+              value={displayName}
+            />
           </Grid.Col>
-          {/* Repository Slug */}
-          <Grid.Col fluid nowrap>
-            <label htmlFor={"target_repo_slug"}>
-              Repository Slug <span>(*)</span>:
+          <Grid.Row fluid nowrap alignItems={"center"} gap={8}>
+            {/* Parent Organization Select */}
+            <Grid.Col fluid nowrap gap={4}>
+              <label htmlFor={"target_org_slug"}>
+                Owner Organization <span>(*)</span>:
+              </label>
+              <Select
+                themeScheme={themeScheme}
+                disabled={disabled}
+                defaultValue={
+                  availableParentOrgs.length >= 1
+                    ? availableParentOrgs[0].slug
+                    : initialValues?.target_org_slug
+                }
+                name={"target_org_slug"}
+                required
+                style={styles.inputMaxWidth}
+              >
+                {availableParentOrgs.map((org) => (
+                  <option key={org.id} value={org.slug}>
+                    {org.displayName || org.slug}
+                  </option>
+                ))}
+              </Select>
+            </Grid.Col>
+            {/* Repository Slug */}
+            <Grid.Col fluid nowrap gap={4}>
+              <label htmlFor={"target_repo_slug"}>
+                Repository Slug <span>(*)</span>:
+              </label>
+              <TextInput
+                themeScheme={themeScheme}
+                name={"target_repo_slug"}
+                disabled={disabled}
+                onChange={onSlugInputChange}
+                placeholder={"i.e. my-super-project"}
+                required
+                style={styles.inputMaxWidth}
+                type={"text"}
+                value={slug}
+              />
+            </Grid.Col>
+          </Grid.Row>
+          {/* Repository Visibility */}
+          <Grid.Col fluid nowrap gap={4}>
+            <label htmlFor={"target_repo_visibility"}>
+              Repository Visibility <span>(*)</span>:
             </label>
-            <input
+            <Select
+              themeScheme={themeScheme}
               disabled={disabled}
-              name={"target_repo_slug"}
-              onChange={onSlugInputChange}
-              placeholder={"i.e. my-super-project"}
-              required
+              defaultValue={initialValues?.target_repo_visibility || "PRIVATE"}
+              name={"target_repo_visibility"}
               style={styles.inputMaxWidth}
-              type={"text"}
-              value={slug}
-            />
+            >
+              <option key={"private"} value={"PRIVATE"}>
+                Private
+              </option>
+              <option key={"unlisted"} value={"UNLISTED"}>
+                Unlisted
+              </option>
+              <option key={"public"} value={"PUBLIC"}>
+                Public
+              </option>
+            </Select>
           </Grid.Col>
-        </Grid.Row>
-        {/* Repository Visibility */}
-        <Grid.Col fluid nowrap>
-          <label htmlFor={"target_repo_visibility"}>
-            Repository Visibility <span>(*)</span>:
-          </label>
-          <select
-            disabled={disabled}
-            defaultValue={initialValues?.target_repo_visibility || "PRIVATE"}
-            name={"target_repo_visibility"}
-            style={styles.inputMaxWidth}
-          >
-            <option key={"private"} value={"PRIVATE"}>
-              Private
-            </option>
-            <option key={"unlisted"} value={"UNLISTED"}>
-              Unlisted
-            </option>
-            <option key={"public"} value={"PUBLIC"}>
-              Public
-            </option>
-          </select>
         </Grid.Col>
       </fieldset>
       {/* Submit Button */}
-      <Button style={styles.inputMaxWidth} type={"submit"} disabled={disabled}>
+      <Button
+        style={{ ...styles.inputMaxWidth, marginTop: 16 }}
+        type={"submit"}
+        disabled={disabled}
+      >
         Fork Repository!
       </Button>
     </div>

app/services/repository/getRepositoryCommitLog.ts
@@ -101,7 +101,6 @@ const makeGetRepositoryCommitLog: ServiceMethodFactory<
                 )
               );
             } catch (err) {
-              // console.log("escapedJson:", escapedJson);
               resolve([]);
             }
           });

app/services/repository/getRepositoryHTTPCloneUrl.ts
@@ -4,7 +4,6 @@ import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
 import { Repository, ResourceVisibility } from "@prisma/client";
 // app
 import { Env } from "../../env";
-import { getEnv } from "../../utils/server";
 // service
 import type { RepositoryServiceDeps } from "./types";
 

...
@@ -13,7 +12,6 @@ const makeGetRepositoryHTTPCloneUrl: ServiceMethodFactory<
   [Repository],
   Promise<string>
 > = ({ request }) => {
-  const env = getEnv();
   return async (repo) => {
     const parentOrg = await request.prisma.organization.findUnique({
       where: {

...
@@ -31,12 +29,10 @@ const makeGetRepositoryHTTPCloneUrl: ServiceMethodFactory<
       repo.visibility === ResourceVisibility.PRIVATE
         ? `${parentOrg.slug}:secret@`
         : "";
-    const baseUrl =
-      env === "development"
-        ? `${Env.DEPLOYMENT_SCHEME}://${authCredentials}${Env.DEPLOYMENT_DOMAIN}:${Env.PORT}`
-        : `${Env.DEPLOYMENT_SCHEME}://${authCredentials}${Env.DEPLOYMENT_DOMAIN}`;
+    const baseUrl = `${Env.DEPLOYMENT_SCHEME}://${authCredentials}${Env.DEPLOYMENT_DOMAIN}`;
+    const port = Env.PORT != 80 && Env.PORT != 443 ? `:${Env.PORT}` : "";
 
-    return `${baseUrl}/${parentOrg.slug}/${repo.slug}.git`;
+    return `${baseUrl}${port}/${parentOrg.slug}/${repo.slug}.git`;
   };
 };
 

app/views/HomeView.tsx
@@ -19,15 +19,15 @@ const HomeView: ReactView<HomeViewProps> = (props) => {
     <Layout {...commonProps}>
       <PageWrapper>
         <StyledButtonsRow>
+          <ButtonAnchor href={buildRouteLink(AppRoute.REPOSITORY_EXPLORE, {})}>
+            Explore
+          </ButtonAnchor>
           <ButtonAnchor href={buildRouteLink(AppRoute.AUTH_REGISTER, {})}>
             Register
           </ButtonAnchor>
           <ButtonAnchor href={buildRouteLink(AppRoute.AUTH_LOGIN, {})}>
             Login
           </ButtonAnchor>
-          <ButtonAnchor href={buildRouteLink(AppRoute.REPOSITORY_EXPLORE, {})}>
-            Explore Repositories
-          </ButtonAnchor>
         </StyledButtonsRow>
       </PageWrapper>
     </Layout>

app/views/repository/RepositoryDetailsView.tsx
@@ -191,12 +191,15 @@ const RepositoryDetailsView: ReactView<RepositoryDetailsViewProps> = ({
             }}
           >
             <Card
-              style={{ width: "100%" }}
+              style={{ width: "100%", gap: 12 }}
               themeScheme={commonProps.themeScheme}
             >
-              <p>{repo.shortDescription}</p>
+              {repo.shortDescription != null &&
+                repo.shortDescription.trim() !== "" && (
+                  <p style={{ margin: 0 }}>{repo.shortDescription}</p>
+                )}
               {repo.websiteUrl != null && (
-                <p>
+                <p style={{ margin: 0 }}>
                   <a
                     href={repo.websiteUrl}
                     target={"_blank"}

...
@@ -206,68 +209,105 @@ const RepositoryDetailsView: ReactView<RepositoryDetailsViewProps> = ({
                   </a>
                 </p>
               )}
-              <p>
-                {repo.keywords.map(
-                  (keyword, idx, self) =>
-                    keyword.trim() !== "" && (
-                      <React.Fragment key={[idx, keyword].join(":")}>
-                        <span>{keyword}</span>
-                        {idx === self.length - 1 ? "." : ", "}
-                      </React.Fragment>
-                    )
-                )}
-              </p>
-              <p>
-                <strong>HTTP Clone:</strong>
+              {repo.keywords.filter((keyword) => keyword.trim() !== "").length >
+                0 && (
+                <p style={{ margin: 0 }}>
+                  {repo.keywords.map(
+                    (keyword, idx, self) =>
+                      keyword.trim() !== "" && (
+                        <React.Fragment key={[idx, keyword].join(":")}>
+                          <span>{keyword}</span>
+                          {idx === self.length - 1 ? "." : ", "}
+                        </React.Fragment>
+                      )
+                  )}
+                </p>
+              )}
+              <div>
+                <strong
+                  style={{ display: "block", width: "100%", marginBottom: 8 }}
+                >
+                  HTTP Clone:
+                </strong>
                 <InlineCode fluid themeScheme={commonProps.themeScheme}>
                   {cloneUrl.http}
                 </InlineCode>
-              </p>
-              <p>
-                <strong>SSH Clone:</strong>
+              </div>
+              <div>
+                <strong
+                  style={{ display: "block", width: "100%", marginBottom: 8 }}
+                >
+                  SSH Clone:
+                </strong>
                 <InlineCode fluid themeScheme={commonProps.themeScheme}>
                   {cloneUrl.ssh}
                 </InlineCode>
-              </p>
-              <p>
-                <strong>Branches:</strong>
-                <br />
-                {branches.map(
-                  (branch, idx, self) =>
-                    branch.trim() != "" && (
-                      <React.Fragment key={branch}>
-                        <a
-                          href={buildRouteLink(AppRoute.REPOSITORY_BROWSER, {
-                            orgSlug: parentOrg.slug,
-                            repoSlug: repo.slug,
-                            currentRef: branch,
-                            "*":
-                              path != null && path.trim() !== "" && path !== "/"
-                                ? path
-                                : "",
-                          })}
-                        >
-                          {branch}
-                        </a>
-                        {idx === self.length - 1 ? "." : ", "}
-                      </React.Fragment>
-                    )
+              </div>
+              {branches != null &&
+                branches.filter((branch) => branch.trim() != "").length > 0 && (
+                  <p style={{ margin: 0 }}>
+                    <strong
+                      style={{
+                        display: "block",
+                        width: "100%",
+                        marginBottom: 8,
+                      }}
+                    >
+                      Branches:
+                    </strong>
+                    {branches.map(
+                      (branch, idx, self) =>
+                        branch.trim() != "" && (
+                          <React.Fragment key={branch}>
+                            <a
+                              href={buildRouteLink(
+                                AppRoute.REPOSITORY_BROWSER,
+                                {
+                                  orgSlug: parentOrg.slug,
+                                  repoSlug: repo.slug,
+                                  currentRef: branch,
+                                  "*":
+                                    path != null &&
+                                    path.trim() !== "" &&
+                                    path !== "/"
+                                      ? path
+                                      : "",
+                                }
+                              )}
+                            >
+                              {branch}
+                            </a>
+                            {idx === self.length - 1 ? "." : ", "}
+                          </React.Fragment>
+                        )
+                    )}
+                  </p>
                 )}
-              </p>
-              <p>
-                <strong>Tags:</strong>
-                <br />
-                {tags.map(
-                  (tag, idx, self) =>
-                    tag != null &&
-                    tag.trim() != "" && (
-                      <React.Fragment key={tag}>
-                        <span>{tag}</span>
-                        {idx === self.length - 1 ? "." : ", "}
-                      </React.Fragment>
-                    )
+              {tags != null &&
+                tags.filter((tag) => tag != null && tag.trim() != "").length >
+                  0 && (
+                  <p style={{ margin: 0 }}>
+                    <strong
+                      style={{
+                        display: "block",
+                        width: "100%",
+                        marginBottom: 8,
+                      }}
+                    >
+                      Tags:
+                    </strong>
+                    {tags.map(
+                      (tag, idx, self) =>
+                        tag != null &&
+                        tag.trim() != "" && (
+                          <React.Fragment key={tag}>
+                            <span>{tag}</span>
+                            {idx === self.length - 1 ? "." : ", "}
+                          </React.Fragment>
+                        )
+                    )}
+                  </p>
                 )}
-              </p>
             </Card>
           </Grid.Col>
         </Grid.Row>

app/views/repository/RepositoryForkView.tsx
@@ -61,6 +61,7 @@ const RepositoryForkView: ReactView<RepositoryForkViewProps> = ({
         >
           <div data-islandid={`${RepositoryForkForm.name}$$0`}>
             <RepositoryForkForm
+              themeScheme={commonProps.themeScheme}
               availableParentOrgs={availableParentOrgs}
               initialValues={initialValues}
             />

app/views/repositoryPullRequests/RepositoryPullRequestDetailsView.tsx
@@ -21,6 +21,8 @@ import {
   Layout,
   MarkdownToJsx,
   PageWrapper,
+  TextInput,
+  TextArea,
 } from "../../components";
 // app islands
 import RepositoryFilesDiffsList from "../../islands/RepositoryFilesDiffsList";

...
@@ -38,108 +40,74 @@ export interface RepositoryPullRequestDetailsViewProps extends CommonProps {
   isCurrentUserAllowedToMerge?: boolean;
 }
 
-const RepositoryPullRequestDetailsView: ReactView<RepositoryPullRequestDetailsViewProps> =
-  ({
-    commonProps,
-    filesDiffs,
-    lastCommit,
-    pullRequest: pr,
-    pullRequestAuthor: prAuthor,
-    sourceParentOrg,
-    sourceRepo,
-    targetParentOrg: parentOrg,
-    targetRepo: repo,
-    isCurrentUserAllowedToMerge = false,
-  }) => {
-    return (
-      <Layout {...commonProps}>
-        <PageWrapper>
-          <IslandWrapper data-islandid={`${RepositoryHero.name}$$0`}>
-            <RepositoryHero
-              forkedFromRepo={repo.forkedFromRepo}
-              forksCount={repo.forks.length}
-              parentOrg={parentOrg}
-              path={`Pull Request / ${pr.uid}`}
-              repo={repo}
-            />
-          </IslandWrapper>
-          <Grid.Col fluid style={{ marginTop: 32 }}>
-            <Grid.Col key={pr.id} fluid>
+const RepositoryPullRequestDetailsView: ReactView<
+  RepositoryPullRequestDetailsViewProps
+> = ({
+  commonProps,
+  filesDiffs,
+  lastCommit,
+  pullRequest: pr,
+  pullRequestAuthor: prAuthor,
+  sourceParentOrg,
+  sourceRepo,
+  targetParentOrg: parentOrg,
+  targetRepo: repo,
+  isCurrentUserAllowedToMerge = false,
+}) => {
+  const totalDiff = filesDiffs.reduce(
+    (acc, diff) => {
+      acc = {
+        ...acc,
+        additions: (acc?.additions || 0) + diff.additions,
+        deletions: (acc?.deletions || 0) + diff.deletions,
+      };
+      return acc;
+    },
+    { additions: 0, deletions: 0 }
+  );
+
+  return (
+    <Layout {...commonProps}>
+      <PageWrapper>
+        <IslandWrapper data-islandid={`${RepositoryHero.name}$$0`}>
+          <RepositoryHero
+            forkedFromRepo={repo.forkedFromRepo}
+            forksCount={repo.forks.length}
+            parentOrg={parentOrg}
+            path={`Pull Request / #${pr.uid}`}
+            repo={repo}
+          />
+        </IslandWrapper>
+        <Grid.Col fluid style={{ marginTop: 24 }}>
+          <Grid.Col key={pr.id} fluid>
+            <Grid.Row fluid alignItems="center" gap={16}>
+              <h1 style={{ margin: 0, marginTop: 8 }}>{pr.summary}</h1>
               <span>
                 <InlineCode themeScheme={commonProps.themeScheme}>
                   {`[${pr.state}]`}
                 </InlineCode>
               </span>
-              <h1 style={{ margin: 0, marginTop: 8 }}>
-                #{pr.uid} - {pr.summary}
-              </h1>
-              <span style={{ opacity: 0.67, marginTop: 8 }}>
-                <a
-                  href={buildRouteLink(
-                    AppRoute.USER_DETAILS,
-                    {
-                      username: prAuthor.username,
-                    },
-                    { encodeURIComponent: false }
-                  )}
-                >
-                  {prAuthor.displayName || prAuthor.username}
-                </a>
-              </span>
-              <span style={{ opacity: 0.67, marginTop: 8 }}>
-                {"wants to merge branch "}
-                <InlineCode themeScheme={commonProps.themeScheme}>
-                  {pr.sourceBranch}
-                </InlineCode>
-                {" from repository "}
-                <InlineCode themeScheme={commonProps.themeScheme}>
-                  {`${sourceParentOrg.slug}/${sourceRepo.slug}`}
-                </InlineCode>
-                {" (source) "}
-              </span>
-              <span style={{ opacity: 0.67, marginTop: 8 }}>
-                {" into branch "}
-                <InlineCode themeScheme={commonProps.themeScheme}>
-                  {pr.targetBranch}
-                </InlineCode>
-                {" of repository "}
-                <InlineCode themeScheme={commonProps.themeScheme}>
-                  {`${parentOrg.slug}/${repo.slug}`}
-                </InlineCode>
-                {" (target) "}
-              </span>
-              <Grid.Row
-                fluid
-                alignItems={"center"}
-                style={{ opacity: 0.67, marginTop: 8 }}
-              >
-                {new Date(pr.createdAt).getTime() <=
-                  new Date(pr.updatedAt).getTime() && (
-                  <span>
-                    opened on {new Date(pr.createdAt).toLocaleString()}
-                  </span>
-                )}
-                {((pr.closedAt == null &&
-                  new Date(pr.updatedAt).getTime() >
-                    new Date(pr.createdAt).getTime()) ||
-                  (pr.closedAt != null &&
-                    new Date(pr.updatedAt).getTime() <
-                      new Date(pr.closedAt).getTime())) && (
-                  <span>
-                    updated on {new Date(pr.updatedAt).toLocaleString()}
-                  </span>
-                )}
-                {pr.closedAt != null && (
-                  <span>
-                    closed on
-                    {new Date(pr.closedAt).toLocaleString()}
-                  </span>
+            </Grid.Row>
+
+            <Grid.Row
+              fluid
+              nowrap
+              gap={16}
+              style={{ opacity: 0.67, marginTop: 8 }}
+            >
+              <a
+                href={buildRouteLink(
+                  AppRoute.USER_DETAILS,
+                  {
+                    username: prAuthor.username,
+                  },
+                  { encodeURIComponent: false }
                 )}
-              </Grid.Row>
-            </Grid.Col>
-            <Grid.Col fluid style={{ marginTop: 32 }}>
-              <Grid.Row fluid>
-                <Grid.Col fluid>
+              >
+                {prAuthor.displayName || prAuthor.username}
+              </a>
+              {isCurrentUserAllowedToMerge && (
+                <>
                   <a
                     href={buildRouteLink(
                       AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION,

...
@@ -164,82 +132,163 @@ const RepositoryPullRequestDetailsView: ReactView<RepositoryPullRequestDetailsVi
                   >
                     Delete PR
                   </a>
-                </Grid.Col>
-                {isCurrentUserAllowedToMerge && (
-                  <Grid.Col>
-                    <form
-                      method={"POST"}
-                      action={buildRouteLink(
-                        AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION,
-                        {
-                          orgSlug: parentOrg.slug,
-                          repoSlug: repo.slug,
-                          pullUid: pr.uid,
-                        }
-                      )}
+                </>
+              )}
+            </Grid.Row>
+            <span style={{ opacity: 0.67, marginTop: 8 }}>
+              {"wants to merge branch "}
+              <InlineCode themeScheme={commonProps.themeScheme}>
+                {pr.sourceBranch}
+              </InlineCode>
+              {" from repository "}
+              <InlineCode themeScheme={commonProps.themeScheme}>
+                {`${sourceParentOrg.slug}/${sourceRepo.slug}`}
+              </InlineCode>
+              {" (source) "}
+            </span>
+            <span style={{ opacity: 0.67, marginTop: 4 }}>
+              {" into branch "}
+              <InlineCode themeScheme={commonProps.themeScheme}>
+                {pr.targetBranch}
+              </InlineCode>
+              {" of repository "}
+              <InlineCode themeScheme={commonProps.themeScheme}>
+                {`${parentOrg.slug}/${repo.slug}`}
+              </InlineCode>
+              {" (target) "}
+            </span>
+            <Grid.Row
+              fluid
+              alignItems={"center"}
+              style={{ opacity: 0.67, marginTop: 8 }}
+            >
+              {new Date(pr.createdAt).getTime() <=
+                new Date(pr.updatedAt).getTime() && (
+                <span>opened on {new Date(pr.createdAt).toLocaleString()}</span>
+              )}
+              {((pr.closedAt == null &&
+                new Date(pr.updatedAt).getTime() >
+                  new Date(pr.createdAt).getTime()) ||
+                (pr.closedAt != null &&
+                  new Date(pr.updatedAt).getTime() <
+                    new Date(pr.closedAt).getTime())) && (
+                <span>
+                  updated on {new Date(pr.updatedAt).toLocaleString()}
+                </span>
+              )}
+              {pr.closedAt != null && (
+                <span>
+                  closed on
+                  {new Date(pr.closedAt).toLocaleString()}
+                </span>
+              )}
+            </Grid.Row>
+          </Grid.Col>
+          {isCurrentUserAllowedToMerge && (
+            <Card
+              style={{ width: "100%", padding: 8, marginTop: 16 }}
+              themeScheme={commonProps.themeScheme}
+            >
+              <Grid.Col fluid style={{ marginTop: 8 }}>
+                <form
+                  style={{ width: "100%" }}
+                  method={"POST"}
+                  action={buildRouteLink(
+                    AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION,
+                    {
+                      orgSlug: parentOrg.slug,
+                      repoSlug: repo.slug,
+                      pullUid: pr.uid,
+                    }
+                  )}
+                >
+                  <Grid.Col fluid nowrap gap={8}>
+                    <TextInput
+                      themeScheme={commonProps.themeScheme}
+                      name={"merge_summary"}
+                      type={"text"}
+                      placeholder={
+                        "Enter a short description of the merged code..."
+                      }
+                      style={{ width: "100%" }}
+                    />
+                    <TextArea
+                      themeScheme={commonProps.themeScheme}
+                      name={"merge_message"}
+                      placeholder={
+                        "Describe what this merge will bring when merged in target repository..."
+                      }
+                      style={{ width: "100%", minHeight: 180 }}
+                    ></TextArea>
+                    <Grid.Row
+                      fluid
+                      nowrap
+                      justifyContent={"flex-end"}
+                      gap={8}
+                      alignItems={"center"}
+                      style={{ marginTop: 8 }}
                     >
-                      <Grid.Row fluid nowrap>
-                        <input
-                          type={"text"}
-                          name={"merge_summary"}
-                          placeholder={
-                            "Enter a short description of the merged code..."
-                          }
-                        />
-                        <textarea
-                          name={"merge_message"}
-                          placeholder={
-                            "Describe what this merge will bring when merged in target repository..."
-                          }
-                        ></textarea>
-                        <button type={"submit"} name={"merge_default"}>
-                          Merge
-                        </button>
-                        <button type={"submit"} name={"merge_squash"}>
-                          Merge w/ Squash
-                        </button>
-                        <button type={"submit"} name={"merge_rebase"}>
-                          Merge w/ Rebase
-                        </button>
-                      </Grid.Row>
-                    </form>
+                      <button type={"submit"} name={"merge_default"}>
+                        Merge
+                      </button>
+                      <button type={"submit"} name={"merge_squash"}>
+                        Merge w/ Squash
+                      </button>
+                      <button type={"submit"} name={"merge_rebase"}>
+                        Merge w/ Rebase
+                      </button>
+                    </Grid.Row>
                   </Grid.Col>
-                )}
-              </Grid.Row>
-            </Grid.Col>
-            <Grid.Col fluid style={{ marginTop: 24 }}>
-              <Card
-                style={{ width: "100%" }}
-                themeScheme={commonProps.themeScheme}
-              >
-                <MarkdownToJsx
-                  markdown={
-                    pr.textMd == null || pr.textMd.trim() === ""
-                      ? "> &lt;no_description_yet /&gt;"
-                      : pr.textMd
-                  }
-                  themeScheme={commonProps.themeScheme}
-                />
-              </Card>
-            </Grid.Col>
-            <Grid.Col
+                </form>
+              </Grid.Col>
+            </Card>
+          )}
+          <Card
+            style={{ width: "100%", padding: 8, marginTop: 8 }}
+            themeScheme={commonProps.themeScheme}
+          >
+            <Grid.Row
               fluid
-              data-islandid={`${RepositoryFilesDiffsList.name}$$0`}
-              style={{ marginTop: 24 }}
+              nowrap
+              alignItems={"center"}
+              style={{ marginBottom: 8 }}
+              gap={16}
             >
-              <RepositoryFilesDiffsList
-                filesDiffs={filesDiffs}
-                themeScheme={commonProps.themeScheme}
-                orgSlug={parentOrg.slug}
-                repoSlug={repo.slug}
-                commitHash={lastCommit != null ? lastCommit.commit : "HEAD"}
-              />
-            </Grid.Col>
+              <div style={{ color: "rgb(43, 176, 90)" }}>
+                <strong>+</strong> <span>{totalDiff.additions}</span>
+              </div>
+              <div style={{ color: "rgb(215, 44, 44)" }}>
+                <strong>-</strong> <span>{totalDiff.deletions}</span>
+              </div>
+            </Grid.Row>
+            <MarkdownToJsx
+              themeScheme={commonProps.themeScheme}
+              markdown={
+                pr.textMd == null || pr.textMd.trim() === ""
+                  ? "> &lt;no_description_yet /&gt;"
+                  : pr.textMd
+              }
+            />
+          </Card>
+          <Grid.Col
+            gap={8}
+            fluid
+            data-islandid={`${RepositoryFilesDiffsList.name}$$0`}
+            style={{ marginTop: 8 }}
+          >
+            <RepositoryFilesDiffsList
+              filesDiffs={filesDiffs}
+              themeScheme={commonProps.themeScheme}
+              orgSlug={parentOrg.slug}
+              repoSlug={repo.slug}
+              commitHash={lastCommit != null ? lastCommit.commit : "HEAD"}
+            />
           </Grid.Col>
-        </PageWrapper>
-      </Layout>
-    );
-  };
+        </Grid.Col>
+      </PageWrapper>
+    </Layout>
+  );
+};
 
 RepositoryPullRequestDetailsView.displayName =
   "RepositoryPullRequestDetailsView";

@@ -53,10 +53,6 @@ async function main(args, sshOriginalCommand) {
     { encoding: "utf8" }
   );
 
-  // console.log(
-  //   `username: ${username}\npublicKey: ${publicKey}\ncommand: ${command}\nrepoSlug: ${repoSlug}\n`
-  // );
-
   const res = await fetch(`http://localhost:1337/_ssh/auth`, {
     method: "POST",
     body: JSON.stringify({