Skip to content
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

chore: git mod - connect modal and branches #38171

Open
wants to merge 101 commits into
base: release
Choose a base branch
from
Open

Conversation

brayn003
Copy link
Contributor

@brayn003 brayn003 commented Dec 15, 2024

Description

  • Connects connect modal to store
  • Adds component for branch list

Fixes #37814
Fixes #37802

Automation

/ok-to-test tags="@tag.Git"

🔍 Cypress test results

Tip

🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/12376713895
Commit: 34d96b4
Cypress dashboard.
Tags: @tag.Git
Spec:


Tue, 17 Dec 2024 16:59:28 UTC

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • New Features

    • Introduced a ConnectInitialize component for Git provider connections.
    • Added ConnectSuccess modal to display successful Git connections.
    • Implemented ImportModal for Git import functionality.
    • Added LocalProfileView for managing user profile settings.
    • Introduced BranchList component for displaying and managing branches.
  • Bug Fixes

    • Enhanced error handling and state management in various components.
  • Refactor

    • Streamlined prop handling and state management in multiple components.
    • Updated action and selector names for clarity and consistency.
  • Tests

    • Expanded test coverage for new and modified components, ensuring accurate behavior under various conditions.
  • Chores

    • Updated import paths and removed unused files to improve project structure.

@brayn003 brayn003 self-assigned this Dec 15, 2024
Copy link
Contributor

coderabbitai bot commented Dec 15, 2024

Walkthrough

This pull request introduces a comprehensive refactoring of the Git-related components and hooks in the Appsmith client application. The changes focus on modularizing the Git functionality, introducing new hooks for state management, and streamlining the component architecture. Key modifications include renaming props, updating error handling, and creating more focused, reusable components across the Git integration ecosystem.

Changes

File/Path Change Summary
app/client/src/git/components/ConnectModal/... Significant restructuring of connection modal components, introducing ConnectInitialize, ConnectModalView, and ConnectSuccess
app/client/src/git/hooks/ New hooks added: useConnect, useMetadata, useStatus, usePull, useCommit, useDiscard, useMerge, useOps
app/client/src/git/components/BranchList/ New components for branch management, including BranchListView, LocalBranchList, RemoteBranchList
app/client/src/git/store/ Updated selectors, actions, and state management for Git-related operations

Sequence Diagram

sequenceDiagram
    participant User
    participant ConnectModal
    participant GitProvider
    participant SSHKeyManager
    
    User->>ConnectModal: Initiate Connection
    ConnectModal->>GitProvider: Select Provider
    ConnectModal->>SSHKeyManager: Generate/Fetch SSH Key
    SSHKeyManager-->>ConnectModal: Return SSH Key
    ConnectModal->>GitProvider: Add Deploy Key
    GitProvider-->>ConnectModal: Connection Successful
Loading

Possibly related PRs

Poem

🌿 Git's Garden of Code

Hooks bloom like spring's first light,
Components dance with modular might,
Branches sway in refactored grace,
A symphony of code's embrace!

🚀 Refactoring's sweet delight!


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@brayn003 brayn003 added the ok-to-test Required label for CI label Dec 15, 2024
@github-actions github-actions bot added the skip-changelog Adding this label to a PR prevents it from being listed in the changelog label Dec 15, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

🧹 Nitpick comments (70)
app/client/src/git/hooks/useAppsmithEnterpriseUrl.ts (3)

7-7: Add TypeScript type for the feature parameter

Consider adding a union type for the feature parameter to restrict it to valid feature names.

-export const useAppsmithEnterpriseUrl = (feature: string) => {
+type EnterpriseFeature = 'git' | 'continuous-delivery' | 'branch-protection';
+export const useAppsmithEnterpriseUrl = (feature: EnterpriseFeature) => {

7-23: Add JSDoc documentation for the hook

The hook would benefit from documentation describing its purpose, parameters, and return value.

+/**
+ * Custom hook that generates an Appsmith Enterprise URL with tracking parameters
+ * @param feature - The enterprise feature being accessed
+ * @returns The constructed enterprise pricing page URL with tracking parameters
+ */
 export const useAppsmithEnterpriseUrl = (feature: string) => {

1-23: LGTM! Clean implementation with proper memoization

The hook is well-structured, uses proper memoization with useMemo, and handles parameters safely. The URL construction is done using the standard URL API which is good practice.

Consider adding URL validation if the ENTERPRISE_PRICING_PAGE constant might be configurable in the future.

app/client/src/ee/git/sagas/index.ts (1)

1-14: Add documentation for action registries

Please add JSDoc comments explaining:

  • The purpose of blocking vs non-blocking actions
  • Examples of what actions belong in each registry
  • How these registries are consumed
app/client/src/git/components/ConnectModal/ConnectModalView.tsx (4)

12-20: Consider using relative units for better responsiveness

The styled component uses hardcoded pixel values and !important override which could cause maintenance issues.

Consider this improvement:

 const StyledModalContent = styled(ModalContent)`
   &&& {
-    width: 640px;
+    width: min(640px, 90vw);
     transform: none !important;
     top: 100px;
-    left: calc(50% - 320px);
+    left: 50%;
+    transform: translateX(-50%);
     max-height: calc(100vh - 200px);
   }
 `;

22-47: Add JSDoc comments to document the interface

The interface is well-typed but lacks documentation for props usage.

Consider adding JSDoc comments:

+/**
+ * Props for the ConnectModalView component
+ * @interface ConnectModalViewProps
+ */
 interface ConnectModalViewProps {
+  /** Type of artifact being connected */
   artifactType: string;
+  /** Callback to handle connection */
   connect: (params: ConnectRequestParams) => void;
   // ... add docs for other props
 }

49-71: Consider adding error boundary for robust error handling

The component handles state well but lacks error boundaries for runtime errors.

Consider wrapping the component with an error boundary:

class GitModalErrorBoundary extends React.Component<{children: React.ReactNode}> {
  componentDidCatch(error: Error) {
    // Handle error logging
  }
  render() {
    return this.props.children;
  }
}

// Usage:
export default function ConnectModalViewWithErrorBoundary(props: ConnectModalViewProps) {
  return (
    <GitModalErrorBoundary>
      <ConnectModalView {...props} />
    </GitModalErrorBoundary>
  );
}

76-92: Improve comment clarity for fragment usage

The current comment doesn't fully explain the necessity of the fragment.

Consider updating the comment:

-          // need fragment to arrange conditions properly
-          // eslint-disable-next-line react/jsx-no-useless-fragment
+          // Fragment is required here to maintain conditional rendering hierarchy
+          // while avoiding additional DOM nesting
app/client/src/git/requests/fetchMetadataRequest.types.ts (1)

Line range hint 3-18: Consider retaining Git context in type names

The interface contains Git-specific fields (branchName, remoteUrl, etc.) but has dropped the "Git" prefix. This might make it less obvious that this type is specifically for Git operations.

app/client/src/git/components/DisableAutocommitModal/DisableAutocommitModalView.tsx (2)

42-46: Add error handling for toggleAutocommit

Consider wrapping the toggleAutocommit call in a try-catch block to handle potential failures gracefully.

 const handleDisableAutocommit = useCallback(() => {
-    toggleAutocommit();
-    AnalyticsUtil.logEvent("GS_AUTO_COMMIT_DISABLED");
-    toggleAutocommitDisableModal(false);
+    try {
+      toggleAutocommit();
+      AnalyticsUtil.logEvent("GS_AUTO_COMMIT_DISABLED");
+      toggleAutocommitDisableModal(false);
+    } catch (error) {
+      // Handle error appropriately
+      console.error("Failed to disable autocommit:", error);
+    }
 }, [toggleAutocommit, toggleAutocommitDisableModal]);

60-60: Consider moving test IDs to constants

Test IDs should be maintained in a separate constants file for better maintainability.

+ // In a constants file
+ export const TEST_IDS = {
+   AUTOCOMMIT_MODAL: "t--autocommit-git-modal",
+   AUTOCOMMIT_CTA_BUTTON: "t--autocommit-modal-cta-button"
+ };

Also applies to: 71-71

app/client/src/git/requests/gitImportRequest.types.ts (1)

Line range hint 12-28: Consider adding JSDoc comments for better documentation.

While the types are well-structured, adding JSDoc comments would improve documentation for other developers.

Here's a suggested improvement:

+/**
+ * Response data structure for Git import operation
+ */
 export interface GitImportResponseData {
   id: string;
   baseId: string;
   gitApplicationMetadata: {
     branchName: string;
     browserSupportedRemoteUrl: string;
     defaultApplicationId: string;
     defaultArtifactId: string;
     defaultBranchName: string;
     isRepoPrivate: boolean;
     lastCommitedAt: string;
     remoteUrl: string;
     repoName: string;
   };
 }

+/**
+ * Wrapped API response type for Git import operations
+ */
 export type GitImportResponse = ApiResponse<GitImportResponseData>;
app/client/src/ee/git/store/helpers/gitSingleArtifactInitialState.ts (1)

6-10: Consider adding JSDoc comments for better maintainability.

While the code is clean, adding documentation about the purpose of these initial states would help future maintainers understand their role in the Redux store.

+/**
+ * Initial UI state for Git single artifact in Enterprise Edition
+ */
 export const gitSingleArtifactInitialUIStateEE: GitSingleArtifactUIReduxStateEE =
   {};

+/**
+ * Initial API responses state for Git single artifact in Enterprise Edition
+ */
 export const gitSingleArtifactInitialAPIResponsesEE: GitSingleArtifactAPIResponsesReduxStateEE =
   {};
app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx (3)

47-51: Consider strengthening type safety for branches prop

The branches prop type could be more specific by using a type that explicitly defines the shape of a branch object.

-  branches: FetchBranchesResponseData | null;
+  branches: Array<{ branchName: string; default: boolean }> | null;

87-90: Remove unnecessary useCallback

The handleGetPopupContainer function has no dependencies and doesn't need memoization.

-  const handleGetPopupContainer = useCallback(
-    (triggerNode) => triggerNode.parentNode,
-    [],
-  );
+  const handleGetPopupContainer = (triggerNode: HTMLElement) => triggerNode.parentNode;

125-138: Add aria-label for accessibility

The select component should have an aria-label for better accessibility.

   <StyledSelect
     data-testid="t--git-default-branch-select"
+    aria-label="Select default branch"
     dropdownMatchSelectWidth
     getPopupContainer={handleGetPopupContainer}
     isDisabled={!isGitProtectedFeatureLicensed}
     onChange={setSelectedValue}
     value={selectedValue}
   >
app/client/src/git/components/ConnectModal/index.tsx (1)

40-62: Consider reducing the number of props passed to ConnectModalView

To improve maintainability, consider grouping related props into an object or using context to pass data, reducing the number of individual props.

app/client/src/git/components/ProtectedBranches/ProtectedBranchesView.tsx (1)

85-86: Use localBranchName directly to avoid redundant code

You can use localBranchName directly instead of calling replace again.

Apply this diff:

-          returnVal.push(
-            branch.branchName.replace(GIT_REMOTE_BRANCH_PREFIX, ""),
-          );
+          returnVal.push(localBranchName);
app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx (1)

193-193: Simplify condition with optional chaining

You can simplify the condition by using optional chaining:

- if (sshPublicKey && sshPublicKey.includes("rsa")) {
+ if (sshPublicKey?.includes("rsa")) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 193-193: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

app/client/src/git/requests/disconnectRequest.types.ts (1)

3-5: Consider strengthening the DisconnectResponseData type definition.

The current string index signature is very permissive. If the response structure is known, consider defining specific properties instead.

Example:

export interface DisconnectResponseData {
  status: string;
  message: string;
  // Add other known properties
}
app/client/src/git/requests/fetchSSHKeyRequest.types.ts (1)

3-8: Consider consolidating redundant boolean flags

The interface includes both isRegeneratedKey and regeneratedKey which appear to serve the same purpose.

 export interface FetchSSHKeyResponseData {
   publicKey: string;
   docUrl: string;
-  isRegeneratedKey: boolean;
   regeneratedKey: boolean;
 }
app/client/src/git/components/ConnectModal/ConnectInitialize/types.ts (1)

3-10: Consider adding JSDoc comments and using enum

The interface would benefit from documentation explaining the purpose of each field. Also, consider using an enum for SSH key types.

+/** Represents the state of the Git connection form */
 export interface ConnectFormDataState {
+  /** Selected Git provider (e.g., GitHub, GitLab) */
   gitProvider?: GitProvider;
+  /** Path to empty Git repository if it exists */
   gitEmptyRepoExists?: string;
+  /** Indicates if an existing Git repository was found */
   gitExistingRepoExists?: boolean;
+  /** Remote repository URL */
   remoteUrl?: string;
+  /** Indicates if deploy key has been added to the repository */
   isAddedDeployKey?: boolean;
-  sshKeyType?: "RSA" | "ECDSA";
+  /** Type of SSH key used for authentication */
+  sshKeyType?: SSHKeyType;
 }

+/** Supported SSH key types */
+export enum SSHKeyType {
+  RSA = "RSA",
+  ECDSA = "ECDSA"
+}
app/client/src/git/components/GitModals/index.tsx (1)

1-14: LGTM! Consider lazy loading for enterprise features.

The component structure is clean and follows good separation of concerns between CE and EE variants.

Consider lazy loading the EE component to reduce initial bundle size:

-import GitModalsEE from "ee/git/components/GitModals/GitModalsEE";
+const GitModalsEE = React.lazy(() => import("ee/git/components/GitModals/GitModalsEE"));
app/client/src/git/requests/generateSSHKeyRequest.types.ts (1)

8-13: Consider consolidating duplicate boolean flags.

Based on the learnings, both isRegeneratedKey and regeneratedKey are intentionally included. However, having two properties for the same concept might cause confusion.

Consider using just one of these properties to maintain clarity:

 export interface GenerateSSHKeyResponseData {
   publicKey: string;
   docUrl: string;
   isRegeneratedKey: boolean;
-  regeneratedKey: boolean;
 }
app/client/src/git/components/ContinuousDelivery/index.tsx (1)

3-4: Standardize import pattern between CE and EE components

There's an inconsistency in the import pattern - CE uses default import while EE uses named import.

Consider standardizing to:

-import { ContinuousDeliveryEE } from "ee/git/components/ContinuousDelivery/ContinuousDeliveryEE";
+import ContinuousDeliveryEE from "ee/git/components/ContinuousDelivery/ContinuousDeliveryEE";
app/client/src/git/hooks/useGitFeatureFlags.ts (1)

4-16: Add TypeScript interface for return type

The hook implementation looks clean, but would benefit from explicit typing.

Consider adding this interface:

interface GitFeatureFlags {
  license_git_branch_protection_enabled: boolean;
  license_git_continuous_delivery_enabled: boolean;
}

And update the function signature:

export default function useGitFeatureFlags(): GitFeatureFlags
app/client/src/git/components/GitModals/GitModalsCE.tsx (1)

9-20: Consider performance optimizations

The component could benefit from the following improvements:

  1. Add memoization since the component renders multiple modals:
const GitModalsCE = React.memo(function GitModalsCE() {
  return (
    <>
      <ConnectModal />
      <OpsModal />
      <SettingsModal />
      <DisconnectModal />
      <DisableAutocommitModal />
      <ConflictErrorModal />
    </>
  );
});
  1. Add TypeScript interface if the component needs to accept props in the future:
interface GitModalsCEProps {
  // Add props here when needed
}
app/client/src/git/requests/generateSSHKeyRequest.ts (1)

13-14: Simplify URL construction

The URL construction can be more maintainable.

Consider using a URL builder pattern:

const getEndpoint = (params: GenerateSSHKeyRequestParams, baseApplicationId: string) => {
  const baseUrl = params.isImport ? GIT_BASE_URL : APPLICATION_BASE_URL;
  const path = params.isImport 
    ? `/import/keys` 
    : `/ssh-keypair/${baseApplicationId}`;
  return `${baseUrl}${path}?keyType=${params.keyType}`;
};
app/client/src/git/components/SettingsModal/TabGeneral/index.tsx (1)

6-8: Consider enhancing container styles for better maintainability

The styled container could benefit from more specific styling properties for scrolling behavior.

const Container = styled.div`
  overflow: auto;
+ max-height: 100%;
+ padding: 0;
+ -webkit-overflow-scrolling: touch;
`;
app/client/src/git/components/DisableAutocommitModal/index.tsx (1)

13-20: Consider adding PropTypes for DisableAutocommitModalView

While TypeScript provides type safety, adding PropTypes can help with runtime validation.

+ import PropTypes from 'prop-types';

+ DisableAutocommitModalView.propTypes = {
+   isAutocommitDisableModalOpen: PropTypes.bool.isRequired,
+   isToggleAutocommitLoading: PropTypes.bool.isRequired,
+   toggleAutocommit: PropTypes.func.isRequired,
+   toggleAutocommitDisableModal: PropTypes.func.isRequired,
+ };
app/client/src/git/hooks/useMetadata.ts (1)

9-26: Well-structured metadata hook with proper error handling

Clean implementation with proper null checks and state management.

Consider adding an explicit return type interface:

interface MetadataHookResult {
  metadata: GitMetadata | null;
  isFetchMetadataLoading: boolean;
  fetchMetadataError: Error | null;
  isGitConnected: boolean;
}
app/client/src/git/components/SettingsModal/TabBranch/index.tsx (2)

10-13: Consider prefixing interface with 'I' for consistency

Following common TypeScript naming conventions, consider renaming the interface to ITabBranchProps.


6-8: Consider adding max-height to Container

The Container component handles overflow but doesn't have a max-height constraint, which might lead to unexpected behavior in different viewport sizes.

const Container = styled.div`
  overflow: auto;
+ max-height: 80vh;
`;
app/client/src/git/components/SettingsModal/index.tsx (1)

1-30: LGTM! Consider adding explicit prop types interface.

The component follows good separation of concerns and correctly uses custom hooks for state management.

Consider adding an explicit interface for the view component props:

interface SettingsModalViewProps {
  isConnectPermitted: boolean;
  isManageAutocommitPermitted: boolean;
  isManageDefaultBranchPermitted: boolean;
  isManageProtectedBranchesPermitted: boolean;
  isSettingsModalOpen: boolean;
  settingsModalTab: string;
  toggleSettingsModal: () => void;
}
app/client/src/git/components/OpsModal/TabMerge/index.tsx (1)

19-21: Consider grouping related props into objects.

The component passes many individual props to the view component. Consider grouping related props to improve maintainability.

Example grouping:

interface BranchState {
  branches: Branch[];
  currentBranch: string;
  fetchBranches: () => void;
  fetchBranchesLoading: boolean;
}

// Usage
const branchState = useBranches();
<TabMergeView
  branchState={branchState}
  // ... other props
/>
app/client/src/git/hooks/useSettings.ts (1)

12-42: Consider adding return type annotation for better type safety

The hook implementation looks solid, but adding an explicit return type would improve type safety and documentation.

-export default function useSettings() {
+export default function useSettings(): {
+  isSettingsModalOpen: boolean;
+  settingsModalTab: GitSettingsTab;
+  toggleSettingsModal: (open: boolean, tab?: keyof typeof GitSettingsTab) => void;
+} {
app/client/src/git/components/ContinuousDelivery/ContinuousDeliveryCE.tsx (2)

12-17: Avoid magic numbers in styles

Extract the magic numbers into named constants for better maintainability.

+const CONTAINER_PADDING_TOP = '8px';
+const CONTAINER_PADDING_BOTTOM = '16px';
+const CONTAINER_MIN_HEIGHT = 'calc(360px + 52px)';

 export const Container = styled.div`
-  padding-top: 8px;
-  padding-bottom: 16px;
+  padding-top: ${CONTAINER_PADDING_TOP};
+  padding-bottom: ${CONTAINER_PADDING_BOTTOM};
   overflow: auto;
-  min-height: calc(360px + 52px);
+  min-height: ${CONTAINER_MIN_HEIGHT};
 `;

45-53: Add aria-label for better accessibility

The enterprise link button should have an aria-label for better screen reader support.

 <StyledButton
   href={enterprisePricingLink}
   kind="primary"
   renderAs="a"
   size="md"
   target="_blank"
+  aria-label="Try Appsmith Enterprise for Continuous Delivery"
 >
   {createMessage(TRY_APPSMITH_ENTERPRISE)}
 </StyledButton>
app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts (2)

20-26: Avoid type duplication in interface

The artifactDef type is duplicated within the interface. Consider extracting it to a separate type.

+type ArtifactDefinition = {
+  artifactType: keyof typeof GitArtifactType;
+  baseArtifactId: string;
+};

 export interface GitContextValue extends UseGitOpsReturnValue {
   artifactType: keyof typeof GitArtifactType;
   baseArtifactId: string;
-  artifactDef: {
-    artifactType: keyof typeof GitArtifactType;
-    baseArtifactId: string;
-  };
+  artifactDef: ArtifactDefinition;

44-46: Consider using nullish coalescing for artifact ID

The current null check could be simplified using the nullish coalescing operator.

 const useGitOpsReturnValue = useGitOps({
   ...artifactDef,
-  artifactId: artifact?.id ?? null,
+  artifactId: artifact?.id || null,
 });
app/client/src/git/hooks/useGlobalProfile.ts (1)

34-37: Consider combining loading and error states

The loading and error states could be combined into a single status object for better state management.

+type ProfileStatus = {
+  loading: boolean;
+  error: Error | null;
+};

 return {
-  globalProfile: fetchGlobalProfileState?.value ?? null,
-  isFetchGlobalProfileLoading: fetchGlobalProfileState?.loading ?? false,
-  fetchGlobalProfileError: fetchGlobalProfileState?.error ?? null,
+  globalProfile: fetchGlobalProfileState?.value || null,
+  fetchStatus: {
+    loading: fetchGlobalProfileState?.loading || false,
+    error: fetchGlobalProfileState?.error || null,
+  },
   fetchGlobalProfile,
app/client/src/git/hooks/useLocalProfile.ts (1)

12-14: Consider adding TypeScript return type annotation

The hook's return type should be explicitly defined for better type safety and documentation.

-export default function useLocalProfile() {
+export default function useLocalProfile(): {
+  localProfile: GitLocalProfile | null;
+  isFetchLocalProfileLoading: boolean;
+  fetchLocalProfileError: Error | null;
+  fetchLocalProfile: () => void;
+  isUpdateLocalProfileLoading: boolean;
+  updateLocalProfileError: Error | null;
+  updateLocalProfile: (params: UpdateLocalProfileRequestParams) => void;
+} {

Also applies to: 41-49

app/client/src/git/hooks/useProtectedBranches.ts (1)

41-50: Add type safety to return object

Consider adding explicit TypeScript interface for the return object.

app/client/src/git/hooks/useDisconnect.ts (1)

44-54: Consider adding loading state type safety

The nullish coalescing for loading and error states could benefit from type definitions.

+ type DisconnectState = {
+   loading: boolean;
+   error: Error | null;
+ };
  return {
-   isDisconnectLoading: disconnectState?.loading ?? false,
-   disconnectError: disconnectState?.error ?? null,
+   isDisconnectLoading: (disconnectState as DisconnectState)?.loading ?? false,
+   disconnectError: (disconnectState as DisconnectState)?.error ?? null,
app/client/src/git/components/QuickActions/index.tsx (1)

37-44: Consider grouping related props

The props could be organized better by grouping related flags together.

    <QuickActionsView
      discard={discard}
+     // Git connection state
+     isGitConnected={isGitConnected}
+     isConnectPermitted={isConnectPermitted}
+     // Autocommit state
      isAutocommitEnabled={isAutocommitEnabled}
      isAutocommitPolling={isAutocommitPolling}
-     isConnectPermitted={isConnectPermitted}
      isDiscardLoading={discardLoading}
      isFetchStatusLoading={fetchStatusLoading}
-     isGitConnected={isGitConnected}
app/client/src/git/sagas/disconnectSaga.ts (3)

30-31: Remove or document commented code blocks

The code contains two commented blocks marked with "!case: why?". These should either be removed if they're no longer needed or documented if they're being kept for future reference.

Also applies to: 41-49


25-28: Consider extracting URL manipulation logic

The URL manipulation logic could be moved to a utility function for better reusability and testing.

+ // In urlUtils.ts
+ export const removeBranchQueryParam = (url: URL): string => {
+   url.searchParams.delete(GIT_BRANCH_QUERY_KEY);
+   return url.toString().slice(url.origin.length);
+ };

- const url = new URL(window.location.href);
- url.searchParams.delete(GIT_BRANCH_QUERY_KEY);
- history.push(url.toString().slice(url.origin.length));
+ const url = new URL(window.location.href);
+ history.push(removeBranchQueryParam(url));

52-54: Use optional chaining for response error access

Consider using optional chaining to simplify the error check.

- if (response && response.responseMeta.error) {
-   const { error } = response.responseMeta;
+ if (response?.responseMeta?.error) {
+   const { error } = response.responseMeta;
🧰 Tools
🪛 Biome (1.9.4)

[error] 52-52: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

app/client/src/git/hooks/useBranches.ts (1)

19-22: Consider memoizing selectors with createSelector

The branch selectors could benefit from memoization using createSelector from Redux toolkit to prevent unnecessary recomputations.

// Example implementation
import { createSelector } from '@reduxjs/toolkit';

export const selectBranchesMemoized = createSelector(
  [selectBranches, (_, artifactDef) => artifactDef],
  (branches, artifactDef) => branches(artifactDef)
);
app/client/src/git/hooks/useConnect.ts (2)

36-41: Add type definition for gitImport parameters

The params parameter in the gitImport function lacks type definition.

-  const gitImport = useCallback(
-    (params) => {
+  const gitImport = useCallback(
+    (params: Record<string, unknown>) => {

59-70: Consider extracting default value from function parameters

The default parameter in the function definition could be moved to the destructuring for better readability.

-  const generateSSHKey = useCallback(
-    (keyType: string, isImport: boolean = false) => {
+  const generateSSHKey = useCallback(
+    (keyType: string, isImport?: boolean) => {
+      const shouldImport = isImport ?? false;
       dispatch(
         gitArtifactActions.generateSSHKeyInit({
           ...artifactDef,
           keyType,
-          isImport,
+          isImport: shouldImport,
         }),
       );
     },
     [artifactDef, dispatch],
   );
app/client/src/git/components/SettingsModal/SettingsModalView.tsx (2)

26-34: Consider using theme variables for measurements

Hard-coded pixel values in styled components make it harder to maintain consistent spacing across the application.

const StyledModalContent = styled(ModalContent)`
  &&& {
-    width: 600px;
+    width: ${({ theme }) => theme.sizes.modal.width.medium};
     transform: none !important;
-    top: 100px;
-    left: calc(50% - 300px);
+    top: ${({ theme }) => theme.spaces[11]}px;
+    left: 50%;
+    transform: translateX(-50%) !important;
-    max-height: calc(100vh - 200px);
+    max-height: calc(100vh - ${({ theme }) => theme.spaces[12]}px);
  }
`;

72-89: Add aria-label to TabsList for better accessibility

The TabsList component should have an aria-label for screen readers.

-          <TabsList>
+          <TabsList aria-label="Git Settings Tabs">
app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx (3)

46-48: Move documentation URL to constants file

The CONNECTING_TO_GIT_DOCS_URL should be moved to a constants file for better maintainability.

Consider moving this URL to a dedicated constants file for documentation URLs.


71-72: Remove TODO comment and implement feature flag

The comment indicates pending feature flag implementation. This should be tracked properly.

Would you like me to create a GitHub issue to track the implementation of feature flags for these messages?


Line range hint 72-80: Consider extracting error message component

The error message block could be extracted into a separate component for reusability.

+const RepoNotEmptyError = () => (
+  <ErrorCallout kind="error">
+    <Text kind="heading-xs" renderAs="h3">
+      {createMessage(ERROR_REPO_NOT_EMPTY_TITLE)}
+    </Text>
+    <Text renderAs="p">
+      {createMessage(ERROR_REPO_NOT_EMPTY_MESSAGE)}
+    </Text>
+  </ErrorCallout>
+);

// In the main component
{connectError?.code === "AE-GIT-4033" && <RepoNotEmptyError />}
app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx (2)

37-38: Consider adding meaningful error messages in test data

The error message is currently empty which makes the test less realistic. Consider adding a meaningful message that matches production scenarios.

 const errorData = {
-      message: "",
+      message: "Repository is not empty",
       code: "AE-GIT-4033",
 };

54-55: Add meaningful error message for non-matching error code test

Similar to the previous comment, add a realistic error message for better test coverage.

 const errorData = {
-      message: "",
+      message: "Generic error occurred",
       code: "SOME_OTHER_ERROR",
 };
app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx (2)

88-91: Enhance analytics event data structure

The analytics event data could be more structured. Consider using a typed interface for the event data.

+interface RepoNameAnalyticsData {
+  value: string;
+  expecting: string | null;
+}
+
 AnalyticsUtil.logEvent("GS_MATCHING_REPO_NAME_ON_GIT_DISCONNECT_MODAL", {
   value: "value" in event.target ? event.target.value : "",
   expecting: disconnectArtifactName,
-});
+} as RepoNameAnalyticsData);

74-75: Consider extracting button disable logic to a memoized value

The disable logic could be memoized using useMemo to prevent unnecessary recalculations.

+const shouldDisableRevokeButton = useMemo(
+  () => artifactName !== disconnectArtifactName || isDisconnectLoading,
+  [artifactName, disconnectArtifactName, isDisconnectLoading]
+);
-const shouldDisableRevokeButton =
-  artifactName !== disconnectArtifactName || isDisconnectLoading;
app/client/src/git/components/DangerZone/DangerZoneView.tsx (2)

88-96: Extract autocommit toggle logic to a reducer

The toggle logic could be simplified using a reducer pattern to make it more maintainable.

+const handleAutocommitToggle = (isEnabled: boolean) => {
+  if (isEnabled) {
+    return {
+      settingsModal: false,
+      disableModal: true,
+      logEvent: false,
+    };
+  }
+  return {
+    settingsModal: true,
+    disableModal: false,
+    logEvent: true,
+  };
+};

 const handleToggleAutocommit = useCallback(() => {
-  if (isAutocommitEnabled) {
-    toggleSettingsModal(false);
-    toggleDisableAutocommitModal(true);
-  } else {
+  const action = handleAutocommitToggle(isAutocommitEnabled);
+  toggleSettingsModal(action.settingsModal);
+  toggleDisableAutocommitModal(action.disableModal);
+  if (action.logEvent) {
     toggleAutocommit();
     AnalyticsUtil.logEvent("GS_AUTO_COMMIT_ENABLED");
   }
 }, [/*...*/]);

103-105: Consider using object destructuring for visibility flags

The visibility logic could be more concise using object destructuring.

-const showAutoCommit = isManageAutocommitPermitted;
-const showDisconnect = isConnectPermitted;
-const showDivider = showAutoCommit && showDisconnect;
+const visibility = {
+  autoCommit: isManageAutocommitPermitted,
+  disconnect: isConnectPermitted,
+  divider: isManageAutocommitPermitted && isConnectPermitted,
+};
app/client/src/git/components/ConnectModal/ConnectSuccess/index.tsx (3)

39-52: Consider memoizing the ConnectionSuccessTitle component.

Since this is a pure presentational component, wrapping it with React.memo could prevent unnecessary re-renders.

-function ConnectionSuccessTitle() {
+const ConnectionSuccessTitle = React.memo(function ConnectionSuccessTitle() {
   return (
     <div className="flex items-center mb-4">
       <Icon className="mr-1" color="#059669" name="oval-check" size="lg" />
       <TitleText
         data-testid="t--git-success-modal-title"
         kind="heading-s"
         renderAs="h3"
       >
         {createMessage(GIT_CONNECT_SUCCESS_TITLE)}
       </TitleText>
     </div>
   );
-}
+});

54-113: Add null checks and improve type safety.

The component handles null values with the || operator, but TypeScript's strictNullChecks would provide better type safety.

-  repoName: string | null;
-  defaultBranch: string | null;
+  repoName: string;
+  defaultBranch: string;
+  fallbackText?: string;

Then update the usage:

-  <Text renderAs="p">{repoName || "-"}</Text>
+  <Text renderAs="p">{repoName || fallbackText || "-"}</Text>

133-146: Consider centralizing analytics events.

The analytics events are scattered in the component. Consider extracting them to a dedicated analytics hook or utility.

const useGitAnalytics = (remoteUrl: string | null) => {
  return {
    logStartUsingGit: () => AnalyticsUtil.logEvent("GS_START_USING_GIT", { repoUrl: remoteUrl }),
    logOpenSettings: () => AnalyticsUtil.logEvent("GS_OPEN_GIT_SETTINGS", { repoUrl: remoteUrl })
  };
};
app/client/src/git/components/DisconnectModal/DisconnectModalView.test.tsx (1)

11-19: Add test cases for edge scenarios.

Consider adding tests for:

  • Empty artifact name
  • Special characters in artifact name
  • Very long artifact names
app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx (1)

67-67: Remove unused mobile detection.

The mobile detection logic has been commented out but the related code structure remains. Clean this up if mobile detection is no longer needed.

Also applies to: 69-69

app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx (2)

160-169: Simplify error handling test setup

The current implementation creates unnecessary complexity with inline error object creation and rerender.

Consider refactoring to:

-  const mockConnect = jest.fn(() => {
-    const connectError = {
-      code: "AE-GIT-4033",
-      message: "",
-    };
-    rerender(
-      <ConnectInitialize {...defaultProps} connectError={connectError} />,
-    );
-  });
+  const connectError = { code: "AE-GIT-4033", message: "" };
+  const mockConnect = jest.fn(() => {
+    rerender(<ConnectInitialize {...defaultProps} connectError={connectError} />);
+  });

Line range hint 216-223: Add assertion for loading indicator presence

The test should verify both the presence of the loading message and the loading indicator.

Add assertion for loading indicator:

  render(<ConnectInitialize {...defaultProps} isConnectLoading />);
  expect(
    screen.getByText("Please wait while we connect to Git..."),
  ).toBeInTheDocument();
+ expect(screen.getByRole("progressbar")).toBeInTheDocument();
  expect(
    screen.queryByTestId("t--git-connect-next-button"),
  ).not.toBeInTheDocument();
app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx (1)

Line range hint 96-124: Centralize error codes and improve error test coverage

The error codes should be centralized as constants, and null error state should be tested.

Consider refactoring to:

+ const ERROR_CODES = {
+   SSH_KEY_MISCONFIGURATION: "AE-GIT-4032",
+   GENERIC_ERROR: "GENERIC-ERROR",
+ };

- const connectError = {
-   code: "GENERIC-ERROR",
+ const connectError = {
+   code: ERROR_CODES.GENERIC_ERROR,
    errorType: "Some Error",
    message: "Something went wrong",
  };

+ it("renders without error message when error is null", () => {
+   render(<AddDeployKey {...defaultProps} connectError={null} />);
+   expect(screen.queryByText("Some Error")).not.toBeInTheDocument();
+ });
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2916b2 and 34f7a00.

📒 Files selected for processing (82)
  • app/client/src/ee/git/components/ContinuousDelivery/ContinuousDeliveryEE.tsx (1 hunks)
  • app/client/src/ee/git/components/DefaultBranch/DefaultBranchEE.tsx (1 hunks)
  • app/client/src/ee/git/components/GitModals/GitModalsEE.tsx (1 hunks)
  • app/client/src/ee/git/hooks/useDefaultBranch.ts (1 hunks)
  • app/client/src/ee/git/sagas/index.ts (1 hunks)
  • app/client/src/ee/git/store/actions/index.ts (1 hunks)
  • app/client/src/ee/git/store/helpers/gitSingleArtifactInitialState.ts (1 hunks)
  • app/client/src/ee/git/store/types.ts (1 hunks)
  • app/client/src/git/components/ConflictError/index.tsx (1 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx (7 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx (8 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx (5 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx (4 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx (3 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx (7 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx (1 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/types.ts (1 hunks)
  • app/client/src/git/components/ConnectModal/ConnectModalView.tsx (1 hunks)
  • app/client/src/git/components/ConnectModal/ConnectSuccess/index.tsx (1 hunks)
  • app/client/src/git/components/ConnectModal/index.tsx (1 hunks)
  • app/client/src/git/components/ContinuousDelivery/ContinuousDeliveryCE.tsx (1 hunks)
  • app/client/src/git/components/ContinuousDelivery/index.tsx (1 hunks)
  • app/client/src/git/components/DangerZone/DangerZoneView.tsx (1 hunks)
  • app/client/src/git/components/DangerZone/index.tsx (1 hunks)
  • app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx (1 hunks)
  • app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx (1 hunks)
  • app/client/src/git/components/DefaultBranch/index.tsx (1 hunks)
  • app/client/src/git/components/DisableAutocommitModal/DisableAutocommitModalView.tsx (1 hunks)
  • app/client/src/git/components/DisableAutocommitModal/index.tsx (1 hunks)
  • app/client/src/git/components/DisconnectModal/DisconnectModalView.test.tsx (8 hunks)
  • app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx (1 hunks)
  • app/client/src/git/components/DisconnectModal/index.tsx (1 hunks)
  • app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts (0 hunks)
  • app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts (2 hunks)
  • app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts (0 hunks)
  • app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts (0 hunks)
  • app/client/src/git/components/GitContextProvider/index.tsx (1 hunks)
  • app/client/src/git/components/GitModals.tsx (0 hunks)
  • app/client/src/git/components/GitModals/GitModalsCE.tsx (1 hunks)
  • app/client/src/git/components/GitModals/index.tsx (1 hunks)
  • app/client/src/git/components/ImportModal/index.tsx (1 hunks)
  • app/client/src/git/components/LocalProfile/LocalProfileView.tsx (1 hunks)
  • app/client/src/git/components/LocalProfile/index.tsx (1 hunks)
  • app/client/src/git/components/OpsModal/TabDeploy/index.tsx (2 hunks)
  • app/client/src/git/components/OpsModal/TabMerge/index.tsx (1 hunks)
  • app/client/src/git/components/OpsModal/index.tsx (1 hunks)
  • app/client/src/git/components/ProtectedBranches/ProtectedBranchesView.tsx (1 hunks)
  • app/client/src/git/components/ProtectedBranches/index.tsx (1 hunks)
  • app/client/src/git/components/QuickActions/index.tsx (2 hunks)
  • app/client/src/git/components/SettingsModal/SettingsModalView.tsx (1 hunks)
  • app/client/src/git/components/SettingsModal/TabBranch/index.tsx (1 hunks)
  • app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx (1 hunks)
  • app/client/src/git/components/SettingsModal/TabGeneral/index.tsx (1 hunks)
  • app/client/src/git/components/SettingsModal/index.tsx (1 hunks)
  • app/client/src/git/components/index.tsx (1 hunks)
  • app/client/src/git/constants/enums.ts (2 hunks)
  • app/client/src/git/constants/misc.ts (1 hunks)
  • app/client/src/git/hooks/useAppsmithEnterpriseUrl.ts (1 hunks)
  • app/client/src/git/hooks/useAutocommit.ts (1 hunks)
  • app/client/src/git/hooks/useBranches.ts (2 hunks)
  • app/client/src/git/hooks/useConnect.ts (1 hunks)
  • app/client/src/git/hooks/useDefaultBranch.ts (1 hunks)
  • app/client/src/git/hooks/useDisconnect.ts (1 hunks)
  • app/client/src/git/hooks/useGitFeatureFlags.ts (1 hunks)
  • app/client/src/git/hooks/useGitPermissions.ts (1 hunks)
  • app/client/src/git/hooks/useGlobalProfile.ts (1 hunks)
  • app/client/src/git/hooks/useLocalProfile.ts (1 hunks)
  • app/client/src/git/hooks/useMetadata.ts (1 hunks)
  • app/client/src/git/hooks/useProtectedBranches.ts (1 hunks)
  • app/client/src/git/hooks/useSettings.ts (1 hunks)
  • app/client/src/git/requests/disconnectRequest.types.ts (1 hunks)
  • app/client/src/git/requests/fetchMetadataRequest.ts (1 hunks)
  • app/client/src/git/requests/fetchMetadataRequest.types.ts (2 hunks)
  • app/client/src/git/requests/fetchSSHKeyRequest.types.ts (1 hunks)
  • app/client/src/git/requests/generateSSHKeyRequest.ts (1 hunks)
  • app/client/src/git/requests/generateSSHKeyRequest.types.ts (1 hunks)
  • app/client/src/git/requests/gitImportRequest.ts (1 hunks)
  • app/client/src/git/requests/gitImportRequest.types.ts (3 hunks)
  • app/client/src/git/requests/toggleAutocommitRequest.types.ts (1 hunks)
  • app/client/src/git/requests/updateProtectedBranchesRequest.types.ts (1 hunks)
  • app/client/src/git/sagas/connectSaga.ts (2 hunks)
  • app/client/src/git/sagas/disconnectSaga.ts (1 hunks)
⛔ Files not processed due to max files limit (22)
  • app/client/src/git/sagas/fetchMetadataSaga.ts
  • app/client/src/git/sagas/fetchSSHKeySaga.ts
  • app/client/src/git/sagas/generateSSHKeySaga.ts
  • app/client/src/git/sagas/index.ts
  • app/client/src/git/sagas/initGitSaga.ts
  • app/client/src/git/sagas/toggleAutocommitSaga.ts
  • app/client/src/git/sagas/triggerAutocommitSaga.ts
  • app/client/src/git/sagas/updateProtectedBranchesSaga.ts
  • app/client/src/git/store/actions/fetchMetadataActions.ts
  • app/client/src/git/store/actions/fetchSSHKeyActions.ts
  • app/client/src/git/store/actions/generateSSHKey.ts
  • app/client/src/git/store/actions/generateSSHKeyActions.ts
  • app/client/src/git/store/actions/gitImportActions.ts
  • app/client/src/git/store/actions/initGitActions.ts
  • app/client/src/git/store/actions/uiActions.ts
  • app/client/src/git/store/actions/updateGlobalProfileActions.ts
  • app/client/src/git/store/actions/updateProtectedBranchesActions.ts
  • app/client/src/git/store/gitArtifactSlice.ts
  • app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts
  • app/client/src/git/store/selectors/gitConfigSelectors.ts
  • app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts
  • app/client/src/git/store/types.ts
💤 Files with no reviewable changes (4)
  • app/client/src/git/components/GitModals.tsx
  • app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts
  • app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts
  • app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts
✅ Files skipped from review due to trivial changes (6)
  • app/client/src/git/constants/misc.ts
  • app/client/src/ee/git/hooks/useDefaultBranch.ts
  • app/client/src/ee/git/components/DefaultBranch/DefaultBranchEE.tsx
  • app/client/src/ee/git/store/actions/index.ts
  • app/client/src/ee/git/components/ContinuousDelivery/ContinuousDeliveryEE.tsx
  • app/client/src/ee/git/components/GitModals/GitModalsEE.tsx
🧰 Additional context used
📓 Learnings (3)
app/client/src/git/requests/generateSSHKeyRequest.types.ts (1)
Learnt from: brayn003
PR: appsmithorg/appsmith#37984
File: app/client/src/git/requests/generateSSHKeyRequest.types.ts:6-11
Timestamp: 2024-12-05T11:02:42.148Z
Learning: In the `GenerateSSHKeyResponse` interface in `app/client/src/git/requests/generateSSHKeyRequest.types.ts`, both `isRegeneratedKey` and `regeneratedKey` are intentionally included and serve the same concept.
app/client/src/git/components/ProtectedBranches/index.tsx (1)
Learnt from: brayn003
PR: appsmithorg/appsmith#38155
File: app/client/src/git/components/ProtectedBranches/index.tsx:18-27
Timestamp: 2024-12-13T22:08:46.336Z
Learning: The `ProtectedBranchesView` component in `app/client/src/git/components/ProtectedBranches/ProtectedBranchesView.tsx` already has a TypeScript interface for its props.
app/client/src/git/components/ProtectedBranches/ProtectedBranchesView.tsx (1)
Learnt from: brayn003
PR: appsmithorg/appsmith#38155
File: app/client/src/git/components/ProtectedBranches/index.tsx:18-27
Timestamp: 2024-12-13T22:08:46.336Z
Learning: The `ProtectedBranchesView` component in `app/client/src/git/components/ProtectedBranches/ProtectedBranchesView.tsx` already has a TypeScript interface for its props.
🪛 Biome (1.9.4)
app/client/src/git/sagas/disconnectSaga.ts

[error] 52-52: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx

[error] 193-193: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

app/client/src/ee/git/store/types.ts

[error] 1-1: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 3-3: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

🔇 Additional comments (45)
app/client/src/git/requests/fetchMetadataRequest.types.ts (1)

19-19: LGTM!

The type correctly extends ApiResponse with the appropriate data interface.

app/client/src/git/components/DisableAutocommitModal/DisableAutocommitModalView.tsx (2)

29-34: LGTM! Well-defined interface with clear prop types

The interface is properly typed with optional props that match the component's implementation.


1-5: Verify enterprise edition imports availability

Ensure these enterprise edition imports are available in both community and enterprise editions to prevent runtime issues.

✅ Verification successful

Import path is correct and constants are available

The constants are properly defined in the community edition (ce/constants/messages.ts) and re-exported through the enterprise edition (ee/constants/messages.ts). This ensures availability in both editions, making the imports safe to use.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if these constants exist in community edition
rg -g '!node_modules' -g '!dist' "AUTOCOMMIT_CONFIRM_DISABLE_MESSAGE|AUTOCOMMIT_DISABLE" ./app/client/src/constants/

Length of output: 118


Script:

#!/bin/bash
# Let's check for these constants in the enterprise edition directory
rg -g '!node_modules' -g '!dist' "AUTOCOMMIT_CONFIRM_DISABLE_MESSAGE|AUTOCOMMIT_DISABLE" ./app/client/src/ee/

# Also check if the ee/constants/messages file exists and its content
fd "messages.ts" ./app/client/src/ee/constants/

Length of output: 201


Script:

#!/bin/bash
# Let's check the content of the messages.ts file
cat ./app/client/src/ee/constants/messages.ts

Length of output: 86


Script:

#!/bin/bash
# Check for these constants in the community edition (ce) directory
rg -g '!node_modules' -g '!dist' "AUTOCOMMIT_CONFIRM_DISABLE_MESSAGE|AUTOCOMMIT_DISABLE" ./app/client/src/ce/constants/messages.ts

Length of output: 300

app/client/src/git/requests/gitImportRequest.ts (1)

4-12: LGTM! Verify all import references are updated.

The renaming follows a consistent pattern and maintains the same functionality.

Let's verify all references to this function have been updated:

✅ Verification successful

Function renaming is complete and consistent

The codebase shows the new gitImportRequest function is properly referenced in all relevant files, and no occurrences of the old name importGitRequest remain. The types are also correctly imported in the components that use them.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to the old function name
rg "importGitRequest" --type ts

Length of output: 31


Script:

#!/bin/bash
# Search for any references to the new function name to verify it's being used
rg "gitImportRequest" --type ts -A 2

# Search for files that might be importing from gitImportRequest
fd "\.ts$" --exec grep -l "gitImportRequest"

Length of output: 3793

app/client/src/git/requests/gitImportRequest.types.ts (2)

1-1: LGTM! Good practice using ApiResponse type.

The addition of ApiResponse type ensures consistent error handling across API responses.


Line range hint 3-11: LGTM! Well-structured interface.

The GitImportRequestParams interface is clean and properly typed with optional properties.

app/client/src/ee/git/store/helpers/gitSingleArtifactInitialState.ts (1)

1-4: LGTM! Clean type imports.

The type imports are well-organized and follow TypeScript best practices.

app/client/src/ee/git/store/types.ts (1)

1-3: Consider future extensibility of these interfaces.

While currently empty, if these interfaces are intended for future properties, please consider:

  1. Adding TODO comments explaining the planned structure
  2. Using type aliases (type) instead of interfaces if no extension is planned
✅ Verification successful

Empty interfaces serve as extension points in the Redux state hierarchy

These empty interfaces are correctly implemented as they are extended by concrete implementations in the non-EE codebase, serving as extension points for the Enterprise Edition state structure. The interfaces are:

  • Extended in app/client/src/git/store/types.ts
  • Used to initialize empty states in app/client/src/ee/git/store/helpers/gitSingleArtifactInitialState.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if these interfaces are extended or implemented elsewhere
ast-grep --pattern 'interface $_ extends GitSingleArtifactAPIResponsesReduxStateEE'
ast-grep --pattern 'interface $_ extends GitSingleArtifactUIReduxStateEE'

Length of output: 161


Script:

#!/bin/bash
# Search for any usage or references to these interfaces
rg "GitSingleArtifactAPIResponsesReduxStateEE|GitSingleArtifactUIReduxStateEE" -A 2

# Check if there are any similar interface patterns in the codebase
ast-grep --pattern 'interface GitSingle$_ReduxState$_ {
  $$$
}'

# Look for any TODO comments related to these interfaces
rg -i "todo.*GitSingleArtifact.*ReduxState"

Length of output: 2146

🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 3-3: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx (2)

153-153: LGTM!

The export statement follows the standard convention.


1-15: Verify enterprise edition imports for circular dependencies

The imports from the enterprise edition (ee/) could potentially create circular dependencies in the community edition.

app/client/src/git/components/DisconnectModal/index.tsx (1)

1-25: Looks good to me!

app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx (1)

1-302: Well-structured ConnectInitialize component

The implementation is clean and follows best practices with appropriate use of hooks and state management.

app/client/src/git/components/index.tsx (1)

2-2: Exporting GitImportModal

The addition of GitImportModal to the exports is appropriate.

app/client/src/git/components/ImportModal/index.tsx (1)

1-8: Addition of ImportModal component is correct

The ImportModal component correctly encapsulates ConnectModal with the isImport prop set to true.

app/client/src/git/requests/toggleAutocommitRequest.types.ts (1)

1-6: LGTM! Clean type definitions for toggle autocommit response.

The implementation properly wraps the boolean response in the ApiResponse type, maintaining consistency with the API response structure.

app/client/src/git/requests/fetchSSHKeyRequest.types.ts (1)

10-10: LGTM! Well-structured response type

Good use of the ApiResponse generic type for consistent API response handling.

app/client/src/git/requests/updateProtectedBranchesRequest.types.ts (1)

7-10: LGTM! Clean type definitions

Good use of type aliases and ApiResponse wrapper for consistency with other API responses.

app/client/src/git/requests/generateSSHKeyRequest.types.ts (1)

14-15: LGTM! Clean API response type structure.

Good use of type composition with ApiResponse generic type.

app/client/src/git/components/ConflictError/index.tsx (1)

4-4: Verify useMetadata hook implementation and data flow

The switch from useGitContext to useMetadata looks good, but let's ensure the hook is properly implemented.

Also applies to: 7-8, 12-12

✅ Verification successful

Let me search for the hook implementation with a different pattern and locate the file containing it. The previous pattern might have been too strict as hooks can be defined in various ways (function declaration, arrow function, const declaration).


Hook implementation is correct and properly used

The useMetadata hook is well-implemented, providing metadata state, loading status, and error handling through Redux selectors. The switch from useGitContext to useMetadata in ConflictError is appropriate as the hook itself uses useGitContext internally and adds a layer of abstraction for metadata-specific state management.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the useMetadata hook implementation
ast-grep --pattern 'export $_ function useMetadata() {
  $$$
}'

Length of output: 65


Script:

#!/bin/bash
# Search for useMetadata hook implementation with a more flexible pattern
ast-grep --pattern 'useMetadata = () => {
  $$$
}'

# Also try finding the file containing useMetadata
fd useMetadata

Length of output: 109


Script:

#!/bin/bash
# Let's examine the content of the useMetadata hook
cat app/client/src/git/hooks/useMetadata.ts

# Also check where this hook is being used
rg "useMetadata" -l

Length of output: 1201

app/client/src/git/components/DefaultBranch/index.tsx (1)

1-16: Well-structured feature flag implementation

Clean implementation of the feature flag pattern with proper separation of CE/EE concerns.

✅ Verification successful

Both CE and EE components exist as expected

The verification confirms that both DefaultBranchCE and DefaultBranchEE components are present at their expected locations in the codebase, validating the import paths and component structure.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence of both CE and EE components
fd "DefaultBranch(CE|EE)\.tsx$"

Length of output: 164

app/client/src/git/components/ContinuousDelivery/index.tsx (1)

6-14: Clean feature flag implementation

The component follows the established pattern for feature flag based rendering.

✅ Verification successful

Feature flag implementation verified

Both CE and EE components exist at the expected locations, confirming proper implementation of the feature flag based rendering pattern.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence of both CE and EE components
fd "ContinuousDelivery(CE|EE)\.tsx$"

Length of output: 189

app/client/src/git/requests/generateSSHKeyRequest.ts (1)

17-17: ⚠️ Potential issue

Add error handling and type safety

The request needs proper error handling and type validation.

Consider these improvements:

  1. Add error handling:
try {
  return params.isImport ? Api.get(url) : Api.post(url);
} catch (error) {
  // Log error for monitoring
  console.error('SSH key generation failed:', error);
  throw error;
}
  1. Add type validation for keyType:
enum SSHKeyType {
  RSA = 'RSA',
  ED25519 = 'ED25519'
}

if (!Object.values(SSHKeyType).includes(params.keyType)) {
  throw new Error(`Invalid key type: ${params.keyType}`);
}
⛔ Skipped due to learnings
Learnt from: brayn003
PR: appsmithorg/appsmith#37984
File: app/client/src/git/requests/generateSSHKeyRequest.ts:9-18
Timestamp: 2024-12-05T11:06:06.127Z
Learning: In the TypeScript file `app/client/src/git/requests/generateSSHKeyRequest.ts`, the function `generateSSHKeyRequest` does not require error handling and input validation.
app/client/src/git/hooks/useDefaultBranch.ts (1)

7-20: LGTM! Clean hook implementation

The hook follows React conventions and properly combines enterprise and community edition functionality.

app/client/src/git/components/SettingsModal/TabGeneral/index.tsx (1)

15-27: LGTM! Clean component implementation

The component has clear responsibilities and proper permission handling.

app/client/src/git/components/DisableAutocommitModal/index.tsx (1)

5-21: LGTM! Clean container component

Good separation of concerns between container and view components.

app/client/src/git/components/GitContextProvider/index.tsx (1)

3-4: Clean type organization

Good separation of type imports for better maintainability.

app/client/src/git/components/OpsModal/index.tsx (2)

8-14: Clean migration to hooks pattern

Good separation of concerns using dedicated hooks instead of direct context usage.


Line range hint 17-24: Verify hook dependencies

Props passing looks clean, but let's verify the hook dependencies are properly set up.

✅ Verification successful

Let me try a different approach to find hook-related code in the repository. The previous command failed because the file type wasn't properly specified. The new commands will search for both hook usage and definitions in TypeScript/JavaScript files, including React components.


Let me try a different approach by searching for these hooks and the component without file type restrictions, as the previous commands had issues with file type recognition.


Hook dependencies are properly configured

The hooks useProtectedBranches and useMetadata are correctly imported and used in the OpsModal component. Their dependencies flow properly:

  • useProtectedBranches provides isProtectedMode
  • useMetadata provides metadata which is used for repoName
  • Both values are correctly passed to OpsModalView

The implementation shows consistent usage across the codebase with proper dependency management.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if hooks are imported and used consistently across the codebase
rg -A 2 "useProtectedBranches|useMetadata" --type typescript

Length of output: 97


Script:

#!/bin/bash
# Search for hook usage patterns in TypeScript and JavaScript files
rg -A 2 "useProtectedBranches|useMetadata" --type ts --type tsx --type js --type jsx

# Search for hook definitions
ast-grep --pattern 'const $_ = use$_($$$)'

Length of output: 159


Script:

#!/bin/bash
# Let's try with simpler ripgrep patterns
rg "useProtectedBranches" -A 3
rg "useMetadata" -A 3

# Also search for the OpsModalView component to understand its dependencies
rg "OpsModalView" -A 5

Length of output: 10508

app/client/src/git/constants/enums.ts (2)

27-27: LGTM: ContinuousDelivery enum addition

The new enum value follows the established naming convention.


48-48: Verify error code usage across the codebase

Let's ensure the new error code is properly handled in all relevant components.

✅ Verification successful

Error code AE-GIT-4033 is properly handled across the codebase

The error code is consistently used in:

  • Error handling conditions in multiple components
  • Associated with proper error messages (ERROR_REPO_NOT_EMPTY_TITLE, ERROR_REPO_NOT_EMPTY_MESSAGE)
  • Covered by unit tests in ConnectInitialize components
  • Properly defined in GitErrorCodes enum
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of the new error code
rg "AE-GIT-4033|REPO_NOT_EMPTY" --type ts

Length of output: 2790

app/client/src/git/components/ProtectedBranches/index.tsx (1)

1-30: LGTM! Well-structured component with good hook organization.

The component follows container pattern effectively and properly separates Git functionality using custom hooks.

app/client/src/git/components/OpsModal/TabMerge/index.tsx (1)

4-5: LGTM! Good migration to dedicated hooks.

The shift from useGitContext to specific hooks improves modularity and maintainability.

app/client/src/git/components/DangerZone/index.tsx (1)

9-36: Clean implementation with good separation of concerns

The component effectively uses custom hooks and follows the container/view pattern. Props are properly passed down to the view component.

app/client/src/git/components/OpsModal/TabDeploy/index.tsx (2)

24-25: LGTM: Clean migration to custom hooks

The migration to useMetadata and useBranches hooks improves code organization and reusability.


31-31: Verify TabDeployView handles null remoteUrl

The default value for remoteUrl has changed from empty string to null. Ensure TabDeployView properly handles this case.

✅ Verification successful

TabDeployView properly handles null remoteUrl

The change from empty string to null is safe. TabDeployView:

  • Explicitly types remoteUrl as string | null
  • Uses null as default value in props
  • Safely handles null in logic with remoteUrl && lastDeployedAt check
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for remoteUrl usage in TabDeployView
ast-grep --pattern 'remoteUrl={$_}' app/client/src/git/components/OpsModal/TabDeploy/TabDeployView.tsx

Length of output: 104


Script:

#!/bin/bash
# First, verify if the file exists
fd TabDeployView.tsx

# If it exists, let's check its content for remoteUrl usage
rg "remoteUrl" -A 3 -B 3 app/client/src/git/components/OpsModal/TabDeploy/

Length of output: 3501

app/client/src/git/hooks/useLocalProfile.ts (1)

21-23: LGTM: Proper usage of useCallback

The memoization of the fetch function with appropriate dependencies is well implemented.

app/client/src/git/hooks/useGitPermissions.ts (1)

11-13: LGTM: Clean destructuring of context

Good use of object destructuring for context values.

app/client/src/git/hooks/useDisconnect.ts (1)

12-54: LGTM! Well-structured hook implementation.

The hook follows React best practices with proper memoization and clear separation of concerns.

app/client/src/git/hooks/useAutocommit.ts (1)

13-58: LGTM! Consistent hook implementation.

The hook maintains consistency with useDisconnect pattern and properly handles state management.

app/client/src/git/components/QuickActions/index.tsx (1)

5-10: LGTM! Clean hook organization.

Good separation of concerns by splitting functionality into specific hooks.

app/client/src/git/components/ConnectModal/ConnectSuccess/index.tsx (1)

1-37: LGTM! Clean imports and styled components.

app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx (1)

15-20: LGTM: Clean mock implementation for Modal component

The mock implementation correctly preserves the component's children while simplifying the rendering logic.

app/client/src/git/sagas/connectSaga.ts (3)

56-62: LGTM: Git editor initialization after successful connection

The initialization of Git editor after successful connection is a logical addition. It ensures the editor has access to the connected repository data.


77-77: LGTM: Cleaner error handling

The simplified error dispatch maintains the same functionality while improving code readability.


58-61: Verify the handling of initGitForEditor action

Let's ensure the new action is properly handled in the reducer and the editor initialization logic exists.

✅ Verification successful

Action is properly integrated in the codebase

The verification shows that:

  • The action is properly defined in gitArtifactSlice.ts
  • A dedicated saga initGitForEditorSaga exists and is correctly mapped in the saga index
  • The action creator is implemented in initGitActions.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for the action handler in reducers and related files
ast-grep --pattern 'case gitArtifactActions.initGitForEditor.type:' 

# Search for any related editor initialization logic
rg -A 5 'initGitForEditor'

Length of output: 3348

app/client/src/ee/git/sagas/index.ts Outdated Show resolved Hide resolved
app/client/src/git/requests/fetchMetadataRequest.ts Outdated Show resolved Hide resolved
app/client/src/git/hooks/useProtectedBranches.ts Outdated Show resolved Hide resolved
app/client/src/git/hooks/useGitPermissions.ts Outdated Show resolved Hide resolved
app/client/src/git/components/QuickActions/index.tsx Outdated Show resolved Hide resolved
@brayn003 brayn003 changed the title chore: adding logic to connect modal chore: connect modal and branches Dec 15, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

🔭 Outside diff range comments (2)
app/client/src/git/components/QuickActions/QuickActionsView.test.tsx (1)

Line range hint 24-44: Add test cases for new branch-related props.

The new props currentBranch, isBranchPopupOpen, isTriggerAutocommitLoading, and toggleBranchPopup are added to defaultProps but lack corresponding test cases. This creates a gap in test coverage.

Add test cases to verify:

  1. Branch button displays the current branch name
  2. Branch popup opens/closes when toggleBranchPopup is called
  3. Loading state is shown when isTriggerAutocommitLoading is true

Example test case:

it("should display current branch name on branch button", () => {
  const props = {
    ...defaultProps,
    isGitConnected: true,
    currentBranch: "feature/test-branch"
  };

  render(
    <ThemeProvider theme={theme}>
      <QuickActionsView {...props} />
    </ThemeProvider>
  );
  
  expect(screen.getByText("feature/test-branch")).toBeInTheDocument();
});
app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts (1)

Line range hint 9-15: Consider memoizing selectors for better performance.

Use createSelector from Redux toolkit to memoize complex selectors and prevent unnecessary recomputations.

+import { createSelector } from '@reduxjs/toolkit';

-export const selectGitArtifact = (
+export const selectGitArtifact = createSelector(
+  [(state: GitRootState) => state.git.artifacts, 
+   (_state: GitRootState, artifactDef: GitArtifactDef) => artifactDef],
+  (artifacts, artifactDef) => {
+    return artifacts[artifactDef.artifactType]?.[artifactDef.baseArtifactId];
+  }
);
♻️ Duplicate comments (1)
app/client/src/git/components/LocalProfile/LocalProfileView.tsx (1)

192-199: ⚠️ Potential issue

Fix profile value usage in onSubmit handler

The onSubmit handler still uses localProfile values when useGlobalProfile is true, which is incorrect based on past review comments.

const onSubmit: SubmitHandler<AuthorInfo> = (data) => {
-  if (data.useGlobalProfile && localProfile) {
-    data.authorName = localProfile.authorName;
-    data.authorEmail = localProfile.authorEmail;
+  if (data.useGlobalProfile && globalProfile) {
+    data.authorName = globalProfile.authorName;
+    data.authorEmail = globalProfile.authorEmail;
  }
  updateLocalProfile(data);
};
🧹 Nitpick comments (44)
app/client/src/git/components/OpsModal/TabMerge/index.tsx (2)

11-21: Consider consolidating loading states

The component tracks multiple loading states (isFetchMergeStatusLoading, isMergeLoading, isFetchStatusLoading, isFetchBranchesLoading). Consider consolidating these into a single loading state to simplify the UI handling.

+ const isLoading = 
+   isFetchMergeStatusLoading || 
+   isMergeLoading || 
+   isFetchStatusLoading || 
+   isFetchBranchesLoading;

Line range hint 26-41: Add TypeScript interface for component props

Consider adding a TypeScript interface for the TabMergeView props to improve type safety and documentation.

interface TabMergeViewProps {
  branches: Branch[];
  clearMergeStatus: () => void;
  currentBranch: string;
  fetchBranches: () => void;
  fetchMergeStatus: () => void;
  isFetchBranchesLoading: boolean;
  isFetchMergeStatusLoading: boolean;
  isFetchStatusLoading: boolean;
  isMergeLoading: boolean;
  isStatusClean: boolean;
  merge: (branch: string) => void;
  mergeError: Error | null;
  mergeStatus: MergeStatus;
  protectedBranches: string[];
}
app/client/src/git/components/GitContextProvider/index.tsx (2)

8-19: Consider strengthening type safety for artifactType.

The artifactType property could be more strictly typed by using the actual enum values instead of keyof typeof.

-  artifactType: keyof typeof GitArtifactType;
+  artifactType: GitArtifactType;

29-40: Add JSDoc documentation for better maintainability.

Consider adding JSDoc comments to document the purpose and usage of each prop.

+/**
+ * Props for the GitContextProvider component
+ * @property {GitArtifactType} artifactType - Type of the Git artifact
+ * @property {string} baseArtifactId - Base ID of the artifact
+ * @property {ApplicationPayload | null} artifact - The application artifact
+ * @property {boolean} isCreateArtifactPermitted - Permission flag for artifact creation
+ * @property {Function} setWorkspaceIdForImport - Callback to set workspace ID for import
+ * @property {Function} statusTransformer - Transforms Git status data
+ */
interface GitContextProviderProps {
app/client/src/git/hooks/useAutocommit.ts (3)

1-13: Consider adding explicit return type for selectors

The selector functions could benefit from explicit return type annotations for better type safety.

- selectAutocommitDisableModalOpen,
+ selectAutocommitDisableModalOpen: (state: GitRootState, artifactDef: ArtifactDef) => boolean,

34-44: Add explicit boolean type for open parameter

Enhance type safety by explicitly typing the open parameter.

- (open: boolean)
+ (open: boolean): void

54-64: Add TypeScript interface for hook return type

Define an explicit interface for better type safety and documentation.

interface UseAutocommitResult {
  isToggleAutocommitLoading: boolean;
  toggleAutocommitError: Error | null;
  toggleAutocommit: () => void;
  isTriggerAutocommitLoading: boolean;
  triggerAutocommitError: Error | null;
  isAutocommitDisableModalOpen: boolean;
  toggleAutocommitDisableModal: (open: boolean) => void;
  isAutocommitEnabled: boolean;
  isAutocommitPolling: boolean;
}
app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts (1)

2-4: LGTM! Good separation of Enterprise Edition state.

The separation of Enterprise Edition state into a dedicated module promotes better code organization and maintainability.

app/client/src/git/components/LocalProfile/LocalProfileView.tsx (3)

21-112: Consider memoizing styled components

The styled components are defined outside the component but could benefit from memoization since they use animations and complex styles.

+const MemoizedContainer = React.memo(styled.div`
-const Container = styled.div`
  padding-top: 8px;
  padding-bottom: 8px;
`);

123-137: Consider using readonly properties for immutable interfaces

Since these interfaces represent props and form data that shouldn't be mutated directly, consider making the properties readonly.

interface AuthorInfo {
-  authorName: string;
-  authorEmail: string;
-  useGlobalProfile: boolean;
+  readonly authorName: string;
+  readonly authorEmail: string;
+  readonly useGlobalProfile: boolean;
}

295-301: Improve email validation regex

The current email validation regex could be more robust. Consider using a more comprehensive pattern.

pattern: {
-  value: /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/,
+  value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
  message: createMessage(FORM_VALIDATION_INVALID_EMAIL),
},
app/client/src/git/components/QuickActions/BranchButton.tsx (2)

75-77: Consider simplifying by removing useMemo

Memoizing the content with useMemo may be unnecessary since <BranchList /> is unlikely to cause performance issues. Removing useMemo could simplify the code.


93-95: Optimize isEllipsisActive check

Calling isEllipsisActive(labelTarget.current) directly in the render may impact performance. Consider calculating this value once and storing it in a state or using a useEffect hook.

app/client/src/git/components/BranchList/BranchListView.tsx (1)

126-133: Disable onClick During Loading State

To prevent user interaction while a branch is being created, disable the onClick handler when isCreateBranchLoading is true.

Apply this diff to implement the change:

- onClick={onClick}
+ onClick={isCreateBranchLoading ? undefined : onClick}
app/client/src/git/components/BranchList/hooks/useHover.ts (1)

23-23: Improve return type specificity

Consider returning a tuple type for better type safety.

- return [hover];
+ return [hover] as const;
app/client/src/git/components/BranchList/hooks/useFilteredBranches.ts (1)

8-9: Move search text transformation inside useEffect

The lowercase transformation should be inside useEffect to avoid unnecessary computation on every render.

- const lowercaseSearchText = searchText.toLowerCase();
  const [filteredBranches, setFilteredBranches] = useState<Array<string>>([]);

  useEffect(
    function setFilteredBranchesEffect() {
+     const lowercaseSearchText = searchText.toLowerCase();
app/client/src/git/components/BranchList/BranchListItemContainer.tsx (1)

3-7: Consider adding prop types interface

The implementation looks good, but for better type safety and documentation, consider extracting the props into a separate interface.

+interface BranchListItemProps {
+  isSelected?: boolean;
+  isActive?: boolean;
+  isDefault?: boolean;
+}

-const BranchListItemContainer = styled.div<{
-  isSelected?: boolean;
-  isActive?: boolean;
-  isDefault?: boolean;
-}>`
+const BranchListItemContainer = styled.div<BranchListItemProps>`
app/client/src/git/hooks/useStatus.ts (1)

25-31: Memoize return object to prevent unnecessary rerenders

The returned object is recreated on every render, which could cause unnecessary rerenders in consuming components.

+ const returnValue = useMemo(() => ({
+   status: statusState?.value,
+   isFetchStatusLoading: statusState?.loading ?? false,
+   fetchStatusError: statusState?.error,
+   fetchStatus,
+ }), [statusState, fetchStatus]);
+
- return {
-   status: statusState?.value,
-   isFetchStatusLoading: statusState?.loading ?? false,
-   fetchStatusError: statusState?.error,
-   fetchStatus,
- };
+ return returnValue;
app/client/src/git/hooks/useDiscard.ts (1)

1-30: LGTM with a minor type safety enhancement suggestion

The hook implementation is clean and follows React hooks best practices. Consider adding explicit return type for better type safety.

-export default function useDiscard() {
+export default function useDiscard(): {
+  isDiscardLoading: boolean;
+  discardError: Error | null;
+  discard: () => void;
+  clearDiscardError: () => void;
+} {
app/client/src/git/hooks/useCommit.ts (2)

16-27: Consider making doPush configurable

The commit function hardcodes doPush: true. Consider making this configurable to support scenarios where immediate push isn't desired.

-const commit = useCallback(
-  (commitMessage: string) => {
+const commit = useCallback(
+  (commitMessage: string, doPush: boolean = true) => {
     dispatch(
       gitArtifactActions.commitInit({
         ...artifactDef,
         commitMessage,
-        doPush: true,
+        doPush,
       }),
     );
   },
   [artifactDef, dispatch],
 );

8-39: Add explicit return type for consistency

For consistency with the suggested changes in useDiscard.ts, consider adding explicit return type.

-export default function useCommit() {
+export default function useCommit(): {
+  isCommitLoading: boolean;
+  commitError: Error | null;
+  commit: (commitMessage: string, doPush?: boolean) => void;
+  clearCommitError: () => void;
+} {
app/client/src/git/components/BranchList/hooks/useActiveHoverIndex.ts (1)

34-40: Optimize effect dependencies

setActiveHoverIndex is a stable callback and doesn't need to be in the dependency array.

  useEffect(
    function activeHoverIndexEffect() {
      // ... effect logic
    },
    [
      currentBranch,
      filteredBranches,
      isCreateNewBranchInputValid,
-     setActiveHoverIndex,
    ],
  );
app/client/src/git/components/BranchList/RemoteBranchList.tsx (2)

26-35: Add aria-label for better accessibility

The container and heading should have proper ARIA attributes for screen readers.

-    <div data-testid="t--git-remote-branch-list-container">
+    <div 
+      data-testid="t--git-remote-branch-list-container"
+      aria-label="Remote branches list"
+      role="list"
+    >
       {remoteBranches?.length > 0 && (
         <Heading
           color="var(--ads-v2-color-fg-muted)"
           data-testid="t--branch-list-header-local"
           kind="heading-s"
+          role="heading"
+          aria-level="2"
         >

36-44: Consider using React.memo for RemoteBranchListItem

Since the list could be large, memoizing the list items would prevent unnecessary re-renders.

+const MemoizedRemoteBranchListItem = React.memo(RemoteBranchListItem);

 {remoteBranches.map((branch: string) => (
-        <RemoteBranchListItem
+        <MemoizedRemoteBranchListItem
           branch={branch}
           checkoutBranch={checkoutBranch}
           checkoutDestBranch={checkoutDestBranch}
           isCheckoutBranchLoading={isCheckoutBranchLoading}
           key={branch}
         />
app/client/src/git/components/BranchList/index.tsx (2)

8-20: Consider using a custom hook for combined branch state

The component is managing multiple branch-related hooks. Consider combining them into a single custom hook for better maintainability.

Example implementation:

function useBranchManagement() {
  const branchState = useBranches();
  const { defaultBranch } = useDefaultBranch();
  const protectedBranchState = useProtectedBranches();
  
  return {
    ...branchState,
    defaultBranch,
    ...protectedBranchState,
  };
}

28-46: Consider memoizing BranchListView props

With multiple state values being passed as props, consider using useMemo to prevent unnecessary re-renders.

+ const branchListViewProps = React.useMemo(
+   () => ({
+     branches,
+     checkoutBranch,
+     // ... other props
+   }),
+   [branches, checkoutBranch, /* ... other dependencies */]
+ );

  return (
-    <BranchListView
-      branches={branches}
-      checkoutBranch={checkoutBranch}
-      // ... other props
-    />
+    <BranchListView {...branchListViewProps} />
  );
app/client/src/git/hooks/useOps.ts (1)

50-57: Add TypeScript interface for return object

Define an interface for the return object to improve type safety and documentation.

+interface UseOpsReturn {
+  opsModalTab: typeof GitOpsTab[keyof typeof GitOpsTab];
+  opsModalOpen: boolean;
+  toggleOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void;
+  conflictErrorModalOpen: boolean;
+  toggleConflictErrorModal: (open: boolean) => void;
+}
+
-return {
+return <UseOpsReturn>{
   opsModalTab,
   opsModalOpen,
   toggleOpsModal,
   conflictErrorModalOpen,
   toggleConflictErrorModal,
 };
app/client/src/git/components/OpsModal/TabDeploy/index.tsx (1)

24-28: Consider consolidating null checks

Multiple null coalescing operators could be simplified using a utility function or destructuring with defaults.

+const {
+  lastDeployedAt = null,
+  isClean: statusIsClean = false,
+  behindCount: statusBehindCount = 0,
+} = {
+  lastDeployedAt: artifact?.lastDeployedAt,
+  isClean: status?.isClean,
+  behindCount: status?.behindCount,
+};
-const lastDeployedAt = artifact?.lastDeployedAt ?? null;
-const statusIsClean = status?.isClean ?? false;
-const statusBehindCount = status?.behindCount ?? 0;
app/client/src/git/hooks/useMerge.ts (1)

48-58: Add TypeScript types for state selectors

Define interfaces for mergeState and mergeStatusState to improve type safety.

+interface MergeState {
+  loading: boolean;
+  error?: Error;
+}
+
+interface MergeStatusState {
+  loading: boolean;
+  error?: Error;
+  value?: unknown;
+}
+
 return {
   isMergeLoading: mergeState?.loading ?? false,
   mergeError: mergeState?.error,
   merge,
   mergeStatus: mergeStatusState?.value,
   isFetchMergeStatusLoading: mergeStatusState?.loading ?? false,
   fetchMergeStatusError: mergeStatusState?.error,
   fetchMergeStatus,
   clearMergeStatus,
 };
app/client/src/git/components/BranchList/RemoteBranchListItem.tsx (1)

41-46: Enhance analytics event payload

Consider adding more context to the analytics event payload, such as the branch name (sanitized).

 AnalyticsUtil.logEvent("GS_SWITCH_BRANCH", {
   source: "BRANCH_LIST_POPUP_FROM_BOTTOM_BAR",
+  branchName: branch.replace(/[^a-zA-Z0-9-_]/g, '_'),
 });
app/client/src/git/components/ConnectModal/index.tsx (1)

12-38: Consider memoizing derived values

The derived values from metadata could benefit from memoization to prevent unnecessary recalculations.

+ import { useMemo } from "react";

  function ConnectModal({ isImport = false }: ConnectModalProps) {
    // ... existing hooks ...
    
+   const derivedValues = useMemo(() => ({
+     sshPublicKey: sshKey?.publicKey ?? null,
+     remoteUrl: metadata?.remoteUrl ?? null,
+     repoName: metadata?.repoName ?? null,
+     defaultBranch: metadata?.defaultBranchName ?? null,
+   }), [sshKey, metadata]);
app/client/src/git/components/BranchList/LocalBranchList.tsx (2)

50-53: Simplify active index calculation

The conditional expression for isActive could be simplified.

- const isActive =
-   (isCreateNewBranchInputValid
-     ? activeHoverIndex - 1
-     : activeHoverIndex) === index;
+ const isActive = activeHoverIndex - Number(isCreateNewBranchInputValid) === index;

56-70: Consider memoizing LocalBranchListItem

Wrap LocalBranchListItem with React.memo to prevent unnecessary re-renders of unchanged branches.

+ const MemoizedLocalBranchListItem = React.memo(LocalBranchListItem);

  return (
-   <LocalBranchListItem
+   <MemoizedLocalBranchListItem
      {...props}
    />
  );
app/client/src/git/store/actions/uiActions.ts (1)

73-87: Consider grouping related modal interfaces

The modal-related interfaces could be grouped under a namespace for better organization.

+ export namespace ModalPayloads {
+   export interface Base {
+     open: boolean;
+   }
+   
+   export interface Autocommit extends Base {}
+   export interface RepoLimit extends Base {}
+   export interface ConflictError extends Base {}
+ }

- interface ToggleAutocommitDisableModalPayload {
-   open: boolean;
- }
+ type ToggleAutocommitDisableModalPayload = ModalPayloads.Autocommit;

Also applies to: 103-130

app/client/src/git/components/BranchList/BranchMoreMenu.tsx (1)

78-132: Ensure menu closes after item selection

The menu should automatically close after an item is selected.

Pass the close handler to the menu items:

 <MenuContent
   align="end"
   onEscapeKeyDown={handleMenuClose}
   onPointerDownOutside={handleMenuClose}
 >
-  {buttons}
+  {React.Children.map(buttons, (button) =>
+    React.cloneElement(button, {
+      onClick: (e) => {
+        button.props.onClick?.(e);
+        handleMenuClose();
+      },
+    })
+  )}
 </MenuContent>
app/client/src/git/store/types.ts (1)

Line range hint 36-61: Add JSDoc comments for complex interfaces

The GitSingleArtifactAPIResponsesReduxState interface contains multiple properties that would benefit from documentation.

Add JSDoc comments to explain the purpose of key properties:

+/**
+ * Represents the API response state for a single Git artifact
+ * @property metadata - Git repository metadata
+ * @property connect - Connection state
+ * @property sshKey - SSH key information
+ */
 export interface GitSingleArtifactAPIResponsesReduxState
   extends GitSingleArtifactAPIResponsesReduxStateEE {
   metadata: GitAsyncState<FetchMetadataResponseData>;
   // ... other properties
 }
app/client/src/git/components/BranchList/LocalBranchListItem.tsx (1)

122-131: Consider debouncing hover state changes

The current implementation might cause unnecessary re-renders on rapid hover state changes.

Consider debouncing the hover state:

+import { useDebouncedCallback } from 'use-debounce';
+
+const [isHovered, setIsHovered] = React.useState(false);
+const debouncedSetHover = useDebouncedCallback(
+  (value: boolean) => setIsHovered(value),
+  100
+);

-{(hover || isMoreMenuOpen) && (
+{(isHovered || isMoreMenuOpen) && (
app/client/src/git/sagas/checkoutBranchSaga.ts (1)

Line range hint 123-124: Consider using typed errors for better error handling

The current error handling could be improved by using specific error types instead of catching all errors.

-} catch (e) {
+} catch (e: GitCheckoutError | unknown) {
   if (response && response.responseMeta.error) {
app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx (2)

15-20: Consider using a separate mock file

Move mock implementations to a separate file to improve test maintainability.


162-172: Add test cases for network failures

Consider adding test cases for network failures and timeout scenarios.

it("handles network timeout during connect", async () => {
  const mockConnect = jest.fn(() => {
    const connectError = {
      code: "NETWORK_TIMEOUT",
      message: "Connection timed out",
    };
    rerender(
      <ConnectInitialize {...defaultProps} connectError={connectError} />,
    );
  });
  // ... test implementation
});
app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx (3)

117-124: Consider using a reducer for complex form state management.

The form state contains multiple related fields that are managed using a single useState hook. Given the complexity of the state and multiple update points, using useReducer would make the state transitions more predictable and easier to test.

Example implementation:

type Action = 
  | { type: 'SET_GIT_PROVIDER', payload: string }
  | { type: 'SET_REPO_STATUS', payload: { empty: boolean, existing: boolean } }
  // ... other actions

const formReducer = (state: ConnectFormDataState, action: Action) => {
  switch (action.type) {
    case 'SET_GIT_PROVIDER':
      return { ...state, gitProvider: action.payload };
    // ... other cases
  }
};

160-212: Extract step handling logic into separate functions.

The handleNextStep function is complex with multiple responsibilities. Consider extracting the step-specific logic into separate functions for better maintainability.

Example:

const handleChooseProviderStep = () => {
  setActiveStep(GIT_CONNECT_STEPS.GENERATE_SSH_KEY);
  AnalyticsUtil.logEvent("GS_CONFIGURE_GIT");
};

const handleGenerateSSHStep = () => {
  setActiveStep(GIT_CONNECT_STEPS.ADD_DEPLOY_KEY);
  AnalyticsUtil.logEvent("GS_GENERATE_KEY_BUTTON_CLICK", {
    repoUrl: formData?.remoteUrl,
    connectFlow: "v2",
  });
};

268-304: Consider extracting footer buttons into a separate component.

The footer logic with conditional rendering and button states could be simplified by extracting it into a dedicated component.

Example:

interface StepFooterProps {
  isLoading: boolean;
  currentStep: string;
  onNext: () => void;
  onPrevious: () => void;
  isNextDisabled: boolean;
}

const StepFooter: React.FC<StepFooterProps> = ({
  isLoading,
  currentStep,
  onNext,
  onPrevious,
  isNextDisabled,
}) => {
  // ... footer implementation
};
app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx (1)

Line range hint 36-61: Consider using strict typing for the GitProvider type.

The GIT_PROVIDERS constant could be better typed using a const assertion to ensure type safety.

-const GIT_PROVIDERS = ["github", "gitlab", "bitbucket", "others"] as const;
+const GIT_PROVIDERS = ["github", "gitlab", "bitbucket", "others"] as const satisfies readonly string[];
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 34f7a00 and 3921112.

📒 Files selected for processing (54)
  • app/client/src/git/components/BranchList/BranchListHotKeys.tsx (1 hunks)
  • app/client/src/git/components/BranchList/BranchListItemContainer.tsx (1 hunks)
  • app/client/src/git/components/BranchList/BranchListView.tsx (1 hunks)
  • app/client/src/git/components/BranchList/BranchMoreMenu.tsx (1 hunks)
  • app/client/src/git/components/BranchList/LocalBranchList.tsx (1 hunks)
  • app/client/src/git/components/BranchList/LocalBranchListItem.tsx (1 hunks)
  • app/client/src/git/components/BranchList/RemoteBranchList.tsx (1 hunks)
  • app/client/src/git/components/BranchList/RemoteBranchListItem.tsx (1 hunks)
  • app/client/src/git/components/BranchList/hooks/useActiveHoverIndex.ts (1 hunks)
  • app/client/src/git/components/BranchList/hooks/useFilteredBranches.ts (1 hunks)
  • app/client/src/git/components/BranchList/hooks/useHover.ts (1 hunks)
  • app/client/src/git/components/BranchList/index.tsx (1 hunks)
  • app/client/src/git/components/ConflictErrorModal/index.tsx (1 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.test.tsx (3 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx (3 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx (7 hunks)
  • app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx (1 hunks)
  • app/client/src/git/components/ConnectModal/ConnectModalView.tsx (1 hunks)
  • app/client/src/git/components/ConnectModal/index.tsx (1 hunks)
  • app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts (0 hunks)
  • app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts (0 hunks)
  • app/client/src/git/components/GitContextProvider/index.tsx (2 hunks)
  • app/client/src/git/components/LocalProfile/LocalProfileView.tsx (1 hunks)
  • app/client/src/git/components/OpsModal/TabDeploy/index.tsx (2 hunks)
  • app/client/src/git/components/OpsModal/TabMerge/index.tsx (2 hunks)
  • app/client/src/git/components/OpsModal/index.tsx (1 hunks)
  • app/client/src/git/components/QuickActions/BranchButton.tsx (2 hunks)
  • app/client/src/git/components/QuickActions/BranchButton/BranchList.tsx (0 hunks)
  • app/client/src/git/components/QuickActions/QuickActionsView.test.tsx (2 hunks)
  • app/client/src/git/components/QuickActions/QuickActionsView.tsx (6 hunks)
  • app/client/src/git/components/QuickActions/index.tsx (1 hunks)
  • app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx (1 hunks)
  • app/client/src/git/components/StatusChanges/index.tsx (1 hunks)
  • app/client/src/git/constants/enums.ts (2 hunks)
  • app/client/src/git/hooks/useAutocommit.ts (1 hunks)
  • app/client/src/git/hooks/useBranches.ts (1 hunks)
  • app/client/src/git/hooks/useCommit.ts (1 hunks)
  • app/client/src/git/hooks/useDiscard.ts (1 hunks)
  • app/client/src/git/hooks/useMerge.ts (1 hunks)
  • app/client/src/git/hooks/useMetadata.ts (1 hunks)
  • app/client/src/git/hooks/useOps.ts (1 hunks)
  • app/client/src/git/hooks/useProtectedBranches.ts (1 hunks)
  • app/client/src/git/hooks/usePull.ts (1 hunks)
  • app/client/src/git/hooks/useStatus.ts (1 hunks)
  • app/client/src/git/sagas/checkoutBranchSaga.ts (1 hunks)
  • app/client/src/git/sagas/createBranchSaga.ts (1 hunks)
  • app/client/src/git/sagas/index.ts (3 hunks)
  • app/client/src/git/store/actions/checkoutBranchActions.ts (2 hunks)
  • app/client/src/git/store/actions/repoLimitErrorModalActions.ts (1 hunks)
  • app/client/src/git/store/actions/uiActions.ts (3 hunks)
  • app/client/src/git/store/gitArtifactSlice.ts (6 hunks)
  • app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts (3 hunks)
  • app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts (2 hunks)
  • app/client/src/git/store/types.ts (2 hunks)
💤 Files with no reviewable changes (3)
  • app/client/src/git/components/QuickActions/BranchButton/BranchList.tsx
  • app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts
  • app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx
  • app/client/src/git/hooks/useMetadata.ts
  • app/client/src/git/hooks/useProtectedBranches.ts
  • app/client/src/git/components/ConnectModal/ConnectModalView.tsx
🧰 Additional context used
📓 Learnings (2)
app/client/src/git/store/actions/checkoutBranchActions.ts (1)
Learnt from: brayn003
PR: appsmithorg/appsmith#37830
File: app/client/packages/git/src/actions/checkoutBranchActions.ts:11-18
Timestamp: 2024-11-29T05:38:54.262Z
Learning: In the Git Redux actions (`app/client/packages/git/src/actions`), the `createSingleArtifactAction` function already handles loading state and error management, so additional checks in action creators are unnecessary.
app/client/src/git/store/gitArtifactSlice.ts (1)
Learnt from: brayn003
PR: appsmithorg/appsmith#36989
File: app/client/packages/git/src/actions/helpers/createSingleArtifactAction.ts:52-68
Timestamp: 2024-11-12T08:11:36.416Z
Learning: In this codebase, when using Redux Toolkit's createSlice from Redux Toolkit, we can directly mutate the state within reducers since Immer handles immutability internally.
🔇 Additional comments (32)
app/client/src/git/components/OpsModal/TabMerge/index.tsx (1)

3-6: LGTM! Well-organized hook imports

The separation of concerns into specific Git operation hooks improves modularity and maintainability.

app/client/src/git/components/QuickActions/index.tsx (3)

4-14: LGTM! Well-organized hook imports

The separation of Git functionality into specific hooks improves modularity and maintainability.


17-31: Clean hook implementation with proper state management

Good separation of concerns with individual hooks handling specific Git operations and their respective loading states.


Line range hint 39-61: Verify prop types in QuickActionsView component

The props passing looks good, but let's verify that QuickActionsView's prop interface is updated to match all these props.

✅ Verification successful

Props interface matches implementation perfectly

All props passed to QuickActionsView are properly typed in the interface definition, including toggleBranchPopup, toggleSettingsModal, and toggleConnectModal. The types are well-defined and match the usage in the component.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check QuickActionsView prop interface
ast-grep --pattern 'interface QuickActionsViewProps {
  $$$
  currentBranch: $_;
  toggleBranchPopup: $_;
  toggleSettingsModal: $_;
  toggleConnectModal: $_;
  $$$
}'

Length of output: 169


Script:

#!/bin/bash
# Let's try a different approach to find the QuickActionsView interface
# First, let's locate the file containing QuickActionsView
fd QuickActionsView

# Then let's examine the interface definition
rg -A 20 "interface QuickActionsViewProps" 

Length of output: 2213


Script:

#!/bin/bash
# Let's get the complete interface definition including toggleBranchPopup
rg -A 25 "interface QuickActionsViewProps" app/client/src/git/components/QuickActions/QuickActionsView.tsx

Length of output: 896

app/client/src/git/components/GitContextProvider/index.tsx (2)

1-7: LGTM! Clean and well-organized imports.

The imports are specific and well-structured, following React best practices.


72-87: LGTM! Well-optimized context value.

The use of useMemo with proper dependency array is a good practice for performance optimization.

app/client/src/git/hooks/useAutocommit.ts (2)

14-16: LGTM! Follows React hooks best practices

The hook is properly defined and uses context correctly.


46-52: LGTM! Follows Redux selector patterns

The selectors are properly implemented and maintain consistency.

app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts (2)

Line range hint 134-138: LGTM! Export structure maintains consistency.

The combined state export follows the established pattern.


13-27: Verify the impact of modal state changes on existing components.

The switch to boolean flags for modal states is cleaner, but we should ensure all components are updated accordingly.

✅ Verification successful

Modal state changes are properly implemented across components

The codebase search confirms that:

  • The new connectModalOpen boolean flag is consistently used in the store and selectors
  • Components like DisconnectModal are already using boolean flags (isDisconnectModalOpen)
  • No legacy modal state structure found
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for components using the old modal state structure
rg -t typescript -t javascript "connectModal\." app/client/src/
# Search for components using the new modal state
rg -t typescript -t javascript "connectModalOpen" app/client/src/

Length of output: 201


Script:

#!/bin/bash
# Search for components using the old modal state structure without file type flags
rg "connectModal\." app/client/src/
# Search for components using the new modal state
rg "connectModalOpen" app/client/src/
# Search for any modal-related state changes in git files
rg -g "git/**" "modal" app/client/src/

Length of output: 1589

app/client/src/git/components/LocalProfile/LocalProfileView.tsx (1)

114-121: LGTM! Clean implementation of loading placeholder

The DummyField component is well-implemented and provides a good loading state experience.

app/client/src/git/constants/enums.ts (2)

36-36: LGTM! Verify error handling implementation.

The error code follows the established pattern.

✅ Verification successful

Error handling for AE-GIT-4033 is properly implemented across the codebase

The error code is consistently handled in both frontend and backend:

  • Backend defines it as "Invalid git repo" error in AppsmithErrorCode.java
  • Frontend components properly handle this error code:
    • Shows appropriate error callouts in GenerateSSH and AddDeployKey components
    • Includes test coverage for error scenarios
    • Correctly transitions to SSH key generation step when this error occurs
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify error handling implementation
rg "AE-GIT-4033" -A 3

Length of output: 5400


15-15: LGTM! Verify component integration.

The enum addition follows the correct pattern.

✅ Verification successful

Enum addition properly integrated

The ContinuousDelivery tab is correctly integrated in SettingsModalView with proper tab rendering and content switching logic. The implementation follows the established pattern.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the usage of ContinuousDelivery tab in components
ast-grep --pattern 'GitSettingsTab.ContinuousDelivery'

Length of output: 86110


Script:

#!/bin/bash
# Let's try a different pattern to find usage of ContinuousDelivery tab
rg -l "GitSettingsTab.ContinuousDelivery" --type ts

Length of output: 117


Script:

#!/bin/bash
# Let's check the actual implementation to verify proper integration
rg "GitSettingsTab.ContinuousDelivery" -A 5 -B 5 app/client/src/git/components/SettingsModal/SettingsModalView.tsx

Length of output: 758

app/client/src/git/hooks/useBranches.ts (1)

16-125: Well-structured custom hook

The useBranches hook is correctly implemented, effectively encapsulating branch-related logic and Redux state management.

app/client/src/git/sagas/index.ts (2)

30-38: Sagas imported and mapped correctly

New sagas for git operations are properly imported and associated with their actions.


60-62: Branch management actions integrated

The actions for branch creation, deletion, and checkout are appropriately added to gitRequestBlockingActions.

app/client/src/git/store/gitArtifactSlice.ts (2)

116-117: Enterprise reducers inclusion

Including gitArtifactCaseReducersEE integrates enterprise-specific reducers seamlessly.


151-153: Consistent action renaming

Renaming actions from fetchGitMetadata to fetchMetadata enhances clarity and consistency across the codebase.

app/client/src/git/components/BranchList/BranchListView.tsx (1)

378-379: Resolve TypeScript Error in SearchInput

The fill prop on SearchInput is causing a TypeScript error. Consider updating the ads library to support this prop or find an alternative solution.

Do you need assistance in resolving this TypeScript issue?

app/client/src/git/store/actions/repoLimitErrorModalActions.ts (1)

12-12: Verify Consistency of State Property

Ensure all references to state.ui.repoLimitErrorModalOpen are updated, and the old property state.ui.repoLimitErrorModal.open is deprecated.

Run the following script to check for outdated references:

✅ Verification successful

Property Update is Consistent

The codebase consistently uses repoLimitErrorModalOpen as a boolean property directly under the UI state. No instances of the old property structure repoLimitErrorModal.open were found. The property is properly defined in types and initial state.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find any usage of the old state property.

rg "state\.ui\.repoLimitErrorModal\.open"

Length of output: 43


Script:

#!/bin/bash
# Let's search for both old and new property patterns to understand the state usage
rg "repoLimitErrorModal" -A 2 -B 2

# Also search for any reducer or action related to this state
fd -e ts -e tsx -e js -e jsx | xargs rg "repoLimitErrorModal.*reducer|repoLimitErrorModal.*action"

Length of output: 1692

app/client/src/git/components/ConflictErrorModal/index.tsx (1)

3-6: Confirm Hook Provides Necessary Context

Ensure that useOps() supplies conflictErrorModalOpen and toggleConflictErrorModal as expected. If useGitContext() is obsolete here, this change is appropriate.

app/client/src/git/components/StatusChanges/index.tsx (1)

4-8: Refactor to Use useStatus Hook

Good work refactoring to use useStatus() for status management. This improves code modularity and clarity.

app/client/src/git/components/OpsModal/index.tsx (1)

9-15: LGTM! Clean implementation with good separation of concerns

The component effectively uses custom hooks to manage different aspects of Git operations, with proper null handling for the repo name.

app/client/src/git/store/actions/checkoutBranchActions.ts (1)

9-14: Verify UI state cleanup across all scenarios

The implementation looks good. The UI state (checkoutDestBranch) is properly managed across init, success, and error cases.

Let's verify all cases where UI state should be cleaned up:

Also applies to: 19-22, 32-34

✅ Verification successful

UI state cleanup is properly implemented

The checkoutDestBranch state is correctly managed:

  • Set during init action (line 12)
  • Reset to null in success case (line 33)
  • Reset to null in error case (line 21)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other places where checkoutDestBranch might need cleanup
rg "checkoutDestBranch" --type ts

Length of output: 2671

app/client/src/git/components/BranchList/hooks/useActiveHoverIndex.ts (1)

15-17: Consider adding boundary checks for effectiveLength

The index wrapping logic assumes effectiveLength is non-negative. Add validation to handle edge cases when filteredBranches is empty.

 if (index < 0) setActiveHoverIndexInState(effectiveLength);
-else if (index > effectiveLength) setActiveHoverIndexInState(0);
+else if (index > effectiveLength || effectiveLength < 0) setActiveHoverIndexInState(0);
 else setActiveHoverIndexInState(index);
app/client/src/git/hooks/useOps.ts (1)

13-15: ⚠️ Potential issue

Add null check for artifactDef

The hook assumes artifactDef will always be available. Consider adding a null check to handle cases where GitContext might not be properly initialized.

app/client/src/git/sagas/createBranchSaga.ts (1)

33-38: LGTM: Modal state management addition

The addition of toggleBranchPopup action is well-placed in the success flow.

✅ Verification successful

The previous pattern didn't yield results, so I'm broadening the search to understand the modal state management patterns across the codebase and specifically in git sagas. This will help verify if the implementation is consistent with existing patterns.


Modal state management is consistent with codebase patterns

The toggleBranchPopup action is used consistently across the codebase:

  • In checkoutBranchSaga.ts for closing after successful checkout
  • In useBranches.ts hook for general state management
  • In UI components like BranchButton.tsx and BranchListView.tsx for user interactions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify consistent modal state management across other sagas
ast-grep --pattern 'yield put($$$gitArtifactActions.toggleBranchPopup$$$)'

Length of output: 76


Script:

#!/bin/bash
# Search for branch popup related actions in the codebase
rg -A 2 "toggleBranchPopup" 

# Search for similar modal state management patterns in git sagas
rg -A 2 "gitArtifactActions" app/client/src/git/sagas/

Length of output: 31266

app/client/src/git/components/ConnectModal/index.tsx (2)

1-6: LGTM: Clean hook organization

Good separation of Git-related hooks for different concerns (connect, metadata, settings).


41-65: Verify prop type consistency with ConnectModalView

Ensure that all props passed to ConnectModalView match its interface definition.

✅ Verification successful

Props passed to ConnectModalView match its interface definition

All props being passed to ConnectModalView in the code snippet match the interface definition in ConnectModalView.tsx. Each prop corresponds to a defined property in the ConnectModalViewProps interface with matching types.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for ConnectModalView interface definition
ast-grep --pattern 'interface ConnectModalViewProps {
  $$$
}'

Length of output: 4658

app/client/src/git/sagas/checkoutBranchSaga.ts (1)

51-51: LGTM: Action name simplified

The action name change from toggleBranchListPopup to toggleBranchPopup improves clarity.

app/client/src/git/components/QuickActions/QuickActionsView.tsx (2)

Line range hint 28-41: LGTM: Well-structured props with defaults

Props are properly typed with appropriate default values, improving component reliability.


136-144: LGTM: Clean BranchButton integration

The BranchButton component is well-integrated with appropriate props passed down.

@brayn003 brayn003 changed the title chore: connect modal and branches chore: git mod - connect modal and branches Dec 15, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

♻️ Duplicate comments (1)
app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts (1)

41-44: ⚠️ Potential issue

Implement missing gitImport saga

While the gitImport state structure is properly defined, the saga implementation is still needed as noted in the previous review.

Also applies to: 131-132

🧹 Nitpick comments (8)
app/client/src/git/sagas/index.ts (1)

41-46: Consider improving type safety.

The type definition uses any which could be made more specific for better type safety.

-  (action: PayloadAction<any>) => Generator<any>
+  (action: PayloadAction<unknown>) => Generator<unknown, void, unknown>
app/client/src/git/components/BranchList/index.tsx (1)

28-46: Add TypeScript interface for component props.

The component would benefit from explicit type definitions for the props being passed to BranchListView.

Consider adding:

interface BranchListViewProps {
  branches: Branch[];
  checkoutBranch: (branch: string) => Promise<void>;
  // ... other props
}
app/client/src/git/ce/components/GitModals/index.tsx (1)

9-20: Consider memoization for performance optimization

The component looks good, but since it renders multiple modals, consider memoizing it to prevent unnecessary re-renders.

-function GitModals() {
+const GitModals = React.memo(function GitModals() {
   return (
     <>
       <ConnectModal />
       <OpsModal />
       <SettingsModal />
       <DisconnectModal />
       <DisableAutocommitModal />
       <ConflictErrorModal />
     </>
   );
-}
+});
app/client/src/git/ce/hooks/useDefaultBranch.ts (1)

6-16: Consider memoizing the return object

The implementation is clean and follows best practices. However, to prevent unnecessary re-renders in consuming components, consider memoizing the return object.

 function useDefaultBranch() {
   const { artifactDef } = useGitContext();

   const defaultBranch = useSelector((state: GitRootState) =>
     selectDefaultBranch(state, artifactDef),
   );

-  return {
-    defaultBranch,
-  };
+  return React.useMemo(() => ({
+    defaultBranch,
+  }), [defaultBranch]);
 }
app/client/src/git/ce/components/ContinuousDelivery/index.tsx (1)

12-17: Avoid magic numbers in calculations

The min-height calculation uses magic numbers. Consider extracting these values into named constants.

+const HEADER_HEIGHT = 52;
+const CONTENT_MIN_HEIGHT = 360;
+
 export const Container = styled.div`
   padding-top: 8px;
   padding-bottom: 16px;
   overflow: auto;
-  min-height: calc(360px + 52px);
+  min-height: calc(${CONTENT_MIN_HEIGHT}px + ${HEADER_HEIGHT}px);
 `;
app/client/src/git/ce/components/DefaultBranch/DefaultBranchView.tsx (3)

1-15: Consider optimizing enterprise-related imports

The component heavily relies on enterprise edition imports. Consider creating a centralized enterprise feature hook to manage all enterprise-related functionality.


58-64: Optimize state initialization logic

The currentDefaultBranch memo could be used for the initial state instead of using a separate effect.

-  const [selectedValue, setSelectedValue] = useState<string | undefined>();
+  const [selectedValue, setSelectedValue] = useState<string | undefined>(() => 
+    branches?.find((b) => b.default)?.branchName
+  );

   const currentDefaultBranch = useMemo(() => {
     const defaultBranch = branches?.find((b) => b.default);
     return defaultBranch?.branchName;
   }, [branches]);

66-68: Memoize enterprise URL hook result

The enterprise URL should be memoized to prevent unnecessary recalculations.

-  const enterprisePricingUrl = useAppsmithEnterpriseUrl(
-    "git_branch_protection",
-  );
+  const enterprisePricingUrl = useMemo(
+    () => useAppsmithEnterpriseUrl("git_branch_protection"),
+    []
+  );
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3921112 and bbbee85.

📒 Files selected for processing (28)
  • app/client/src/git/ce/components/ContinuousDelivery/index.tsx (1 hunks)
  • app/client/src/git/ce/components/DefaultBranch/DefaultBranchView.tsx (1 hunks)
  • app/client/src/git/ce/components/DefaultBranch/index.tsx (1 hunks)
  • app/client/src/git/ce/components/GitModals/index.tsx (1 hunks)
  • app/client/src/git/ce/hooks/useDefaultBranch.ts (1 hunks)
  • app/client/src/git/ce/sagas/index.ts (1 hunks)
  • app/client/src/git/ce/store/actions/index.ts (1 hunks)
  • app/client/src/git/ce/store/helpers/initialState.ts (1 hunks)
  • app/client/src/git/ce/store/selectors/gitArtifactSelectors.ts (1 hunks)
  • app/client/src/git/ce/store/types.ts (1 hunks)
  • app/client/src/git/components/BranchList/index.tsx (1 hunks)
  • app/client/src/git/components/ProtectedBranches/index.tsx (1 hunks)
  • app/client/src/git/components/SettingsModal/TabBranch/index.tsx (1 hunks)
  • app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx (1 hunks)
  • app/client/src/git/components/index.tsx (1 hunks)
  • app/client/src/git/ee/components/ContinuousDelivery/index.tsx (1 hunks)
  • app/client/src/git/ee/components/DefaultBranch/index.tsx (1 hunks)
  • app/client/src/git/ee/components/GitModals/index.tsx (1 hunks)
  • app/client/src/git/ee/hooks/useDefaultBranch.ts (1 hunks)
  • app/client/src/git/ee/sagas/index.ts (1 hunks)
  • app/client/src/git/ee/store/actions/index.ts (1 hunks)
  • app/client/src/git/ee/store/helpers/initialState.ts (1 hunks)
  • app/client/src/git/ee/store/selectors/gitArtifactSelectors.ts (1 hunks)
  • app/client/src/git/ee/store/types.ts (1 hunks)
  • app/client/src/git/sagas/index.ts (3 hunks)
  • app/client/src/git/store/gitArtifactSlice.ts (6 hunks)
  • app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts (3 hunks)
  • app/client/src/git/store/types.ts (2 hunks)
✅ Files skipped from review due to trivial changes (12)
  • app/client/src/git/ce/store/selectors/gitArtifactSelectors.ts
  • app/client/src/git/ee/store/helpers/initialState.ts
  • app/client/src/git/ee/components/GitModals/index.tsx
  • app/client/src/git/ee/hooks/useDefaultBranch.ts
  • app/client/src/git/ee/store/actions/index.ts
  • app/client/src/git/ee/store/types.ts
  • app/client/src/git/ee/components/ContinuousDelivery/index.tsx
  • app/client/src/git/ee/components/DefaultBranch/index.tsx
  • app/client/src/git/ce/store/actions/index.ts
  • app/client/src/git/ee/sagas/index.ts
  • app/client/src/git/ee/store/selectors/gitArtifactSelectors.ts
  • app/client/src/git/ce/store/helpers/initialState.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • app/client/src/git/components/index.tsx
  • app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx
  • app/client/src/git/components/SettingsModal/TabBranch/index.tsx
  • app/client/src/git/store/types.ts
  • app/client/src/git/components/ProtectedBranches/index.tsx
🧰 Additional context used
📓 Learnings (1)
app/client/src/git/store/gitArtifactSlice.ts (1)
Learnt from: brayn003
PR: appsmithorg/appsmith#36989
File: app/client/packages/git/src/actions/helpers/createSingleArtifactAction.ts:52-68
Timestamp: 2024-11-12T08:11:36.416Z
Learning: In this codebase, when using Redux Toolkit's createSlice from Redux Toolkit, we can directly mutate the state within reducers since Immer handles immutability internally.
🪛 Biome (1.9.4)
app/client/src/git/ce/store/types.ts

[error] 1-1: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 3-3: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

🔇 Additional comments (15)
app/client/src/git/sagas/index.ts (3)

26-34: LGTM! Well-organized saga imports.

The new saga imports are properly structured and follow consistent naming conventions.


Line range hint 41-81: Well-structured action organization.

The clear separation between blocking and non-blocking actions, along with logical grouping by functionality, enhances maintainability. The EE integration pattern allows for clean extensibility.

Also applies to: 84-98


112-112: LGTM! Robust watcher implementation.

The watcher implementations properly handle both blocking and non-blocking actions using type-safe key extraction.

Also applies to: 118-118, 123-123, 126-126

app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts (2)

2-4: LGTM: Clean modular approach for enterprise extensions

The import structure cleanly separates enterprise-specific state extensions.


13-27: Verify saga implementation for disconnect functionality

While the UI state changes look good with simplified modal management, we need to ensure the saga implementation exists for the new disconnect flow.

✅ Verification successful

Disconnect functionality implementation is complete and well-structured

The codebase shows a complete implementation of the disconnect functionality:

  • Saga implementation exists in disconnectSaga.ts
  • UI state is properly managed through actions and selectors
  • Component implementation includes proper view and test coverage
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for disconnect saga implementation
rg -A 5 "function\* disconnect" app/client/src/git/sagas/

# Check for disconnect action handlers
rg "disconnectBaseArtifactId|disconnectArtifactName" app/client/src/git/

Length of output: 3263

app/client/src/git/components/BranchList/index.tsx (1)

1-5: LGTM! Clean and well-organized imports.

The imports follow a logical organization, properly separating core and enterprise edition hooks.

app/client/src/git/store/gitArtifactSlice.ts (4)

10-13: LGTM: Clean action naming

The simplified action names improve code clarity while maintaining functionality.


174-175: LGTM: Consistent modal management

The modal actions are well-organized and follow consistent naming patterns.

Also applies to: 216-216, 245-245


247-247: Verify enterprise feature availability handling

The spread of enterprise case reducers needs verification for proper handling when enterprise features are not available.

✅ Verification successful

Let me check the enterprise feature handling implementation further.


Let me check the actual implementation of these imports and feature handling.


Enterprise feature handling is properly implemented

The codebase follows a safe pattern for handling enterprise features:

  • CE version exports an empty object for gitArtifactCaseReducers
  • EE version re-exports from CE, allowing for extension
  • The spread operator safely merges any additional reducers, whether they exist or not
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for enterprise feature availability checks
rg -A 5 "gitArtifactCaseReducers" app/client/src/git

Length of output: 1108


Script:

#!/bin/bash
# Check the EE implementation and imports
rg -l "gitArtifactCaseReducers" app/client/src/git/ee/

# Check how CE and EE imports are handled
fd -e ts -e js "index.ts" app/client/src/git/

Length of output: 402


Script:

#!/bin/bash
# Check the CE and EE implementations
cat app/client/src/git/ce/store/actions/index.ts
cat app/client/src/git/ee/store/actions/index.ts

# Check how the imports are handled in the main slice
cat app/client/src/git/store/gitArtifactSlice.ts

Length of output: 9114


117-138: Verify error handling implementation

The new feature implementations follow Redux patterns correctly. However, let's verify the error handling implementation across the codebase.

Also applies to: 159-172

✅ Verification successful

Let me verify the error handling implementation further by checking the actual error handling logic in the reducers.


Error handling implementation is consistent and complete

The error handling implementation follows a consistent pattern across all Git-related actions:

  • All error actions properly update loading state
  • Error states are correctly stored in respective API response sections
  • Error handling is uniform across all features including the new SSH key, disconnect, and git import functionality
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for error handling patterns in related files
rg -A 2 "gitImportError|fetchSSHKeyError|generateSSHKeyError|disconnectError" app/client/src/git

Length of output: 5015


Script:

#!/bin/bash
# Search for error handling reducer implementations
ast-grep --pattern 'createSingleArtifactAction<$_>((state, action) => {
  const { error } = action.payload;
  $$$
})'

Length of output: 12570

app/client/src/git/ce/components/GitModals/index.tsx (1)

11-18: Verify modal state management

The modals are correctly composed, but we should verify they're properly connected to the store as per PR objectives.

✅ Verification successful

Let me check the store connections in the modal components to verify their proper integration.


Let me try a different path to check the modal components and their store connections.


Let me check the individual modal components for their store connections.


Modal components are properly connected to store

The verification shows that all Git modal components are correctly integrated with Redux store:

  • ConnectModal uses hooks for store connection and error handling
  • OpsModal uses useSelector for deployment state
  • DisconnectModal uses custom hooks (useDisconnect, useSettings) for store integration
  • All modals have proper error handling and loading states
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for store connections in modal components
echo "Checking store connections in modal components..."
rg -l "useSelector|useDispatch|connect" $(fd --type f "Modal" | grep -i "index.tsx\$")

Length of output: 68877


Script:

#!/bin/bash
# Search for store connections in the Git modal components
rg -A 5 "useSelector|useDispatch|connect" "app/client/src/git/components/.*Modal.*"

Length of output: 165


Script:

#!/bin/bash
# Search for store connections in Git modal components with correct path
rg -A 5 "useSelector|useDispatch|connect" "app/client/src/git/ce/components/GitModals/"

Length of output: 1048


Script:

#!/bin/bash
# Search for store connections in the individual Git modal components
echo "Checking ConnectModal..."
rg -A 5 "useSelector|useDispatch|connect" "app/client/src/git/components/ConnectModal/"

echo -e "\nChecking OpsModal..."
rg -A 5 "useSelector|useDispatch|connect" "app/client/src/git/components/OpsModal/"

echo -e "\nChecking DisconnectModal..."
rg -A 5 "useSelector|useDispatch|connect" "app/client/src/git/components/DisconnectModal/"

echo -e "\nChecking DisableAutocommitModal..."
rg -A 5 "useSelector|useDispatch|connect" "app/client/src/git/components/DisableAutocommitModal/"

Length of output: 67870

app/client/src/git/ce/components/DefaultBranch/index.tsx (1)

5-14: 💡 Codebase verification

Use the useGitFeatureFlags hook instead of hard-coding the license check

The isGitProtectedFeatureLicensed should be obtained from the useGitFeatureFlags hook like other components in the codebase, rather than being hard-coded to false. The EE version currently re-exports the CE component, so this change is needed in the CE implementation.

  • Replace isGitProtectedFeatureLicensed={false} with isGitProtectedFeatureLicensed={license_git_branch_protection_enabled} in app/client/src/git/ce/components/DefaultBranch/index.tsx
  • Add import { useGitFeatureFlags } from "git/hooks/useGitFeatureFlags";
  • Add const { license_git_branch_protection_enabled } = useGitFeatureFlags();
🔗 Analysis chain

Verify the hard-coded license check

The implementation is clean, but the hard-coded false for isGitProtectedFeatureLicensed needs verification.


The search results show that isGitProtectedFeatureLicensed is determined by a feature flag in other components. Let me check the feature flag definition and if there's an Enterprise Edition (EE) implementation that might override this CE (Community Edition) component.


I noticed there's an ee directory that might contain an Enterprise Edition implementation. Let me verify if there's an EE version of this component and check the typical usage pattern of the feature flags hook.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other occurrences of isGitProtectedFeatureLicensed to verify if it should be dynamic
rg "isGitProtectedFeatureLicensed" -A 3

Length of output: 5107


Script:

#!/bin/bash
# Check for feature flag definition and usage pattern
rg "license_git_branch_protection_enabled" -A 3

# Look for EE implementation
fd "DefaultBranch" --exec grep -l "isGitProtectedFeatureLicensed"

Length of output: 4701


Script:

#!/bin/bash
# Check if there's an EE implementation that overrides this component
cat app/client/src/git/ee/components/DefaultBranch/index.tsx 2>/dev/null || echo "File does not exist"

# Check for the feature flag hook usage pattern
ast-grep --pattern 'const { $$ } = useGitFeatureFlags();'

Length of output: 181

⛔ Skipped due to learnings
Learnt from: brayn003
PR: appsmithorg/appsmith#38171
File: app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx:1-14
Timestamp: 2024-12-15T17:45:48.303Z
Learning: In `app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx`, the feature flag check is performed at a higher level, so it's acceptable to have `isGitProtectedFeatureLicensed={false}` in this component.
app/client/src/git/ce/components/DefaultBranch/DefaultBranchView.tsx (2)

47-51: LGTM! Well-structured interface definition

The props interface is clear and properly typed.


153-153: LGTM! Proper export statement

The default export is appropriate for this component.

app/client/src/git/ce/sagas/index.ts (1)

3-13: Verify saga registration mechanism

Since both registries are initialized as empty objects, we should ensure there's a proper mechanism to register sagas at runtime.

✅ Verification successful

Saga registration mechanism is properly implemented

The registries are initialized with saga mappings directly in the same file:

  • blockingActionSagas maps action types to corresponding blocking sagas (e.g., commit, pull, branch operations)
  • nonBlockingActionSagas maps action types to non-blocking sagas (e.g., git editor init, SSH operations)
  • Both registries are extended with EE (Enterprise Edition) sagas via spread operator
  • The sagas are properly consumed in watchGitBlockingRequests and watchGitNonBlockingRequests functions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for places where sagas are registered to these objects
rg -l "blockingActionSagas\[.*\]|nonBlockingActionSagas\[.*\]"

# Look for saga registration patterns
ast-grep --pattern 'blockingActionSagas[$_] = $_'

Length of output: 150


Script:

#!/bin/bash
# Let's check the content of the file where sagas are registered
cat app/client/src/git/sagas/index.ts

# Also search for any imports of these registries
rg "import.*\{.*(?:blocking|nonBlocking)ActionSagas.*\}" -g "*.ts"

# Look for alternative registration patterns
ast-grep --pattern '$_ = nonBlockingActionSagas[$_]'
ast-grep --pattern 'nonBlockingActionSagas[$_] = $_'

Length of output: 4991

app/client/src/git/ce/store/types.ts Outdated Show resolved Hide resolved
app/client/src/git/ce/components/GitModals/index.tsx Outdated Show resolved Hide resolved
app/client/src/git/ce/sagas/index.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
app/client/src/git/ce/components/ContinuousDelivery/index.tsx (1)

4-6: Consider using React.memo for performance optimization

Since this is a simple wrapper component with no props, wrapping it with React.memo could prevent unnecessary re-renders.

-function ContinuousDelivery() {
+const ContinuousDelivery = React.memo(function ContinuousDelivery() {
   return <CDUnLicnesed />;
-}
+});
app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx (2)

16-16: Avoid hardcoded calculations in styles

The min-height calculation uses magic numbers. Consider extracting these values into constants or CSS variables for better maintainability.

-  min-height: calc(360px + 52px);
+  min-height: var(--continuous-delivery-min-height, 412px);

32-56: Add TypeScript interface for component props

Even though the component currently doesn't accept props, it's good practice to define an interface for future extensibility.

+interface CDUnLicensedProps {}
+
-function CDUnLicensed() {
+function CDUnLicensed({}: CDUnLicensedProps) {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bbbee85 and a6529bc.

📒 Files selected for processing (3)
  • app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx (1 hunks)
  • app/client/src/git/ce/components/ContinuousDelivery/index.tsx (1 hunks)
  • app/client/src/git/ee/components/ContinuousDelivery/CDUnLicensed/index.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • app/client/src/git/ee/components/ContinuousDelivery/CDUnLicensed/index.tsx
🔇 Additional comments (1)
app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx (1)

45-54: Add aria-label for better accessibility

The enterprise link button should have an aria-label for better screen reader support.

 <StyledButton
   href={enterprisePricingLink}
   kind="primary"
   renderAs="a"
   size="md"
   target="_blank"
+  aria-label="Try Appsmith Enterprise for Continuous Delivery features"
 >
   {createMessage(TRY_APPSMITH_ENTERPRISE)}
 </StyledButton>

@brayn003 brayn003 requested a review from ashit-rath December 17, 2024 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ok-to-test Required label for CI Packages & Git Pod All issues belonging to Packages and Git Packages Pod issues that belong to the packages pod skip-changelog Adding this label to a PR prevents it from being listed in the changelog Task A simple Todo
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Task] Git mod - Components - Error states [Task] Git mod - Components - Connect modal
2 participants