Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/client/src/git/ce/constants/messages.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const OPS_MODAL = {
TAB_RELEASE: "RELEASE",
TAB_RELEASE: "Release",
};

export const TAB_RELEASE = {
Expand All @@ -16,3 +16,8 @@ export const RELEASE_NOTES_INPUT = {
TITLE: "Release notes",
PLACEHOLDER: "Your release notes here",
};

export const LATEST_COMMIT_INFO = {
LOADING_COMMIT_MESSAGE: "Fetching latest commit...",
NO_COMMIT_MESSAGE: "No commit message found",
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,91 +4,143 @@ import LatestCommitInfoView from "./LatestCommitInfoView";
import "@testing-library/jest-dom";

describe("LatestCommitInfoView", () => {
const currentTimestamp = Math.floor((Date.now() - 3600000) / 1000);

it("renders correctly with all props", () => {
const { getByText } = render(
const { getByTestId } = render(
<LatestCommitInfoView
authorName="John Doe"
committedAt="2025-03-01"
committedAt={currentTimestamp}
hash="abc123"
isLoading={false}
message="Initial commit"
/>,
);

expect(getByText("Initial commit")).toBeInTheDocument();
expect(getByText("John Doe committed 2025-03-01")).toBeInTheDocument();
expect(getByText("abc123")).toBeInTheDocument();
expect(getByTestId("t--git-latest-commit-message")).toHaveTextContent(
"Initial commit",
);
expect(getByTestId("t--git-latest-commit-commited-by")).toHaveTextContent(
"John Doe committed 1 hr ago",
);
expect(getByTestId("t--git-latest-commit-hash")).toHaveTextContent(
"abc123",
);
});

it("renders correctly with null authorName", () => {
const { getByText } = render(
const { getByTestId, queryByTestId } = render(
<LatestCommitInfoView
authorName={null}
committedAt="2025-03-01"
committedAt={currentTimestamp}
hash="abc123"
isLoading={false}
message="Initial commit"
/>,
);

expect(getByText("Initial commit")).toBeInTheDocument();
expect(getByText("- committed 2025-03-01")).toBeInTheDocument();
expect(getByText("abc123")).toBeInTheDocument();
expect(
queryByTestId("t--git-latest-commit-commited-by"),
).not.toBeInTheDocument();
expect(getByTestId("t--git-latest-commit-message")).toHaveTextContent(
"Initial commit",
);
});

it("renders correctly with null committedAt", () => {
const { getByText } = render(
const { getByTestId } = render(
<LatestCommitInfoView
authorName="John Doe"
committedAt={null}
hash="abc123"
isLoading={false}
message="Initial commit"
/>,
);

expect(getByText("Initial commit")).toBeInTheDocument();
expect(getByText("John Doe committed -")).toBeInTheDocument();
expect(getByText("abc123")).toBeInTheDocument();
expect(getByTestId("t--git-latest-commit-message")).toHaveTextContent(
"Initial commit",
);
expect(getByTestId("t--git-latest-commit-commited-by")).toHaveTextContent(
"Committed by John Doe",
);
});

it("renders correctly with null hash", () => {
const { getByText } = render(
const { getByTestId } = render(
<LatestCommitInfoView
authorName="John Doe"
committedAt="2025-03-01"
committedAt={currentTimestamp}
hash={null}
isLoading={false}
message="Initial commit"
/>,
);

expect(getByText("Initial commit")).toBeInTheDocument();
expect(getByText("John Doe committed 2025-03-01")).toBeInTheDocument();
expect(getByText("-")).toBeInTheDocument();
expect(getByTestId("t--git-latest-commit-message")).toHaveTextContent(
"Initial commit",
);
expect(getByTestId("t--git-latest-commit-commited-by")).toHaveTextContent(
"John Doe committed 1 hr ago",
);
expect(getByTestId("t--git-latest-commit-hash")).toHaveTextContent("-");
});

it("renders correctly with null message", () => {
const { getByText } = render(
const { getByTestId } = render(
<LatestCommitInfoView
authorName="John Doe"
committedAt="2025-03-01"
committedAt={currentTimestamp}
hash="abc123"
isLoading={false}
message={null}
/>,
);

expect(getByText("John Doe committed 2025-03-01")).toBeInTheDocument();
expect(getByText("abc123")).toBeInTheDocument();
expect(getByTestId("t--git-latest-commit-message")).toHaveTextContent(
"No commit message found",
);
expect(getByTestId("t--git-latest-commit-commited-by")).toHaveTextContent(
"John Doe committed 1 hr ago",
);
expect(getByTestId("t--git-latest-commit-hash")).toHaveTextContent(
"abc123",
);
});

it("renders correctly with all null props", () => {
const { getByText } = render(
const { queryByTestId } = render(
<LatestCommitInfoView
authorName={null}
committedAt={null}
hash={null}
isLoading={false}
message={null}
/>,
);

expect(getByText("- committed -")).toBeInTheDocument();
expect(getByText("-")).toBeInTheDocument();
expect(
queryByTestId("t--git-latest-commit-commited-by"),
).not.toBeInTheDocument();
expect(queryByTestId("t--git-latest-commit-message")).toHaveTextContent(
"No commit message found",
);
expect(queryByTestId("t--git-latest-commit-hash")).toHaveTextContent("-");
});

it("renders loading state correctly", () => {
const { getByTestId } = render(
<LatestCommitInfoView
authorName="John Doe"
committedAt={currentTimestamp}
hash="abc123"
isLoading
message="Initial commit"
/>,
);

expect(getByTestId("t--git-latest-commit-loading")).toHaveTextContent(
"Fetching latest commit...",
);
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Flex, Icon, Text } from "@appsmith/ads";
import { Flex, Icon, Spinner, Text } from "@appsmith/ads";
import { LATEST_COMMIT_INFO } from "git/ee/constants/messages";
import React from "react";
import styled from "styled-components";
import { howMuchTimeBeforeText } from "utils/helpers";

const Container = styled(Flex)`
border-radius: 4px;
Expand All @@ -9,29 +11,65 @@ const Container = styled(Flex)`

interface LatestCommitInfoViewProps {
authorName: string | null;
committedAt: string | null;
committedAt: number | null;
hash: string | null;
isLoading: boolean;
message: string | null;
}

function LatestCommitInfoView({
authorName = null,
committedAt = null,
hash = null,
isLoading = false,
message = null,
}: LatestCommitInfoViewProps) {
const readableCommittedAt = committedAt
? howMuchTimeBeforeText(new Date(committedAt * 1000).toString())
: null;

if (isLoading) {
return (
<Container
alignItems="center"
data-testid="t--git-latest-commit-loading"
gap="spaces-3"
marginBottom="spaces-4"
padding="spaces-3"
>
<Spinner size="md" />
<Text renderAs="p">{LATEST_COMMIT_INFO.LOADING_COMMIT_MESSAGE}</Text>
</Container>
);
}

return (
<Container marginBottom="spaces-4" padding="spaces-3">
<Flex flex={1} flexDirection="column" gap="spaces-3">
<Text renderAs="p">{message}</Text>
<Text kind="body-s" renderAs="p">
{authorName ?? "-"} committed {committedAt ?? "-"}
<Text data-testid="t--git-latest-commit-message" renderAs="p">
{message ?? <em>{LATEST_COMMIT_INFO.NO_COMMIT_MESSAGE}</em>}
</Text>
{authorName && (
<Text
data-testid="t--git-latest-commit-commited-by"
kind="body-s"
renderAs="p"
>
{authorName && !readableCommittedAt
? `Committed by ${authorName}`
: null}
{authorName && readableCommittedAt
? `${authorName} committed ${readableCommittedAt} ago`
: null}
</Text>
)}
</Flex>
<Flex alignItems="center" justifyContent="center">
<Flex gap="spaces-2">
<Icon name="git-commit" size="md" />
<Text renderAs="p">{hash ?? "-"}</Text>
<Text data-testid="t--git-latest-commit-hash" renderAs="p">
{hash ?? "-"}
</Text>
</Flex>
</Flex>
</Container>
Expand Down
17 changes: 11 additions & 6 deletions app/client/src/git/components/LatestCommitInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import React from "react";
import LatestCommitInfoView from "./LatestCommitInfoView";
import useLatestCommit from "git/hooks/useLatestCommit";
import usePretag from "git/hooks/usePretag";

function LatestCommitInfo() {
const { latestCommit } = useLatestCommit();
const { isPretagLoading, pretagResponse } = usePretag();

const commitHash = pretagResponse?.hash
? pretagResponse.hash.slice(0, 7)
: null;

return (
<LatestCommitInfoView
authorName={latestCommit?.authorName ?? null}
committedAt={latestCommit?.committedAt ?? null}
hash={latestCommit?.hash ?? null}
message={latestCommit?.message ?? null}
authorName={pretagResponse?.author.name ?? null}
committedAt={pretagResponse?.commitedAt ?? null}
hash={commitHash}
isLoading={isPretagLoading}
message={pretagResponse?.commitMessage ?? null}
/>
);
}
Expand Down
20 changes: 20 additions & 0 deletions app/client/src/git/components/OpsModal/OpsModalView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import styled from "styled-components";
// import ReconnectSSHError from "../components/ReconnectSSHError";
import { GitOpsTab } from "git/constants/enums";
import noop from "lodash/noop";
import isGitTaggingEnabled from "git/helpers/isGitTaggingEnabled";
import type { GitArtifactDef } from "git/types";
import TabRelease from "./TabRelease";
import { OPS_MODAL } from "git/ee/constants/messages";

const StyledModalContent = styled(ModalContent)`
&&& {
Expand All @@ -27,6 +31,7 @@ const StyledModalContent = styled(ModalContent)`
`;

interface OpsModalViewProps {
artifactDef: GitArtifactDef | null;
fetchStatus: () => void;
isOpsModalOpen: boolean;
isProtectedMode: boolean;
Expand All @@ -36,13 +41,16 @@ interface OpsModalViewProps {
}

function OpsModalView({
artifactDef = null,
fetchStatus = noop,
isOpsModalOpen = false,
isProtectedMode = false,
opsModalTab = GitOpsTab.Deploy,
repoName = null,
toggleOpsModal = noop,
}: OpsModalViewProps) {
const isTaggingEnabled = isGitTaggingEnabled(artifactDef);

useEffect(
function fetchStatusOnMountEffect() {
if (isOpsModalOpen) {
Expand Down Expand Up @@ -91,10 +99,22 @@ function OpsModalView({
>
{createMessage(MERGE)}
</Tab>
{isTaggingEnabled && (
<Tab
data-testid={"t--git-ops-tab-tag"}
disabled={isProtectedMode}
value={GitOpsTab.Release}
>
{OPS_MODAL.TAB_RELEASE}
</Tab>
)}
</TabsList>
</Tabs>
{opsModalTab === GitOpsTab.Deploy && <TabDeploy />}
{opsModalTab === GitOpsTab.Merge && <TabMerge />}
{isTaggingEnabled && opsModalTab === GitOpsTab.Release && (
<TabRelease />
)}
</StyledModalContent>
</Modal>
{/* <GitErrorPopup /> */}
Expand Down
Loading
Loading